From 299b43b68d638e83202fbff528e8b8dd659fd2d6 Mon Sep 17 00:00:00 2001 From: Remi Gacogne Date: Tue, 4 Jul 2017 21:59:00 +0200 Subject: [PATCH] Add support for Botan 2.x 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 | 12 +++ m4/pdns_enable_botan.m4 | 28 ++--- pdns/Makefile.am | 27 +++-- pdns/{botan110signers.cc => botansigners.cc} | 102 ++++++++++++------- pdns/recursordist/Makefile.am | 10 +- pdns/recursordist/botan110signers.cc | 1 - pdns/recursordist/botansigners.cc | 1 + pdns/recursordist/configure.ac | 4 + pdns/version.cc | 10 +- 9 files changed, 128 insertions(+), 67 deletions(-) rename pdns/{botan110signers.cc => botansigners.cc} (78%) delete mode 120000 pdns/recursordist/botan110signers.cc create mode 120000 pdns/recursordist/botansigners.cc diff --git a/configure.ac b/configure.ac index e9922021e..686139af8 100644 --- a/configure.ac +++ b/configure.ac @@ -358,6 +358,18 @@ 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$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])] diff --git a/m4/pdns_enable_botan.m4 b/m4/pdns_enable_botan.m4 index cb907443a..6728bf4c9 100644 --- a/m4/pdns_enable_botan.m4 +++ b/m4/pdns_enable_botan.m4 @@ -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])] + ) + ] )] ) ]) diff --git a/pdns/Makefile.am b/pdns/Makefile.am index fc73177b8..7ed13af89 100644 --- a/pdns/Makefile.am +++ b/pdns/Makefile.am @@ -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 @@ -713,9 +713,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 @@ -1196,6 +1196,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) diff --git a/pdns/botan110signers.cc b/pdns/botansigners.cc similarity index 78% rename from pdns/botan110signers.cc rename to pdns/botansigners.cc index e99ceda4c..2c25d991c 100644 --- a/pdns/botan110signers.cc +++ b/pdns/botansigners.cc @@ -23,8 +23,10 @@ #include "config.h" #endif #include +#include #include #include +#include #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& 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 d_key; shared_ptr 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(new GOST_3410_PrivateKey(rng, params)); + d_key = std::make_shared(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 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(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(new GOST_3410_PrivateKey(rng, params, bigint)); + d_key=std::make_shared(rng, getParams(), bigint); //cerr<<"Is the just imported key on the curve? " << d_key->public_point().on_the_curve()<public_point().is_zero()<private_value(); - SecureVector buffer=BigInt::encode(x); + auto buffer = BigInt::encode(x); // cerr<<"And out again! "< msg_le(msg, msg_len); +#else + Botan::secure_vector 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(new GOST_3410_PublicKey(params, point)); + d_pubkey = std::make_shared(params, point); d_key.reset(); } std::string GOSTDNSCryptoKeyEngine::getPubKeyHash() const { const BigInt&x = d_key->private_value(); - SecureVector 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 bits(2*part_size); - +#else + std::vector 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 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 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 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(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); } diff --git a/pdns/recursordist/Makefile.am b/pdns/recursordist/Makefile.am index d1c6b306e..b41f82d72 100644 --- a/pdns/recursordist/Makefile.am +++ b/pdns/recursordist/Makefile.am @@ -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 \ @@ -229,10 +229,10 @@ testrunner_LDADD = \ $(LIBCRYPTO_LIBS) \ $(RT_LIBS) -if BOTAN110 +if BOTAN pdns_recursor_SOURCES += \ - botan110signers.cc -pdns_recursor_LDADD += $(BOTAN110_LIBS) + botansigners.cc +pdns_recursor_LDADD += $(BOTAN_LIBS) endif if LIBSODIUM diff --git a/pdns/recursordist/botan110signers.cc b/pdns/recursordist/botan110signers.cc deleted file mode 120000 index e6cfd3552..000000000 --- a/pdns/recursordist/botan110signers.cc +++ /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 index 000000000..edbcea7f5 --- /dev/null +++ b/pdns/recursordist/botansigners.cc @@ -0,0 +1 @@ +../botansigners.cc \ No newline at end of file diff --git a/pdns/recursordist/configure.ac b/pdns/recursordist/configure.ac index e5e645fe2..59356969a 100644 --- a/pdns/recursordist/configure.ac +++ b/pdns/recursordist/configure.ac @@ -211,6 +211,10 @@ 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])] diff --git a/pdns/version.cc b/pdns/version.cc index 7ac335138..c735977e7 100644 --- a/pdns/version.cc +++ b/pdns/version.cc @@ -26,6 +26,10 @@ #include "logger.hh" #include "version.hh" +#ifdef HAVE_BOTAN +#include +#endif /* HAVE_BOTAN */ + static ProductType productType; string compilerVersion() @@ -84,8 +88,8 @@ void showProductVersion() void showBuildConfiguration() { theL()<