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,
diff --git a/delta_performer_unittest.cc b/delta_performer_unittest.cc
index df73e56..3bdb2d8 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