diff --git a/Makefile b/Makefile
index 73ea23e..98ec760 100644
--- a/Makefile
+++ b/Makefile
@@ -76,7 +76,7 @@ objs = cache.o rfc1035.o util.o option.o forward.o network.o \
helper.o tftp.o log.o conntrack.o dhcp6.o rfc3315.o \
dhcp-common.o outpacket.o radv.o slaac.o auth.o ipset.o \
domain.o dnssec.o blockdata.o tables.o loop.o inotify.o \
- poll.o rrfilter.o edns0.o arp.o
+ poll.o rrfilter.o edns0.o arp.o crypto.o
hdrs = dnsmasq.h config.h dhcp-protocol.h dhcp6-protocol.h \
dns-protocol.h radv-protocol.h ip6addr.h
diff --git a/bld/Android.mk b/bld/Android.mk
index eafef35..80ec842 100644
--- a/bld/Android.mk
+++ b/bld/Android.mk
@@ -10,7 +10,7 @@ LOCAL_SRC_FILES := bpf.c cache.c dbus.c dhcp.c dnsmasq.c \
dhcp6.c rfc3315.c dhcp-common.c outpacket.c \
radv.c slaac.c auth.c ipset.c domain.c \
dnssec.c dnssec-openssl.c blockdata.c tables.c \
- loop.c inotify.c poll.c rrfilter.c edns0.c arp.c
+ loop.c inotify.c poll.c rrfilter.c edns0.c arp.c crypto.c
LOCAL_MODULE := dnsmasq
diff --git a/src/blockdata.c b/src/blockdata.c
index 8683b9b..a4e1f81 100644
--- a/src/blockdata.c
+++ b/src/blockdata.c
@@ -25,7 +25,7 @@ static void blockdata_expand(int n)
{
struct blockdata *new = whine_malloc(n * sizeof(struct blockdata));
- if (n > 0 && new)
+ if (new)
{
int i;
@@ -100,6 +100,7 @@ struct blockdata *blockdata_alloc(char *data, size_t len)
return ret;
}
+
void blockdata_free(struct blockdata *blocks)
{
struct blockdata *tmp;
diff --git a/src/crypto.c b/src/crypto.c
new file mode 100644
index 0000000..83372c7
--- /dev/null
+++ b/src/crypto.c
@@ -0,0 +1,456 @@
+/* dnsmasq is Copyright (c) 2000-2017 Simon Kelley
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; version 2 dated June, 1991, or
+ (at your option) version 3 dated 29 June, 2007.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see .
+*/
+
+#include "dnsmasq.h"
+
+#ifdef HAVE_DNSSEC
+
+#include
+#include
+#ifndef NO_NETTLE_ECC
+# include
+# include
+# include
+#endif
+#include
+#include
+
+/* Nettle-3.0 moved to a new API for DSA. We use a name that's defined in the new API
+ to detect Nettle-3, and invoke the backwards compatibility mode. */
+#ifdef dsa_params_init
+#include
+#endif
+
+/* Implement a "hash-function" to the nettle API, which simply returns
+ the input data, concatenated into a single, statically maintained, buffer.
+
+ Used for the EdDSA sigs, which operate on the whole message, rather
+ than a digest. */
+
+struct null_hash_digest
+{
+ uint8_t *buff;
+ size_t len;
+};
+
+struct null_hash_ctx
+{
+ size_t len;
+};
+
+static size_t null_hash_buff_sz = 0;
+static uint8_t *null_hash_buff = NULL;
+#define BUFF_INCR 128
+
+static void null_hash_init(void *ctx)
+{
+ ((struct null_hash_ctx *)ctx)->len = 0;
+}
+
+static void null_hash_update(void *ctxv, size_t length, const uint8_t *src)
+{
+ struct null_hash_ctx *ctx = ctxv;
+ size_t new_len = ctx->len + length;
+
+ if (new_len > null_hash_buff_sz)
+ {
+ uint8_t *new;
+
+ if (!(new = whine_malloc(new_len + BUFF_INCR)))
+ return;
+
+ if (null_hash_buff)
+ {
+ if (ctx->len != 0)
+ memcpy(new, null_hash_buff, ctx->len);
+ free(null_hash_buff);
+ }
+
+ null_hash_buff_sz = new_len + BUFF_INCR;
+ null_hash_buff = new;
+ }
+
+ memcpy(null_hash_buff + ctx->len, src, length);
+ ctx->len += length;
+}
+
+
+static void null_hash_digest(void *ctx, size_t length, uint8_t *dst)
+{
+ (void)length;
+
+ ((struct null_hash_digest *)dst)->buff = null_hash_buff;
+ ((struct null_hash_digest *)dst)->len = ((struct null_hash_ctx *)ctx)->len;
+}
+
+static struct nettle_hash null_hash = {
+ "null_hash",
+ sizeof(struct null_hash_ctx),
+ sizeof(struct null_hash_digest),
+ 0,
+ (nettle_hash_init_func *) null_hash_init,
+ (nettle_hash_update_func *) null_hash_update,
+ (nettle_hash_digest_func *) null_hash_digest
+};
+
+/* Find pointer to correct hash function in nettle library */
+const struct nettle_hash *hash_find(char *name)
+{
+ int i;
+
+ if (!name)
+ return NULL;
+
+ for (i = 0; nettle_hashes[i]; i++)
+ {
+ if (strcmp(nettle_hashes[i]->name, name) == 0)
+ return nettle_hashes[i];
+ }
+
+ /* We provide a "null" hash which returns the input data as digest. */
+ if (strcmp(null_hash.name, name) == 0)
+ return &null_hash;
+
+ return NULL;
+}
+
+/* expand ctx and digest memory allocations if necessary and init hash function */
+int hash_init(const struct nettle_hash *hash, void **ctxp, unsigned char **digestp)
+{
+ static void *ctx = NULL;
+ static unsigned char *digest = NULL;
+ static unsigned int ctx_sz = 0;
+ static unsigned int digest_sz = 0;
+
+ void *new;
+
+ if (ctx_sz < hash->context_size)
+ {
+ if (!(new = whine_malloc(hash->context_size)))
+ return 0;
+ if (ctx)
+ free(ctx);
+ ctx = new;
+ ctx_sz = hash->context_size;
+ }
+
+ if (digest_sz < hash->digest_size)
+ {
+ if (!(new = whine_malloc(hash->digest_size)))
+ return 0;
+ if (digest)
+ free(digest);
+ digest = new;
+ digest_sz = hash->digest_size;
+ }
+
+ *ctxp = ctx;
+ *digestp = digest;
+
+ hash->init(ctx);
+
+ return 1;
+}
+
+static int dnsmasq_rsa_verify(struct blockdata *key_data, unsigned int key_len, unsigned char *sig, size_t sig_len,
+ unsigned char *digest, size_t digest_len, int algo)
+{
+ unsigned char *p;
+ size_t exp_len;
+
+ static struct rsa_public_key *key = NULL;
+ static mpz_t sig_mpz;
+
+ (void)digest_len;
+
+ if (key == NULL)
+ {
+ if (!(key = whine_malloc(sizeof(struct rsa_public_key))))
+ return 0;
+
+ nettle_rsa_public_key_init(key);
+ mpz_init(sig_mpz);
+ }
+
+ if ((key_len < 3) || !(p = blockdata_retrieve(key_data, key_len, NULL)))
+ return 0;
+
+ key_len--;
+ if ((exp_len = *p++) == 0)
+ {
+ GETSHORT(exp_len, p);
+ key_len -= 2;
+ }
+
+ if (exp_len >= key_len)
+ return 0;
+
+ key->size = key_len - exp_len;
+ mpz_import(key->e, exp_len, 1, 1, 0, 0, p);
+ mpz_import(key->n, key->size, 1, 1, 0, 0, p + exp_len);
+
+ mpz_import(sig_mpz, sig_len, 1, 1, 0, 0, sig);
+
+ switch (algo)
+ {
+ case 1:
+ return nettle_rsa_md5_verify_digest(key, digest, sig_mpz);
+ case 5: case 7:
+ return nettle_rsa_sha1_verify_digest(key, digest, sig_mpz);
+ case 8:
+ return nettle_rsa_sha256_verify_digest(key, digest, sig_mpz);
+ case 10:
+ return nettle_rsa_sha512_verify_digest(key, digest, sig_mpz);
+ }
+
+ return 0;
+}
+
+static int dnsmasq_dsa_verify(struct blockdata *key_data, unsigned int key_len, unsigned char *sig, size_t sig_len,
+ unsigned char *digest, size_t digest_len, int algo)
+{
+ unsigned char *p;
+ unsigned int t;
+
+ static struct dsa_public_key *key = NULL;
+ static struct dsa_signature *sig_struct;
+
+ (void)digest_len;
+
+ if (key == NULL)
+ {
+ if (!(sig_struct = whine_malloc(sizeof(struct dsa_signature))) ||
+ !(key = whine_malloc(sizeof(struct dsa_public_key))))
+ return 0;
+
+ nettle_dsa_public_key_init(key);
+ nettle_dsa_signature_init(sig_struct);
+ }
+
+ if ((sig_len < 41) || !(p = blockdata_retrieve(key_data, key_len, NULL)))
+ return 0;
+
+ t = *p++;
+
+ if (key_len < (213 + (t * 24)))
+ return 0;
+
+ mpz_import(key->q, 20, 1, 1, 0, 0, p); p += 20;
+ mpz_import(key->p, 64 + (t*8), 1, 1, 0, 0, p); p += 64 + (t*8);
+ mpz_import(key->g, 64 + (t*8), 1, 1, 0, 0, p); p += 64 + (t*8);
+ mpz_import(key->y, 64 + (t*8), 1, 1, 0, 0, p); p += 64 + (t*8);
+
+ mpz_import(sig_struct->r, 20, 1, 1, 0, 0, sig+1);
+ mpz_import(sig_struct->s, 20, 1, 1, 0, 0, sig+21);
+
+ (void)algo;
+
+ return nettle_dsa_sha1_verify_digest(key, digest, sig_struct);
+}
+
+#ifndef NO_NETTLE_ECC
+static int dnsmasq_ecdsa_verify(struct blockdata *key_data, unsigned int key_len,
+ unsigned char *sig, size_t sig_len,
+ unsigned char *digest, size_t digest_len, int algo)
+{
+ unsigned char *p;
+ unsigned int t;
+ struct ecc_point *key;
+
+ static struct ecc_point *key_256 = NULL, *key_384 = NULL;
+ static mpz_t x, y;
+ static struct dsa_signature *sig_struct;
+
+ if (!sig_struct)
+ {
+ if (!(sig_struct = whine_malloc(sizeof(struct dsa_signature))))
+ return 0;
+
+ nettle_dsa_signature_init(sig_struct);
+ mpz_init(x);
+ mpz_init(y);
+ }
+
+ switch (algo)
+ {
+ case 13:
+ if (!key_256)
+ {
+ if (!(key_256 = whine_malloc(sizeof(struct ecc_point))))
+ return 0;
+
+ nettle_ecc_point_init(key_256, &nettle_secp_256r1);
+ }
+
+ key = key_256;
+ t = 32;
+ break;
+
+ case 14:
+ if (!key_384)
+ {
+ if (!(key_384 = whine_malloc(sizeof(struct ecc_point))))
+ return 0;
+
+ nettle_ecc_point_init(key_384, &nettle_secp_384r1);
+ }
+
+ key = key_384;
+ t = 48;
+ break;
+
+ default:
+ return 0;
+ }
+
+ if (sig_len != 2*t || key_len != 2*t ||
+ !(p = blockdata_retrieve(key_data, key_len, NULL)))
+ return 0;
+
+ mpz_import(x, t , 1, 1, 0, 0, p);
+ mpz_import(y, t , 1, 1, 0, 0, p + t);
+
+ if (!ecc_point_set(key, x, y))
+ return 0;
+
+ mpz_import(sig_struct->r, t, 1, 1, 0, 0, sig);
+ mpz_import(sig_struct->s, t, 1, 1, 0, 0, sig + t);
+
+ return nettle_ecdsa_verify(key, digest_len, digest, sig_struct);
+}
+
+static int dnsmasq_eddsa_verify(struct blockdata *key_data, unsigned int key_len,
+ unsigned char *sig, size_t sig_len,
+ unsigned char *digest, size_t digest_len, int algo)
+{
+ unsigned char *p;
+
+ if (key_len != ED25519_KEY_SIZE ||
+ sig_len != ED25519_SIGNATURE_SIZE ||
+ digest_len != sizeof(struct null_hash_digest) ||
+ !(p = blockdata_retrieve(key_data, key_len, NULL)))
+ return 0;
+
+ /* The "digest" returned by the null_hash function is simply a struct null_hash_digest
+ which has a pointer to the actual data and a length, because the buffer
+ may need to be extended during "hashing". */
+
+ switch (algo)
+ {
+ case 15:
+ return ed25519_sha512_verify(p,
+ ((struct null_hash_digest *)digest)->len,
+ ((struct null_hash_digest *)digest)->buff,
+ sig);
+ case 16:
+ /* Ed448 when available */
+ return 0;
+ }
+
+ return 0;
+}
+
+#endif
+
+int (*verify_func(int algo))(struct blockdata *key_data, unsigned int key_len, unsigned char *sig, size_t sig_len,
+ unsigned char *digest, size_t digest_len, int algo)
+{
+
+ /* Enure at runtime that we have support for this digest */
+ if (!hash_find(algo_digest_name(algo)))
+ return NULL;
+
+ /* This switch defines which sig algorithms we support, can't introspect Nettle for that. */
+ switch (algo)
+ {
+ case 1: case 5: case 7: case 8: case 10:
+ return dnsmasq_rsa_verify;
+
+ case 3: case 6:
+ return dnsmasq_dsa_verify;
+
+#ifndef NO_NETTLE_ECC
+ case 13: case 14:
+ return dnsmasq_ecdsa_verify;
+
+ case 15: case 16:
+ return dnsmasq_eddsa_verify;
+#endif
+ }
+
+ return NULL;
+}
+
+int verify(struct blockdata *key_data, unsigned int key_len, unsigned char *sig, size_t sig_len,
+ unsigned char *digest, size_t digest_len, int algo)
+{
+
+ int (*func)(struct blockdata *key_data, unsigned int key_len, unsigned char *sig, size_t sig_len,
+ unsigned char *digest, size_t digest_len, int algo);
+
+ func = verify_func(algo);
+
+ if (!func)
+ return 0;
+
+ return (*func)(key_data, key_len, sig, sig_len, digest, digest_len, algo);
+}
+
+/* http://www.iana.org/assignments/ds-rr-types/ds-rr-types.xhtml */
+char *ds_digest_name(int digest)
+{
+ switch (digest)
+ {
+ case 1: return "sha1";
+ case 2: return "sha256";
+ case 3: return "gosthash94";
+ case 4: return "sha384";
+ default: return NULL;
+ }
+}
+
+/* http://www.iana.org/assignments/dns-sec-alg-numbers/dns-sec-alg-numbers.xhtml */
+char *algo_digest_name(int algo)
+{
+ switch (algo)
+ {
+ case 1: return "md5";
+ case 3: return "sha1";
+ case 5: return "sha1";
+ case 6: return "sha1";
+ case 7: return "sha1";
+ case 8: return "sha256";
+ case 10: return "sha512";
+ case 12: return "gosthash94";
+ case 13: return "sha256";
+ case 14: return "sha384";
+ case 15: return "null_hash"; /* Ed25519 */
+ case 16: return NULL; /* Ed448 */
+ default: return NULL;
+ }
+}
+
+/* http://www.iana.org/assignments/dnssec-nsec3-parameters/dnssec-nsec3-parameters.xhtml */
+char *nsec3_digest_name(int digest)
+{
+ switch (digest)
+ {
+ case 1: return "sha1";
+ default: return NULL;
+ }
+}
+
+#endif
diff --git a/src/dnsmasq.h b/src/dnsmasq.h
index e0184a9..b4d836a 100644
--- a/src/dnsmasq.h
+++ b/src/dnsmasq.h
@@ -142,6 +142,10 @@ extern int capget(cap_user_header_t header, cap_user_data_t data);
#include
#endif
+#ifdef HAVE_DNSSEC
+# include
+#endif
+
/* daemon is function in the C library.... */
#define daemon dnsmasq_daemon
@@ -1179,6 +1183,17 @@ size_t filter_rrsigs(struct dns_header *header, size_t plen);
unsigned char* hash_questions(struct dns_header *header, size_t plen, char *name);
int setup_timestamp(void);
+/* crypto.c */
+const struct nettle_hash *hash_find(char *name);
+int hash_init(const struct nettle_hash *hash, void **ctxp, unsigned char **digestp);
+int (*verify_func(int algo))(struct blockdata *key_data, unsigned int key_len, unsigned char *sig, size_t sig_len,
+ unsigned char *digest, size_t digest_len, int algo);
+int verify(struct blockdata *key_data, unsigned int key_len, unsigned char *sig, size_t sig_len,
+ unsigned char *digest, size_t digest_len, int algo);
+char *ds_digest_name(int digest);
+char *algo_digest_name(int algo);
+char *nsec3_digest_name(int digest);
+
/* util.c */
void rand_init(void);
unsigned short rand16(void);
diff --git a/src/dnssec.c b/src/dnssec.c
index 3819eda..cc79a23 100644
--- a/src/dnssec.c
+++ b/src/dnssec.c
@@ -19,332 +19,11 @@
#ifdef HAVE_DNSSEC
-#include
-#include
-#ifndef NO_NETTLE_ECC
-# include
-# include
-#endif
-#include
-#include
-
-/* Nettle-3.0 moved to a new API for DSA. We use a name that's defined in the new API
- to detect Nettle-3, and invoke the backwards compatibility mode. */
-#ifdef dsa_params_init
-#include
-#endif
-
#define SERIAL_UNDEF -100
#define SERIAL_EQ 0
#define SERIAL_LT -1
#define SERIAL_GT 1
-/* http://www.iana.org/assignments/ds-rr-types/ds-rr-types.xhtml */
-static char *ds_digest_name(int digest)
-{
- switch (digest)
- {
- case 1: return "sha1";
- case 2: return "sha256";
- case 3: return "gosthash94";
- case 4: return "sha384";
- default: return NULL;
- }
-}
-
-/* http://www.iana.org/assignments/dns-sec-alg-numbers/dns-sec-alg-numbers.xhtml */
-static char *algo_digest_name(int algo)
-{
- switch (algo)
- {
- case 1: return "md5";
- case 3: return "sha1";
- case 5: return "sha1";
- case 6: return "sha1";
- case 7: return "sha1";
- case 8: return "sha256";
- case 10: return "sha512";
- case 12: return "gosthash94";
- case 13: return "sha256";
- case 14: return "sha384";
- default: return NULL;
- }
-}
-
-/* http://www.iana.org/assignments/dnssec-nsec3-parameters/dnssec-nsec3-parameters.xhtml */
-static char *nsec3_digest_name(int digest)
-{
- switch (digest)
- {
- case 1: return "sha1";
- default: return NULL;
- }
-}
-
-/* Find pointer to correct hash function in nettle library */
-static const struct nettle_hash *hash_find(char *name)
-{
- int i;
-
- if (!name)
- return NULL;
-
- for (i = 0; nettle_hashes[i]; i++)
- {
- if (strcmp(nettle_hashes[i]->name, name) == 0)
- return nettle_hashes[i];
- }
-
- return NULL;
-}
-
-/* expand ctx and digest memory allocations if necessary and init hash function */
-static int hash_init(const struct nettle_hash *hash, void **ctxp, unsigned char **digestp)
-{
- static void *ctx = NULL;
- static unsigned char *digest = NULL;
- static unsigned int ctx_sz = 0;
- static unsigned int digest_sz = 0;
-
- void *new;
-
- if (ctx_sz < hash->context_size)
- {
- if (!(new = whine_malloc(hash->context_size)))
- return 0;
- if (ctx)
- free(ctx);
- ctx = new;
- ctx_sz = hash->context_size;
- }
-
- if (digest_sz < hash->digest_size)
- {
- if (!(new = whine_malloc(hash->digest_size)))
- return 0;
- if (digest)
- free(digest);
- digest = new;
- digest_sz = hash->digest_size;
- }
-
- *ctxp = ctx;
- *digestp = digest;
-
- hash->init(ctx);
-
- return 1;
-}
-
-static int dnsmasq_rsa_verify(struct blockdata *key_data, unsigned int key_len, unsigned char *sig, size_t sig_len,
- unsigned char *digest, size_t digest_len, int algo)
-{
- unsigned char *p;
- size_t exp_len;
-
- static struct rsa_public_key *key = NULL;
- static mpz_t sig_mpz;
-
- (void)digest_len;
-
- if (key == NULL)
- {
- if (!(key = whine_malloc(sizeof(struct rsa_public_key))))
- return 0;
-
- nettle_rsa_public_key_init(key);
- mpz_init(sig_mpz);
- }
-
- if ((key_len < 3) || !(p = blockdata_retrieve(key_data, key_len, NULL)))
- return 0;
-
- key_len--;
- if ((exp_len = *p++) == 0)
- {
- GETSHORT(exp_len, p);
- key_len -= 2;
- }
-
- if (exp_len >= key_len)
- return 0;
-
- key->size = key_len - exp_len;
- mpz_import(key->e, exp_len, 1, 1, 0, 0, p);
- mpz_import(key->n, key->size, 1, 1, 0, 0, p + exp_len);
-
- mpz_import(sig_mpz, sig_len, 1, 1, 0, 0, sig);
-
- switch (algo)
- {
- case 1:
- return nettle_rsa_md5_verify_digest(key, digest, sig_mpz);
- case 5: case 7:
- return nettle_rsa_sha1_verify_digest(key, digest, sig_mpz);
- case 8:
- return nettle_rsa_sha256_verify_digest(key, digest, sig_mpz);
- case 10:
- return nettle_rsa_sha512_verify_digest(key, digest, sig_mpz);
- }
-
- return 0;
-}
-
-static int dnsmasq_dsa_verify(struct blockdata *key_data, unsigned int key_len, unsigned char *sig, size_t sig_len,
- unsigned char *digest, size_t digest_len, int algo)
-{
- unsigned char *p;
- unsigned int t;
-
- static struct dsa_public_key *key = NULL;
- static struct dsa_signature *sig_struct;
-
- (void)digest_len;
-
- if (key == NULL)
- {
- if (!(sig_struct = whine_malloc(sizeof(struct dsa_signature))) ||
- !(key = whine_malloc(sizeof(struct dsa_public_key))))
- return 0;
-
- nettle_dsa_public_key_init(key);
- nettle_dsa_signature_init(sig_struct);
- }
-
- if ((sig_len < 41) || !(p = blockdata_retrieve(key_data, key_len, NULL)))
- return 0;
-
- t = *p++;
-
- if (key_len < (213 + (t * 24)))
- return 0;
-
- mpz_import(key->q, 20, 1, 1, 0, 0, p); p += 20;
- mpz_import(key->p, 64 + (t*8), 1, 1, 0, 0, p); p += 64 + (t*8);
- mpz_import(key->g, 64 + (t*8), 1, 1, 0, 0, p); p += 64 + (t*8);
- mpz_import(key->y, 64 + (t*8), 1, 1, 0, 0, p); p += 64 + (t*8);
-
- mpz_import(sig_struct->r, 20, 1, 1, 0, 0, sig+1);
- mpz_import(sig_struct->s, 20, 1, 1, 0, 0, sig+21);
-
- (void)algo;
-
- return nettle_dsa_sha1_verify_digest(key, digest, sig_struct);
-}
-
-#ifndef NO_NETTLE_ECC
-static int dnsmasq_ecdsa_verify(struct blockdata *key_data, unsigned int key_len,
- unsigned char *sig, size_t sig_len,
- unsigned char *digest, size_t digest_len, int algo)
-{
- unsigned char *p;
- unsigned int t;
- struct ecc_point *key;
-
- static struct ecc_point *key_256 = NULL, *key_384 = NULL;
- static mpz_t x, y;
- static struct dsa_signature *sig_struct;
-
- if (!sig_struct)
- {
- if (!(sig_struct = whine_malloc(sizeof(struct dsa_signature))))
- return 0;
-
- nettle_dsa_signature_init(sig_struct);
- mpz_init(x);
- mpz_init(y);
- }
-
- switch (algo)
- {
- case 13:
- if (!key_256)
- {
- if (!(key_256 = whine_malloc(sizeof(struct ecc_point))))
- return 0;
-
- nettle_ecc_point_init(key_256, &nettle_secp_256r1);
- }
-
- key = key_256;
- t = 32;
- break;
-
- case 14:
- if (!key_384)
- {
- if (!(key_384 = whine_malloc(sizeof(struct ecc_point))))
- return 0;
-
- nettle_ecc_point_init(key_384, &nettle_secp_384r1);
- }
-
- key = key_384;
- t = 48;
- break;
-
- default:
- return 0;
- }
-
- if (sig_len != 2*t || key_len != 2*t ||
- !(p = blockdata_retrieve(key_data, key_len, NULL)))
- return 0;
-
- mpz_import(x, t , 1, 1, 0, 0, p);
- mpz_import(y, t , 1, 1, 0, 0, p + t);
-
- if (!ecc_point_set(key, x, y))
- return 0;
-
- mpz_import(sig_struct->r, t, 1, 1, 0, 0, sig);
- mpz_import(sig_struct->s, t, 1, 1, 0, 0, sig + t);
-
- return nettle_ecdsa_verify(key, digest_len, digest, sig_struct);
-}
-#endif
-
-static int (*verify_func(int algo))(struct blockdata *key_data, unsigned int key_len, unsigned char *sig, size_t sig_len,
- unsigned char *digest, size_t digest_len, int algo)
-{
-
- /* Enure at runtime that we have support for this digest */
- if (!hash_find(algo_digest_name(algo)))
- return NULL;
-
- /* This switch defines which sig algorithms we support, can't introspect Nettle for that. */
- switch (algo)
- {
- case 1: case 5: case 7: case 8: case 10:
- return dnsmasq_rsa_verify;
-
- case 3: case 6:
- return dnsmasq_dsa_verify;
-
-#ifndef NO_NETTLE_ECC
- case 13: case 14:
- return dnsmasq_ecdsa_verify;
-#endif
- }
-
- return NULL;
-}
-
-static int verify(struct blockdata *key_data, unsigned int key_len, unsigned char *sig, size_t sig_len,
- unsigned char *digest, size_t digest_len, int algo)
-{
-
- int (*func)(struct blockdata *key_data, unsigned int key_len, unsigned char *sig, size_t sig_len,
- unsigned char *digest, size_t digest_len, int algo);
-
- func = verify_func(algo);
-
- if (!func)
- return 0;
-
- return (*func)(key_data, key_len, sig, sig_len, digest, digest_len, algo);
-}
-
/* Convert from presentation format to wire format, in place.
Also map UC -> LC.
Note that using extract_name to get presentation format