Index: delta_performer.cc |
diff --git a/delta_performer.cc b/delta_performer.cc |
index 92d4733d02fbc2269f722e47fe206f42958f73a5..f807665cbacffe092759d0f0977d4ae37f206f86 100644 |
--- a/delta_performer.cc |
+++ b/delta_performer.cc |
@@ -190,12 +190,11 @@ ssize_t DeltaPerformer::Write(const void* bytes, size_t count) { |
} |
// Remove protobuf and header info from buffer_, so buffer_ contains |
// just data blobs |
- size_t metadata_size = strlen(kDeltaMagic) + kDeltaVersionLength + |
+ manifest_metadata_size_ = strlen(kDeltaMagic) + kDeltaVersionLength + |
kDeltaProtobufLengthLength + protobuf_length; |
- DiscardBufferHeadBytes(metadata_size, |
- true); // do_hash |
+ DiscardBufferHeadBytes(manifest_metadata_size_); |
LOG_IF(WARNING, !prefs_->SetInt64(kPrefsManifestMetadataSize, |
- metadata_size)) |
+ manifest_metadata_size_)) |
<< "Unable to save the manifest metadata size."; |
manifest_valid_ = true; |
block_size_ = manifest_.block_size(); |
@@ -281,8 +280,8 @@ bool DeltaPerformer::PerformReplaceOperation( |
CHECK_EQ(buffer_offset_, operation.data_offset()); |
CHECK_GE(buffer_.size(), operation.data_length()); |
- // Don't include the signature data blob in the hash. |
- bool do_hash = !ExtractSignatureMessage(operation); |
+ // Extract the signature message if it's in this operation. |
+ ExtractSignatureMessage(operation); |
DirectExtentWriter direct_writer; |
ZeroPadExtentWriter zero_pad_writer(&direct_writer); |
@@ -315,7 +314,7 @@ bool DeltaPerformer::PerformReplaceOperation( |
// Update buffer |
buffer_offset_ += operation.data_length(); |
- DiscardBufferHeadBytes(operation.data_length(), do_hash); |
+ DiscardBufferHeadBytes(operation.data_length()); |
return true; |
} |
@@ -458,8 +457,7 @@ bool DeltaPerformer::PerformBsdiffOperation( |
// Update buffer. |
buffer_offset_ += operation.data_length(); |
- DiscardBufferHeadBytes(operation.data_length(), |
- true); // do_hash |
+ DiscardBufferHeadBytes(operation.data_length()); |
return true; |
} |
@@ -479,20 +477,40 @@ bool DeltaPerformer::ExtractSignatureMessage( |
signatures_message_data_.begin(), |
buffer_.begin(), |
buffer_.begin() + manifest_.signatures_size()); |
+ // The hash of all data consumed so far should be verified against the signed |
+ // hash. |
+ signed_hash_context_ = hash_calculator_.GetContext(); |
+ LOG_IF(WARNING, !prefs_->SetString(kPrefsUpdateStateSignedSHA256Context, |
+ signed_hash_context_)) |
+ << "Unable to store the signed hash context."; |
LOG(INFO) << "Extracted signature data of size " |
<< manifest_.signatures_size() << " at " |
<< manifest_.signatures_offset(); |
return true; |
} |
-bool DeltaPerformer::VerifyPayload(const string& public_key_path) { |
+bool DeltaPerformer::VerifyPayload( |
+ const string& public_key_path, |
+ const std::string& update_check_response_hash, |
+ const uint64_t update_check_response_size) { |
string key_path = public_key_path; |
if (key_path.empty()) { |
key_path = kUpdatePayloadPublicKeyPath; |
} |
LOG(INFO) << "Verifying delta payload. Public key path: " << key_path; |
+ |
+ // Verifies the download hash. |
+ const string& download_hash_data = hash_calculator_.hash(); |
+ TEST_AND_RETURN_FALSE(!download_hash_data.empty()); |
+ TEST_AND_RETURN_FALSE(download_hash_data == update_check_response_hash); |
+ |
+ // Verifies the download size. |
+ TEST_AND_RETURN_FALSE(update_check_response_size == |
+ manifest_metadata_size_ + buffer_offset_); |
+ |
+ // Verifies the signed payload hash. |
if (!utils::FileExists(key_path.c_str())) { |
- LOG(WARNING) << "Not verifying delta payload due to missing public key."; |
+ LOG(WARNING) << "Not verifying signed delta payload -- missing public key."; |
return true; |
} |
TEST_AND_RETURN_FALSE(!signatures_message_data_.empty()); |
@@ -500,15 +518,19 @@ bool DeltaPerformer::VerifyPayload(const string& public_key_path) { |
TEST_AND_RETURN_FALSE(PayloadSigner::VerifySignature(signatures_message_data_, |
key_path, |
&signed_hash_data)); |
- const vector<char>& hash_data = hash_calculator_.raw_hash(); |
+ OmahaHashCalculator signed_hasher; |
+ // TODO(petkov): Make sure signed_hash_context_ is loaded when resuming an |
+ // update. |
+ TEST_AND_RETURN_FALSE(signed_hasher.SetContext(signed_hash_context_)); |
+ TEST_AND_RETURN_FALSE(signed_hasher.Finalize()); |
+ const vector<char>& hash_data = signed_hasher.raw_hash(); |
TEST_AND_RETURN_FALSE(!hash_data.empty()); |
- return hash_data == signed_hash_data; |
+ TEST_AND_RETURN_FALSE(hash_data == signed_hash_data); |
+ return true; |
} |
-void DeltaPerformer::DiscardBufferHeadBytes(size_t count, bool do_hash) { |
- if (do_hash) { |
- hash_calculator_.Update(&buffer_[0], count); |
- } |
+void DeltaPerformer::DiscardBufferHeadBytes(size_t count) { |
+ hash_calculator_.Update(&buffer_[0], count); |
buffer_.erase(buffer_.begin(), buffer_.begin() + count); |
} |
@@ -532,11 +554,10 @@ bool DeltaPerformer::CanResumeUpdate(PrefsInterface* prefs, |
&next_data_offset) && |
next_data_offset >= 0); |
- string signed_sha256_context; |
+ string sha256_context; |
TEST_AND_RETURN_FALSE( |
- prefs->GetString(kPrefsUpdateStateSignedSHA256Context, |
- &signed_sha256_context) && |
- !signed_sha256_context.empty()); |
+ prefs->GetString(kPrefsUpdateStateSHA256Context, &sha256_context) && |
+ !sha256_context.empty()); |
int64_t manifest_metadata_size = 0; |
TEST_AND_RETURN_FALSE(prefs->GetInt64(kPrefsManifestMetadataSize, |
@@ -557,7 +578,7 @@ bool DeltaPerformer::CheckpointUpdateProgress() { |
ResetUpdateProgress(prefs_); |
if (last_updated_buffer_offset_ != buffer_offset_) { |
TEST_AND_RETURN_FALSE( |
- prefs_->SetString(kPrefsUpdateStateSignedSHA256Context, |
+ prefs_->SetString(kPrefsUpdateStateSHA256Context, |
hash_calculator_.GetContext())); |
TEST_AND_RETURN_FALSE(prefs_->SetInt64(kPrefsUpdateStateNextDataOffset, |
buffer_offset_)); |