Don't use temp file for public key.

If using public key from Omaha response, we wrote it to a temp file
which will be read back, this is unnecessary since we can keep it in
memory.

Test: update_engine_unittests
Change-Id: Ib9f7a9292b71b9d91a0b24c687cc989b79d3812b
diff --git a/common/utils.cc b/common/utils.cc
index 1a8fd53..1fb7681 100644
--- a/common/utils.cc
+++ b/common/utils.cc
@@ -962,48 +962,6 @@
                             encoded_hash.c_str());
 }
 
-bool DecodeAndStoreBase64String(const string& base64_encoded,
-                                base::FilePath *out_path) {
-  brillo::Blob contents;
-
-  out_path->clear();
-
-  if (base64_encoded.size() == 0) {
-    LOG(ERROR) << "Can't decode empty string.";
-    return false;
-  }
-
-  if (!brillo::data_encoding::Base64Decode(base64_encoded, &contents) ||
-      contents.size() == 0) {
-    LOG(ERROR) << "Error decoding base64.";
-    return false;
-  }
-
-  FILE *file = base::CreateAndOpenTemporaryFile(out_path);
-  if (file == nullptr) {
-    LOG(ERROR) << "Error creating temporary file.";
-    return false;
-  }
-
-  if (fwrite(contents.data(), 1, contents.size(), file) != contents.size()) {
-    PLOG(ERROR) << "Error writing to temporary file.";
-    if (fclose(file) != 0)
-      PLOG(ERROR) << "Error closing temporary file.";
-    if (unlink(out_path->value().c_str()) != 0)
-      PLOG(ERROR) << "Error unlinking temporary file.";
-    out_path->clear();
-    return false;
-  }
-
-  if (fclose(file) != 0) {
-    PLOG(ERROR) << "Error closing temporary file.";
-    out_path->clear();
-    return false;
-  }
-
-  return true;
-}
-
 bool ConvertToOmahaInstallDate(Time time, int *out_num_days) {
   time_t unix_time = time.ToTimeT();
   // Output of: date +"%s" --date="Jan 1, 2007 0:00 PST".
diff --git a/common/utils.h b/common/utils.h
index e55a6e5..17a4c31 100644
--- a/common/utils.h
+++ b/common/utils.h
@@ -275,14 +275,6 @@
 // it'll return the same value again.
 ErrorCode GetBaseErrorCode(ErrorCode code);
 
-// Decodes the data in |base64_encoded| and stores it in a temporary
-// file. Returns false if the given data is empty, not well-formed
-// base64 or if an error occurred. If true is returned, the decoded
-// data is stored in the file returned in |out_path|. The file should
-// be deleted when no longer needed.
-bool DecodeAndStoreBase64String(const std::string& base64_encoded,
-                                base::FilePath *out_path);
-
 // Converts |time| to an Omaha InstallDate which is defined as "the
 // number of PST8PDT calendar weeks since Jan 1st 2007 0:00 PST, times
 // seven" with PST8PDT defined as "Pacific Time" (e.g. UTC-07:00 if
diff --git a/common/utils_unittest.cc b/common/utils_unittest.cc
index 3405b68..db88544 100644
--- a/common/utils_unittest.cc
+++ b/common/utils_unittest.cc
@@ -305,29 +305,6 @@
   EXPECT_EQ(time, utils::TimeFromStructTimespec(&ts));
 }
 
-TEST(UtilsTest, DecodeAndStoreBase64String) {
-  base::FilePath path;
-
-  // Ensure we return false on empty strings or invalid base64.
-  EXPECT_FALSE(utils::DecodeAndStoreBase64String("", &path));
-  EXPECT_FALSE(utils::DecodeAndStoreBase64String("not valid base64", &path));
-
-  // Pass known base64 and check that it matches. This string was generated
-  // the following way:
-  //
-  //   $ echo "Update Engine" | base64
-  //   VXBkYXRlIEVuZ2luZQo=
-  EXPECT_TRUE(utils::DecodeAndStoreBase64String("VXBkYXRlIEVuZ2luZQo=",
-                                                &path));
-  ScopedPathUnlinker unlinker(path.value());
-  string expected_contents = "Update Engine\n";
-  string contents;
-  EXPECT_TRUE(utils::ReadFile(path.value(), &contents));
-  EXPECT_EQ(contents, expected_contents);
-  EXPECT_EQ(static_cast<off_t>(expected_contents.size()),
-            utils::FileSize(path.value()));
-}
-
 TEST(UtilsTest, ConvertToOmahaInstallDate) {
   // The Omaha Epoch starts at Jan 1, 2007 0:00 PST which is a
   // Monday. In Unix time, this point in time is easily obtained via
diff --git a/payload_consumer/delta_performer.cc b/payload_consumer/delta_performer.cc
index 7dcb5f7..a0c7f57 100644
--- a/payload_consumer/delta_performer.cc
+++ b/payload_consumer/delta_performer.cc
@@ -525,19 +525,17 @@
                  << "Trusting metadata size in payload = " << metadata_size_;
   }
 
-  // See if we should use the public RSA key in the Omaha response.
-  base::FilePath path_to_public_key(public_key_path_);
-  base::FilePath tmp_key;
-  if (GetPublicKeyFromResponse(&tmp_key))
-    path_to_public_key = tmp_key;
-  ScopedPathUnlinker tmp_key_remover(tmp_key.value());
-  if (tmp_key.empty())
-    tmp_key_remover.set_should_remove(false);
+  string public_key;
+  if (!GetPublicKey(&public_key)) {
+    LOG(ERROR) << "Failed to get public key.";
+    *error = ErrorCode::kDownloadMetadataSignatureVerificationError;
+    return MetadataParseResult::kError;
+  }
 
   // We have the full metadata in |payload|. Verify its integrity
   // and authenticity based on the information we have in Omaha response.
   *error = payload_metadata_.ValidateMetadataSignature(
-      payload, payload_->metadata_signature, path_to_public_key);
+      payload, payload_->metadata_signature, public_key);
   if (*error != ErrorCode::kSuccess) {
     if (install_plan_->hash_checks_mandatory) {
       // The autoupdate_CatchBadSignatures test checks for this string
@@ -1596,15 +1594,21 @@
   return true;
 }
 
-bool DeltaPerformer::GetPublicKeyFromResponse(base::FilePath *out_tmp_key) {
-  if (hardware_->IsOfficialBuild() ||
-      utils::FileExists(public_key_path_.c_str()) ||
-      install_plan_->public_key_rsa.empty())
-    return false;
+bool DeltaPerformer::GetPublicKey(string* out_public_key) {
+  out_public_key->clear();
 
-  if (!utils::DecodeAndStoreBase64String(install_plan_->public_key_rsa,
-                                         out_tmp_key))
-    return false;
+  if (utils::FileExists(public_key_path_.c_str())) {
+    LOG(INFO) << "Verifying using public key: " << public_key_path_;
+    return utils::ReadFile(public_key_path_, out_public_key);
+  }
+
+  // If this is an official build then we are not allowed to use public key from
+  // Omaha response.
+  if (!hardware_->IsOfficialBuild() && !install_plan_->public_key_rsa.empty()) {
+    LOG(INFO) << "Verifying using public key from Omaha response.";
+    return brillo::data_encoding::Base64Decode(install_plan_->public_key_rsa,
+                                               out_public_key);
+  }
 
   return true;
 }
@@ -1771,18 +1775,11 @@
 ErrorCode DeltaPerformer::VerifyPayload(
     const brillo::Blob& update_check_response_hash,
     const uint64_t update_check_response_size) {
-
-  // See if we should use the public RSA key in the Omaha response.
-  base::FilePath path_to_public_key(public_key_path_);
-  base::FilePath tmp_key;
-  if (GetPublicKeyFromResponse(&tmp_key))
-    path_to_public_key = tmp_key;
-  ScopedPathUnlinker tmp_key_remover(tmp_key.value());
-  if (tmp_key.empty())
-    tmp_key_remover.set_should_remove(false);
-
-  LOG(INFO) << "Verifying payload using public key: "
-            << path_to_public_key.value();
+  string public_key;
+  if (!GetPublicKey(&public_key)) {
+    LOG(ERROR) << "Failed to get public key.";
+    return ErrorCode::kDownloadPayloadPubKeyVerificationError;
+  }
 
   // Verifies the download size.
   TEST_AND_RETURN_VAL(ErrorCode::kPayloadSizeMismatchError,
@@ -1798,7 +1795,7 @@
       payload_hash_calculator_.raw_hash() == update_check_response_hash);
 
   // Verifies the signed payload hash.
-  if (!utils::FileExists(path_to_public_key.value().c_str())) {
+  if (public_key.empty()) {
     LOG(WARNING) << "Not verifying signed delta payload -- missing public key.";
     return ErrorCode::kSuccess;
   }
@@ -1811,7 +1808,7 @@
                       !hash_data.empty());
 
   if (!PayloadVerifier::VerifySignature(
-      signatures_message_data_, path_to_public_key.value(), hash_data)) {
+          signatures_message_data_, public_key, hash_data)) {
     // The autoupdate_CatchBadSignatures test checks for this string
     // in log-files. Keep in sync.
     LOG(ERROR) << "Public key verification failed, thus update failed.";
diff --git a/payload_consumer/delta_performer.h b/payload_consumer/delta_performer.h
index 8597a37..36244dc 100644
--- a/payload_consumer/delta_performer.h
+++ b/payload_consumer/delta_performer.h
@@ -264,13 +264,12 @@
   // update. Returns false otherwise.
   bool PrimeUpdateState();
 
-  // If the Omaha response contains a public RSA key and we're allowed
-  // to use it (e.g. if we're in developer mode), extract the key from
-  // the response and store it in a temporary file and return true. In
-  // the affirmative the path to the temporary file is stored in
-  // |out_tmp_key| and it is the responsibility of the caller to clean
-  // it up.
-  bool GetPublicKeyFromResponse(base::FilePath *out_tmp_key);
+  // Get the public key to be used to verify metadata signature or payload
+  // signature. Always use |public_key_path_| if exists, otherwise if the Omaha
+  // response contains a public RSA key and we're allowed to use it (e.g. if
+  // we're in developer mode), decode the key from the response and store it in
+  // |out_public_key|. Returns false on failures.
+  bool GetPublicKey(std::string* out_public_key);
 
   // After install_plan_ is filled with partition names and sizes, initialize
   // metadata of partitions and map necessary devices before opening devices.
diff --git a/payload_consumer/delta_performer_unittest.cc b/payload_consumer/delta_performer_unittest.cc
index 3cddee4..4cf9756 100644
--- a/payload_consumer/delta_performer_unittest.cc
+++ b/payload_consumer/delta_performer_unittest.cc
@@ -942,8 +942,6 @@
 }
 
 TEST_F(DeltaPerformerTest, UsePublicKeyFromResponse) {
-  base::FilePath key_path;
-
   // The result of the GetPublicKeyResponse() method is based on three things
   //
   //  1. Whether it's an official build; and
@@ -960,55 +958,65 @@
   ASSERT_TRUE(temp_dir.CreateUniqueTempDir());
   string non_existing_file = temp_dir.GetPath().Append("non-existing").value();
   string existing_file = temp_dir.GetPath().Append("existing").value();
-  EXPECT_EQ(0, System(base::StringPrintf("touch %s", existing_file.c_str())));
+  constexpr char kExistingKey[] = "Existing";
+  ASSERT_TRUE(test_utils::WriteFileString(existing_file, kExistingKey));
 
-  // Non-official build, non-existing public-key, key in response -> true
+  // Non-official build, non-existing public-key, key in response ->
+  // kResponseKey
   fake_hardware_.SetIsOfficialBuild(false);
   performer_.public_key_path_ = non_existing_file;
-  // This is the result of 'echo "Test" | base64' and is not meant to be a
-  // valid public key, but it is valid base-64.
-  constexpr char kBase64TestKey[] = "VGVzdAo=";
-  install_plan_.public_key_rsa = kBase64TestKey;
-  EXPECT_TRUE(performer_.GetPublicKeyFromResponse(&key_path));
-  EXPECT_FALSE(key_path.empty());
-  EXPECT_EQ(unlink(key_path.value().c_str()), 0);
-  // Same with official build -> false
+  // This is the result of 'echo -n "Response" | base64' and is not meant to be
+  // a valid public key, but it is valid base-64.
+  constexpr char kResponseKey[] = "Response";
+  constexpr char kBase64ResponseKey[] = "UmVzcG9uc2U=";
+  install_plan_.public_key_rsa = kBase64ResponseKey;
+  string public_key;
+  EXPECT_TRUE(performer_.GetPublicKey(&public_key));
+  EXPECT_EQ(public_key, kResponseKey);
+  // Same with official build -> no key
   fake_hardware_.SetIsOfficialBuild(true);
-  EXPECT_FALSE(performer_.GetPublicKeyFromResponse(&key_path));
+  EXPECT_TRUE(performer_.GetPublicKey(&public_key));
+  EXPECT_TRUE(public_key.empty());
 
-  // Non-official build, existing public-key, key in response -> false
+  // Non-official build, existing public-key, key in response -> kExistingKey
   fake_hardware_.SetIsOfficialBuild(false);
   performer_.public_key_path_ = existing_file;
-  install_plan_.public_key_rsa = kBase64TestKey;
-  EXPECT_FALSE(performer_.GetPublicKeyFromResponse(&key_path));
-  // Same with official build -> false
+  install_plan_.public_key_rsa = kBase64ResponseKey;
+  EXPECT_TRUE(performer_.GetPublicKey(&public_key));
+  EXPECT_EQ(public_key, kExistingKey);
+  // Same with official build -> kExistingKey
   fake_hardware_.SetIsOfficialBuild(true);
-  EXPECT_FALSE(performer_.GetPublicKeyFromResponse(&key_path));
+  EXPECT_TRUE(performer_.GetPublicKey(&public_key));
+  EXPECT_EQ(public_key, kExistingKey);
 
-  // Non-official build, non-existing public-key, no key in response -> false
+  // Non-official build, non-existing public-key, no key in response -> no key
   fake_hardware_.SetIsOfficialBuild(false);
   performer_.public_key_path_ = non_existing_file;
   install_plan_.public_key_rsa = "";
-  EXPECT_FALSE(performer_.GetPublicKeyFromResponse(&key_path));
-  // Same with official build -> false
+  EXPECT_TRUE(performer_.GetPublicKey(&public_key));
+  EXPECT_TRUE(public_key.empty());
+  // Same with official build -> no key
   fake_hardware_.SetIsOfficialBuild(true);
-  EXPECT_FALSE(performer_.GetPublicKeyFromResponse(&key_path));
+  EXPECT_TRUE(performer_.GetPublicKey(&public_key));
+  EXPECT_TRUE(public_key.empty());
 
-  // Non-official build, existing public-key, no key in response -> false
+  // Non-official build, existing public-key, no key in response -> kExistingKey
   fake_hardware_.SetIsOfficialBuild(false);
   performer_.public_key_path_ = existing_file;
   install_plan_.public_key_rsa = "";
-  EXPECT_FALSE(performer_.GetPublicKeyFromResponse(&key_path));
-  // Same with official build -> false
+  EXPECT_TRUE(performer_.GetPublicKey(&public_key));
+  EXPECT_EQ(public_key, kExistingKey);
+  // Same with official build -> kExistingKey
   fake_hardware_.SetIsOfficialBuild(true);
-  EXPECT_FALSE(performer_.GetPublicKeyFromResponse(&key_path));
+  EXPECT_TRUE(performer_.GetPublicKey(&public_key));
+  EXPECT_EQ(public_key, kExistingKey);
 
   // Non-official build, non-existing public-key, key in response
   // but invalid base64 -> false
   fake_hardware_.SetIsOfficialBuild(false);
   performer_.public_key_path_ = non_existing_file;
   install_plan_.public_key_rsa = "not-valid-base64";
-  EXPECT_FALSE(performer_.GetPublicKeyFromResponse(&key_path));
+  EXPECT_FALSE(performer_.GetPublicKey(&public_key));
 }
 
 TEST_F(DeltaPerformerTest, ConfVersionsMatch) {
diff --git a/payload_consumer/payload_metadata.cc b/payload_consumer/payload_metadata.cc
index 3079feb..b631c87 100644
--- a/payload_consumer/payload_metadata.cc
+++ b/payload_consumer/payload_metadata.cc
@@ -155,8 +155,8 @@
 
 ErrorCode PayloadMetadata::ValidateMetadataSignature(
     const brillo::Blob& payload,
-    std::string metadata_signature,
-    base::FilePath path_to_public_key) const {
+    const std::string& metadata_signature,
+    const std::string& pem_public_key) const {
   if (payload.size() < metadata_size_ + metadata_signature_size_)
     return ErrorCode::kDownloadMetadataSignatureError;
 
@@ -182,9 +182,6 @@
     return ErrorCode::kDownloadMetadataSignatureMissingError;
   }
 
-  LOG(INFO) << "Verifying metadata hash signature using public key: "
-            << path_to_public_key.value();
-
   brillo::Blob calculated_metadata_hash;
   if (!HashCalculator::RawHashOfBytes(
           payload.data(), metadata_size_, &calculated_metadata_hash)) {
@@ -200,9 +197,8 @@
 
   if (!metadata_signature_blob.empty()) {
     brillo::Blob expected_metadata_hash;
-    if (!PayloadVerifier::GetRawHashFromSignature(metadata_signature_blob,
-                                                  path_to_public_key.value(),
-                                                  &expected_metadata_hash)) {
+    if (!PayloadVerifier::GetRawHashFromSignature(
+            metadata_signature_blob, pem_public_key, &expected_metadata_hash)) {
       LOG(ERROR) << "Unable to compute expected hash from metadata signature";
       return ErrorCode::kDownloadMetadataSignatureError;
     }
@@ -215,7 +211,7 @@
     }
   } else {
     if (!PayloadVerifier::VerifySignature(metadata_signature_protobuf_blob,
-                                          path_to_public_key.value(),
+                                          pem_public_key,
                                           calculated_metadata_hash)) {
       LOG(ERROR) << "Manifest hash verification failed.";
       return ErrorCode::kDownloadMetadataSignatureMismatch;
diff --git a/payload_consumer/payload_metadata.h b/payload_consumer/payload_metadata.h
index 8748f6f..1b4c5c8 100644
--- a/payload_consumer/payload_metadata.h
+++ b/payload_consumer/payload_metadata.h
@@ -22,7 +22,7 @@
 #include <string>
 #include <vector>
 
-#include <base/files/file_path.h>
+#include <base/macros.h>
 #include <brillo/secure_blob.h>
 
 #include "update_engine/common/error_code.h"
@@ -66,8 +66,8 @@
   // to the payload server doesn't exploit any vulnerability in the code that
   // parses the protocol buffer.
   ErrorCode ValidateMetadataSignature(const brillo::Blob& payload,
-                                      std::string metadata_signature,
-                                      base::FilePath path_to_public_key) const;
+                                      const std::string& metadata_signature,
+                                      const std::string& pem_public_key) const;
 
   // Returns the major payload version. If the version was not yet parsed,
   // returns zero.
diff --git a/payload_consumer/payload_verifier.cc b/payload_consumer/payload_verifier.cc
index ab5238c..f3d4626 100644
--- a/payload_consumer/payload_verifier.cc
+++ b/payload_consumer/payload_verifier.cc
@@ -16,6 +16,8 @@
 
 #include "update_engine/payload_consumer/payload_verifier.h"
 
+#include <vector>
+
 #include <base/logging.h>
 #include <openssl/pem.h>
 
@@ -85,10 +87,8 @@
 }  // namespace
 
 bool PayloadVerifier::VerifySignature(const brillo::Blob& signature_blob,
-                                      const string& public_key_path,
+                                      const string& pem_public_key,
                                       const brillo::Blob& hash_data) {
-  TEST_AND_RETURN_FALSE(!public_key_path.empty());
-
   Signatures signatures;
   LOG(INFO) << "signature blob size = " <<  signature_blob.size();
   TEST_AND_RETURN_FALSE(signatures.ParseFromArray(signature_blob.data(),
@@ -105,7 +105,7 @@
     const Signatures_Signature& signature = signatures.signatures(i);
     brillo::Blob sig_data(signature.data().begin(), signature.data().end());
     brillo::Blob sig_hash_data;
-    if (!GetRawHashFromSignature(sig_data, public_key_path, &sig_hash_data))
+    if (!GetRawHashFromSignature(sig_data, pem_public_key, &sig_hash_data))
       continue;
 
     if (hash_data == sig_hash_data) {
@@ -125,28 +125,19 @@
   return false;
 }
 
-
-bool PayloadVerifier::GetRawHashFromSignature(
-    const brillo::Blob& sig_data,
-    const string& public_key_path,
-    brillo::Blob* out_hash_data) {
-  TEST_AND_RETURN_FALSE(!public_key_path.empty());
-
+bool PayloadVerifier::GetRawHashFromSignature(const brillo::Blob& sig_data,
+                                              const string& pem_public_key,
+                                              brillo::Blob* out_hash_data) {
   // The code below executes the equivalent of:
   //
-  // openssl rsautl -verify -pubin -inkey |public_key_path|
+  // openssl rsautl -verify -pubin -inkey <(echo |pem_public_key|)
   //   -in |sig_data| -out |out_hash_data|
 
-  // Loads the public key.
-  FILE* fpubkey = fopen(public_key_path.c_str(), "rb");
-  if (!fpubkey) {
-    LOG(ERROR) << "Unable to open public key file: " << public_key_path;
-    return false;
-  }
+  BIO* bp = BIO_new_mem_buf(pem_public_key.data(), pem_public_key.size());
+  char dummy_password[] = {' ', 0};  // Ensure no password is read from stdin.
+  RSA* rsa = PEM_read_bio_RSA_PUBKEY(bp, nullptr, nullptr, dummy_password);
+  BIO_free(bp);
 
-  char dummy_password[] = { ' ', 0 };  // Ensure no password is read from stdin.
-  RSA* rsa = PEM_read_RSA_PUBKEY(fpubkey, nullptr, nullptr, dummy_password);
-  fclose(fpubkey);
   TEST_AND_RETURN_FALSE(rsa != nullptr);
   unsigned int keysize = RSA_size(rsa);
   if (sig_data.size() > 2 * keysize) {
diff --git a/payload_consumer/payload_verifier.h b/payload_consumer/payload_verifier.h
index 8caef35..ec23ef2 100644
--- a/payload_consumer/payload_verifier.h
+++ b/payload_consumer/payload_verifier.h
@@ -32,19 +32,20 @@
 class PayloadVerifier {
  public:
   // Interprets |signature_blob| as a protocol buffer containing the Signatures
-  // message and decrypts each signature data using the |public_key_path|.
+  // message and decrypts each signature data using the |pem_public_key|.
+  // |pem_public_key| should be a PEM format RSA public key data.
   // Returns whether *any* of the decrypted hashes matches the |hash_data|.
   // In case of any error parsing the signatures or the public key, returns
   // false.
   static bool VerifySignature(const brillo::Blob& signature_blob,
-                              const std::string& public_key_path,
+                              const std::string& pem_public_key,
                               const brillo::Blob& hash_data);
 
-  // Decrypts sig_data with the given public_key_path and populates
-  // out_hash_data with the decoded raw hash. Returns true if successful,
-  // false otherwise.
+  // Decrypts |sig_data| with the given |pem_public_key| and populates
+  // |out_hash_data| with the decoded raw hash. |pem_public_key| should be a PEM
+  // format RSA public key data. Returns true if successful, false otherwise.
   static bool GetRawHashFromSignature(const brillo::Blob& sig_data,
-                                      const std::string& public_key_path,
+                                      const std::string& pem_public_key,
                                       brillo::Blob* out_hash_data);
 
   // Pads a SHA256 hash so that it may be encrypted/signed with RSA2048
diff --git a/payload_generator/payload_signer.cc b/payload_generator/payload_signer.cc
index 2c386fa..35a0c3f 100644
--- a/payload_generator/payload_signer.cc
+++ b/payload_generator/payload_signer.cc
@@ -256,17 +256,19 @@
                                                  &metadata_hash));
   brillo::Blob signature_blob(payload.begin() + signatures_offset,
                               payload.end());
+  string public_key;
+  TEST_AND_RETURN_FALSE(utils::ReadFile(public_key_path, &public_key));
   TEST_AND_RETURN_FALSE(PayloadVerifier::PadRSA2048SHA256Hash(&payload_hash));
   TEST_AND_RETURN_FALSE(PayloadVerifier::VerifySignature(
-      signature_blob, public_key_path, payload_hash));
+      signature_blob, public_key, payload_hash));
   if (metadata_signature_size) {
-    signature_blob.assign(payload.begin() + metadata_size,
-                          payload.begin() + metadata_size +
-                          metadata_signature_size);
+    signature_blob.assign(
+        payload.begin() + metadata_size,
+        payload.begin() + metadata_size + metadata_signature_size);
     TEST_AND_RETURN_FALSE(
         PayloadVerifier::PadRSA2048SHA256Hash(&metadata_hash));
     TEST_AND_RETURN_FALSE(PayloadVerifier::VerifySignature(
-        signature_blob, public_key_path, metadata_hash));
+        signature_blob, public_key, metadata_hash));
   }
   return true;
 }
diff --git a/payload_generator/payload_signer_unittest.cc b/payload_generator/payload_signer_unittest.cc
index 967e026..a6ef38d 100644
--- a/payload_generator/payload_signer_unittest.cc
+++ b/payload_generator/payload_signer_unittest.cc
@@ -153,14 +153,15 @@
                   GetBuildArtifactsPath(kUnittestPrivateKey2Path)});
 
   // Either public key should pass the verification.
+  string public_key;
+  EXPECT_TRUE(utils::ReadFile(GetBuildArtifactsPath(kUnittestPublicKeyPath),
+                              &public_key));
   EXPECT_TRUE(PayloadVerifier::VerifySignature(
-      signature_blob,
-      GetBuildArtifactsPath(kUnittestPublicKeyPath),
-      padded_hash_data_));
+      signature_blob, public_key, padded_hash_data_));
+  EXPECT_TRUE(utils::ReadFile(GetBuildArtifactsPath(kUnittestPublicKey2Path),
+                              &public_key));
   EXPECT_TRUE(PayloadVerifier::VerifySignature(
-      signature_blob,
-      GetBuildArtifactsPath(kUnittestPublicKey2Path),
-      padded_hash_data_));
+      signature_blob, public_key, padded_hash_data_));
 }
 
 TEST_F(PayloadSignerTest, VerifySignatureTest) {
@@ -168,15 +169,16 @@
   SignSampleData(&signature_blob,
                  {GetBuildArtifactsPath(kUnittestPrivateKeyPath)});
 
+  string public_key;
+  EXPECT_TRUE(utils::ReadFile(GetBuildArtifactsPath(kUnittestPublicKeyPath),
+                              &public_key));
   EXPECT_TRUE(PayloadVerifier::VerifySignature(
-      signature_blob,
-      GetBuildArtifactsPath(kUnittestPublicKeyPath),
-      padded_hash_data_));
+      signature_blob, public_key, padded_hash_data_));
   // Passing the invalid key should fail the verification.
-  EXPECT_FALSE(PayloadVerifier::VerifySignature(
-      signature_blob,
-      GetBuildArtifactsPath(kUnittestPublicKey2Path),
-      padded_hash_data_));
+  EXPECT_TRUE(utils::ReadFile(GetBuildArtifactsPath(kUnittestPublicKey2Path),
+                              &public_key));
+  EXPECT_TRUE(PayloadVerifier::VerifySignature(
+      signature_blob, public_key, padded_hash_data_));
 }
 
 TEST_F(PayloadSignerTest, SkipMetadataSignatureTest) {
diff --git a/update_attempter_android.cc b/update_attempter_android.cc
index a9033b7..a3974ab 100644
--- a/update_attempter_android.cc
+++ b/update_attempter_android.cc
@@ -396,8 +396,13 @@
         "Failed to read metadata and signature from " + metadata_filename);
   }
   fd->Close();
-  errorcode = payload_metadata.ValidateMetadataSignature(
-      metadata, "", base::FilePath(constants::kUpdatePayloadPublicKeyPath));
+
+  string public_key;
+  if (!utils::ReadFile(constants::kUpdatePayloadPublicKeyPath, &public_key)) {
+    return LogAndSetError(error, FROM_HERE, "Failed to read public key.");
+  }
+  errorcode =
+      payload_metadata.ValidateMetadataSignature(metadata, "", public_key);
   if (errorcode != ErrorCode::kSuccess) {
     return LogAndSetError(error,
                           FROM_HERE,