Add and enforce MinorVersion in Payload Manifest.

The MinorVersion is also set to 0 for Full payloads, and to 1 for
DeltaPayloads (for now). If the field is not set, it defaults to 0.

The default is important, since Full payloads will be generated without this
value set in production because older payload generators will be used for
Full payloads for some time to come.

If an unexpected MinorVersion is received, we will refuse to process it, and
send an kErrorCodeUnsupportedMinorPayloadVersion error result.

Add unittests to delta_performer_unittests to unittest the ValidateManifest
method (never individually tested before).

BUG=chromium:322564
TEST=Unittests

Change-Id: Icbd2ebeb739431905497e79edb4b99629c8d6f7f
Reviewed-on: https://chromium-review.googlesource.com/177823
Reviewed-by: Don Garrett <dgarrett@chromium.org>
Commit-Queue: Don Garrett <dgarrett@chromium.org>
Tested-by: Don Garrett <dgarrett@chromium.org>
diff --git a/delta_performer.cc b/delta_performer.cc
index eaa65d3..2af555c 100644
--- a/delta_performer.cc
+++ b/delta_performer.cc
@@ -42,6 +42,8 @@
 const uint64_t DeltaPerformer::kDeltaVersionSize = 8;
 const uint64_t DeltaPerformer::kDeltaManifestSizeSize = 8;
 const uint64_t DeltaPerformer::kSupportedMajorPayloadVersion = 1;
+const uint64_t DeltaPerformer::kSupportedMinorPayloadVersion = 1;
+const uint64_t DeltaPerformer::kFullPayloadMinorVersion = 0;
 
 const char DeltaPerformer::kUpdatePayloadPublicKeyPath[] =
     "/usr/share/update_engine/update-payload-key.pub.pem";
@@ -891,8 +893,8 @@
 }
 
 ErrorCode DeltaPerformer::ValidateManifest() {
-  // Ensure that a full update does not contain old partition hashes, which is
-  // indicative of a delta.
+  // Perform assorted checks to sanity check the manifest, make sure it
+  // matches data from other sources, and that it is a supported version.
   //
   // TODO(garnold) in general, the presence of an old partition hash should be
   // the sole indicator for a delta update, as we would generally like update
@@ -901,11 +903,28 @@
   // flow (making filesystem copying happen conditionally only *after*
   // downloading and parsing of the update manifest) we'll put it off for now.
   // See chromium-os:7597 for further discussion.
-  if (install_plan_->is_full_update &&
-      (manifest_.has_old_kernel_info() || manifest_.has_old_rootfs_info())) {
-    LOG(ERROR) << "Purported full payload contains old partition "
-                  "hash(es), aborting update";
-    return kErrorCodePayloadMismatchedType;
+  if (install_plan_->is_full_update) {
+    if (manifest_.has_old_kernel_info() || manifest_.has_old_rootfs_info()) {
+      LOG(ERROR) << "Purported full payload contains old partition "
+                    "hash(es), aborting update";
+      return kErrorCodePayloadMismatchedType;
+    }
+
+    if (manifest_.minor_version() != kFullPayloadMinorVersion) {
+      LOG(ERROR) << "Manifest contains minor version "
+                 << manifest_.minor_version()
+                 << ", but all full payloads should have version "
+                 << kFullPayloadMinorVersion << ".";
+      return kErrorCodeUnsupportedMinorPayloadVersion;
+    }
+  } else {
+    if (manifest_.minor_version() != kSupportedMinorPayloadVersion) {
+      LOG(ERROR) << "Manifest contains minor version "
+                 << manifest_.minor_version()
+                 << " not the supported "
+                 << kSupportedMinorPayloadVersion;
+      return kErrorCodeUnsupportedMinorPayloadVersion;
+    }
   }
 
   // TODO(garnold) we should be adding more and more manifest checks, such as