Skip to content

Commit

Permalink
Make the filename argument to createFromPEMFile optional
Browse files Browse the repository at this point in the history
  • Loading branch information
fredmorcos committed Feb 14, 2023
1 parent a538f95 commit c97af73
Show file tree
Hide file tree
Showing 4 changed files with 88 additions and 28 deletions.
44 changes: 34 additions & 10 deletions pdns/decafsigners.cc
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ class DecafED25519DNSCryptoKeyEngine : public DNSCryptoKeyEngine
*
* \return An ED25519 key engine populated with the contents of the PEM file.
*/
void createFromPEMFile(DNSKEYRecordContent& drc, std::FILE& inputFile, const std::string& filename) override;
void createFromPEMFile(DNSKEYRecordContent& drc, std::FILE& inputFile, std::optional<std::reference_wrapper<const std::string>> filename = std::nullopt) override;

/**
* \brief Writes this key's contents to a file.
Expand Down Expand Up @@ -85,24 +85,36 @@ void DecafED25519DNSCryptoKeyEngine::create(unsigned int bits)
}

#if defined(HAVE_LIBCRYPTO_ED25519)
void DecafED25519DNSCryptoKeyEngine::createFromPEMFile(DNSKEYRecordContent& drc, std::FILE& inputFile, const string& filename)
void DecafED25519DNSCryptoKeyEngine::createFromPEMFile(DNSKEYRecordContent& drc, std::FILE& inputFile, std::optional<std::reference_wrapper<const std::string>> filename)
{
drc.d_algorithm = d_algorithm;
auto key = std::unique_ptr<EVP_PKEY, decltype(&EVP_PKEY_free)>(PEM_read_PrivateKey(&inputFile, nullptr, nullptr, nullptr), &EVP_PKEY_free);
if (key == nullptr) {
throw runtime_error(getName() + ": Failed to read private key from PEM file `" + filename + "`");
if (filename.has_value()) {
throw runtime_error(getName() + ": Failed to read private key from PEM file `" + filename->get() + "`");
}

throw runtime_error(getName() + ": Failed to read private key from PEM contents");
}

std::size_t keylen = DECAF_EDDSA_25519_PRIVATE_BYTES;
int ret = EVP_PKEY_get_raw_private_key(key.get(), d_seckey, &keylen);
if (ret == 0) {
throw runtime_error(getName() + ": Failed to get private key from PEM file contents `" + filename + "`");
if (filename.has_value()) {
throw runtime_error(getName() + ": Failed to get private key from PEM file contents `" + filename->get() + "`");
}

throw runtime_error(getName() + ": Failed to get private key from PEM contents");
}

keylen = DECAF_EDDSA_25519_PUBLIC_BYTES;
ret = EVP_PKEY_get_raw_public_key(key.get(), d_pubkey, &keylen);
if (ret == 0) {
throw runtime_error(getName() + ": Failed to get public key from PEM file contents `" + filename + "`");
if (filename.has_value()) {
throw runtime_error(getName() + ": Failed to get public key from PEM file contents `" + filename->get() + "`");
}

throw runtime_error(getName() + ": Failed to get public key from PEM contents");
}
}

Expand Down Expand Up @@ -230,7 +242,7 @@ class DecafED448DNSCryptoKeyEngine : public DNSCryptoKeyEngine
*
* \return An ED448 key engine populated with the contents of the PEM file.
*/
void createFromPEMFile(DNSKEYRecordContent& drc, std::FILE& inputFile, const std::string& filename) override;
void createFromPEMFile(DNSKEYRecordContent& drc, std::FILE& inputFile, std::optional<std::reference_wrapper<const std::string>> filename = std::nullopt) override;

/**
* \brief Writes this key's contents to a file.
Expand Down Expand Up @@ -279,24 +291,36 @@ void DecafED448DNSCryptoKeyEngine::create(unsigned int bits)
}

#if defined(HAVE_LIBCRYPTO_ED448)
void DecafED448DNSCryptoKeyEngine::createFromPEMFile(DNSKEYRecordContent& drc, std::FILE& inputFile, const string& filename)
void DecafED448DNSCryptoKeyEngine::createFromPEMFile(DNSKEYRecordContent& drc, std::FILE& inputFile, std::optional<std::reference_wrapper<const std::string>> filename)
{
drc.d_algorithm = d_algorithm;
auto key = std::unique_ptr<EVP_PKEY, decltype(&EVP_PKEY_free)>(PEM_read_PrivateKey(&inputFile, nullptr, nullptr, nullptr), &EVP_PKEY_free);
if (key == nullptr) {
throw runtime_error(getName() + ": Failed to read private key from PEM file `" + filename + "`");
if (filename.has_value()) {
throw runtime_error(getName() + ": Failed to read private key from PEM file `" + filename->get() + "`");
}

throw runtime_error(getName() + ": Failed to read private key from PEM contents");
}

std::size_t keylen = DECAF_EDDSA_448_PRIVATE_BYTES;
int ret = EVP_PKEY_get_raw_private_key(key.get(), d_seckey, &keylen);
if (ret == 0) {
throw runtime_error(getName() + ": Failed to get private key from PEM file contents `" + filename + "`");
if (filename.has_value()) {
throw runtime_error(getName() + ": Failed to get private key from PEM file contents `" + filename->get() + "`");
}

throw runtime_error(getName() + ": Failed to get private key from PEM contents");
}

keylen = DECAF_EDDSA_448_PUBLIC_BYTES;
ret = EVP_PKEY_get_raw_public_key(key.get(), d_pubkey, &keylen);
if (ret == 0) {
throw runtime_error(getName() + ": Failed to get public key from PEM file contents `" + filename + "`");
if (filename.has_value()) {
throw runtime_error(getName() + ": Failed to get public key from PEM file contents `" + filename->get() + "`");
}

throw runtime_error(getName() + ": Failed to get public key from PEM contents");
}
}

Expand Down
8 changes: 6 additions & 2 deletions pdns/dnssecinfra.hh
Original file line number Diff line number Diff line change
Expand Up @@ -43,9 +43,13 @@ class DNSCryptoKeyEngine
using storvector_t = std::vector<std::pair<std::string, std::string>>;
virtual void create(unsigned int bits)=0;

virtual void createFromPEMFile(DNSKEYRecordContent& /* drc */, std::FILE& /* inputFile */, const std::string& /* filename */)
virtual void createFromPEMFile(DNSKEYRecordContent& /* drc */, std::FILE& /* inputFile */, const std::optional<std::reference_wrapper<const std::string>> filename = std::nullopt)
{
throw std::runtime_error("Can't create key from PEM file");
if (filename.has_value()) {
throw std::runtime_error("Can't create key from PEM file `" + filename->get() + "`");
}

throw std::runtime_error("Can't create key from PEM contents");
}

[[nodiscard]] virtual storvector_t convertToISCVector() const =0;
Expand Down
42 changes: 31 additions & 11 deletions pdns/opensslsigners.cc
Original file line number Diff line number Diff line change
Expand Up @@ -225,7 +225,7 @@ class OpenSSLRSADNSCryptoKeyEngine : public DNSCryptoKeyEngine
*
* \return An RSA key engine populated with the contents of the PEM file.
*/
void createFromPEMFile(DNSKEYRecordContent& drc, std::FILE& inputFile, const std::string& filename) override;
void createFromPEMFile(DNSKEYRecordContent& drc, std::FILE& inputFile, std::optional<std::reference_wrapper<const std::string>> filename = std::nullopt) override;

/**
* \brief Writes this key's contents to a file.
Expand Down Expand Up @@ -380,21 +380,29 @@ void OpenSSLRSADNSCryptoKeyEngine::create(unsigned int bits)
#endif
}

void OpenSSLRSADNSCryptoKeyEngine::createFromPEMFile(DNSKEYRecordContent& drc, std::FILE& inputFile, const std::string& filename)
void OpenSSLRSADNSCryptoKeyEngine::createFromPEMFile(DNSKEYRecordContent& drc, std::FILE& inputFile, const std::optional<std::reference_wrapper<const std::string>> filename)
{
drc.d_algorithm = d_algorithm;

#if OPENSSL_VERSION_MAJOR >= 3
EVP_PKEY* key = nullptr;
if (PEM_read_PrivateKey(&inputFile, &key, nullptr, nullptr) == nullptr) {
throw pdns::OpenSSL::error(getName(), "Could not read private key from PEM file `" + filename + "`");
if (filename.has_value()) {
throw pdns::OpenSSL::error(getName(), "Could not read private key from PEM file `" + filename->get() + "`");
}

throw pdns::OpenSSL::error(getName(), "Could not read private key from PEM contents");
}

d_key.reset(key);
#else
d_key = Key(PEM_read_RSAPrivateKey(&inputFile, nullptr, nullptr, nullptr), &RSA_free);
if (d_key == nullptr) {
throw runtime_error(getName() + ": Failed to read private key from PEM file `" + filename + "`");
if (filename.has_value()) {
throw runtime_error(getName() + ": Failed to read private key from PEM file `" + filename->get() + "`");
}

throw runtime_error(getName() + ": Failed to read private key from PEM contents");
}
#endif
}
Expand Down Expand Up @@ -1007,7 +1015,7 @@ class OpenSSLECDSADNSCryptoKeyEngine : public DNSCryptoKeyEngine
*
* \return An ECDSA key engine populated with the contents of the PEM file.
*/
void createFromPEMFile(DNSKEYRecordContent& drc, std::FILE& inputFile, const std::string& filename) override;
void createFromPEMFile(DNSKEYRecordContent& drc, std::FILE& inputFile, std::optional<std::reference_wrapper<const std::string>> filename = std::nullopt) override;

/**
* \brief Writes this key's contents to a file.
Expand Down Expand Up @@ -1148,21 +1156,29 @@ void OpenSSLECDSADNSCryptoKeyEngine::create(unsigned int bits)
#endif
}

void OpenSSLECDSADNSCryptoKeyEngine::createFromPEMFile(DNSKEYRecordContent& drc, std::FILE& inputFile, const string& filename)
void OpenSSLECDSADNSCryptoKeyEngine::createFromPEMFile(DNSKEYRecordContent& drc, std::FILE& inputFile, std::optional<std::reference_wrapper<const std::string>> filename)
{
drc.d_algorithm = d_algorithm;

#if OPENSSL_VERSION_MAJOR >= 3
EVP_PKEY* key = nullptr;
if (PEM_read_PrivateKey(&inputFile, &key, nullptr, nullptr) == nullptr) {
throw pdns::OpenSSL::error(getName(), "Failed to read private key from PEM file `" + filename + "`");
if (filename.has_value()) {
throw pdns::OpenSSL::error(getName(), "Failed to read private key from PEM file `" + filename->get() + "`");
}

throw pdns::OpenSSL::error(getName(), "Failed to read private key from PEM contents");
}

d_eckey.reset(key);
#else
d_eckey = Key(PEM_read_ECPrivateKey(&inputFile, nullptr, nullptr, nullptr), &EC_KEY_free);
if (d_eckey == nullptr) {
throw runtime_error(getName() + ": Failed to read private key from PEM file `" + filename + "`");
if (filename.has_value()) {
throw runtime_error(getName() + ": Failed to read private key from PEM file `" + filename->get() + "`");
}

throw runtime_error(getName() + ": Failed to read private key from PEM contents");
}

int ret = EC_KEY_set_group(d_eckey.get(), d_group.get());
Expand Down Expand Up @@ -1758,7 +1774,7 @@ class OpenSSLEDDSADNSCryptoKeyEngine : public DNSCryptoKeyEngine
*
* \return An EDDSA key engine populated with the contents of the PEM file.
*/
void createFromPEMFile(DNSKEYRecordContent& drc, std::FILE& inputFile, const std::string& filename) override;
void createFromPEMFile(DNSKEYRecordContent& drc, std::FILE& inputFile, std::optional<std::reference_wrapper<const std::string>> filename = std::nullopt) override;

/**
* \brief Writes this key's contents to a file.
Expand Down Expand Up @@ -1884,12 +1900,16 @@ void OpenSSLEDDSADNSCryptoKeyEngine::create(unsigned int /* bits */)
d_edkey.reset(newKey);
}

void OpenSSLEDDSADNSCryptoKeyEngine::createFromPEMFile(DNSKEYRecordContent& drc, std::FILE& inputFile, const string& filename)
void OpenSSLEDDSADNSCryptoKeyEngine::createFromPEMFile(DNSKEYRecordContent& drc, std::FILE& inputFile, std::optional<std::reference_wrapper<const std::string>> filename)
{
drc.d_algorithm = d_algorithm;
d_edkey = Key(PEM_read_PrivateKey(&inputFile, nullptr, nullptr, nullptr), &EVP_PKEY_free);
if (d_edkey == nullptr) {
throw pdns::OpenSSL::error(getName(), "Failed to read private key from PEM file `" + filename + "`");
if (filename.has_value()) {
throw pdns::OpenSSL::error(getName(), "Failed to read private key from PEM file `" + filename->get() + "`");
}

throw pdns::OpenSSL::error(getName(), "Failed to read private key from PEM contents");
}
}

Expand Down
22 changes: 17 additions & 5 deletions pdns/sodiumsigners.cc
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ class SodiumED25519DNSCryptoKeyEngine : public DNSCryptoKeyEngine
*
* \return An ED25519 key engine populated with the contents of the PEM file.
*/
void createFromPEMFile(DNSKEYRecordContent& drc, std::FILE& inputFile, const std::string& filename) override;
void createFromPEMFile(DNSKEYRecordContent& drc, std::FILE& inputFile, std::optional<std::reference_wrapper<const std::string>> filename = std::nullopt) override;

/**
* \brief Writes this key's contents to a file.
Expand Down Expand Up @@ -75,26 +75,38 @@ void SodiumED25519DNSCryptoKeyEngine::create(unsigned int bits)
}

#if defined(HAVE_LIBCRYPTO_ED25519)
void SodiumED25519DNSCryptoKeyEngine::createFromPEMFile(DNSKEYRecordContent& drc, std::FILE& inputFile, const string& filename)
void SodiumED25519DNSCryptoKeyEngine::createFromPEMFile(DNSKEYRecordContent& drc, std::FILE& inputFile, std::optional<std::reference_wrapper<const std::string>> filename)
{
drc.d_algorithm = d_algorithm;
auto key = std::unique_ptr<EVP_PKEY, decltype(&EVP_PKEY_free)>(PEM_read_PrivateKey(&inputFile, nullptr, nullptr, nullptr), &EVP_PKEY_free);
if (key == nullptr) {
throw runtime_error(getName() + ": Failed to read private key from PEM file `" + filename + "`");
if (filename.has_value()) {
throw runtime_error(getName() + ": Failed to read private key from PEM file `" + filename->get() + "`");
}

throw runtime_error(getName() + ": Failed to read private key from PEM contents");
}

// The secret key is 64 bytes according to libsodium. But OpenSSL returns 32 in
// secKeyLen. Perhaps secret key means private key + public key in libsodium terms.
std::size_t secKeyLen = crypto_sign_ed25519_SECRETKEYBYTES;
int ret = EVP_PKEY_get_raw_private_key(key.get(), d_seckey, &secKeyLen);
if (ret == 0) {
throw runtime_error(getName() + ": Failed to get private key from PEM file contents `" + filename + "`");
if (filename.has_value()) {
throw runtime_error(getName() + ": Failed to get private key from PEM file contents `" + filename->get() + "`");
}

throw runtime_error(getName() + ": Failed to get private key from PEM contents");
}

std::size_t pubKeyLen = crypto_sign_ed25519_PUBLICKEYBYTES;
ret = EVP_PKEY_get_raw_public_key(key.get(), d_pubkey, &pubKeyLen);
if (ret == 0) {
throw runtime_error(getName() + ": Failed to get public key from PEM file contents `" + filename + "`");
if (filename.has_value()) {
throw runtime_error(getName() + ": Failed to get public key from PEM file contents `" + filename->get() + "`");
}

throw runtime_error(getName() + ": Failed to get public key from PEM contents");
}

// It looks like libsodium expects the public key to be appended to the private key,
Expand Down

0 comments on commit c97af73

Please sign in to comment.