]> granicus.if.org Git - pdns/commitdiff
Add support for Botan 2.x
authorRemi Gacogne <remi.gacogne@powerdns.com>
Tue, 4 Jul 2017 19:59:00 +0000 (21:59 +0200)
committerPieter Lexis <pieter.lexis@powerdns.com>
Tue, 7 Nov 2017 20:25:45 +0000 (21:25 +0100)
Initial testing indicates that both 2.0.1 and 2.1.0 work fine,
but signature is 10 times slower with 2.1.0, apparently due to
blinding (callgrind reports a lot of CPU spent in the `RNG`).

(cherry picked from commit 13f34f2e0ccff514cbd5f9ec076c220473da347a)

configure.ac
m4/pdns_enable_botan.m4
pdns/Makefile.am
pdns/botansigners.cc [moved from pdns/botan110signers.cc with 78% similarity]
pdns/recursordist/Makefile.am
pdns/recursordist/botan110signers.cc [deleted symlink]
pdns/recursordist/botansigners.cc [new symlink]
pdns/recursordist/configure.ac
pdns/version.cc

index 9409ef3891fb19ecf3a92c404d5bdb1b390698fc..47fb8f76e55aa46d1661bd33975c1c871b350bbf 100644 (file)
@@ -357,6 +357,10 @@ AS_IF([test "x$LIBDECAF_LIBS" != "x"],
   [AC_MSG_NOTICE([ed448: yes])],
   [AC_MSG_NOTICE([ed448: no])]
 )
+AS_IF([test "x$BOTAN_LIBS" != "x"],
+  [AC_MSG_NOTICE([gost: yes])],
+  [AC_MSG_NOTICE([gost: no])]
+)
 AS_IF([test "x$needsqlite3" != "x"],
   [AC_MSG_NOTICE([SQLite3: yes])],
   [AC_MSG_NOTICE([SQLite3: no])]
index cb907443a1a7bc862feae21db0fa9feff8f8251e..6728bf4c9e0fffb36a565cf21db480a946a9d991 100644 (file)
@@ -1,18 +1,22 @@
 AC_DEFUN([PDNS_ENABLE_BOTAN],[
-  AC_MSG_CHECKING([whether we will be linking in Botan 1.10])
-  AC_ARG_ENABLE([botan1.10],
-    [AS_HELP_STRING([--enable-botan1.10],[use Botan 1.10 @<:@default=no@:>@])],
-    [enable_botan110=$enableval],
-    [enable_botan110=no]
+  AC_MSG_CHECKING([whether we will be linking in Botan])
+  AC_ARG_ENABLE([botan],
+    [AS_HELP_STRING([--enable-botan],[use Botan @<:@default=no@:>@])],
+    [enable_botan=$enableval],
+    [enable_botan=no]
   )
-  AC_MSG_RESULT([$enable_botan110])
-  AM_CONDITIONAL(BOTAN110, [test "x$enable_botan110" != "xno"])
+  AC_MSG_RESULT([$enable_botan])
+  AM_CONDITIONAL(BOTAN, [test "x$enable_botan" != "xno"])
 
-
-  AS_IF([test "x$enable_botan110" != "xno"], [
-    PKG_CHECK_MODULES([BOTAN110], [botan-1.10],
-      [AC_DEFINE([HAVE_BOTAN110],[1],[Define to 1 if you have botan 1.10])],
-      [AC_MSG_ERROR([Could not find botan 1.10])]
+  AS_IF([test "x$enable_botan" != "xno"], [
+    PKG_CHECK_MODULES([BOTAN], [botan-1.10],
+      [AC_DEFINE([HAVE_BOTAN],[1],[Define to 1 if you have botan])],
+      [
+        PKG_CHECK_MODULES([BOTAN], [botan-2],
+          [AC_DEFINE([HAVE_BOTAN],[1],[Define to 1 if you have botan])],
+          [AC_MSG_ERROR([Could not find botan])]
+        )
+      ]
     )]
   )
 ])
index f423cc01d8d402c4d4bc348e5e92c44743f87c9f..5b47ff5b73a2f6aa01858eb05b0f5e611a1a45a4 100644 (file)
@@ -19,8 +19,8 @@ AM_LDFLAGS = \
 AM_LFLAGS = -i
 AM_YFLAGS = -d --verbose --debug
 
-if BOTAN110
-AM_CPPFLAGS += $(BOTAN110_CFLAGS)
+if BOTAN
+AM_CPPFLAGS += $(BOTAN_CFLAGS)
 endif
 
 if PKCS11
@@ -223,9 +223,9 @@ pdns_server_LDADD = \
        $(LIBCRYPTO_LIBS) \
        $(SYSTEMD_LIBS)
 
-if BOTAN110
-pdns_server_SOURCES += botan110signers.cc
-pdns_server_LDADD += $(BOTAN110_LIBS)
+if BOTAN
+pdns_server_SOURCES += botansigners.cc
+pdns_server_LDADD += $(BOTAN_LIBS)
 endif
 
 if LIBSODIUM
@@ -319,9 +319,9 @@ pdnsutil_LDADD = \
        $(BOOST_PROGRAM_OPTIONS_LIBS) \
        $(LIBCRYPTO_LIBS)
 
-if BOTAN110
-pdnsutil_SOURCES += botan110signers.cc
-pdnsutil_LDADD += $(BOTAN110_LIBS)
+if BOTAN
+pdnsutil_SOURCES += botansigners.cc
+pdnsutil_LDADD += $(BOTAN_LIBS)
 endif
 
 if LIBSODIUM
@@ -712,9 +712,9 @@ if GSS_TSIG
 toysdig_LDADD += $(GSS_LIBS)
 endif
 
-if BOTAN110
-toysdig_SOURCES += botan110signers.cc
-toysdig_LDADD += $(BOTAN110_LIBS)
+if BOTAN
+toysdig_SOURCES += botansigners.cc
+toysdig_LDADD += $(BOTAN_LIBS)
 endif
 
 if PKCS11
@@ -1205,6 +1205,11 @@ testrunner_SOURCES += sodiumsigners.cc
 testrunner_LDADD += $(LIBSODIUM_LIBS)
 endif
 
+if BOTAN
+testrunner_SOURCES += botansigners.cc
+testrunner_LDADD += $(BOTAN_LIBS)
+endif
+
 if LIBDECAF
 testrunner_SOURCES += decafsigners.cc
 testrunner_LDADD += $(LIBDECAF_LIBS)
similarity index 78%
rename from pdns/botan110signers.cc
rename to pdns/botansigners.cc
index e99ceda4c010c3c2d64592bfb7685ea6f6818037..2c25d991cae7d4057ee82dfa9ccc96ca1021871a 100644 (file)
 #include "config.h"
 #endif
 #include <botan/botan.h>
+#include <botan/build.h>
 #include <botan/gost_3410.h>
 #include <botan/gost_3411.h>
+#include <botan/pubkey.h>
 #include "dnssecinfra.hh"
 
 using namespace Botan;
@@ -43,15 +45,18 @@ class GOSTDNSCryptoKeyEngine : public DNSCryptoKeyEngine
 {
 public:
   explicit GOSTDNSCryptoKeyEngine(unsigned int algorithm) : DNSCryptoKeyEngine(algorithm) {}
-  // XXX FIXME NEEDS COPY CONSTRUCTOR SO WE DON'T SHARE KEYS
   ~GOSTDNSCryptoKeyEngine(){}
   void create(unsigned int bits) override;
+#if BOTAN_VERSION_MAJOR < 2
   string getName() const override { return "Botan 1.10 GOST"; }
+#else
+  string getName() const override { return "Botan 2 GOST"; }
+#endif
   storvector_t convertToISCVector() const override;
   std::string getPubKeyHash() const override;
-  std::string sign(const std::string& hash) const override;
-  std::string hash(const std::string& hash) const override;
-  bool verify(const std::string& hash, const std::string& signature) const override;
+  std::string sign(const std::string& msg) const override;
+  std::string hash(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>& content) override;
@@ -65,6 +70,18 @@ public:
   }
 
 private:
+#if BOTAN_VERSION_MAJOR < 2
+  static EC_Domain_Params getParams()
+  {
+    return EC_Domain_Params("1.2.643.2.2.35.1");
+  }
+#else
+  static EC_Group getParams()
+  {
+    return EC_Group("gost_256A");
+  }
+#endif
+
   shared_ptr<GOST_3410_PrivateKey> d_key;
   shared_ptr<GOST_3410_PublicKey> d_pubkey;
 };
@@ -80,8 +97,7 @@ private:
 void GOSTDNSCryptoKeyEngine::create(unsigned int bits)
 {
   AutoSeeded_RNG rng;
-  EC_Domain_Params params("1.2.643.2.2.35.1");
-  d_key = shared_ptr<GOST_3410_PrivateKey>(new GOST_3410_PrivateKey(rng, params));
+  d_key = std::make_shared<GOST_3410_PrivateKey>(rng, getParams());
 }
 
 int GOSTDNSCryptoKeyEngine::getBits() const
@@ -98,17 +114,17 @@ int GOSTDNSCryptoKeyEngine::getBits() const
 
 DNSCryptoKeyEngine::storvector_t GOSTDNSCryptoKeyEngine::convertToISCVector() const
 { 
-  storvector_t storvect;
-  storvect.push_back(make_pair("Algorithm", "12 (ECC-GOST)"));
-  
-  unsigned char asn1Prefix[]=
+  static const unsigned char asn1Prefix[]=
   {0x30, 0x45, 0x02, 0x01, 0x00, 0x30, 0x1c, 0x06, 0x06, 0x2a, 0x85, 0x03, 0x02, 0x02, 
    0x13, 0x30, 0x12, 0x06, 0x07, 0x2a, 0x85, 0x03, 0x02, 0x02, 0x23, 0x01, 0x06, 0x07, 
    0x2a, 0x85, 0x03, 0x02, 0x02, 0x1e, 0x01, 0x04, 0x22, 0x04, 0x20}; // this is DER, fixed for a 32 byte key
 
-  SecureVector<byte> buffer=BigInt::encode(d_key->private_value());
-  string gostasn1((const char*)asn1Prefix, sizeof(asn1Prefix));
-  gostasn1.append((const char*)&*buffer.begin(), (const char*)&*buffer.end());
+  storvector_t storvect;
+  storvect.push_back(make_pair("Algorithm", "12 (ECC-GOST)"));
+
+  auto buffer = BigInt::encode(d_key->private_value());
+  string gostasn1(reinterpret_cast<const char*>(asn1Prefix), sizeof(asn1Prefix));
+  gostasn1.append(buffer.begin(), buffer.end());
   storvect.push_back(make_pair("GostAsn1", gostasn1));
   return storvect;
 }
@@ -135,22 +151,25 @@ void GOSTDNSCryptoKeyEngine::fromISCMap(DNSKEYRecordContent& drc, std::map<std::
   
   BigInt bigint((byte*)rawKey.c_str(), rawKey.size());
  
-  EC_Group params("1.2.643.2.2.35.1");
   AutoSeeded_RNG rng;
-  d_key=shared_ptr<GOST_3410_PrivateKey>(new GOST_3410_PrivateKey(rng, params, bigint));
+  d_key=std::make_shared<GOST_3410_PrivateKey>(rng, getParams(), bigint);
   
   //cerr<<"Is the just imported key on the curve? " << d_key->public_point().on_the_curve()<<endl;
   //cerr<<"Is the just imported key zero? " << d_key->public_point().is_zero()<<endl;
   
   const BigInt&x = d_key->private_value();
-  SecureVector<byte> buffer=BigInt::encode(x);
+  auto buffer = BigInt::encode(x);
  // cerr<<"And out again! "<<makeHexDump(string((const char*)buffer.begin(), (const char*)buffer.end()))<<endl;
 }
 namespace {
 
 BigInt decode_le(const byte msg[], size_t msg_len)
    {
+#if BOTAN_VERSION_MAJOR < 2
    SecureVector<byte> msg_le(msg, msg_len);
+#else
+   Botan::secure_vector<byte> msg_le(msg, msg + msg_len);
+#endif
 
    for(size_t i = 0; i != msg_le.size() / 2; ++i)
       std::swap(msg_le[i], msg_le[msg_le.size()-1-i]);
@@ -166,17 +185,17 @@ void GOSTDNSCryptoKeyEngine::fromPublicKeyString(const std::string& input)
   x=decode_le((const byte*)input.c_str(), input.length()/2);
   y=decode_le((const byte*)input.c_str() + input.length()/2, input.length()/2);
 
-  EC_Domain_Params params("1.2.643.2.2.35.1");
+  auto params = getParams();
   PointGFp point(params.get_curve(), x,y);
-  d_pubkey = shared_ptr<GOST_3410_PublicKey>(new GOST_3410_PublicKey(params, point));
+  d_pubkey = std::make_shared<GOST_3410_PublicKey>(params, point);
   d_key.reset();
 }
 
 std::string GOSTDNSCryptoKeyEngine::getPubKeyHash() const
 {
   const BigInt&x = d_key->private_value();
-  SecureVector<byte> buffer=BigInt::encode(x);
-  return string((const char*)buffer.begin(), (const char*)buffer.end());
+  auto buffer = BigInt::encode(x);
+  return string(buffer.begin(), buffer.end());
 }
 
 std::string GOSTDNSCryptoKeyEngine::getPublicKeyString() const
@@ -186,8 +205,12 @@ std::string GOSTDNSCryptoKeyEngine::getPublicKeyString() const
   
   size_t part_size = std::max(x.bytes(), y.bytes());
  
+#if BOTAN_VERSION_MAJOR < 2
   MemoryVector<byte> bits(2*part_size);
+#else
+  std::vector<byte> bits(2*part_size);
+#endif
+
   x.binary_encode(&bits[part_size - x.bytes()]);
   y.binary_encode(&bits[2*part_size - y.bytes()]);
 
@@ -198,7 +221,7 @@ std::string GOSTDNSCryptoKeyEngine::getPublicKeyString() const
     std::swap(bits[part_size+i], bits[2*part_size-1-i]);
   }
  
-  return string((const char*)bits.begin(), (const char*)bits.end());
+  return string(bits.begin(), bits.end());
 }
 
 /*
@@ -210,11 +233,11 @@ std::string GOSTDNSCryptoKeyEngine::getPublicKeyString() const
 
 std::string GOSTDNSCryptoKeyEngine::sign(const std::string& msg) const
 {
-  GOST_3410_Signature_Operation ops(*d_key);
   AutoSeeded_RNG rng;
+#if BOTAN_VERSION_MAJOR < 2
+  GOST_3410_Signature_Operation ops(*d_key);
   
   string hash= this->hash(msg);
-  
   SecureVector<byte> signature=ops.sign((byte*)hash.c_str(), hash.length(), rng);
 
 #if BOTAN_VERSION_CODE <= BOTAN_VERSION_CODE_FOR(1,9,12)  // see http://bit.ly/gTytUf
@@ -224,28 +247,29 @@ std::string GOSTDNSCryptoKeyEngine::sign(const std::string& msg) const
 #else  
   return string((const char*)signature.begin(), (const char*) signature.end());
 #endif
+
+#else /* BOTAN_VERSION_MAJOR < 2 */
+  PK_Signer signer(*d_key, rng, "Raw");
+  signer.update(hash(msg));
+  auto signature = signer.signature(rng);
+  return string(signature.begin(), signature.end());
+#endif /* BOTAN_VERSION_MAJOR < 2*/
 }
 
 std::string GOSTDNSCryptoKeyEngine::hash(const std::string& orig) const
 {
-  SecureVector<byte> result;
-  
   GOST_34_11 hasher;
-  result= hasher.process(orig);
-  return string((const char*)result.begin(), (const char*) result.end());
+  auto result = hasher.process(orig);
+  return string(result.begin(), result.end());
 }
 
 
 bool GOSTDNSCryptoKeyEngine::verify(const std::string& message, const std::string& signature) const
 {
+  std::shared_ptr<GOST_3410_PublicKey> pk = d_pubkey ? d_pubkey : d_key;
+#if BOTAN_VERSION_MAJOR < 2
   string hash = this->hash(message);
-  GOST_3410_PublicKey* pk;
-  if(d_pubkey) {
-    pk =d_pubkey.get();
-  }
-  else
-    pk = d_key.get();
-    
+
   GOST_3410_Verification_Operation ops(*pk);
 #if BOTAN_VERSION_CODE <= BOTAN_VERSION_CODE_FOR(1,9,12)  // see http://bit.ly/gTytUf
   string rsignature(signature.substr(32));
@@ -254,6 +278,12 @@ bool GOSTDNSCryptoKeyEngine::verify(const std::string& message, const std::strin
 #else
   return ops.verify ((byte*)hash.c_str(), hash.length(), (byte*)signature.c_str(), signature.length());
 #endif
+
+#else /* BOTAN_VERSION_MAJOR < 2 */
+  PK_Verifier verifier(*pk, "Raw");
+  verifier.update(hash(message));
+  return verifier.check_signature(reinterpret_cast<const uint8_t*>(signature.c_str()), signature.size());
+#endif /* BOTAN_VERSION_MAJOR < 2*/
 }
 
 /*
@@ -271,9 +301,11 @@ struct LoaderStruct
 {
   LoaderStruct()
   {
+#if BOTAN_VERSION_MAJOR < 2
     new Botan::LibraryInitializer("thread_safe=true");
     // this leaks, but is fine
     Botan::global_state().set_default_allocator("malloc"); // the other Botan allocator slows down for us
+#endif /* BOTAN_VERSION_MAJOR < 2*/
 
     DNSCryptoKeyEngine::report(12, &GOSTDNSCryptoKeyEngine::maker);
   }
index a945b82b0c0aaf7657d77197f610d8bcea83ab72..196e8178cfbcc34464c697fe2eb4b0866aced23b 100644 (file)
@@ -1,6 +1,6 @@
 JSON11_LIBS = $(top_srcdir)/ext/json11/libjson11.la
 
-AM_CPPFLAGS = $(LUA_CFLAGS) $(YAHTTP_CFLAGS) $(BOOST_CPPFLAGS) $(BOTAN110_CFLAGS) $(SANITIZER_FLAGS) -O3 -Wall -pthread -DSYSCONFDIR=\"${sysconfdir}\" $(SYSTEMD_CFLAGS)
+AM_CPPFLAGS = $(LUA_CFLAGS) $(YAHTTP_CFLAGS) $(BOOST_CPPFLAGS) $(BOTAN_CFLAGS) $(SANITIZER_FLAGS) -O3 -Wall -pthread -DSYSCONFDIR=\"${sysconfdir}\" $(SYSTEMD_CFLAGS)
 
 AM_CPPFLAGS += \
        -I$(top_srcdir)/ext/json11 \
@@ -36,7 +36,7 @@ endif
 EXTRA_DIST = \
        NOTICE \
        .version \
-       botan110signers.cc \
+       botansigners.cc \
        build-aux/gen-version \
        contrib/* \
        devpollmplexer.cc \
@@ -155,10 +155,33 @@ pdns_recursor_LDADD = \
 pdns_recursor_LDFLAGS = $(AM_LDFLAGS) \
        $(LIBCRYPTO_LDFLAGS)
 
-if BOTAN110
+testrunner_LDADD = \
+       $(BOOST_UNIT_TEST_FRAMEWORK_LIBS) \
+       $(LIBCRYPTO_LIBS) \
+       $(RT_LIBS)
+
+if BOTAN
+pdns_recursor_SOURCES += \
+       botansigners.cc
+pdns_recursor_LDADD += $(BOTAN_LIBS)
+testrunner_SOURCES += \
+       botansigners.cc
+testrunner_LDADD += $(BOTAN_LIBS)
+endif
+
+if LIBSODIUM
+pdns_recursor_SOURCES += \
+       sodiumsigners.cc
+pdns_recursor_LDADD += $(LIBSODIUM_LIBS)
+testrunner_SOURCES += \
+       sodiumsigners.cc
+testrunner_LDADD += $(LIBSODIUM_LIBS)
+endif
+
+if LIBDECAF
 pdns_recursor_SOURCES += \
-       botan110signers.cc
-pdns_recursor_LDADD += $(BOTAN110_LIBS)
+       decafsigners.cc
+pdns_recursor_LDADD += $(LIBDECAF_LIBS)
 endif
 
 if MALLOC_TRACE
diff --git a/pdns/recursordist/botan110signers.cc b/pdns/recursordist/botan110signers.cc
deleted file mode 120000 (symlink)
index e6cfd35..0000000
+++ /dev/null
@@ -1 +0,0 @@
-../botan110signers.cc
\ No newline at end of file
diff --git a/pdns/recursordist/botansigners.cc b/pdns/recursordist/botansigners.cc
new file mode 120000 (symlink)
index 0000000..edbcea7
--- /dev/null
@@ -0,0 +1 @@
+../botansigners.cc
\ No newline at end of file
index 19ad1133c812b8b8c8ace8aa1855f04c2802042b..58892313c31887ec7ad92d6ce8b7b3d194875a32 100644 (file)
@@ -192,6 +192,18 @@ 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$BOTAN_LIBS" != "x"],
+  [AC_MSG_NOTICE([Botan gost: yes])],
+  [AC_MSG_NOTICE([Botan gost: no])]
+)
 AS_IF([test "x$PROTOBUF_LIBS" != "x" -a x"$PROTOC" != "x"],
   [AC_MSG_NOTICE([Protobuf: yes])],
   [AC_MSG_NOTICE([Protobuf: no])]
index 7ac3351380e65bf0f8c4fd0fe851d57399908cc3..c735977e7aa336ee0fb83720b8e62f0821feb2dd 100644 (file)
 #include "logger.hh"
 #include "version.hh"
 
+#ifdef HAVE_BOTAN
+#include <botan/version.h>
+#endif /* HAVE_BOTAN */
+
 static ProductType productType;
 
 string compilerVersion()
@@ -84,8 +88,8 @@ void showProductVersion()
 void showBuildConfiguration()
 {
   theL()<<Logger::Warning<<"Features: "<<
-#ifdef HAVE_BOTAN110
-    "botan1.10 " <<
+#ifdef HAVE_BOTAN
+    "botan" << BOTAN_VERSION_MAJOR << "." << BOTAN_VERSION_MINOR  << " " <<
 #endif
 #ifdef HAVE_LIBSODIUM
     "sodium " <<
@@ -101,7 +105,7 @@ void showBuildConfiguration()
     "lua " <<
 #endif
 #ifdef REMOTEBACKEND_ZEROMQ
-    "remotebackend-zeromq" <<
+    "remotebackend-zeromq " <<
 #endif
 #ifdef VERBOSELOG
     "verboselog" <<