]> granicus.if.org Git - pdns/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>
Wed, 21 Jun 2017 11:33:42 +0000 (13:33 +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

configure.ac
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/version.cc

index bfd6f7e6c78f0bf9a5403aec1b6fe6fcb9f99d4f..9409ef3891fb19ecf3a92c404d5bdb1b390698fc 100644 (file)
@@ -95,6 +95,7 @@ AC_CHECK_HEADERS(
 
 PDNS_ENABLE_BOTAN
 PDNS_CHECK_LIBSODIUM
+PDNS_CHECK_LIBDECAF
 PDNS_CHECK_LIBCRYPTO([
 ],[
    AC_MSG_ERROR([OpenSSL/libcrypto not found])
@@ -348,6 +349,14 @@ AS_IF([test "x$libcrypto_ecdsa" = "xyes"],
   [AC_MSG_NOTICE([OpenSSL ecdsa: yes])],
   [AC_MSG_NOTICE([OpenSSL ecdsa: no])]
 )
+AS_IF([test "x$LIBSODIUM_LIBS" != "x" || test "x$LIBDECAF_LIBS" != "x"],
+  [AC_MSG_NOTICE([ed25519: yes])],
+  [AC_MSG_NOTICE([ed25519: no])]
+)
+AS_IF([test "x$LIBDECAF_LIBS" != "x"],
+  [AC_MSG_NOTICE([ed448: yes])],
+  [AC_MSG_NOTICE([ed448: no])]
+)
 AS_IF([test "x$needsqlite3" != "x"],
   [AC_MSG_NOTICE([SQLite3: yes])],
   [AC_MSG_NOTICE([SQLite3: no])]
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 66cd5676aa76ca28b64191a1fed2a57818c83c19..1dddd5bc776b3c40239e405f96140554eab0751c 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 f5ba7a60b86adf97a3e98868bbb8e25363c5bfc6..b8662b8e97b79fcb8f54f11b1b500b20f9282d06 100644 (file)
@@ -88,6 +88,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 c6d2249d199cb53800264fc1f2af19e4f4f21ac8..684ff4171f6ea3bc7e554490bab266fa3496bbfe 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 d310ecc4c643b36546a56fa43d17c55e02543d41..2361bee48077b10a0a84fcad0b35f7dfa95ca358 100644 (file)
@@ -1909,8 +1909,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;
@@ -2702,6 +2705,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 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