]> git.ipfire.org Git - thirdparty/pdns.git/commitdiff
Support the export of ECDSA keys to PEM
authorFred Morcos <fred.morcos@open-xchange.com>
Mon, 14 Mar 2022 10:26:43 +0000 (11:26 +0100)
committerFred Morcos <fred.morcos@open-xchange.com>
Thu, 17 Mar 2022 10:33:39 +0000 (11:33 +0100)
Part of #11325

pdns/dnssecinfra.hh
pdns/opensslsigners.cc
pdns/pdnsutil.cc
pdns/test-signers.cc

index 9341c2fb67b84df1c2650de6f4f9c49f10482ec7..4b9e5f56c709020f0419beb83625e178c3cfbd89 100644 (file)
@@ -47,6 +47,10 @@ class DNSCryptoKeyEngine
     }
     virtual storvector_t convertToISCVector() const =0;
     std::string convertToISC() const ;
+    virtual void convertToPEM(std::FILE& fp) const
+    {
+      throw std::runtime_error(getName() + ": Conversion to PEM not supported");
+    };
     virtual std::string sign(const std::string& msg) const =0;
     virtual std::string hash(const std::string& msg) const
     {
index e6c4f0a4214bf2ddc4fb3834c608534e98ab119b..280d8b15efb27a092c5f037f9b15ce55b6631df5 100644 (file)
@@ -613,6 +613,18 @@ public:
    */
   void createFromPEMFile(DNSKEYRecordContent& drc, const std::string& filename, std::FILE& fp) override;
 
+  /**
+   * \brief Writes this key's contents to a file.
+   *
+   * Receives an open file handle and writes this key's contents to the
+   * file.
+   *
+   * \param[in] fp An open file handle for writing.
+   *
+   * \exception std::runtime_error In case of OpenSSL errors.
+   */
+  void convertToPEM(std::FILE& fp) const override;
+
   storvector_t convertToISCVector() const override;
   std::string hash(const std::string& hash) const override;
   std::string sign(const std::string& hash) const override;
@@ -682,6 +694,14 @@ void OpenSSLECDSADNSCryptoKeyEngine::createFromPEMFile(DNSKEYRecordContent& drc,
   EC_KEY_set_asn1_flag(d_eckey.get(), OPENSSL_EC_NAMED_CURVE);
 }
 
+void OpenSSLECDSADNSCryptoKeyEngine::convertToPEM(std::FILE& fp) const
+{
+  auto ret = PEM_write_ECPrivateKey(&fp, d_eckey.get(), nullptr, nullptr, 0, nullptr, nullptr);
+  if (ret == 0) {
+    throw runtime_error(getName() + ": Could not convert private key to PEM");
+  }
+}
+
 DNSCryptoKeyEngine::storvector_t OpenSSLECDSADNSCryptoKeyEngine::convertToISCVector() const
 {
   storvector_t storvect;
index 285d9bbbf1e1686bc1c86413f9b6f1c21bc003fc..ef3593b307baf023deb40f02f721a308553f794d 100644 (file)
@@ -3272,6 +3272,17 @@ try
     DNSSECPrivateKey dpk = dk.getKeyById(DNSName(zone), id);
     cout << dpk.getKey()->convertToISC() << endl;
   }
+  else if (cmds.at(0) == "export-zone-key-pem") {
+    if (cmds.size() < 3) {
+      cerr << "Syntax: pdnsutil export-zone-key-pem ZONE KEY-ID" << endl;
+      return 1;
+    }
+
+    string zone = cmds.at(1);
+    auto id = pdns::checked_stoi<unsigned int>(cmds.at(2));
+    DNSSECPrivateKey dpk = dk.getKeyById(DNSName(zone), id);
+    dpk.getKey()->convertToPEM(*stdout);
+  }
   else if (cmds.at(0) == "increase-serial") {
     if (cmds.size() < 2) {
       cerr << "Syntax: pdnsutil increase-serial ZONE" << endl;
index 21654f7ec7b95c026cda3c964b06dc208fb1fb6b..364017d58c90c796cdeec3d6ca7e61f2d2eea733 100644 (file)
@@ -276,6 +276,26 @@ BOOST_AUTO_TEST_CASE(test_generic_signers)
       BOOST_CHECK_EQUAL(pemKey->convertToISC(), dcke->convertToISC());
 
       test_generic_signer(pemKey, pemDRC, signer);
+
+      const size_t buflen = 4096;
+
+      std::string dckePEMOutput{};
+      dckePEMOutput.resize(buflen);
+      unique_ptr<std::FILE, decltype(&std::fclose)> dckePEMOutputFp{fmemopen(static_cast<void*>(dckePEMOutput.data()), dckePEMOutput.length() - 1, "w"), &std::fclose};
+      dcke->convertToPEM(*dckePEMOutputFp);
+      std::fflush(dckePEMOutputFp.get());
+      dckePEMOutput.resize(std::ftell(dckePEMOutputFp.get()));
+
+      BOOST_CHECK_EQUAL(dckePEMOutput, *signer.pem);
+
+      std::string pemKeyOutput{};
+      pemKeyOutput.resize(buflen);
+      unique_ptr<std::FILE, decltype(&std::fclose)> pemKeyOutputFp{fmemopen(static_cast<void*>(pemKeyOutput.data()), pemKeyOutput.length() - 1, "w"), &std::fclose};
+      pemKey->convertToPEM(*pemKeyOutputFp);
+      std::fflush(pemKeyOutputFp.get());
+      pemKeyOutput.resize(std::ftell(pemKeyOutputFp.get()));
+
+      BOOST_CHECK_EQUAL(pemKeyOutput, *signer.pem);
     }
   }
 }