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
Reviewed-on: http://gerrit.chromium.org/gerrit/1594
Tested-by: Darin Petkov <[email protected]>
Reviewed-by: Andrew de los Reyes <[email protected]>
(cherry picked from commit 4f0a07bc1bc46c3c1ac36ba57d693c61a71227ce)
Change-Id: I07ed754bdd0398c42b122874dfeb9e462d2f45b4
Reviewed-on: http://gerrit.chromium.org/gerrit/1652
Tested-by: Darin Petkov <[email protected]>
Reviewed-by: Ryan Cairns <[email protected]>
diff --git a/delta_performer.cc b/delta_performer.cc
index b5d1cff..093673f 100644
--- a/delta_performer.cc
+++ b/delta_performer.cc
@@ -553,10 +553,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();
@@ -725,6 +738,7 @@
prefs->SetInt64(kPrefsUpdateStateNextDataOffset, -1);
prefs->SetString(kPrefsUpdateStateSHA256Context, "");
prefs->SetString(kPrefsUpdateStateSignedSHA256Context, "");
+ prefs->SetString(kPrefsUpdateStateSignatureBlob, "");
prefs->SetInt64(kPrefsManifestMetadataSize, -1);
prefs->SetInt64(kPrefsResumedUpdateFailures, 0);
}
@@ -769,10 +783,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,
diff --git a/delta_performer_unittest.cc b/delta_performer_unittest.cc
index 9c926d5..95e41ad 100644
--- a/delta_performer_unittest.cc
+++ b/delta_performer_unittest.cc
@@ -1,4 +1,4 @@
-// Copyright (c) 2009 The Chromium OS Authors. All rights reserved.
+// Copyright (c) 2011 The Chromium OS Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
@@ -412,6 +412,8 @@
if (signature_test != kSignatureNone) {
EXPECT_CALL(prefs, SetString(kPrefsUpdateStateSignedSHA256Context, _))
.WillOnce(Return(true));
+ EXPECT_CALL(prefs, SetString(kPrefsUpdateStateSignatureBlob, _))
+ .WillOnce(Return(true));
}
// Update the A image in place.
diff --git a/prefs.cc b/prefs.cc
index 1bde4cd..94d0baa 100644
--- a/prefs.cc
+++ b/prefs.cc
@@ -1,4 +1,4 @@
-// Copyright (c) 2010 The Chromium OS Authors. All rights reserved.
+// Copyright (c) 2011 The Chromium OS Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
@@ -25,6 +25,7 @@
const char kPrefsUpdateStateNextDataOffset[] = "update-state-next-data-offset";
const char kPrefsUpdateStateNextOperation[] = "update-state-next-operation";
const char kPrefsUpdateStateSHA256Context[] = "update-state-sha-256-context";
+const char kPrefsUpdateStateSignatureBlob[] = "update-state-signature-blob";
const char kPrefsUpdateStateSignedSHA256Context[] =
"update-state-signed-sha-256-context";
diff --git a/prefs_interface.h b/prefs_interface.h
index 8d07dde..ddebb3b 100644
--- a/prefs_interface.h
+++ b/prefs_interface.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2010 The Chromium OS Authors. All rights reserved.
+// Copyright (c) 2011 The Chromium OS Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
@@ -19,6 +19,7 @@
extern const char kPrefsUpdateStateNextDataOffset[];
extern const char kPrefsUpdateStateNextOperation[];
extern const char kPrefsUpdateStateSHA256Context[];
+extern const char kPrefsUpdateStateSignatureBlob[];
extern const char kPrefsUpdateStateSignedSHA256Context[];
// The prefs interface allows access to a persistent preferences