Support overwriting existing signatures when signing OTA

Bug: 258771794

Test: Run brillo_update_payload hash && sign on an already signed
payload

Change-Id: I6a108fd245672053a5e1e42a6e09ccde868c2944
diff --git a/payload_generator/payload_signer.cc b/payload_generator/payload_signer.cc
index d9f0dd7..33b8033 100644
--- a/payload_generator/payload_signer.cc
+++ b/payload_generator/payload_signer.cc
@@ -28,17 +28,14 @@
 #include <brillo/data_encoding.h>
 #include <openssl/err.h>
 #include <openssl/pem.h>
+#include <unistd.h>
 
 #include "update_engine/common/constants.h"
 #include "update_engine/common/hash_calculator.h"
 #include "update_engine/common/subprocess.h"
 #include "update_engine/common/utils.h"
-#include "update_engine/payload_consumer/delta_performer.h"
-#include "update_engine/payload_consumer/payload_constants.h"
 #include "update_engine/payload_consumer/payload_metadata.h"
 #include "update_engine/payload_consumer/payload_verifier.h"
-#include "update_engine/payload_generator/delta_diff_generator.h"
-#include "update_engine/payload_generator/payload_file.h"
 #include "update_engine/update_metadata.pb.h"
 
 using std::string;
@@ -122,45 +119,35 @@
   DeltaArchiveManifest manifest;
   TEST_AND_RETURN_FALSE(payload_metadata.GetManifest(payload, &manifest));
 
-  // Is there already a signature op in place?
-  if (manifest.has_signatures_size()) {
-    // The signature op is tied to the size of the signature blob, but not it's
-    // contents. We don't allow the manifest to change if there is already an op
-    // present, because that might invalidate previously generated
-    // hashes/signatures.
-    if (manifest.signatures_size() != payload_signature.size()) {
-      LOG(ERROR) << "Attempt to insert different signature sized blob. "
-                 << "(current:" << manifest.signatures_size()
-                 << "new:" << payload_signature.size() << ")";
-      return false;
-    }
-
-    LOG(INFO) << "Matching signature sizes already present.";
-  } else {
-    // Updates the manifest to include the signature operation.
-    PayloadSigner::AddSignatureToManifest(
-        payload.size() - metadata_size - metadata_signature_size,
-        payload_signature.size(),
-        &manifest);
-
-    // Updates the payload to include the new manifest.
-    string serialized_manifest;
-    TEST_AND_RETURN_FALSE(manifest.AppendToString(&serialized_manifest));
-    LOG(INFO) << "Updated protobuf size: " << serialized_manifest.size();
-    payload.erase(payload.begin() + manifest_offset,
-                  payload.begin() + metadata_size);
-    payload.insert(payload.begin() + manifest_offset,
-                   serialized_manifest.begin(),
-                   serialized_manifest.end());
-
-    // Updates the protobuf size.
-    uint64_t size_be = htobe64(serialized_manifest.size());
-    memcpy(&payload[kProtobufSizeOffset], &size_be, sizeof(size_be));
-    metadata_size = serialized_manifest.size() + manifest_offset;
-
-    LOG(INFO) << "Updated payload size: " << payload.size();
-    LOG(INFO) << "Updated metadata size: " << metadata_size;
+  // Erase existing signatures.
+  if (manifest.has_signatures_offset()) {
+    payload.resize(manifest.signatures_offset() + metadata_size +
+                   metadata_signature_size);
   }
+
+  // Updates the manifest to include the signature operation.
+  PayloadSigner::AddSignatureToManifest(
+      payload.size() - metadata_size - metadata_signature_size,
+      payload_signature.size(),
+      &manifest);
+
+  // Updates the payload to include the new manifest.
+  string serialized_manifest;
+  TEST_AND_RETURN_FALSE(manifest.AppendToString(&serialized_manifest));
+  LOG(INFO) << "Updated protobuf size: " << serialized_manifest.size();
+  payload.erase(payload.begin() + manifest_offset,
+                payload.begin() + metadata_size);
+  payload.insert(payload.begin() + manifest_offset,
+                 serialized_manifest.begin(),
+                 serialized_manifest.end());
+
+  // Updates the protobuf size.
+  uint64_t size_be = htobe64(serialized_manifest.size());
+  memcpy(&payload[kProtobufSizeOffset], &size_be, sizeof(size_be));
+  metadata_size = serialized_manifest.size() + manifest_offset;
+
+  LOG(INFO) << "Updated payload size: " << payload.size();
+  LOG(INFO) << "Updated metadata size: " << metadata_size;
   uint64_t signatures_offset =
       metadata_size + metadata_signature_size + manifest.signatures_offset();
   LOG(INFO) << "Signature Blob Offset: " << signatures_offset;
@@ -471,6 +458,13 @@
                                                   &signatures_offset));
 
   LOG(INFO) << "Signed payload size: " << payload.size();
+  const auto ret =
+      HANDLE_EINTR(truncate(signed_payload_path.c_str(), payload.size()));
+  if (ret < 0) {
+    PLOG(ERROR) << "Failed to truncate file " << signed_payload_path
+                << " to size " << payload.size();
+    return false;
+  }
   TEST_AND_RETURN_FALSE(utils::WriteFile(
       signed_payload_path.c_str(), payload.data(), payload.size()));
   return true;