]> granicus.if.org Git - pdns/commitdiff
use libsodium for ed25519
authorKees Monshouwer <mind04@monshouwer.org>
Sat, 8 Aug 2015 11:28:42 +0000 (13:28 +0200)
committermind04 <mind04@monshouwer.org>
Sun, 9 Aug 2015 20:15:04 +0000 (22:15 +0200)
Testing algorithm 250: 'Ref10 ED25519' ->'Ref10 ED25519' -> 'Ref10 ED25519' Signature & verify ok, signature 164usec, verify 400usec
Testing algorithm 250: 'Ref10 ED25519' ->'Ref10 ED25519' -> 'Sodium' Signature & verify ok, signature 169usec, verify 165usec
Testing algorithm 250: 'Ref10 ED25519' ->'Sodium' -> 'Ref10 ED25519' Signature & verify ok, signature 62usec, verify 407usec
Testing algorithm 250: 'Ref10 ED25519' ->'Sodium' -> 'Sodium' Signature & verify ok, signature 62usec, verify 149usec
Testing algorithm 250: 'Sodium' ->'Ref10 ED25519' -> 'Ref10 ED25519' Signature & verify ok, signature 162usec, verify 397usec
Testing algorithm 250: 'Sodium' ->'Ref10 ED25519' -> 'Sodium' Signature & verify ok, signature 161usec, verify 149usec
Testing algorithm 250: 'Sodium' ->'Sodium' -> 'Ref10 ED25519' Signature & verify ok, signature 61usec, verify 394usec
Testing algorithm 250: 'Sodium' ->'Sodium' -> 'Sodium' Signature & verify ok, signature 60usec, verify 150usec

.travis.yml
pdns/Makefile.am
pdns/pdnssec.cc
pdns/receiver.cc
pdns/sodiumsigners.cc [new file with mode: 0644]

index 35c18cf411443e908db795b943ecd96eb2e1de6e..f53eecd7b1d109808bf4cbbe97e3275fb3b19225 100644 (file)
@@ -64,6 +64,7 @@ before_script:
  - sudo dpkg -i dnsperf_2.0.0.0-2_amd64.deb
  - wget https://xs.powerdns.com/tmp/libsodium_1.0.2-1_amd64.deb
  - sudo dpkg -i libsodium_1.0.2-1_amd64.deb
+ - sudo mv /usr/local/lib/libsodium.* /usr/lib
  - wget http://s3.amazonaws.com/alexa-static/top-1m.csv.zip
  - unzip top-1m.csv.zip -d ./pdns/regression-tests
  - cd pdns
index 3b2b5221b6495e22ea18233806cc2ca076e11fc8..d19d09e5d1c6f4afbba53d4b2b663166bf7cbca8 100644 (file)
@@ -231,6 +231,11 @@ pdns_server_SOURCES += ed25519signers.cc
 pdns_server_LDADD += $(ED25519_LIBS)
 endif
 
+if LIBSODIUM
+pdns_server_SOURCES += sodiumsigners.cc
+pdns_server_LDADD += $(LIBSODIUM_LIBS)
+endif
+
 if SQLITE3
 pdns_server_SOURCES += ssqlite3.cc ssqlite3.hh
 pdns_server_LDADD += $(SQLITE3_LIBS)
@@ -331,6 +336,11 @@ pdnssec_SOURCES += ed25519signers.cc
 pdnssec_LDADD += $(ED25519_LIBS)
 endif
 
+if LIBSODIUM
+pdnssec_SOURCES += sodiumsigners.cc
+pdnssec_LDADD += $(LIBSODIUM_LIBS)
+endif
+
 if SQLITE3
 pdnssec_SOURCES += ssqlite3.cc ssqlite3.hh
 pdnssec_LDADD += $(SQLITE3_LIBS)
index 88c5b91190d06770e6131581761778083e8a89fd..b83968fa8c110e60fdb027bf13350df5bb820950 100644 (file)
@@ -18,6 +18,9 @@
 #include "signingpipe.hh"
 #include "dns_random.hh"
 #include <fstream>
+#ifdef HAVE_LIBSODIUM
+#include <sodium.h>
+#endif
 #ifdef HAVE_SQLITE3
 #include "ssqlite3.hh"
 #include "bind-dnssec.schema.sqlite3.sql.h"
@@ -1336,6 +1339,13 @@ try
     return 0;
   }
 
+#ifdef HAVE_LIBSODIUM
+  if (sodium_init() == -1) {
+    cerr<<"Unable to initialize sodium crypto library"<<endl;
+    exit(99);
+  }
+#endif
+
   if (cmds[0] == "test-algorithm") {
     if(cmds.size() != 2) {
       cerr << "Syntax: pdnssec test-algorithm algonum"<<endl;
index 35e8585bd28a28a69b2378b824375fdbccbc709c..7eb6e7d0fff694fe12e2f763c7988b567b51d2c8 100644 (file)
@@ -46,6 +46,9 @@
 #include <fcntl.h>
 #include <fstream>
 #include <boost/algorithm/string.hpp>
+#ifdef HAVE_LIBSODIUM
+#include <sodium.h>
+#endif
 
 #include "dns.hh"
 #include "dnsbackend.hh"
@@ -482,6 +485,13 @@ int main(int argc, char **argv)
 #endif
 
     seedRandom(::arg()["entropy-source"]);
+
+#ifdef HAVE_LIBSODIUM
+      if (sodium_init() == -1) {
+        cerr<<"Unable to initialize sodium crypto library"<<endl;
+        exit(99);
+      }
+#endif
     
     loadModules();
     BackendMakers().launch(::arg()["launch"]); // vrooooom!
diff --git a/pdns/sodiumsigners.cc b/pdns/sodiumsigners.cc
new file mode 100644 (file)
index 0000000..a7db679
--- /dev/null
@@ -0,0 +1,152 @@
+extern "C" {
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+#include <sodium.h>
+}
+#include "dnssecinfra.hh"
+
+class SodiumED25519DNSCryptoKeyEngine : public DNSCryptoKeyEngine
+{
+public:
+  explicit SodiumED25519DNSCryptoKeyEngine(unsigned int algo) : DNSCryptoKeyEngine(algo)
+  {}
+  string getName() const { return "Sodium ED25519"; }
+  void create(unsigned int bits);
+  storvector_t convertToISCVector() const;
+  std::string getPubKeyHash() const;
+  std::string sign(const std::string& hash) const;
+  std::string hash(const std::string& hash) const;
+  bool verify(const std::string& msg, const std::string& signature) const;
+  std::string getPublicKeyString() const;
+  int getBits() const;
+  void fromISCMap(DNSKEYRecordContent& drc, std::map<std::string, std::string>& stormap);
+  void fromPublicKeyString(const std::string& content);
+  void fromPEMString(DNSKEYRecordContent& drc, const std::string& raw)
+  {}
+
+  static DNSCryptoKeyEngine* maker(unsigned int algorithm)
+  {
+    return new SodiumED25519DNSCryptoKeyEngine(algorithm);
+  }
+
+private:
+  unsigned char d_pubkey[crypto_sign_ed25519_PUBLICKEYBYTES];
+  unsigned char d_seckey[crypto_sign_ed25519_SECRETKEYBYTES];
+};
+
+void SodiumED25519DNSCryptoKeyEngine::create(unsigned int bits)
+{
+  if(bits != crypto_sign_ed25519_SEEDBYTES * 8) {
+    throw runtime_error("Unsupported key length of "+lexical_cast<string>(bits)+" bits requested, SodiumED25519 class");
+  }
+  crypto_sign_ed25519_keypair(d_pubkey, d_seckey);
+}
+
+int SodiumED25519DNSCryptoKeyEngine::getBits() const
+{
+  return crypto_sign_ed25519_SEEDBYTES * 8;
+}
+
+DNSCryptoKeyEngine::storvector_t SodiumED25519DNSCryptoKeyEngine::convertToISCVector() const
+{
+  /*
+    Private-key-format: v1.2
+    Algorithm: 250 (ED25519SHA512)
+    PrivateKey: GU6SnQ/Ou+xC5RumuIUIuJZteXT2z0O/ok1s38Et6mQ=
+  */
+
+  storvector_t storvector;
+  string algorithm = "250 (ED25519SHA512)";
+
+  storvector.push_back(make_pair("Algorithm", algorithm));
+
+  vector<unsigned char> buffer;
+  storvector.push_back(make_pair("PrivateKey", string((char*)d_seckey, crypto_sign_ed25519_SEEDBYTES)));
+  return storvector;
+}
+
+void SodiumED25519DNSCryptoKeyEngine::fromISCMap(DNSKEYRecordContent& drc, std::map<std::string, std::string>& stormap )
+{
+  /*
+    Private-key-format: v1.2
+    Algorithm: 250 (ED25519SHA512)
+    PrivateKey: GU6SnQ/Ou+xC5RumuIUIuJZteXT2z0O/ok1s38Et6mQ=
+  */
+
+  drc.d_algorithm = atoi(stormap["algorithm"].c_str());
+  string privateKey = stormap["privatekey"];
+
+  if (privateKey.length() != crypto_sign_ed25519_SEEDBYTES)
+    throw runtime_error("Seed size mismatch in ISCMap, SodiumED25519 class");
+
+  std::unique_ptr<unsigned char[]> seed(new unsigned char[crypto_sign_ed25519_SEEDBYTES]);
+
+  memcpy(seed.get(), privateKey.c_str(), crypto_sign_ed25519_SEEDBYTES);
+  crypto_sign_ed25519_seed_keypair(d_pubkey, d_seckey, seed.get());
+}
+
+std::string SodiumED25519DNSCryptoKeyEngine::getPubKeyHash() const
+{
+  return this->getPublicKeyString();
+}
+
+std::string SodiumED25519DNSCryptoKeyEngine::getPublicKeyString() const
+{
+  return string((char*)d_pubkey, crypto_sign_ed25519_PUBLICKEYBYTES);
+}
+
+void SodiumED25519DNSCryptoKeyEngine::fromPublicKeyString(const std::string& input)
+{
+  if (input.length() != crypto_sign_ed25519_PUBLICKEYBYTES)
+    throw runtime_error("Public key size mismatch, SodiumED25519 class");
+
+  memcpy(d_pubkey, input.c_str(), crypto_sign_ed25519_PUBLICKEYBYTES);
+}
+
+std::string SodiumED25519DNSCryptoKeyEngine::sign(const std::string& msg) const
+{
+  string hash=this->hash(msg);
+  unsigned long long smlen = hash.length() + crypto_sign_ed25519_BYTES;
+  std::unique_ptr<unsigned char[]> sm(new unsigned char[smlen]);
+
+  crypto_sign_ed25519(sm.get(), &smlen, (const unsigned char*)hash.c_str(), hash.length(), d_seckey);
+
+  return string((const char*)sm.get(), crypto_sign_ed25519_BYTES);
+}
+
+std::string SodiumED25519DNSCryptoKeyEngine::hash(const std::string& orig) const
+{
+  std::unique_ptr<unsigned char[]> out(new unsigned char[crypto_hash_sha512_BYTES]);
+
+  crypto_hash_sha512(out.get(), (const unsigned char*)orig.c_str(), orig.length());
+
+  return string((const char*)out.get(), crypto_hash_sha512_BYTES);
+}
+
+bool SodiumED25519DNSCryptoKeyEngine::verify(const std::string& msg, const std::string& signature) const
+{
+  if (signature.length() != crypto_sign_ed25519_BYTES)
+    return false;
+
+  string hash=this->hash(msg);
+  unsigned long long smlen = hash.length() + crypto_sign_ed25519_BYTES;
+  std::unique_ptr<unsigned char[]> sm(new unsigned char[smlen]);
+
+  memcpy(sm.get(), signature.c_str(), crypto_sign_ed25519_BYTES);
+  memcpy(sm.get() + crypto_sign_ed25519_BYTES, hash.c_str(), hash.length());
+
+  std::unique_ptr<unsigned char[]> m(new unsigned char[smlen]);
+
+  return crypto_sign_ed25519_open(m.get(), &smlen, sm.get(), smlen, d_pubkey) == 0;
+}
+
+namespace {
+struct LoaderSodiumStruct
+{
+  LoaderSodiumStruct()
+  {
+    DNSCryptoKeyEngine::report(250, &SodiumED25519DNSCryptoKeyEngine::maker);
+  }
+} loadersodium;
+}