Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(2203)

Unified Diff: delta_performer.cc

Issue 3592008: AU: Verify delta payload signature and signed hash. (Closed) Base URL: ssh://git@gitrw.chromium.org:9222/update_engine.git
Patch Set: move /tmp files to /var/run Created 10 years, 2 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « delta_performer.h ('k') | delta_performer_unittest.cc » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: delta_performer.cc
diff --git a/delta_performer.cc b/delta_performer.cc
index 04273f34e732037e543e29b64254da8485def354..2436797210fa895738ee43d28d8f9fd7d4180c25 100644
--- a/delta_performer.cc
+++ b/delta_performer.cc
@@ -3,21 +3,24 @@
// found in the LICENSE file.
#include "update_engine/delta_performer.h"
+
#include <endian.h>
#include <errno.h>
+
#include <algorithm>
#include <cstring>
#include <string>
#include <vector>
+#include <base/scoped_ptr.h>
+#include <base/string_util.h>
#include <google/protobuf/repeated_field.h>
-#include "base/scoped_ptr.h"
-#include "base/string_util.h"
#include "update_engine/bzip_extent_writer.h"
#include "update_engine/delta_diff_generator.h"
#include "update_engine/extent_writer.h"
#include "update_engine/graph_types.h"
+#include "update_engine/payload_signer.h"
#include "update_engine/subprocess.h"
using std::min;
@@ -31,11 +34,8 @@ namespace {
const int kDeltaVersionLength = 8;
const int kDeltaProtobufLengthLength = 8;
-
-// Remove count bytes from the beginning of *buffer.
-void RemoveBufferHeadBytes(vector<char>* buffer, size_t count) {
- buffer->erase(buffer->begin(), buffer->begin() + count);
-}
+const char kUpdatePayloadPublicKeyPath[] =
+ "/usr/share/update_engine/update-payload-key.pub.pem";
// Converts extents to a human-readable string, for use by DumpUpdateProto().
string ExtentsToString(const RepeatedPtrField<Extent>& extents) {
@@ -136,6 +136,7 @@ int DeltaPerformer::Close() {
err = errno;
PLOG(ERROR) << "Unable to close rootfs fd:";
}
+ LOG_IF(ERROR, !hash_calculator_.Finalize()) << "Unable to finalize the hash.";
fd_ = -2; // Set so that isn't not valid AND calls to Open() will fail.
path_ = "";
return -err;
@@ -176,10 +177,10 @@ ssize_t DeltaPerformer::Write(const void* bytes, size_t count) {
}
// Remove protobuf and header info from buffer_, so buffer_ contains
// just data blobs
- RemoveBufferHeadBytes(&buffer_,
- strlen(kDeltaMagic) +
- kDeltaVersionLength +
- kDeltaProtobufLengthLength + protobuf_length);
+ DiscardBufferHeadBytes(strlen(kDeltaMagic) +
+ kDeltaVersionLength +
+ kDeltaProtobufLengthLength + protobuf_length,
+ true); // do_hash
manifest_valid_ = true;
block_size_ = manifest_.block_size();
}
@@ -239,7 +240,7 @@ bool DeltaPerformer::CanPerformInstallOperation(
LOG(ERROR) << "we threw away data it seems?";
return false;
}
-
+
return (operation.data_offset() + operation.data_length()) <=
(buffer_offset_ + buffer_.size());
}
@@ -256,11 +257,14 @@ bool DeltaPerformer::PerformReplaceOperation(
// the data we need should be exactly at the beginning of the buffer.
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);
+
DirectExtentWriter direct_writer;
ZeroPadExtentWriter zero_pad_writer(&direct_writer);
scoped_ptr<BzipExtentWriter> bzip_writer;
-
+
// Since bzip decompression is optional, we have a variable writer that will
// point to one of the ExtentWriter objects above.
ExtentWriter* writer = NULL;
@@ -285,10 +289,10 @@ bool DeltaPerformer::PerformReplaceOperation(
TEST_AND_RETURN_FALSE(writer->Init(fd, extents, block_size_));
TEST_AND_RETURN_FALSE(writer->Write(&buffer_[0], operation.data_length()));
TEST_AND_RETURN_FALSE(writer->End());
-
+
// Update buffer
buffer_offset_ += operation.data_length();
- RemoveBufferHeadBytes(&buffer_, operation.data_length());
+ DiscardBufferHeadBytes(operation.data_length(), do_hash);
return true;
}
@@ -431,8 +435,58 @@ bool DeltaPerformer::PerformBsdiffOperation(
// Update buffer.
buffer_offset_ += operation.data_length();
- RemoveBufferHeadBytes(&buffer_, operation.data_length());
+ DiscardBufferHeadBytes(operation.data_length(),
+ true); // do_hash
+ return true;
+}
+
+bool DeltaPerformer::ExtractSignatureMessage(
+ const DeltaArchiveManifest_InstallOperation& operation) {
+ if (operation.type() != DeltaArchiveManifest_InstallOperation_Type_REPLACE ||
+ !manifest_.has_signatures_offset() ||
+ manifest_.signatures_offset() != operation.data_offset()) {
+ return false;
+ }
+ TEST_AND_RETURN_FALSE(manifest_.has_signatures_size() &&
+ manifest_.signatures_size() == operation.data_length());
+ 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(),
+ buffer_.begin(),
+ buffer_.begin() + manifest_.signatures_size());
+ LOG(INFO) << "Extracted signature data of size "
+ << manifest_.signatures_size() << " at "
+ << manifest_.signatures_offset();
return true;
}
+bool DeltaPerformer::VerifyPayload(const string& public_key_path) {
+ string key_path = public_key_path;
+ if (key_path.empty()) {
+ key_path = kUpdatePayloadPublicKeyPath;
+ }
+ LOG(INFO) << "Verifying delta payload. Public key path: " << key_path;
+ if (!utils::FileExists(key_path.c_str())) {
+ LOG(WARNING) << "Not verifying delta payload due to missing public key.";
+ return true;
+ }
+ TEST_AND_RETURN_FALSE(!signatures_message_data_.empty());
+ vector<char> signed_hash_data;
+ TEST_AND_RETURN_FALSE(PayloadSigner::VerifySignature(signatures_message_data_,
+ key_path,
+ &signed_hash_data));
+ const vector<char>& hash_data = hash_calculator_.raw_hash();
+ TEST_AND_RETURN_FALSE(!hash_data.empty());
+ return hash_data == signed_hash_data;
+}
+
+void DeltaPerformer::DiscardBufferHeadBytes(size_t count, bool do_hash) {
+ if (do_hash) {
+ hash_calculator_.Update(&buffer_[0], count);
+ }
+ buffer_.erase(buffer_.begin(), buffer_.begin() + count);
+}
+
} // namespace chromeos_update_engine
« no previous file with comments | « delta_performer.h ('k') | delta_performer_unittest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698