]> git.ipfire.org Git - thirdparty/pdns.git/commitdiff
hello decaf signers (ED25519 and ED448)
authorKees Monshouwer <mind04@monshouwer.org>
Sat, 17 Jun 2017 15:31:41 +0000 (17:31 +0200)
committermind04 <mind04@monshouwer.org>
Thu, 22 Jun 2017 09:18:28 +0000 (11:18 +0200)
Testing algorithm 15: 'Decaf ED25519' ->'Decaf ED25519' -> 'Decaf ED25519' Signature & verify ok, signature 68usec, verify 93usec
Testing algorithm 16: 'Decaf ED448' ->'Decaf ED448' -> 'Decaf ED448' Signature & verify ok, signature 163usec, verify 252usec

12 files changed:
m4/pdns_check_libdecaf.m4 [new file with mode: 0644]
pdns/Makefile.am
pdns/dbdnsseckeeper.cc
pdns/decafsigners.cc [new file with mode: 0644]
pdns/dnssecinfra.cc
pdns/dnsseckeeper.hh
pdns/pdnsutil.cc
pdns/recursordist/Makefile.am
pdns/recursordist/configure.ac
pdns/recursordist/decafsigners.cc [new symlink]
pdns/recursordist/m4/pdns_check_libdecaf.m4 [new symlink]
pdns/version.cc

diff --git a/m4/pdns_check_libdecaf.m4 b/m4/pdns_check_libdecaf.m4
new file mode 100644 (file)
index 0000000..e810903
--- /dev/null
@@ -0,0 +1,23 @@
+AC_DEFUN([PDNS_CHECK_LIBDECAF],[
+  AC_MSG_CHECKING([whether we will be linking in libdecaf])
+  AC_ARG_ENABLE([libdecaf],
+    [AS_HELP_STRING([--enable-libdecaf],[use libdecaf  @<:@default=no@:>@])],
+    [enable_libdecaf=$enableval],
+    [enable_libdecaf=no]
+  )
+  AC_MSG_RESULT([$enable_libdecaf])
+
+  AM_CONDITIONAL([LIBDECAF],[test "x$enable_libdecaf" != "xno"])
+
+  AS_IF([test "x$enable_libdecaf" != "xno"],[
+    save_LIBS=$LIBS
+    LIBS=""
+    AC_SEARCH_LIBS([decaf_ed25519_sign],[decaf],[
+      AC_DEFINE([HAVE_LIBDECAF],[1],[Define to 1 if you have libdecaf])
+      AC_SUBST([LIBDECAF_LIBS],["$LIBS"])
+    ],[
+        AC_MSG_ERROR([Could not find libdecaf])
+    ])
+    LIBS="$save_LIBS"
+  ])
+])
index 175a37a2221da8b11048c58ff5c6773e7ab23a11..6a86241a27b94e49fbda648ce2e68745d16a3b6c 100644 (file)
@@ -233,6 +233,11 @@ pdns_server_SOURCES += sodiumsigners.cc
 pdns_server_LDADD += $(LIBSODIUM_LIBS)
 endif
 
+if LIBDECAF
+pdns_server_SOURCES += decafsigners.cc
+pdns_server_LDADD += $(LIBDECAF_LIBS)
+endif
+
 if SQLITE3
 pdns_server_SOURCES += ssqlite3.cc ssqlite3.hh
 pdns_server_LDADD += $(SQLITE3_LIBS)
@@ -324,6 +329,11 @@ pdnsutil_SOURCES += sodiumsigners.cc
 pdnsutil_LDADD += $(LIBSODIUM_LIBS)
 endif
 
+if LIBDECAF
+pdnsutil_SOURCES += decafsigners.cc
+pdnsutil_LDADD += $(LIBDECAF_LIBS)
+endif
+
 if SQLITE3
 pdnsutil_SOURCES += ssqlite3.cc ssqlite3.hh
 pdnsutil_LDADD += $(SQLITE3_LIBS)
index 37bd27c0d09656bcf80a2ecbc7e332296adbab59..11ee50074b3b0c857b3aa0369fe36559346b997f 100644 (file)
@@ -83,6 +83,8 @@ bool DNSSECKeeper::addKey(const DNSName& name, bool setSEPBit, int algorithm, in
         bits = 256;
       else if(algorithm == 14) // ECDSAP384SHA384
         bits = 384;
+      else if(algorithm == 16) // ED448
+        bits = 456;
       else {
         throw runtime_error("Can't guess key size for algorithm "+std::to_string(algorithm));
       }
diff --git a/pdns/decafsigners.cc b/pdns/decafsigners.cc
new file mode 100644 (file)
index 0000000..5e2bbc4
--- /dev/null
@@ -0,0 +1,293 @@
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+#include <decaf.hxx>
+#include <decaf/eddsa.hxx>
+#include <decaf/spongerng.hxx>
+
+#include "dnssecinfra.hh"
+
+using namespace decaf;
+
+class DecafED25519DNSCryptoKeyEngine : public DNSCryptoKeyEngine
+{
+public:
+  explicit DecafED25519DNSCryptoKeyEngine(unsigned int algo) : DNSCryptoKeyEngine(algo)
+  {
+
+  }
+  string getName() const override { return "Decaf ED25519"; }
+  void create(unsigned int bits) override;
+  storvector_t convertToISCVector() const override;
+  std::string getPubKeyHash() const override;
+  std::string sign(const std::string& msg) const override;
+  bool verify(const std::string& msg, const std::string& signature) const override;
+  std::string getPublicKeyString() const override;
+  int getBits() const override;
+  void fromISCMap(DNSKEYRecordContent& drc, std::map<std::string, std::string>& stormap) override;
+  void fromPublicKeyString(const std::string& content) override;
+  void fromPEMString(DNSKEYRecordContent& drc, const std::string& raw) override
+  {}
+
+  static std::shared_ptr<DNSCryptoKeyEngine> maker(unsigned int algorithm)
+  {
+    return std::make_shared<DecafED25519DNSCryptoKeyEngine>(algorithm);
+  }
+
+private:
+  unsigned char d_pubkey[DECAF_EDDSA_25519_PUBLIC_BYTES];
+  unsigned char d_seckey[DECAF_EDDSA_25519_PRIVATE_BYTES];
+};
+
+void DecafED25519DNSCryptoKeyEngine::create(unsigned int bits)
+{
+  if(bits != (unsigned int)getBits()) {
+    throw runtime_error("Unsupported key length of "+std::to_string(bits)+" bits requested, DecafED25519 class");
+  }
+
+  SpongeRng rng("/dev/urandom");
+
+  typename EdDSA<IsoEd25519>::PrivateKey priv(rng);
+  typename EdDSA<IsoEd25519>::PublicKey pub(priv);
+
+  priv.serialize_into(d_seckey);
+  pub.serialize_into(d_pubkey);
+}
+
+int DecafED25519DNSCryptoKeyEngine::getBits() const
+{
+  return DECAF_EDDSA_25519_PRIVATE_BYTES << 3;
+}
+
+DNSCryptoKeyEngine::storvector_t DecafED25519DNSCryptoKeyEngine::convertToISCVector() const
+{
+  /*
+    Private-key-format: v1.2
+    Algorithm: 15 (ED25519)
+    PrivateKey: ODIyNjAzODQ2MjgwODAxMjI2NDUxOTAyMDQxNDIyNjI=
+  */
+
+  storvector_t storvector;
+
+  storvector.push_back(make_pair("Algorithm", "15 (ED25519)"));
+  storvector.push_back(make_pair("PrivateKey", string((char*)d_seckey, DECAF_EDDSA_25519_PRIVATE_BYTES)));
+
+  return storvector;
+}
+
+void DecafED25519DNSCryptoKeyEngine::fromISCMap(DNSKEYRecordContent& drc, std::map<std::string, std::string>& stormap )
+{
+  /*
+    Private-key-format: v1.2
+    Algorithm: 15 (ED25519)
+    PrivateKey: ODIyNjAzODQ2MjgwODAxMjI2NDUxOTAyMDQxNDIyNjI=
+  */
+
+  drc.d_algorithm = pdns_stou(stormap["algorithm"]);
+  string privateKey = stormap["privatekey"];
+
+  if (privateKey.length() != DECAF_EDDSA_25519_PRIVATE_BYTES)
+    throw runtime_error("Private key size mismatch in ISCMap, DecafED25519 class");
+
+  typename EdDSA<IsoEd25519>::PrivateKey priv(Block((const unsigned char*)privateKey.c_str(), DECAF_EDDSA_25519_PRIVATE_BYTES));
+  typename EdDSA<IsoEd25519>::PublicKey pub(priv);
+
+  priv.serialize_into(d_seckey);
+  pub.serialize_into(d_pubkey);
+}
+
+std::string DecafED25519DNSCryptoKeyEngine::getPubKeyHash() const
+{
+  return this->getPublicKeyString();
+}
+
+std::string DecafED25519DNSCryptoKeyEngine::getPublicKeyString() const
+{
+  return string((char*)d_pubkey, DECAF_EDDSA_25519_PUBLIC_BYTES);
+}
+
+void DecafED25519DNSCryptoKeyEngine::fromPublicKeyString(const std::string& input)
+{
+  if (input.length() != DECAF_EDDSA_25519_PUBLIC_BYTES)
+    throw runtime_error("Public key size mismatch, DecafED25519 class");
+
+  memcpy(d_pubkey, input.c_str(), DECAF_EDDSA_25519_PUBLIC_BYTES);
+}
+
+std::string DecafED25519DNSCryptoKeyEngine::sign(const std::string& msg) const
+{
+  typename EdDSA<IsoEd25519>::PrivateKey priv(Block(d_seckey, DECAF_EDDSA_25519_PRIVATE_BYTES));
+
+  SecureBuffer message(msg.begin(), msg.end());
+
+  SecureBuffer sig = priv.sign(message);
+
+  return string(sig.begin(), sig.end());
+}
+
+bool DecafED25519DNSCryptoKeyEngine::verify(const std::string& msg, const std::string& signature) const
+{
+  if (signature.length() != DECAF_EDDSA_25519_SIGNATURE_BYTES)
+    return false;
+
+  typename EdDSA<IsoEd25519>::PublicKey pub(Block(d_pubkey, DECAF_EDDSA_25519_PUBLIC_BYTES));
+
+  SecureBuffer sig(signature.begin(), signature.end());
+  SecureBuffer message(msg.begin(), msg.end());
+
+  try {
+    pub.verify(sig, message);
+  } catch(CryptoException) {
+    return false;
+  }
+
+  return true;
+}
+
+
+class DecafED448DNSCryptoKeyEngine : public DNSCryptoKeyEngine
+{
+public:
+  explicit DecafED448DNSCryptoKeyEngine(unsigned int algo) : DNSCryptoKeyEngine(algo)
+  {
+
+  }
+  string getName() const override { return "Decaf ED448"; }
+  void create(unsigned int bits) override;
+  storvector_t convertToISCVector() const override;
+  std::string getPubKeyHash() const override;
+  std::string sign(const std::string& msg) const override;
+  bool verify(const std::string& msg, const std::string& signature) const override;
+  std::string getPublicKeyString() const override;
+  int getBits() const override;
+  void fromISCMap(DNSKEYRecordContent& drc, std::map<std::string, std::string>& stormap) override;
+  void fromPublicKeyString(const std::string& content) override;
+  void fromPEMString(DNSKEYRecordContent& drc, const std::string& raw) override
+  {}
+
+  static std::shared_ptr<DNSCryptoKeyEngine> maker(unsigned int algorithm)
+  {
+    return std::make_shared<DecafED448DNSCryptoKeyEngine>(algorithm);
+  }
+
+private:
+  unsigned char d_pubkey[DECAF_EDDSA_448_PUBLIC_BYTES];
+  unsigned char d_seckey[DECAF_EDDSA_448_PRIVATE_BYTES];
+};
+
+void DecafED448DNSCryptoKeyEngine::create(unsigned int bits)
+{
+  if(bits != (unsigned int)getBits()) {
+    throw runtime_error("Unsupported key length of "+std::to_string(bits)+" bits requested, DecafED448 class");
+  }
+
+  SpongeRng rng("/dev/urandom");
+
+  typename EdDSA<Ed448Goldilocks>::PrivateKey priv(rng);
+  typename EdDSA<Ed448Goldilocks>::PublicKey pub(priv);
+
+  priv.serialize_into(d_seckey);
+  pub.serialize_into(d_pubkey);
+}
+
+int DecafED448DNSCryptoKeyEngine::getBits() const
+{
+  return DECAF_EDDSA_448_PRIVATE_BYTES << 3;
+}
+
+DNSCryptoKeyEngine::storvector_t DecafED448DNSCryptoKeyEngine::convertToISCVector() const
+{
+  /*
+    Private-key-format: v1.2
+    Algorithm: 16 (ED448)
+    PrivateKey: xZ+5Cgm463xugtkY5B0Jx6erFTXp13rYegst0qRtNsOYnaVpMx0Z/c5EiA9x8wWbDDct/U3FhYWA
+  */
+
+  storvector_t storvector;
+
+  storvector.push_back(make_pair("Algorithm", "16 (ED448)"));
+  storvector.push_back(make_pair("PrivateKey", string((char*)d_seckey, DECAF_EDDSA_448_PRIVATE_BYTES)));
+
+  return storvector;
+}
+
+void DecafED448DNSCryptoKeyEngine::fromISCMap(DNSKEYRecordContent& drc, std::map<std::string, std::string>& stormap )
+{
+  /*
+    Private-key-format: v1.2
+    Algorithm: 16 (ED448)
+    PrivateKey: xZ+5Cgm463xugtkY5B0Jx6erFTXp13rYegst0qRtNsOYnaVpMx0Z/c5EiA9x8wWbDDct/U3FhYWA
+  */
+
+  drc.d_algorithm = pdns_stou(stormap["algorithm"]);
+  string privateKey = stormap["privatekey"];
+
+  if (privateKey.length() != DECAF_EDDSA_448_PRIVATE_BYTES)
+    throw runtime_error("Private key size mismatch in ISCMap, DecafED448 class");
+
+  typename EdDSA<Ed448Goldilocks>::PrivateKey priv(Block((const unsigned char*)privateKey.c_str(), DECAF_EDDSA_448_PRIVATE_BYTES));
+  typename EdDSA<Ed448Goldilocks>::PublicKey pub(priv);
+
+  priv.serialize_into(d_seckey);
+  pub.serialize_into(d_pubkey);
+}
+
+std::string DecafED448DNSCryptoKeyEngine::getPubKeyHash() const
+{
+  return this->getPublicKeyString();
+}
+
+std::string DecafED448DNSCryptoKeyEngine::getPublicKeyString() const
+{
+  return string((char*)d_pubkey, DECAF_EDDSA_448_PUBLIC_BYTES);
+}
+
+void DecafED448DNSCryptoKeyEngine::fromPublicKeyString(const std::string& input)
+{
+  if (input.length() != DECAF_EDDSA_448_PUBLIC_BYTES)
+    throw runtime_error("Public key size mismatch, DecafED448 class");
+
+  memcpy(d_pubkey, input.c_str(), DECAF_EDDSA_448_PUBLIC_BYTES);
+}
+
+std::string DecafED448DNSCryptoKeyEngine::sign(const std::string& msg) const
+{
+  typename EdDSA<Ed448Goldilocks>::PrivateKey priv(Block(d_seckey, DECAF_EDDSA_448_PRIVATE_BYTES));
+
+  SecureBuffer message(msg.begin(), msg.end());
+
+  SecureBuffer sig = priv.sign(message);
+
+  return string(sig.begin(), sig.end());
+}
+
+bool DecafED448DNSCryptoKeyEngine::verify(const std::string& msg, const std::string& signature) const
+{
+  if (signature.length() != DECAF_EDDSA_448_SIGNATURE_BYTES)
+    return false;
+
+  typename EdDSA<Ed448Goldilocks>::PublicKey pub(Block(d_pubkey, DECAF_EDDSA_448_PUBLIC_BYTES));
+
+  SecureBuffer sig(signature.begin(), signature.end());
+  SecureBuffer message(msg.begin(), msg.end());
+
+  try {
+    pub.verify(sig, message);
+  } catch(CryptoException) {
+    return false;
+  }
+
+  return true;
+}
+
+
+namespace {
+struct LoaderDecafStruct
+{
+  LoaderDecafStruct()
+  {
+    DNSCryptoKeyEngine::report(15, &DecafED25519DNSCryptoKeyEngine::maker);
+    DNSCryptoKeyEngine::report(16, &DecafED448DNSCryptoKeyEngine::maker);
+  }
+} loaderdecaf;
+}
index d2654d1d91d8a07e56a285656f4dea37cbd17fed..05766582fb453bab2583cb909fc9a9c27a723e31 100644 (file)
@@ -239,6 +239,8 @@ pair<unsigned int, unsigned int> DNSCryptoKeyEngine::testMakers(unsigned int alg
     bits=256;
   else if(algo == 14) // ECDSAP384SHA384
     bits = 384;
+  else if(algo == 16) // ED448
+    bits = 456;
   else
     throw runtime_error("Can't guess key size for algorithm "+std::to_string(algo));
 
index 9c8582f3cfda4fbb6dc3aa4d41e589c804ce135d..332c3a01b6ef177a78c5933200b08db86df103e5 100644 (file)
@@ -51,7 +51,8 @@ public:
     ECCGOST=12,
     ECDSA256=13,
     ECDSA384=14,
-    ED25519=15
+    ED25519=15,
+    ED448=16
   };
 
   struct KeyMetaData
@@ -92,6 +93,7 @@ public:
     if (!algorithm.compare("ecdsa256")) return ECDSA256;
     if (!algorithm.compare("ecdsa384")) return ECDSA384;
     if (!algorithm.compare("ed25519")) return ED25519;
+    if (!algorithm.compare("ed448")) return ED448;
     return -1;
   }
 
@@ -126,6 +128,8 @@ public:
         return "ECDSAP384SHA384";
       case ED25519:
         return "ED25519";
+      case ED448:
+        return "ED448";
       case 252:
         return "INDIRECT";
       case 253:
index 7e58164e45981d171111d067f19d8a9ce61728d9..04c586dc0f3f5325626a596221d6a2fbfc8c3883 100644 (file)
@@ -1905,8 +1905,11 @@ try
     cout<<"             [content..]           Add one or more records to ZONE"<<endl;
     cout<<"add-zone-key ZONE {zsk|ksk} [BITS] [active|inactive]"<<endl;
     cout<<"             [rsasha1|rsasha256|rsasha512|gost|ecdsa256|ecdsa384";
-#ifdef HAVE_LIBSODIUM
+#if defined(HAVE_LIBSODIUM) || defined(HAVE_LIBDECAF)
     cout<<"|ed25519";
+#endif
+#ifdef HAVE_LIBDECAF
+    cout<<"|ed448";
 #endif
     cout<<"]"<<endl;
     cout<<"                                   Add a ZSK or KSK to zone and specify algo&bits"<<endl;
@@ -2698,6 +2701,8 @@ loadMainConfig(g_vm["config-dir"].as<string>());
           bits = 256;
         else if(algorithm == 14)
           bits = 384;
+        else if(algorithm == 16) // ED448
+          bits = 456;
         else {
           throw runtime_error("Can't guess key size for algorithm "+std::to_string(algorithm));
         }
index 8b4b7280f04764a3cf680e8f57e87fb46ab3c6e1..c80444056fccb4dfaae093b89b01d7f242e860bd 100644 (file)
@@ -237,6 +237,12 @@ pdns_recursor_SOURCES += \
 pdns_recursor_LDADD += $(LIBSODIUM_LIBS)
 endif
 
+if LIBDECAF
+pdns_recursor_SOURCES += \
+       decafsigners.cc
+pdns_recursor_LDADD += $(LIBDECAF_LIBS)
+endif
+
 if MALLOC_TRACE
 pdns_recursor_SOURCES += \
        malloctrace.cc \
index 19b69b21220e0bed013b8bc25b3b14676c09f1f9..e5e645fe2630bc83f2dfda9256b138c62f11265d 100644 (file)
@@ -114,6 +114,7 @@ PDNS_CHECK_LIBCRYPTO([
 )
 PDNS_CHECK_LIBCRYPTO_ECDSA
 PDNS_CHECK_LIBSODIUM
+PDNS_CHECK_LIBDECAF
 
 # check for tools we might need
 PDNS_CHECK_RAGEL
@@ -202,6 +203,14 @@ AS_IF([test "x$LUAPC" != "x"],
     [AC_MSG_NOTICE([Lua/LuaJit: no])])
 ])
 AC_MSG_NOTICE([OpenSSL ECDSA: $libcrypto_ecdsa])
+AS_IF([test "x$LIBSODIUM_LIBS" != "x"],
+  [AC_MSG_NOTICE([libsodium ed25519: yes])],
+  [AC_MSG_NOTICE([libsodium ed25519: no])]
+)
+AS_IF([test "x$LIBDECAF_LIBS" != "x"],
+  [AC_MSG_NOTICE([libdecaf ed25519 and ed448: yes])],
+  [AC_MSG_NOTICE([libdecaf ed25519 and ed448: no])]
+)
 AS_IF([test "x$PROTOBUF_LIBS" != "x" -a x"$PROTOC" != "x"],
   [AC_MSG_NOTICE([Protobuf: yes])],
   [AC_MSG_NOTICE([Protobuf: no])]
diff --git a/pdns/recursordist/decafsigners.cc b/pdns/recursordist/decafsigners.cc
new file mode 120000 (symlink)
index 0000000..4aaed31
--- /dev/null
@@ -0,0 +1 @@
+../decafsigners.cc
\ No newline at end of file
diff --git a/pdns/recursordist/m4/pdns_check_libdecaf.m4 b/pdns/recursordist/m4/pdns_check_libdecaf.m4
new file mode 120000 (symlink)
index 0000000..01bef52
--- /dev/null
@@ -0,0 +1 @@
+../../../m4/pdns_check_libdecaf.m4
\ No newline at end of file
index 06a7bee36997d3a01ec2067e84ec514492954166..bb478a305c29e8c3eebcf8f89ee6aa452bab0bd8 100644 (file)
@@ -89,6 +89,9 @@ void showBuildConfiguration()
 #endif
 #ifdef HAVE_LIBSODIUM
     "sodium " <<
+#endif
+#ifdef HAVE_LIBDECAF
+    "decaf " <<
 #endif
     "openssl " <<
 #ifdef HAVE_LIBDL