summaryrefslogtreecommitdiffstats
path: root/image_verify.cpp
diff options
context:
space:
mode:
authorJayanth Othayoth <ojayanth@in.ibm.com>2018-02-21 05:43:20 -0600
committerJayanth Othayoth <ojayanth@in.ibm.com>2018-03-13 07:51:14 -0500
commitfb6e1fc202b43141b2d57b641d784501a837096a (patch)
treee432283fc7170eaafcda9d70ea4c19839ef2a262 /image_verify.cpp
parent2ab9b1098efa8280f0cea165d1b6856e1ce05170 (diff)
downloadphosphor-bmc-code-mgmt-fb6e1fc202b43141b2d57b641d784501a837096a.tar.gz
phosphor-bmc-code-mgmt-fb6e1fc202b43141b2d57b641d784501a837096a.zip
Enabled OpenSSL based signature validation functions
Added support for OpenSSL based function for the signed image validation. Change-Id: I45bb677276694b0bbb92c7c694c7f95b8b2c011d Signed-off-by: Jayanth Othayoth <ojayanth@in.ibm.com>
Diffstat (limited to 'image_verify.cpp')
-rw-r--r--image_verify.cpp140
1 files changed, 132 insertions, 8 deletions
diff --git a/image_verify.cpp b/image_verify.cpp
index 5b50f39..99c7d2b 100644
--- a/image_verify.cpp
+++ b/image_verify.cpp
@@ -1,4 +1,8 @@
#include <set>
+#include <fstream>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <openssl/err.h>
#include "image_verify.hpp"
#include "config.h"
@@ -152,25 +156,35 @@ bool Signature::systemLevelVerify()
// Verify the file signature with available key types
// public keys and hash function.
+ // For any internal failure during the key/hash pair specific
+ // validation, should continue the validation with next
+ // available Key/hash pair.
for (const auto& keyType : keyTypes)
{
auto keyHashPair = getKeyHashFileNames(keyType);
auto hashFunc = Version::getValue(keyHashPair.first, hashFunctionTag);
- // Verify manifest file signature
- valid = verifyFile(manifestFile, manifestFileSig, keyHashPair.second,
- hashFunc);
- if (valid)
+ try
{
- // Verify publickey file signature.
- valid =
- verifyFile(pkeyFile, pkeyFileSig, keyHashPair.second, hashFunc);
+ // Verify manifest file signature
+ valid = verifyFile(manifestFile, manifestFileSig,
+ keyHashPair.second, hashFunc);
if (valid)
{
- break;
+ // Verify publickey file signature.
+ valid = verifyFile(pkeyFile, pkeyFileSig, keyHashPair.second,
+ hashFunc);
+ if (valid)
+ {
+ break;
+ }
}
}
+ catch (const InternalFailure& e)
+ {
+ valid = false;
+ }
}
return valid;
}
@@ -179,9 +193,119 @@ bool Signature::verifyFile(const fs::path& file, const fs::path& sigFile,
const fs::path& publicKey,
const std::string& hashFunc)
{
+
+ // Check existence of the files in the system.
+ if (!(fs::exists(file) && fs::exists(sigFile)))
+ {
+ log<level::ERR>("Failed to find the Data or signature file.",
+ entry("FILE=%s", file.c_str()));
+ elog<InternalFailure>();
+ }
+
+ // Create RSA.
+ auto publicRSA = createPublicRSA(publicKey);
+ if (publicRSA == nullptr)
+ {
+ log<level::ERR>("Failed to create RSA",
+ entry("FILE=%s", publicKey.c_str()));
+ elog<InternalFailure>();
+ }
+
+ // Assign key to RSA.
+ EVP_PKEY_Ptr pKeyPtr(EVP_PKEY_new(), ::EVP_PKEY_free);
+ EVP_PKEY_assign_RSA(pKeyPtr.get(), publicRSA);
+
+ // Initializes a digest context.
+ EVP_MD_CTX_Ptr rsaVerifyCtx(EVP_MD_CTX_create(), ::EVP_MD_CTX_destroy);
+
+ // Adds all digest algorithms to the internal table
+ OpenSSL_add_all_digests();
+
+ // Create Hash structre.
+ auto hashStruct = EVP_get_digestbyname(hashFunc.c_str());
+ if (!hashStruct)
+ {
+ log<level::ERR>("EVP_get_digestbynam: Unknown message digest",
+ entry("HASH=%s", hashFunc.c_str()));
+ elog<InternalFailure>();
+ }
+
+ auto result = EVP_DigestVerifyInit(rsaVerifyCtx.get(), nullptr, hashStruct,
+ nullptr, pKeyPtr.get());
+
+ if (result <= 0)
+ {
+ log<level::ERR>("Error occured during EVP_DigestVerifyInit",
+ entry("ERRCODE=%lu", ERR_get_error()));
+ elog<InternalFailure>();
+ }
+
+ // Hash the data file and update the verification context
+ auto size = fs::file_size(file);
+ auto dataPtr = mapFile(file, size);
+
+ result = EVP_DigestVerifyUpdate(rsaVerifyCtx.get(), dataPtr(), size);
+ if (result <= 0)
+ {
+ log<level::ERR>("Error occured during EVP_DigestVerifyUpdate",
+ entry("ERRCODE=%lu", ERR_get_error()));
+ elog<InternalFailure>();
+ }
+
+ // Verify the data with signature.
+ size = fs::file_size(sigFile);
+ auto signature = mapFile(sigFile, size);
+
+ result = EVP_DigestVerifyFinal(
+ rsaVerifyCtx.get(), reinterpret_cast<unsigned char*>(signature()),
+ size);
+
+ // Check the verification result.
+ if (result < 0)
+ {
+ log<level::ERR>("Error occured during EVP_DigestVerifyFinal",
+ entry("ERRCODE=%lu", ERR_get_error()));
+ elog<InternalFailure>();
+ }
+
+ if (result == 0)
+ {
+ log<level::ERR>("EVP_DigestVerifyFinal:Signature validation failed",
+ entry("PATH=%s", sigFile.c_str()));
+ return false;
+ }
return true;
}
+inline RSA* Signature::createPublicRSA(const fs::path& publicKey)
+{
+ RSA* rsa = nullptr;
+ auto size = fs::file_size(publicKey);
+
+ // Read public key file
+ auto data = mapFile(publicKey, size);
+
+ BIO_MEM_Ptr keyBio(BIO_new_mem_buf(data(), -1), &::BIO_free);
+ if (keyBio.get() == nullptr)
+ {
+ log<level::ERR>("Failed to create new BIO Memory buffer");
+ elog<InternalFailure>();
+ }
+
+ rsa = PEM_read_bio_RSA_PUBKEY(keyBio.get(), &rsa, nullptr, nullptr);
+
+ return rsa;
+}
+
+CustomMap Signature::mapFile(const fs::path& path, size_t size)
+{
+
+ CustomFd fd(open(path.c_str(), O_RDONLY));
+
+ return CustomMap(mmap(nullptr, size, PROT_READ, MAP_PRIVATE, fd(), 0),
+ size);
+}
+
} // namespace image
} // namespace software
} // namespace phosphor
OpenPOWER on IntegriCloud