Store the signature blob as part of the update checkpoint.

If a signed update is interrupted after the download phase, then on resume we
don't re-download the signature blob from the server and fail the update due to
missing signature. This patch makes it so that the signature blob is stored and
restored as part of the update state checkpoint.

Some alternatives that we may want to consider in the future are:

- Redownload the signature blob from the server and re-verify it.

- Verify the signature as soon as it's received and don't checkpoint the blob
  and the signed sha-256 context.

BUG=chromium-os:15711
TEST=unit tests, tested manually interrupting updates on the device

Change-Id: If9b97e7f40c97c97da3049813c9332526ea65015
Reviewed-on: http://gerrit.chromium.org/gerrit/1594
Tested-by: Darin Petkov <petkov@chromium.org>
Reviewed-by: Andrew de los Reyes <adlr@chromium.org>
diff --git a/delta_performer.cc b/delta_performer.cc
index 6466795..96bc7f4 100644
--- a/delta_performer.cc
+++ b/delta_performer.cc
@@ -554,10 +554,23 @@
   TEST_AND_RETURN_FALSE(signatures_message_data_.empty());
   TEST_AND_RETURN_FALSE(buffer_offset_ == manifest_.signatures_offset());
   TEST_AND_RETURN_FALSE(buffer_.size() >= manifest_.signatures_size());
-  signatures_message_data_.insert(
-      signatures_message_data_.begin(),
+  signatures_message_data_.assign(
       buffer_.begin(),
       buffer_.begin() + manifest_.signatures_size());
+
+  // Save the signature blob because if the update is interrupted after the
+  // download phase we don't go through this path anymore. Some alternatives to
+  // consider:
+  //
+  // 1. On resume, re-download the signature blob from the server and re-verify
+  // it.
+  //
+  // 2. Verify the signature as soon as it's received and don't checkpoint the
+  // blob and the signed sha-256 context.
+  LOG_IF(WARNING, !prefs_->SetString(kPrefsUpdateStateSignatureBlob,
+                                     string(&signatures_message_data_[0],
+                                            signatures_message_data_.size())))
+      << "Unable to store the signature blob.";
   // The hash of all data consumed so far should be verified against the signed
   // hash.
   signed_hash_context_ = hash_calculator_.GetContext();
@@ -726,6 +739,7 @@
     prefs->SetInt64(kPrefsUpdateStateNextDataOffset, -1);
     prefs->SetString(kPrefsUpdateStateSHA256Context, "");
     prefs->SetString(kPrefsUpdateStateSignedSHA256Context, "");
+    prefs->SetString(kPrefsUpdateStateSignatureBlob, "");
     prefs->SetInt64(kPrefsManifestMetadataSize, -1);
     prefs->SetInt64(kPrefsResumedUpdateFailures, 0);
   }
@@ -770,10 +784,15 @@
                         next_data_offset >= 0);
   buffer_offset_ = next_data_offset;
 
-  // The signed hash context may be empty if the interrupted update didn't reach
-  // the signature blob.
+  // The signed hash context and the signature blob may be empty if the
+  // interrupted update didn't reach the signature.
   prefs_->GetString(kPrefsUpdateStateSignedSHA256Context,
                     &signed_hash_context_);
+  string signature_blob;
+  if (prefs_->GetString(kPrefsUpdateStateSignatureBlob, &signature_blob)) {
+    signatures_message_data_.assign(signature_blob.begin(),
+                                    signature_blob.end());
+  }
 
   string hash_context;
   TEST_AND_RETURN_FALSE(prefs_->GetString(kPrefsUpdateStateSHA256Context,