]> git.ipfire.org Git - thirdparty/pdns.git/commitdiff
Merge remote-tracking branch 'origin/master' into rsakey-warn-keysize 6958/head
authorPieter Lexis <pieter.lexis@powerdns.com>
Wed, 24 Oct 2018 07:57:57 +0000 (09:57 +0200)
committerPieter Lexis <pieter.lexis@powerdns.com>
Wed, 24 Oct 2018 08:42:10 +0000 (10:42 +0200)
1  2 
pdns/opensslsigners.cc
pdns/test-signers.cc

index afa55b87cc41333396577775b55dd56ae12e976b,dc746006d54ca4d3699695b1d3cf469beaf78aad..694264eb80d05e33dbb9777d601aff14b4a2cf7b
@@@ -533,36 -516,12 +518,32 @@@ void OpenSSLRSADNSCryptoKeyEngine::from
      throw runtime_error(getName()+" tried to feed an algorithm "+std::to_string(drc.d_algorithm)+" to a "+std::to_string(d_algorithm)+" key");
    }
  
-   if (d_key)
-     RSA_free(d_key);
-   d_key = key;
+   d_key = std::move(key);
  }
  
 -bool OpenSSLRSADNSCryptoKeyEngine::checkKey() const
 +bool OpenSSLRSADNSCryptoKeyEngine::checkKey(vector<string> *errorMessages) const
  {
 -  return (RSA_check_key(d_key.get()) == 1);
 +  bool retval = true;
 +  // When changing the bitsizes, also edit them in ::create
 +  if ((d_algorithm == DNSSECKeeper::RSASHA1 || d_algorithm == DNSSECKeeper::RSASHA1NSEC3SHA1 || d_algorithm == DNSSECKeeper::RSASHA256) && (getBits() < 512 || getBits()> 4096)) {
 +    retval = false;
 +    if (errorMessages != nullptr) {
 +      errorMessages->push_back("key is " + std::to_string(getBits()) + " bytes, should be between 512 and 4096");
 +    }
 +  }
 +  if (d_algorithm == DNSSECKeeper::RSASHA512 && (getBits() < 1024 || getBits() > 4096)) {
 +    retval = false;
 +    if (errorMessages != nullptr) {
 +      errorMessages->push_back("key is " + std::to_string(getBits()) + " bytes, should be between 1024 and 4096");
 +    }
 +  }
-   if (RSA_check_key(d_key) != 1) {
++  if (RSA_check_key(d_key.get()) != 1) {
 +    retval = false;
 +    if (errorMessages != nullptr) {
 +      errorMessages->push_back(ERR_reason_error_string(ERR_get_error()));
 +    }
 +  }
 +  return retval;
  }
  
  void OpenSSLRSADNSCryptoKeyEngine::fromPublicKeyString(const std::string& input)
@@@ -889,29 -817,15 +839,22 @@@ void OpenSSLECDSADNSCryptoKeyEngine::fr
      throw runtime_error(getName()+" computing public key from private failed");
    }
  
-   BN_clear_free(prv_key);
-   ret = EC_KEY_set_public_key(d_eckey, pub_key);
+   ret = EC_KEY_set_public_key(d_eckey.get(), pub_key.get());
    if (ret != 1) {
-     EC_POINT_free(pub_key);
      throw runtime_error(getName()+" setting public key failed");
    }
-   EC_POINT_free(pub_key);
  }
  
 -bool OpenSSLECDSADNSCryptoKeyEngine::checkKey() const
 +bool OpenSSLECDSADNSCryptoKeyEngine::checkKey(vector<string> *errorMessages) const
  {
 -  return (EC_KEY_check_key(d_eckey.get()) == 1);
 +  bool retval = true;
-   if (EC_KEY_check_key(d_eckey) != 1) {
++  if (EC_KEY_check_key(d_eckey.get()) != 1) {
 +    retval = false;
 +    if (errorMessages != nullptr) {
 +      errorMessages->push_back(ERR_reason_error_string(ERR_get_error()));
 +    }
 +  }
 +  return retval;
  }
  
  void OpenSSLECDSADNSCryptoKeyEngine::fromPublicKeyString(const std::string& input)
      throw runtime_error(getName()+" setting private key failed");
    }
  
-   ret = EC_KEY_set_public_key(d_eckey, pub_key);
+   ret = EC_KEY_set_public_key(d_eckey.get(), pub_key.get());
    if (ret != 1) {
-     EC_POINT_free(pub_key);
      throw runtime_error(getName()+" setting public key failed");
    }
 -  bool checkKey() const override;
+ }
+ #endif
+ #ifdef HAVE_LIBCRYPTO_EDDSA
+ class OpenSSLEDDSADNSCryptoKeyEngine : public DNSCryptoKeyEngine
+ {
+ public:
+   explicit OpenSSLEDDSADNSCryptoKeyEngine(unsigned int algo) : DNSCryptoKeyEngine(algo), d_edkey(std::unique_ptr<EVP_PKEY, void(*)(EVP_PKEY*)>(nullptr, EVP_PKEY_free))
+   {
+     int ret = RAND_status();
+     if (ret != 1) {
+       throw runtime_error(getName()+" insufficient entropy");
+     }
+ #ifdef HAVE_LIBCRYPTO_ED25519
+     if(d_algorithm == 15) {
+       d_len = 32;
+       d_id = NID_ED25519;
+     }
+ #endif
+ #ifdef HAVE_LIBCRYPTO_ED448
+     if (d_algorithm == 16) {
+       d_len = 57;
+       d_id = NID_ED448;
+     }
+ #endif
+     if (d_len == 0) {
+       throw runtime_error(getName()+" unknown algorithm "+std::to_string(d_algorithm));
+     }
+   }
+   ~OpenSSLEDDSADNSCryptoKeyEngine()
+   {
+   }
+   string getName() const override { return "OpenSSL EDDSA"; }
+   int getBits() const override { return d_len; }
+   void create(unsigned int bits) override;
+   storvector_t convertToISCVector() const override;
+   std::string sign(const std::string& hash) const override;
+   bool verify(const std::string& msg, const std::string& signature) const override;
+   std::string getPubKeyHash() const override;
+   std::string getPublicKeyString() const override;
+   void fromISCMap(DNSKEYRecordContent& drc, std::map<std::string, std::string>& stormap) override;
+   void fromPublicKeyString(const std::string& content) override;
++  bool checkKey(vector<string> *errorMessages) const override;
+   static std::shared_ptr<DNSCryptoKeyEngine> maker(unsigned int algorithm)
+   {
+     return std::make_shared<OpenSSLEDDSADNSCryptoKeyEngine>(algorithm);
+   }
+ private:
+   size_t d_len{0};
+   int d_id{0};
+   std::unique_ptr<EVP_PKEY, void(*)(EVP_PKEY*)> d_edkey;
+ };
  
-   EC_POINT_free(pub_key);
 -bool OpenSSLEDDSADNSCryptoKeyEngine::checkKey() const
++bool OpenSSLEDDSADNSCryptoKeyEngine::checkKey(vector<string> *errorMessages) const
+ {
+   return (d_edkey ? true : false);
+ }
+ void OpenSSLEDDSADNSCryptoKeyEngine::create(unsigned int bits)
+ {
+   auto pctx = std::unique_ptr<EVP_PKEY_CTX, void(*)(EVP_PKEY_CTX*)>(EVP_PKEY_CTX_new_id(d_id, nullptr), EVP_PKEY_CTX_free);
+   if (!pctx) {
+     throw runtime_error(getName()+" context initialization failed");
+   }
+   if (EVP_PKEY_keygen_init(pctx.get()) < 1) {
+     throw runtime_error(getName()+" keygen initialization failed");
+   }
+   EVP_PKEY* newKey = nullptr;
+   if (EVP_PKEY_keygen(pctx.get(), &newKey) < 1) {
+     throw runtime_error(getName()+" key generation failed");
+   }
+   d_edkey = std::unique_ptr<EVP_PKEY, void(*)(EVP_PKEY*)>(newKey, EVP_PKEY_free);
  }
+ DNSCryptoKeyEngine::storvector_t OpenSSLEDDSADNSCryptoKeyEngine::convertToISCVector() const
+ {
+   storvector_t storvect;
+   string algorithm;
+ #ifdef HAVE_LIBCRYPTO_ED25519
+   if(d_algorithm == 15) {
+     algorithm = "15 (ED25519)";
+   }
  #endif
+ #ifdef HAVE_LIBCRYPTO_ED448
+   if(d_algorithm == 16) {
+     algorithm = "16 (ED448)";
+   }
+ #endif
+   if (algorithm.empty()) {
+     algorithm = " ? (?)";
+   }
+   storvect.push_back(make_pair("Algorithm", algorithm));
+   string buf;
+   size_t len = d_len;
+   buf.resize(len);
+   if (EVP_PKEY_get_raw_private_key(d_edkey.get(), reinterpret_cast<unsigned char*>(&buf.at(0)), &len) < 1) {
+     throw runtime_error(getName() + " Could not get private key from d_edkey");
+   }
+   storvect.push_back(make_pair("PrivateKey", buf));
+   return storvect;
+ }
+ std::string OpenSSLEDDSADNSCryptoKeyEngine::sign(const std::string& msg) const
+ {
+   auto mdctx = std::unique_ptr<EVP_MD_CTX, void(*)(EVP_MD_CTX*)>(EVP_MD_CTX_new(), EVP_MD_CTX_free);
+   if (!mdctx) {
+     throw runtime_error(getName()+" MD context initialization failed");
+   }
+   if(EVP_DigestSignInit(mdctx.get(), nullptr, nullptr, nullptr, d_edkey.get()) < 1) {
+     throw runtime_error(getName()+" unable to initialize signer");
+   }
+   string msgToSign = msg;
+   size_t siglen = d_len * 2;
+   string signature;
+   signature.resize(siglen);
+   if (EVP_DigestSign(mdctx.get(),
+         reinterpret_cast<unsigned char*>(&signature.at(0)), &siglen,
+         reinterpret_cast<unsigned char*>(&msgToSign.at(0)), msgToSign.length()) < 1) {
+     throw runtime_error(getName()+" signing error");
+   }
+   return signature;
+ }
+ bool OpenSSLEDDSADNSCryptoKeyEngine::verify(const std::string& msg, const std::string& signature) const
+ {
+   auto mdctx = std::unique_ptr<EVP_MD_CTX, void(*)(EVP_MD_CTX*)>(EVP_MD_CTX_new(), EVP_MD_CTX_free);
+   if (!mdctx) {
+     throw runtime_error(getName()+" MD context initialization failed");
+   }
+   if(EVP_DigestVerifyInit(mdctx.get(), nullptr, nullptr, nullptr, d_edkey.get()) < 1) {
+     throw runtime_error(getName()+" unable to initialize signer");
+   }
+   string checkSignature = signature;
+   string checkMsg = msg;
+   auto r = EVP_DigestVerify(mdctx.get(),
+       reinterpret_cast<unsigned char*>(&checkSignature.at(0)), checkSignature.length(),
+       reinterpret_cast<unsigned char*>(&checkMsg.at(0)), checkMsg.length());
+   if (r < 0) {
+     throw runtime_error(getName()+" verification failure");
+   }
+   return (r == 1);
+ }
+ std::string OpenSSLEDDSADNSCryptoKeyEngine::getPubKeyHash() const
+ {
+   return this->getPublicKeyString();
+ }
+ std::string OpenSSLEDDSADNSCryptoKeyEngine::getPublicKeyString() const
+ {
+   string buf;
+   size_t len = d_len;
+   buf.resize(len);
+   if (EVP_PKEY_get_raw_public_key(d_edkey.get(), reinterpret_cast<unsigned char*>(&buf.at(0)), &len) < 1) {
+     throw std::runtime_error(getName() + " unable to get public key from key struct");
+   }
+   return buf;
+ }
+ void OpenSSLEDDSADNSCryptoKeyEngine::fromISCMap(DNSKEYRecordContent& drc, std::map<std::string, std::string>& stormap) {
+   drc.d_algorithm = atoi(stormap["algorithm"].c_str());
+   if (drc.d_algorithm != d_algorithm) {
+     throw runtime_error(getName()+" tried to feed an algorithm "+std::to_string(drc.d_algorithm)+" to a "+std::to_string(d_algorithm)+" key");
+   }
  
+   d_edkey = std::unique_ptr<EVP_PKEY, void(*)(EVP_PKEY*)>(EVP_PKEY_new_raw_private_key(d_id, nullptr, reinterpret_cast<unsigned char*>(&stormap["privatekey"].at(0)), stormap["privatekey"].length()), EVP_PKEY_free);
+   if (!d_edkey) {
+     throw std::runtime_error(getName() + " could not create key structure from private key");
+   }
+ }
+ void OpenSSLEDDSADNSCryptoKeyEngine::fromPublicKeyString(const std::string& content)
+ {
+   if (content.length() != d_len) {
+     throw runtime_error(getName() + " wrong public key length for algorithm " + std::to_string(d_algorithm));
+   }
+   const unsigned char* raw = reinterpret_cast<const unsigned char*>(content.c_str());
+   d_edkey = std::unique_ptr<EVP_PKEY, void(*)(EVP_PKEY*)>(EVP_PKEY_new_raw_public_key(d_id, nullptr, raw, d_len), EVP_PKEY_free);
+   if (!d_edkey) {
+     throw runtime_error(getName()+" allocation of public key structure failed");
+   }
+ }
+ #endif // HAVE_LIBCRYPTO_EDDSA
  
  namespace {
    struct LoaderStruct
Simple merge