]> git.ipfire.org Git - thirdparty/unbound.git/commitdiff
- Fix #594. libunbound: optionally use libnettle for crypto.
authorWouter Wijngaards <wouter@nlnetlabs.nl>
Tue, 17 Nov 2015 09:43:07 +0000 (09:43 +0000)
committerWouter Wijngaards <wouter@nlnetlabs.nl>
Tue, 17 Nov 2015 09:43:07 +0000 (09:43 +0000)
  Contributed by Luca Bruno.  Added --with-nettle for use with
  --with-libunbound-only.

git-svn-id: file:///svn/unbound/trunk@3533 be551aaa-1e26-0410-a405-d3ace91eadb9

12 files changed:
Makefile.in
compat/getentropy_linux.c
config.h.in
configure
configure.ac
doc/Changelog
testcode/testbound.c
testcode/unitverify.c
util/random.c
validator/val_nsec3.c
validator/val_secalgo.c
validator/val_sigcrypt.c

index b2e5ba334db1c8063d45300503e03a051d4c5359..4ffb5e45e2070f81cc5fd7a4129ad9c50847d2c0 100644 (file)
@@ -38,6 +38,7 @@ UNBOUND_VERSION_MINOR=@UNBOUND_VERSION_MINOR@
 UNBOUND_VERSION_MICRO=@UNBOUND_VERSION_MICRO@
 ALLTARGET=@ALLTARGET@
 INSTALLTARGET=@INSTALLTARGET@
+SSLLIB=@SSLLIB@
 
 # _unbound.la if pyunbound enabled.
 PYUNBOUND_TARGET=@PYUNBOUND_TARGET@
@@ -295,22 +296,22 @@ longtest: tests
 lib:   libunbound.la unbound.h
 
 libunbound.la: $(LIBUNBOUND_OBJ_LINK)
-       $(LINK_LIB) $(UBSYMS) -o $@ $(LIBUNBOUND_OBJ_LINK) -rpath $(libdir) -lssl $(LIBS)
+       $(LINK_LIB) $(UBSYMS) -o $@ $(LIBUNBOUND_OBJ_LINK) -rpath $(libdir) $(SSLLIB) $(LIBS)
 
 unbound$(EXEEXT):      $(DAEMON_OBJ_LINK) libunbound.la
-       $(LINK) -o $@ $(DAEMON_OBJ_LINK) $(EXTRALINK) -lssl $(LIBS)
+       $(LINK) -o $@ $(DAEMON_OBJ_LINK) $(EXTRALINK) $(SSLLIB) $(LIBS)
 
 unbound-checkconf$(EXEEXT):    $(CHECKCONF_OBJ_LINK) libunbound.la
-       $(LINK) -o $@ $(CHECKCONF_OBJ_LINK) $(EXTRALINK) -lssl $(LIBS)
+       $(LINK) -o $@ $(CHECKCONF_OBJ_LINK) $(EXTRALINK) $(SSLLIB) $(LIBS)
 
 unbound-control$(EXEEXT):      $(CONTROL_OBJ_LINK) libunbound.la
-       $(LINK) -o $@ $(CONTROL_OBJ_LINK) $(EXTRALINK) -lssl $(LIBS)
+       $(LINK) -o $@ $(CONTROL_OBJ_LINK) $(EXTRALINK) $(SSLLIB) $(LIBS)
 
 unbound-host$(EXEEXT): $(HOST_OBJ_LINK) libunbound.la
        $(LINK) -o $@ $(HOST_OBJ_LINK) -L. -L.libs -lunbound $(LIBS)
 
 unbound-anchor$(EXEEXT):       $(UBANCHOR_OBJ_LINK) libunbound.la
-       $(LINK) -o $@ $(UBANCHOR_OBJ_LINK) -L. -L.libs -lunbound -lexpat -lssl $(LIBS)
+       $(LINK) -o $@ $(UBANCHOR_OBJ_LINK) -L. -L.libs -lunbound -lexpat $(SSLLIB) $(LIBS)
 
 unbound-service-install$(EXEEXT):      $(SVCINST_OBJ_LINK)
        $(LINK) -o $@ $(SVCINST_OBJ_LINK) $(LIBS)
@@ -322,37 +323,37 @@ anchor-update$(EXEEXT):  $(ANCHORUPD_OBJ_LINK) libunbound.la
        $(LINK) -o $@ $(ANCHORUPD_OBJ_LINK) -L. -L.libs -lunbound $(LIBS)
 
 unittest$(EXEEXT):     $(UNITTEST_OBJ_LINK)
-       $(LINK) -o $@ $(UNITTEST_OBJ_LINK) -lssl $(LIBS)
+       $(LINK) -o $@ $(UNITTEST_OBJ_LINK) $(SSLLIB) $(LIBS)
 
 testbound$(EXEEXT):    $(TESTBOUND_OBJ_LINK)
-       $(LINK) -o $@ $(TESTBOUND_OBJ_LINK) -lssl $(LIBS)
+       $(LINK) -o $@ $(TESTBOUND_OBJ_LINK) $(SSLLIB) $(LIBS)
 
 lock-verify$(EXEEXT):  $(LOCKVERIFY_OBJ_LINK)
-       $(LINK) -o $@ $(LOCKVERIFY_OBJ_LINK) -lssl $(LIBS)
+       $(LINK) -o $@ $(LOCKVERIFY_OBJ_LINK) $(SSLLIB) $(LIBS)
 
 petal$(EXEEXT):        $(PETAL_OBJ_LINK)
-       $(LINK) -o $@ $(PETAL_OBJ_LINK) -lssl $(LIBS)
+       $(LINK) -o $@ $(PETAL_OBJ_LINK) $(SSLLIB) $(LIBS)
 
 pktview$(EXEEXT):      $(PKTVIEW_OBJ_LINK)
-       $(LINK) -o $@ $(PKTVIEW_OBJ_LINK) -lssl $(LIBS)
+       $(LINK) -o $@ $(PKTVIEW_OBJ_LINK) $(SSLLIB) $(LIBS)
 
 memstats$(EXEEXT):     $(MEMSTATS_OBJ_LINK)
-       $(LINK) -o $@ $(MEMSTATS_OBJ_LINK) -lssl $(LIBS)
+       $(LINK) -o $@ $(MEMSTATS_OBJ_LINK) $(SSLLIB) $(LIBS)
 
 asynclook$(EXEEXT):    $(ASYNCLOOK_OBJ_LINK) libunbound.la
        $(LINK) -o $@ $(ASYNCLOOK_OBJ_LINK) $(LIBS) -L. -L.libs -lunbound
 
 streamtcp$(EXEEXT):    $(STREAMTCP_OBJ_LINK)
-       $(LINK) -o $@ $(STREAMTCP_OBJ_LINK) -lssl $(LIBS)
+       $(LINK) -o $@ $(STREAMTCP_OBJ_LINK) $(SSLLIB) $(LIBS)
 
 perf$(EXEEXT): $(PERF_OBJ_LINK)
-       $(LINK) -o $@ $(PERF_OBJ_LINK) -lssl $(LIBS)
+       $(LINK) -o $@ $(PERF_OBJ_LINK) $(SSLLIB) $(LIBS)
 
 delayer$(EXEEXT):      $(DELAYER_OBJ_LINK)
-       $(LINK) -o $@ $(DELAYER_OBJ_LINK) -lssl $(LIBS)
+       $(LINK) -o $@ $(DELAYER_OBJ_LINK) $(SSLLIB) $(LIBS)
 
 signit$(EXEEXT):       testcode/signit.c
-       $(CC) $(CPPFLAGS) $(CFLAGS) -o $@ testcode/signit.c $(LDFLAGS) -lldns -lssl $(LIBS)
+       $(CC) $(CPPFLAGS) $(CFLAGS) -o $@ testcode/signit.c $(LDFLAGS) -lldns $(SSLLIB) $(LIBS)
 
 unbound.h:     $(srcdir)/libunbound/unbound.h
        sed -e 's/@''UNBOUND_VERSION_MAJOR@/$(UNBOUND_VERSION_MAJOR)/' -e 's/@''UNBOUND_VERSION_MINOR@/$(UNBOUND_VERSION_MINOR)/' -e 's/@''UNBOUND_VERSION_MICRO@/$(UNBOUND_VERSION_MICRO)/' < $(srcdir)/libunbound/unbound.h > $@
index 76f0f9df5f1b6ad286d447dbb56f895a4a0967a9..ad86f234b728fc1cca6c304b3614d1b05a418a67 100644 (file)
 #include <errno.h>
 #include <unistd.h>
 #include <time.h>
+
+#if defined(HAVE_SSL)
 #include <openssl/sha.h>
+#elif defined(HAVE_NETTLE)
+#include <nettle/sha.h>
+#endif
 
 #include <linux/types.h>
 #include <linux/random.h>
                        HD(b); \
        } while (0)
 
+#if defined(HAVE_SSL)
+#define CRYPTO_SHA512_CTX              SHA512_CTX
+#define CRYPTO_SHA512_INIT(x)          SHA512_Init(x)
+#define CRYPTO_SHA512_FINAL(r, c)      SHA512_Final(r, c)
 #define HR(x, l) (SHA512_Update(&ctx, (char *)(x), (l)))
 #define HD(x)   (SHA512_Update(&ctx, (char *)&(x), sizeof (x)))
 #define HF(x)    (SHA512_Update(&ctx, (char *)&(x), sizeof (void*)))
+#elif defined(HAVE_NETTLE)
+#define CRYPTO_SHA512_CTX              struct sha512_ctx
+#define CRYPTO_SHA512_INIT(x)          sha512_init(x)
+#define CRYPTO_SHA512_FINAL(r, c)      sha512_digest(c, SHA512_DIGEST_SIZE, r)
+#define HR(x, l) (sha512_update(&ctx, (l), (uint8_t *)(x)))
+#define HD(x)   (sha512_update(&ctx, sizeof (x), (uint8_t *)&(x)))
+#define HF(x)    (sha512_update(&ctx, sizeof (void*), (uint8_t *)&(x)))
+#endif
 
 int    getentropy(void *buf, size_t len);
 
@@ -337,7 +354,7 @@ getentropy_fallback(void *buf, size_t len)
        struct rusage ru;
        sigset_t sigset;
        struct stat st;
-       SHA512_CTX ctx;
+       CRYPTO_SHA512_CTX ctx;
        static pid_t lastpid;
        pid_t pid;
        size_t i, ii, m;
@@ -354,7 +371,7 @@ getentropy_fallback(void *buf, size_t len)
        }
        for (i = 0; i < len; ) {
                int j;
-               SHA512_Init(&ctx);
+               CRYPTO_SHA512_INIT(&ctx);
                for (j = 0; j < repeat; j++) {
                        HX((e = gettimeofday(&tv, NULL)) == -1, tv);
                        if (e != -1) {
@@ -526,7 +543,7 @@ getentropy_fallback(void *buf, size_t len)
 #  endif
 #endif /* HAVE_GETAUXVAL */
 
-               SHA512_Final(results, &ctx);
+               CRYPTO_SHA512_FINAL(results, &ctx);
                memcpy((char*)buf + i, results, min(sizeof(results), len - i));
                i += min(sizeof(results), len - i);
        }
index 1e44741a3a04df7c97f8f0879d6e941321e3c0fc..e90f036cfaa882b1d31253417d464f853626f544 100644 (file)
 /* Define to 1 if you have the <netinet/in.h> header file. */
 #undef HAVE_NETINET_IN_H
 
+/* Use libnettle for crypto */
+#undef HAVE_NETTLE
+
 /* Use libnss for crypto */
 #undef HAVE_NSS
 
index 7e23744140bcf79fde6951f53a07e50cfee8ad99..acfb10739e478007a04ff3a4aca524a0e5459fb9 100755 (executable)
--- a/configure
+++ b/configure
@@ -661,6 +661,7 @@ CHECKLOCK_OBJ
 staticexe
 UNBOUND_EVENT_UNINSTALL
 UNBOUND_EVENT_INSTALL
+SSLLIB
 HAVE_SSL
 CONFIG_DATE
 NETBSD_LINTFLAGS
@@ -823,6 +824,7 @@ with_solaris_threads
 with_pyunbound
 with_pythonmodule
 with_nss
+with_nettle
 with_ssl
 enable_sha2
 enable_gost
@@ -1534,6 +1536,7 @@ Optional Packages:
   --with-pythonmodule     build Python module, or --without-pythonmodule to
                           disable script engine. (default=no)
   --with-nss=path         use libnss instead of openssl, installed at path.
+  --with-nettle=path      use libnettle as crypto library, installed at path.
   --with-ssl=pathname     enable SSL (will check /usr/local/ssl /usr/lib/ssl
                           /usr/ssl /usr/pkg /usr/local /opt/local /usr/sfw
                           /usr)
@@ -16408,13 +16411,44 @@ $as_echo "#define HAVE_NSS 1" >>confdefs.h
                CPPFLAGS="-I/usr/include/nspr4 $CPPFLAGS"
        fi
         LIBS="$LIBS -lnss3 -lnspr4"
+       SSLLIB=""
+
+
+fi
+
+
+# libnettle
+USE_NETTLE="no"
+
+# Check whether --with-nettle was given.
+if test "${with_nettle+set}" = set; then :
+  withval=$with_nettle;
+       USE_NETTLE="yes"
+
+$as_echo "#define HAVE_NETTLE 1" >>confdefs.h
+
+       if test "$withval" != "" -a "$withval" != "yes"; then
+               CPPFLAGS="$CPPFLAGS -I$withval/include/nettle"
+               LDFLAGS="$LDFLAGS -L$withval/lib"
+
+       if test "x$enable_rpath" = xyes; then
+               if echo "$withval/lib" | grep "^/" >/dev/null; then
+                       RUNTIME_PATH="$RUNTIME_PATH -R$withval/lib"
+               fi
+       fi
+
+       else
+               CPPFLAGS="$CPPFLAGS -I/usr/include/nettle"
+       fi
+        LIBS="$LIBS -lhogweed -lnettle -lgmp"
+       SSLLIB=""
 
 
 fi
 
 
 # openssl
-if test $USE_NSS = "no"; then
+if test $USE_NSS = "no" -a $USE_NETTLE = "no"; then
 
 
 # Check whether --with-ssl was given.
@@ -16720,6 +16754,7 @@ fi
 fi
 rm -f core conftest.err conftest.$ac_objext \
     conftest$ac_exeext conftest.$ac_ext
+SSLLIB="-lssl"
 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for LibreSSL" >&5
 $as_echo_n "checking for LibreSSL... " >&6; }
 if grep VERSION_TEXT $ssldir/include/openssl/opensslv.h | grep "LibreSSL" >/dev/null; then
@@ -16917,6 +16952,7 @@ _ACEOF
 fi
 
 
+
 # Check whether --enable-sha2 was given.
 if test "${enable_sha2+set}" = set; then :
   enableval=$enable_sha2;
@@ -16940,7 +16976,7 @@ if test "${enable_gost+set}" = set; then :
 fi
 
 use_gost="no"
-if test $USE_NSS = "no"; then
+if test $USE_NSS = "no" -a $USE_NETTLE = "no"; then
 case "$enable_gost" in
        no)
        ;;
@@ -17093,7 +17129,7 @@ case "$enable_ecdsa" in
     no)
       ;;
     *)
-      if test $USE_NSS = "no"; then
+      if test $USE_NSS = "no" -a $USE_NETTLE = "no"; then
              ac_fn_c_check_func "$LINENO" "ECDSA_sign" "ac_cv_func_ECDSA_sign"
 if test "x$ac_cv_func_ECDSA_sign" = xyes; then :
 
index dd7bd2a57b7cc5c053e224b0fb8eb47804b6c08f..13d83045692fa7d5f48b7330d800828b254d1541 100644 (file)
@@ -563,13 +563,34 @@ AC_ARG_WITH([nss], AC_HELP_STRING([--with-nss=path],
                CPPFLAGS="-I/usr/include/nspr4 $CPPFLAGS"
        fi
         LIBS="$LIBS -lnss3 -lnspr4"
+       SSLLIB=""
+       ]
+)
+
+# libnettle
+USE_NETTLE="no"
+AC_ARG_WITH([nettle], AC_HELP_STRING([--with-nettle=path],
+       [use libnettle as crypto library, installed at path.]),
+       [
+       USE_NETTLE="yes"
+       AC_DEFINE(HAVE_NETTLE, 1, [Use libnettle for crypto])
+       if test "$withval" != "" -a "$withval" != "yes"; then
+               CPPFLAGS="$CPPFLAGS -I$withval/include/nettle"
+               LDFLAGS="$LDFLAGS -L$withval/lib"
+               ACX_RUNTIME_PATH_ADD([$withval/lib])
+       else
+               CPPFLAGS="$CPPFLAGS -I/usr/include/nettle"
+       fi
+        LIBS="$LIBS -lhogweed -lnettle -lgmp"
+       SSLLIB=""
        ]
 )
 
 # openssl
-if test $USE_NSS = "no"; then
+if test $USE_NSS = "no" -a $USE_NETTLE = "no"; then
 ACX_WITH_SSL
 ACX_LIB_SSL
+SSLLIB="-lssl"
 AC_MSG_CHECKING([for LibreSSL])
 if grep VERSION_TEXT $ssldir/include/openssl/opensslv.h | grep "LibreSSL" >/dev/null; then
        AC_MSG_RESULT([yes])
@@ -604,6 +625,7 @@ AC_INCLUDES_DEFAULT
 #include <openssl/evp.h>
 ])
 fi
+AC_SUBST(SSLLIB)
 
 
 AC_ARG_ENABLE(sha2, AC_HELP_STRING([--disable-sha2], [Disable SHA256 and SHA512 RRSIG support]))
@@ -715,7 +737,7 @@ AC_MSG_RESULT($ac_cv_c_gost_works)
 
 AC_ARG_ENABLE(gost, AC_HELP_STRING([--disable-gost], [Disable GOST support]))
 use_gost="no"
-if test $USE_NSS = "no"; then
+if test $USE_NSS = "no" -a $USE_NETTLE = "no"; then
 case "$enable_gost" in
        no)
        ;;
@@ -729,7 +751,7 @@ case "$enable_gost" in
        fi
        ;;
 esac
-fi dnl !USE_NSS
+fi dnl !USE_NSS && !USE_NETTLE
 
 AC_ARG_ENABLE(ecdsa, AC_HELP_STRING([--disable-ecdsa], [Disable ECDSA support]))
 use_ecdsa="no"
@@ -737,7 +759,7 @@ case "$enable_ecdsa" in
     no)
       ;;
     *)
-      if test $USE_NSS = "no"; then
+      if test $USE_NSS = "no" -a $USE_NETTLE = "no"; then
              AC_CHECK_FUNC(ECDSA_sign, [], [AC_MSG_ERROR([OpenSSL does not support ECDSA: please upgrade or rerun with --disable-ecdsa])])
              AC_CHECK_FUNC(SHA384_Init, [], [AC_MSG_ERROR([OpenSSL does not support SHA384: please upgrade or rerun with --disable-ecdsa])])
              AC_CHECK_DECLS([NID_X9_62_prime256v1, NID_secp384r1], [], [AC_MSG_ERROR([OpenSSL does not support the ECDSA curves: please upgrade or rerun with --disable-ecdsa])], [AC_INCLUDES_DEFAULT
index 1bbecfc3354b8c8ae637884c266a577832581faf..a86cd6344a00d40004723bc69d59332ac48707f2 100644 (file)
@@ -1,3 +1,8 @@
+17 November 2015: Wouter
+       - Fix #594. libunbound: optionally use libnettle for crypto.
+         Contributed by Luca Bruno.  Added --with-nettle for use with
+         --with-libunbound-only.
+
 16 November 2015: Wouter
        - Fix for lenient accept of reverse order DNAME and CNAME.
 
index b297f477476e81e3006a83d4babdf0a532291efa..834dd0e4fc367aea562f029881d8a8268254854f 100644 (file)
@@ -286,7 +286,7 @@ main(int argc, char* argv[])
                        testbound_selftest();
                        exit(0);
                case '2':
-#if (defined(HAVE_EVP_SHA256) || defined(HAVE_NSS)) && defined(USE_SHA2)
+#if (defined(HAVE_EVP_SHA256) || defined(HAVE_NSS) || defined(HAVE_NETTLE)) && defined(USE_SHA2)
                        printf("SHA256 supported\n");
                        exit(0);
 #else
index 078af0a9c7c5b3967323643a468044c8c94a3580..9e75ce1c62883fb8883a566ce040cbc9a93e0d5f 100644 (file)
@@ -191,7 +191,8 @@ verifytest_rrset(struct module_env* env, struct val_env* ve,
                printf("verify outcome is: %s %s\n", sec_status_to_string(sec),
                        reason?reason:"");
        }
-       if(should_be_bogus(rrset, qinfo)) {
+       if(should_be_bogus(rrset, qinfo) ||
+               (reason && strncmp(reason, "(custom)", 8) == 0)) {
                unit_assert(sec == sec_status_bogus);
        } else {
                unit_assert(sec == sec_status_secure);
@@ -504,12 +505,12 @@ verify_test(void)
        verifytest_file("testdata/test_signatures.6", "20080416005004");
        verifytest_file("testdata/test_signatures.7", "20070829144150");
        verifytest_file("testdata/test_signatures.8", "20070829144150");
-#if (defined(HAVE_EVP_SHA256) || defined(HAVE_NSS)) && defined(USE_SHA2)
+#if (defined(HAVE_EVP_SHA256) || defined(HAVE_NSS) || defined(HAVE_NETTLE)) && defined(USE_SHA2)
        verifytest_file("testdata/test_sigs.rsasha256", "20070829144150");
        verifytest_file("testdata/test_sigs.sha1_and_256", "20070829144150");
        verifytest_file("testdata/test_sigs.rsasha256_draft", "20090101000000");
 #endif
-#if (defined(HAVE_EVP_SHA512) || defined(HAVE_NSS)) && defined(USE_SHA2)
+#if (defined(HAVE_EVP_SHA512) || defined(HAVE_NSS) || defined(HAVE_NETTLE)) && defined(USE_SHA2)
        verifytest_file("testdata/test_sigs.rsasha512_draft", "20070829144150");
 #endif
        verifytest_file("testdata/test_sigs.hinfo", "20090107100022");
index 71f0ba53e48033c8aacca9dd08fb35ef20d1adfe..684464e7d84134696ae2678e0a3940651482c747 100644 (file)
@@ -68,6 +68,8 @@
 /* nss3 */
 #include "secport.h"
 #include "pk11pub.h"
+#elif defined(HAVE_NETTLE)
+#include "yarrow.h"
 #endif
 
 /** 
@@ -76,7 +78,7 @@
  */
 #define MAX_VALUE 0x7fffffff
 
-#ifndef HAVE_NSS
+#if defined(HAVE_SSL)
 void
 ub_systemseed(unsigned int ATTR_UNUSED(seed))
 {
@@ -110,7 +112,7 @@ ub_random_max(struct ub_randstate* state, long int x)
        return (long)arc4random_uniform((uint32_t)x);
 }
 
-#else
+#elif defined(HAVE_NSS)
 
 /* not much to remember for NSS since we use its pk11_random, placeholder */
 struct ub_randstate {
@@ -144,6 +146,72 @@ long int ub_random(struct ub_randstate* ATTR_UNUSED(state))
        return x & MAX_VALUE;
 }
 
+#elif defined(HAVE_NETTLE)
+
+/**
+ * libnettle implements a Yarrow-256 generator (SHA256 + AES),
+ * and we have to ensure it is seeded before use.
+ */
+struct ub_randstate {
+       struct yarrow256_ctx ctx;
+       int seeded;
+};
+
+void ub_systemseed(unsigned int ATTR_UNUSED(seed))
+{
+/**
+ * We seed on init and not here, as we need the ctx to re-seed.
+ * This also means that re-seeding is not supported.
+ */
+       log_err("Re-seeding not supported, generator untouched");
+}
+
+struct ub_randstate* ub_initstate(unsigned int seed,
+       struct ub_randstate* ATTR_UNUSED(from))
+{
+       struct ub_randstate* s = (struct ub_randstate*)calloc(1, sizeof(*s));
+       uint8_t buf[YARROW256_SEED_FILE_SIZE];
+       if(!s) {
+               log_err("malloc failure in random init");
+               return NULL;
+       }
+       /* Setup Yarrow context */
+       yarrow256_init(&s->ctx, 0, NULL);
+
+       if(getentropy(buf, sizeof(buf)) != -1) {
+               /* got entropy */
+               yarrow256_seed(&s->ctx, YARROW256_SEED_FILE_SIZE, buf);
+               s->seeded = yarrow256_is_seeded(&s->ctx);
+       } else {
+               /* Stretch the uint32 input seed and feed it to Yarrow */
+               uint32_t v = seed;
+               size_t i;
+               for(i=0; i < (YARROW256_SEED_FILE_SIZE/sizeof(seed)); i++) {
+                       memmove(buf+i*sizeof(seed), &v, sizeof(seed));
+                       v = v*seed + (uint32_t)i;
+               }
+               yarrow256_seed(&s->ctx, YARROW256_SEED_FILE_SIZE, buf);
+               s->seeded = yarrow256_is_seeded(&s->ctx);
+       }
+
+       return s;
+}
+
+long int ub_random(struct ub_randstate* s)
+{
+       /* random 31 bit value. */
+       long int x = 0;
+       if (!s || !s->seeded) {
+               log_err("Couldn't generate randomness, Yarrow-256 generator not yet seeded");
+       } else {
+               yarrow256_random(&s->ctx, sizeof(x), (uint8_t *)&x);
+       }
+       return x & MAX_VALUE;
+}
+#endif /* HAVE_SSL or HAVE_NSS or HAVE_NETTLE */
+
+
+#if defined(HAVE_NSS) || defined(HAVE_NETTLE)
 long int
 ub_random_max(struct ub_randstate* state, long int x)
 {
@@ -155,7 +223,7 @@ ub_random_max(struct ub_randstate* state, long int x)
                v = ub_random(state);
        return (v % x);
 }
-#endif /* HAVE_NSS */
+#endif /* HAVE_NSS or HAVE_NETTLE */
 
 void 
 ub_randfree(struct ub_randstate* s)
index 80ca4d0ba36fbad6128bf13d7f1c70b5ae48fad2..3ec157e741e77a6542cc00af0ef76e999f6e7bac 100644 (file)
@@ -48,6 +48,8 @@
 #ifdef HAVE_NSS
 /* nss3 */
 #include "sechash.h"
+#elif defined(HAVE_NETTLE)
+#include "sha1.h"
 #endif
 #include "validator/val_nsec3.h"
 #include "validator/validator.h"
@@ -546,43 +548,70 @@ nsec3_get_hashed(sldns_buffer* buf, uint8_t* nm, size_t nmlen, int algo,
        sldns_buffer_write(buf, salt, saltlen);
        sldns_buffer_flip(buf);
        switch(algo) {
-#if defined(HAVE_EVP_SHA1) || defined(HAVE_NSS)
+#if defined(HAVE_EVP_SHA1)
                case NSEC3_HASH_SHA1:
-#ifdef HAVE_SSL
                        hash_len = SHA_DIGEST_LENGTH;
-#else
-                       hash_len = SHA1_LENGTH;
-#endif
                        if(hash_len > max)
                                return 0;
-#  ifdef HAVE_SSL
                        (void)SHA1((unsigned char*)sldns_buffer_begin(buf),
                                (unsigned long)sldns_buffer_limit(buf),
                                (unsigned char*)res);
-#  else
-                       (void)HASH_HashBuf(HASH_AlgSHA1, (unsigned char*)res,
-                               (unsigned char*)sldns_buffer_begin(buf),
-                               (unsigned long)sldns_buffer_limit(buf));
-#  endif
                        for(i=0; i<iter; i++) {
                                sldns_buffer_clear(buf);
                                sldns_buffer_write(buf, res, hash_len);
                                sldns_buffer_write(buf, salt, saltlen);
                                sldns_buffer_flip(buf);
-#  ifdef HAVE_SSL
                                (void)SHA1(
                                        (unsigned char*)sldns_buffer_begin(buf),
                                        (unsigned long)sldns_buffer_limit(buf),
                                        (unsigned char*)res);
-#  else
+                       }
+                       break;
+#elif defined(HAVE_NSS)
+               case NSEC3_HASH_SHA1:
+                       hash_len = SHA1_LENGTH;
+                       if(hash_len > max)
+                               return 0;
+                       (void)HASH_HashBuf(HASH_AlgSHA1, (unsigned char*)res,
+                               (unsigned char*)sldns_buffer_begin(buf),
+                               (unsigned long)sldns_buffer_limit(buf));
+                       for(i=0; i<iter; i++) {
+                               sldns_buffer_clear(buf);
+                               sldns_buffer_write(buf, res, hash_len);
+                               sldns_buffer_write(buf, salt, saltlen);
+                               sldns_buffer_flip(buf);
                                (void)HASH_HashBuf(HASH_AlgSHA1,
                                        (unsigned char*)res,
                                        (unsigned char*)sldns_buffer_begin(buf),
                                        (unsigned long)sldns_buffer_limit(buf));
-#  endif
                        }
                        break;
-#endif /* HAVE_EVP_SHA1 or NSS */
+#elif defined(HAVE_NETTLE)
+               case NSEC3_HASH_SHA1:
+                       {
+                       struct sha1_ctx ctx;
+                       hash_len = SHA1_DIGEST_SIZE;
+                       if(hash_len > max)
+                               return 0;
+                       sha1_init(&ctx);
+                       sha1_update(&ctx,
+                               (size_t)sldns_buffer_limit(buf),
+                               (const uint8_t*)sldns_buffer_begin(buf));
+                       sha1_digest(&ctx, SHA1_DIGEST_SIZE, (uint8_t *)res);
+                       for(i=0; i<iter; i++) {
+                               sldns_buffer_clear(buf);
+                               sldns_buffer_write(buf, res, hash_len);
+                               sldns_buffer_write(buf, salt, saltlen);
+                               sldns_buffer_flip(buf);
+                               sha1_init(&ctx);
+                               sha1_update(&ctx,
+                                       (size_t)sldns_buffer_limit(buf),
+                                       (const uint8_t*)sldns_buffer_begin(buf));
+                               sha1_digest(&ctx, SHA1_DIGEST_SIZE, (uint8_t *)res);
+                       }
+                       break;
+                       }
+#endif /* HAVE_EVP_SHA1 or HAVE_NSS or HAVE_NETTLE*/
                default:
                        log_err("nsec3 hash of unknown algo %d", algo);
                        return 0;
@@ -608,46 +637,77 @@ nsec3_calc_hash(struct regional* region, sldns_buffer* buf,
        sldns_buffer_write(buf, salt, saltlen);
        sldns_buffer_flip(buf);
        switch(algo) {
-#if defined(HAVE_EVP_SHA1) || defined(HAVE_NSS)
-               case NSEC3_HASH_SHA1:
 #ifdef HAVE_SSL
+               case NSEC3_HASH_SHA1:
                        c->hash_len = SHA_DIGEST_LENGTH;
-#else
-                       c->hash_len = SHA1_LENGTH;
-#endif
-                       c->hash = (uint8_t*)regional_alloc(region, 
+                       c->hash = (uint8_t*)regional_alloc(region,
                                c->hash_len);
                        if(!c->hash)
                                return 0;
-#  ifdef HAVE_SSL
                        (void)SHA1((unsigned char*)sldns_buffer_begin(buf),
                                (unsigned long)sldns_buffer_limit(buf),
                                (unsigned char*)c->hash);
-#  else
-                       (void)HASH_HashBuf(HASH_AlgSHA1,
-                               (unsigned char*)c->hash,
-                               (unsigned char*)sldns_buffer_begin(buf),
-                               (unsigned long)sldns_buffer_limit(buf));
-#  endif
                        for(i=0; i<iter; i++) {
                                sldns_buffer_clear(buf);
                                sldns_buffer_write(buf, c->hash, c->hash_len);
                                sldns_buffer_write(buf, salt, saltlen);
                                sldns_buffer_flip(buf);
-#  ifdef HAVE_SSL
                                (void)SHA1(
                                        (unsigned char*)sldns_buffer_begin(buf),
                                        (unsigned long)sldns_buffer_limit(buf),
                                        (unsigned char*)c->hash);
-#  else
+                       }
+                       break;
+#elif defined(HAVE_NSS)
+               case NSEC3_HASH_SHA1:
+                       c->hash_len = SHA1_LENGTH;
+                       c->hash = (uint8_t*)regional_alloc(region,
+                               c->hash_len);
+                       if(!c->hash)
+                               return 0;
+                       (void)HASH_HashBuf(HASH_AlgSHA1,
+                               (unsigned char*)c->hash,
+                               (unsigned char*)sldns_buffer_begin(buf),
+                               (unsigned long)sldns_buffer_limit(buf));
+                       for(i=0; i<iter; i++) {
+                               sldns_buffer_clear(buf);
+                               sldns_buffer_write(buf, c->hash, c->hash_len);
+                               sldns_buffer_write(buf, salt, saltlen);
+                               sldns_buffer_flip(buf);
                                (void)HASH_HashBuf(HASH_AlgSHA1,
                                        (unsigned char*)c->hash,
                                        (unsigned char*)sldns_buffer_begin(buf),
                                        (unsigned long)sldns_buffer_limit(buf));
-#  endif
                        }
                        break;
-#endif /* HAVE_EVP_SHA1 or NSS */
+#elif defined(HAVE_NETTLE)
+               case NSEC3_HASH_SHA1:
+                       {
+                       struct sha1_ctx ctx;
+                       c->hash_len = SHA1_DIGEST_SIZE;
+                       c->hash = (uint8_t*)regional_alloc(region,
+                               c->hash_len);
+                       if(!c->hash)
+                               return 0;
+                       sha1_init(&ctx);
+                       sha1_update(&ctx,
+                               (size_t)sldns_buffer_limit(buf),
+                               (const uint8_t*)sldns_buffer_begin(buf));
+                       sha1_digest(&ctx, SHA1_DIGEST_SIZE, (uint8_t *)c->hash);
+                       for(i=0; i<iter; i++) {
+                               sldns_buffer_clear(buf);
+                               sldns_buffer_write(buf, c->hash, c->hash_len);
+                               sldns_buffer_write(buf, salt, saltlen);
+                               sldns_buffer_flip(buf);
+                               sha1_init(&ctx);
+                               sha1_update(&ctx,
+                                       (size_t)sldns_buffer_limit(buf),
+                                       (const uint8_t*)sldns_buffer_begin(buf));
+                               sha1_digest(&ctx, SHA1_DIGEST_SIZE, (uint8_t *)c->hash);
+                       }
+                       break;
+                       }
+#endif /* HAVE_SSL or HAVE_NSS or HAVE_NETTLE */
                default:
                        log_err("nsec3 hash of unknown algo %d", algo);
                        return -1;
index 8ed403dfcf92d10b5076fc068a1c2d6faf9cfbb6..dd56edf6f086933b4d50f18a9f2fe067b0393c0a 100644 (file)
@@ -49,7 +49,7 @@
 #include "sldns/keyraw.h"
 #include "sldns/sbuffer.h"
 
-#if !defined(HAVE_SSL) && !defined(HAVE_NSS)
+#if !defined(HAVE_SSL) && !defined(HAVE_NSS) && !defined(HAVE_NETTLE)
 #error "Need crypto library to do digital signature cryptography"
 #endif
 
@@ -74,7 +74,7 @@
 /**
  * Return size of DS digest according to its hash algorithm.
  * @param algo: DS digest algo.
- * @return size in bytes of digest, or 0 if not supported. 
+ * @return size in bytes of digest, or 0 if not supported.
  */
 size_t
 ds_digest_size_supported(int algo)
@@ -1069,5 +1069,425 @@ verify_canonrrset(sldns_buffer* buf, int algo, unsigned char* sigblock,
        return sec_status_bogus;
 }
 
+#elif defined(HAVE_NETTLE)
 
-#endif /* HAVE_SSL or HAVE_NSS */
+#include "sha.h"
+#include "bignum.h"
+#include "macros.h"
+#include "rsa.h"
+#include "dsa.h"
+#ifdef USE_ECDSA
+#include "ecdsa.h"
+#include "ecc-curve.h"
+#endif
+
+/**
+ * Return size of DS digest according to its hash algorithm.
+ * @param algo: DS digest algo.
+ * @return size in bytes of digest, or 0 if not supported.
+ */
+size_t
+ds_digest_size_supported(int algo)
+{
+       switch(algo) {
+               case LDNS_SHA1:
+                       return SHA1_DIGEST_SIZE;
+#ifdef USE_SHA2
+               case LDNS_SHA256:
+                       return SHA256_DIGEST_SIZE;
+#endif
+#ifdef USE_ECDSA
+               case LDNS_SHA384:
+                       return SHA384_DIGEST_SIZE;
+#endif
+               /* GOST not supported */
+               case LDNS_HASH_GOST:
+               default:
+                       break;
+       }
+       return 0;
+}
+
+
+
+static int
+_digest_nettle(int algo, uint8_t* buf, size_t len,
+       unsigned char* res)
+{
+       switch(algo) {
+               case SHA1_DIGEST_SIZE:
+               {
+                       struct sha1_ctx ctx;
+                       sha1_init(&ctx);
+                       sha1_update(&ctx, len, buf);
+                       sha1_digest(&ctx, SHA1_DIGEST_SIZE, res);
+                       return 1;
+               }
+               case SHA256_DIGEST_SIZE:
+               {
+                       struct sha256_ctx ctx;
+                       sha256_init(&ctx);
+                       sha256_update(&ctx, len, buf);
+                       sha256_digest(&ctx, SHA256_DIGEST_SIZE, res);
+                       return 1;
+               }
+               case SHA384_DIGEST_SIZE:
+               {
+                       struct sha384_ctx ctx;
+                       sha384_init(&ctx);
+                       sha384_update(&ctx, len, buf);
+                       sha384_digest(&ctx, SHA384_DIGEST_SIZE, res);
+                       return 1;
+               }
+               case SHA512_DIGEST_SIZE:
+               {
+                       struct sha512_ctx ctx;
+                       sha512_init(&ctx);
+                       sha512_update(&ctx, len, buf);
+                       sha512_digest(&ctx, SHA512_DIGEST_SIZE, res);
+                       return 1;
+               }
+               default:
+                       break;
+       }
+       return 0;
+}
+
+int
+secalgo_ds_digest(int algo, unsigned char* buf, size_t len,
+       unsigned char* res)
+{
+       switch(algo) {
+               case LDNS_SHA1:
+                       return _digest_nettle(SHA1_DIGEST_SIZE, buf, len, res);
+#if defined(USE_SHA2)
+               case LDNS_SHA256:
+                       return _digest_nettle(SHA256_DIGEST_SIZE, buf, len, res);
+#endif
+#ifdef USE_ECDSA
+               case LDNS_SHA384:
+                       return _digest_nettle(SHA384_DIGEST_SIZE, buf, len, res);
+
+#endif
+               case LDNS_HASH_GOST:
+               default:
+                       verbose(VERB_QUERY, "unknown DS digest algorithm %d",
+                               algo);
+                       break;
+       }
+       return 0;
+}
+
+int
+dnskey_algo_id_is_supported(int id)
+{
+       /* uses libnettle */
+       switch(id) {
+       case LDNS_DSA:
+       case LDNS_DSA_NSEC3:
+       case LDNS_RSASHA1:
+       case LDNS_RSASHA1_NSEC3:
+#ifdef USE_SHA2
+       case LDNS_RSASHA256:
+       case LDNS_RSASHA512:
+#endif
+#ifdef USE_ECDSA
+       case LDNS_ECDSAP256SHA256:
+       case LDNS_ECDSAP384SHA384:
+#endif
+               return 1;
+       case LDNS_RSAMD5: /* RFC 6725 deprecates RSAMD5 */
+       case LDNS_ECC_GOST:
+       default:
+               return 0;
+       }
+}
+
+static char *
+_verify_nettle_dsa(sldns_buffer* buf, unsigned char* sigblock,
+       unsigned int sigblock_len, unsigned char* key, unsigned int keylen)
+{
+       uint8_t digest[SHA1_DIGEST_SIZE];
+       uint8_t key_t;
+       int res = 0;
+       size_t offset;
+       struct dsa_public_key pubkey;
+       struct dsa_signature signature;
+       unsigned int expected_len;
+
+       // Validate T values constraints - RFC 2536 sec. 2 & sec. 3
+       key_t = key[0];
+       if (key_t != sigblock[0] || key_t > 8 ) {
+               return "invalid T value in DSA signature or pubkey";
+       }
+
+       // Signature length: 41 bytes - RFC 2536 sec. 3
+       if (sigblock_len != 41) {
+               return "invalid DSA signature length";
+       }
+
+       // Pubkey minimum length: 21 bytes - RFC 2536 sec. 2
+       if (keylen < 21) {
+               return "DSA pubkey too short";
+       }
+
+       expected_len =   1 +            // T
+                       20 +            // Q
+                      (64 + key_t*8) + // P
+                      (64 + key_t*8) + // G
+                      (64 + key_t*8);  // Y
+       if (keylen != expected_len ) {
+               return "invalid DSA pubkey length";
+       }
+
+       // Extract DSA pubkey from the record
+       nettle_dsa_public_key_init(&pubkey);
+       offset = 1;
+       nettle_mpz_set_str_256_u(pubkey.q, 20, key+offset);
+       offset += 20;
+       nettle_mpz_set_str_256_u(pubkey.p, (64 + key_t*8), key+offset);
+       offset += (64 + key_t*8);
+       nettle_mpz_set_str_256_u(pubkey.g, (64 + key_t*8), key+offset);
+       offset += (64 + key_t*8);
+       nettle_mpz_set_str_256_u(pubkey.y, (64 + key_t*8), key+offset);
+
+       // Extract DSA signature from the record
+       nettle_dsa_signature_init(&signature);
+       nettle_mpz_set_str_256_u(signature.r, 20, sigblock+1);
+       nettle_mpz_set_str_256_u(signature.s, 20, sigblock+1+20);
+
+       // Digest content of "buf" and verify its DSA signature in "sigblock"
+       res = _digest_nettle(SHA1_DIGEST_SIZE, (unsigned char*)sldns_buffer_begin(buf),
+                                               (unsigned int)sldns_buffer_limit(buf), digest);
+       res &= dsa_sha1_verify_digest(&pubkey, digest, &signature);
+
+       // Clear and return
+       nettle_dsa_signature_clear(&signature);
+       nettle_dsa_public_key_clear(&pubkey);
+       if (!res)
+               return "DSA signature verification failed";
+       else
+               return NULL;
+}
+
+static char *
+_verify_nettle_rsa(sldns_buffer* buf, unsigned int digest_size, char* sigblock,
+       unsigned int sigblock_len, uint8_t* key, unsigned int keylen)
+{
+       uint16_t exp_len = 0;
+       size_t exp_offset = 0, mod_offset = 0;
+       struct rsa_public_key pubkey;
+       mpz_t signature;
+       int res = 0;
+
+       // RSA pubkey parsing as per RFC 3110 sec. 2
+       if( keylen <= 1) {
+               return "null RSA key";
+       }
+       if (key[0] != 0) {
+               // 1-byte length
+               exp_len = key[0];
+               exp_offset = 1;
+       } else {
+               // 1-byte NUL + 2-bytes exponent length
+               if (keylen < 3) {
+                       return "incorrect RSA key length";
+               }
+               exp_len = READ_UINT16(key+1);
+               if (exp_len == 0)
+                       return "null RSA exponent length";
+               exp_offset = 3;
+       }
+       // Check that we are not over-running input length
+       if (keylen < exp_offset + exp_len + 1) {
+               return "RSA key content shorter than expected";
+       }
+       mod_offset = exp_offset + exp_len;
+       nettle_rsa_public_key_init(&pubkey);
+       pubkey.size = keylen - mod_offset;
+       nettle_mpz_set_str_256_u(pubkey.e, exp_len, &key[exp_offset]);
+       nettle_mpz_set_str_256_u(pubkey.n, pubkey.size, &key[mod_offset]);
+
+       // Digest content of "buf" and verify its RSA signature in "sigblock"
+       nettle_mpz_init_set_str_256_u(signature, sigblock_len, (uint8_t*)sigblock);
+       switch (digest_size) {
+               case SHA1_DIGEST_SIZE:
+               {
+                       uint8_t digest[SHA1_DIGEST_SIZE];
+                       res = _digest_nettle(SHA1_DIGEST_SIZE, (unsigned char*)sldns_buffer_begin(buf),
+                                               (unsigned int)sldns_buffer_limit(buf), digest);
+                       res &= rsa_sha1_verify_digest(&pubkey, digest, signature);
+                       break;
+               }
+               case SHA256_DIGEST_SIZE:
+               {
+                       uint8_t digest[SHA256_DIGEST_SIZE];
+                       res = _digest_nettle(SHA256_DIGEST_SIZE, (unsigned char*)sldns_buffer_begin(buf),
+                                               (unsigned int)sldns_buffer_limit(buf), digest);
+                       res &= rsa_sha256_verify_digest(&pubkey, digest, signature);
+                       break;
+               }
+               case SHA512_DIGEST_SIZE:
+               {
+                       uint8_t digest[SHA512_DIGEST_SIZE];
+                       res = _digest_nettle(SHA512_DIGEST_SIZE, (unsigned char*)sldns_buffer_begin(buf),
+                                               (unsigned int)sldns_buffer_limit(buf), digest);
+                       res &= rsa_sha512_verify_digest(&pubkey, digest, signature);
+                       break;
+               }
+               default:
+                       break;
+       }
+
+       // Clear and return
+       nettle_rsa_public_key_clear(&pubkey);
+       mpz_clear(signature);
+       if (!res) {
+               return "RSA signature verification failed";
+       } else {
+               return NULL;
+       }
+}
+
+#ifdef USE_ECDSA
+static char *
+_verify_nettle_ecdsa(sldns_buffer* buf, unsigned int digest_size, unsigned char* sigblock,
+       unsigned int sigblock_len, unsigned char* key, unsigned int keylen)
+{
+       int res = 0;
+       struct ecc_point pubkey;
+       struct dsa_signature signature;
+
+       // Always matched strength, as per RFC 6605 sec. 1
+       if (sigblock_len != 2*digest_size || keylen != 2*digest_size) {
+               return "wrong ECDSA signature length";
+       }
+
+       // Parse ECDSA signature as per RFC 6605 sec. 4
+       nettle_dsa_signature_init(&signature);
+       switch (digest_size) {
+               case SHA256_DIGEST_SIZE:
+               {
+                       uint8_t digest[SHA256_DIGEST_SIZE];
+                       mpz_t x, y;
+                       nettle_ecc_point_init(&pubkey, &nettle_secp_256r1);
+                       nettle_mpz_init_set_str_256_u(x, SHA256_DIGEST_SIZE, key);
+                       nettle_mpz_init_set_str_256_u(y, SHA256_DIGEST_SIZE, key+SHA256_DIGEST_SIZE);
+                       nettle_mpz_set_str_256_u(signature.r, SHA256_DIGEST_SIZE, sigblock);
+                       nettle_mpz_set_str_256_u(signature.s, SHA256_DIGEST_SIZE, sigblock+SHA256_DIGEST_SIZE);
+                       res = _digest_nettle(SHA256_DIGEST_SIZE, (unsigned char*)sldns_buffer_begin(buf),
+                                               (unsigned int)sldns_buffer_limit(buf), digest);
+                       res &= nettle_ecc_point_set(&pubkey, x, y);
+                       res &= nettle_ecdsa_verify (&pubkey, SHA256_DIGEST_SIZE, digest, &signature);
+                       mpz_clear(x);
+                       mpz_clear(y);
+                       break;
+               }
+               case SHA384_DIGEST_SIZE:
+               {
+                       uint8_t digest[SHA384_DIGEST_SIZE];
+                       mpz_t x, y;
+                       nettle_ecc_point_init(&pubkey, &nettle_secp_384r1);
+                       nettle_mpz_init_set_str_256_u(x, SHA384_DIGEST_SIZE, key);
+                       nettle_mpz_init_set_str_256_u(y, SHA384_DIGEST_SIZE, key+SHA384_DIGEST_SIZE);
+                       nettle_mpz_set_str_256_u(signature.r, SHA384_DIGEST_SIZE, sigblock);
+                       nettle_mpz_set_str_256_u(signature.s, SHA384_DIGEST_SIZE, sigblock+SHA384_DIGEST_SIZE);
+                       res = _digest_nettle(SHA384_DIGEST_SIZE, (unsigned char*)sldns_buffer_begin(buf),
+                                               (unsigned int)sldns_buffer_limit(buf), digest);
+                       res &= nettle_ecc_point_set(&pubkey, x, y);
+                       res &= nettle_ecdsa_verify (&pubkey, SHA384_DIGEST_SIZE, digest, &signature);
+                       mpz_clear(x);
+                       mpz_clear(y);
+                       nettle_ecc_point_clear(&pubkey);
+                       break;
+               }
+               default:
+                       return "unknown ECDSA algorithm";
+       }
+
+       // Clear and return
+       nettle_dsa_signature_clear(&signature);
+       if (!res)
+               return "ECDSA signature verification failed";
+       else
+               return NULL;
+}
+#endif
+
+/**
+ * Check a canonical sig+rrset and signature against a dnskey
+ * @param buf: buffer with data to verify, the first rrsig part and the
+ *     canonicalized rrset.
+ * @param algo: DNSKEY algorithm.
+ * @param sigblock: signature rdata field from RRSIG
+ * @param sigblock_len: length of sigblock data.
+ * @param key: public key data from DNSKEY RR.
+ * @param keylen: length of keydata.
+ * @param reason: bogus reason in more detail.
+ * @return secure if verification succeeded, bogus on crypto failure,
+ *     unchecked on format errors and alloc failures.
+ */
+enum sec_status
+verify_canonrrset(sldns_buffer* buf, int algo, unsigned char* sigblock,
+       unsigned int sigblock_len, unsigned char* key, unsigned int keylen,
+       char** reason)
+{
+       unsigned int digest_size = 0;
+
+       if (sigblock_len == 0 || keylen == 0) {
+               *reason = "null signature";
+               return sec_status_bogus;
+       }
+
+       switch(algo) {
+       case LDNS_DSA:
+       case LDNS_DSA_NSEC3:
+               // Some of these signatures are non-standard
+               if (key[0] > 8 || sigblock_len != 41) {
+                       *reason = "(custom) unknown DSA signature";
+                       return sec_status_unchecked;
+               }
+               *reason = _verify_nettle_dsa(buf, sigblock, sigblock_len, key, keylen);
+               if (*reason != NULL)
+                       return sec_status_bogus;
+               else
+                       return sec_status_secure;
+
+       case LDNS_RSASHA1:
+       case LDNS_RSASHA1_NSEC3:
+               digest_size = (digest_size ? digest_size : SHA1_DIGEST_SIZE);
+#ifdef USE_SHA2
+       case LDNS_RSASHA256:
+               digest_size = (digest_size ? digest_size : SHA256_DIGEST_SIZE);
+       case LDNS_RSASHA512:
+               digest_size = (digest_size ? digest_size : SHA512_DIGEST_SIZE);
+
+#endif
+               *reason = _verify_nettle_rsa(buf, digest_size, (char*)sigblock,
+                                               sigblock_len, key, keylen);
+               if (*reason != NULL)
+                       return sec_status_bogus;
+               else
+                       return sec_status_secure;
+
+#ifdef USE_ECDSA
+       case LDNS_ECDSAP256SHA256:
+               digest_size = (digest_size ? digest_size : SHA256_DIGEST_SIZE);
+       case LDNS_ECDSAP384SHA384:
+               digest_size = (digest_size ? digest_size : SHA384_DIGEST_SIZE);
+               *reason = _verify_nettle_ecdsa(buf, digest_size, sigblock,
+                                               sigblock_len, key, keylen);
+               if (*reason != NULL)
+                       return sec_status_bogus;
+               else
+                       return sec_status_secure;
+#endif
+       case LDNS_RSAMD5:
+       case LDNS_ECC_GOST:
+       default:
+               *reason = "unable to verify signature, unknown algorithm";
+               return sec_status_bogus;
+       }
+}
+
+#endif /* HAVE_SSL or HAVE_NSS or HAVE_NETTLE */
index a2f126529380335d073b0c0837fc43fbff5e0d50..1dd07b420bd5c3fedbc4e67b35683c0dda13d450 100644 (file)
@@ -57,7 +57,7 @@
 #include "sldns/wire2str.h"
 
 #include <ctype.h>
-#if !defined(HAVE_SSL) && !defined(HAVE_NSS)
+#if !defined(HAVE_SSL) && !defined(HAVE_NSS) && !defined(HAVE_NETTLE)
 #error "Need crypto library to do digital signature cryptography"
 #endif