diff options
author | Alex Deymo <deymo@chromium.org> | 2015-11-03 17:50:08 -0800 |
---|---|---|
committer | chrome-bot <chrome-bot@chromium.org> | 2015-11-11 14:56:47 -0800 |
commit | de38188abe87e2bfbaeb14c19833ae2667c16346 (patch) | |
tree | 3b56adcce204f5e7b77e925297e0db2055cf61d3 | |
parent | f8369fde766ef811a5a65fecf2b405d3ad59736b (diff) | |
download | chromite-de38188abe87e2bfbaeb14c19833ae2667c16346.tar.gz |
cros payload: --signatures flag shows the metadata signatures
The existing --signatures flag now dumps the metadata signatures
embedded in the payload.
BUG=None
TEST=Added unittests; manually check a signed payload.
Change-Id: I4e2eb5cafeabbafd40af31716840d405a79b1023
Reviewed-on: https://chromium-review.googlesource.com/310654
Commit-Ready: Alex Deymo <deymo@chromium.org>
Tested-by: Alex Deymo <deymo@chromium.org>
Reviewed-by: Sen Jiang <senj@chromium.org>
-rw-r--r-- | cli/cros/cros_payload.py | 41 | ||||
-rw-r--r-- | cli/cros/cros_payload_unittest.py | 64 |
2 files changed, 77 insertions, 28 deletions
diff --git a/cli/cros/cros_payload.py b/cli/cros/cros_payload.py index 61c41417a..9581b597d 100644 --- a/cli/cros/cros_payload.py +++ b/cli/cros/cros_payload.py @@ -8,7 +8,6 @@ from __future__ import print_function import itertools import os -import string import sys import textwrap @@ -37,7 +36,7 @@ def DisplayHexData(data, indent=0): ' '.join('%.2x' % ord(c) for c in chunk) + ' ' * (16 - len(chunk)) + ' | ' + - ''.join(c if c in string.printable else '.' for c in chunk)) + ''.join(c if 32 <= ord(c) and ord(c) < 127 else '.' for c in chunk)) @command.CommandDecorator('payload') @@ -101,22 +100,38 @@ Example: def _DisplaySignatures(self): """Show information about the signatures from the manifest.""" - manifest = self.payload.manifest - if not manifest.HasField('signatures_offset'): - print('No signatures stored in the payload') - return + header = self.payload.header + if header.metadata_signature_len: + offset = header.size + header.manifest_len + DisplayValue('Metadata signatures blob', + 'file_offset=%d (%d bytes)' % + (offset, header.metadata_signature_len)) + signatures_blob = self.payload.ReadDataBlob( + -header.metadata_signature_len, + header.metadata_signature_len) + self._DisplaySignaturesBlob('Metadata', signatures_blob) + else: + print('No metadata signatures stored in the payload') - signature_msg = 'offset=%d' % manifest.signatures_offset - if manifest.signatures_size: - signature_msg += ' (%d bytes)' % manifest.signatures_size - DisplayValue('Signature blob', signature_msg) - signatures_blob = self.payload.ReadDataBlob(manifest.signatures_offset, - manifest.signatures_size) + manifest = self.payload.manifest + if manifest.HasField('signatures_offset'): + signature_msg = 'blob_offset=%d' % manifest.signatures_offset + if manifest.signatures_size: + signature_msg += ' (%d bytes)' % manifest.signatures_size + DisplayValue('Payload signatures blob', signature_msg) + signatures_blob = self.payload.ReadDataBlob(manifest.signatures_offset, + manifest.signatures_size) + self._DisplaySignaturesBlob('Payload', signatures_blob) + else: + print('No payload signatures stored in the payload') + @staticmethod + def _DisplaySignaturesBlob(signature_name, signatures_blob): from dev.host.lib.update_payload import update_metadata_pb2 signatures = update_metadata_pb2.Signatures() signatures.ParseFromString(signatures_blob) - print('Payload signatures: (%d entries)' % len(signatures.signatures)) + print('%s signatures: (%d entries)' % + (signature_name, len(signatures.signatures))) for signature in signatures.signatures: print(' version=%s, hex_data: (%d bytes)' % (signature.version if signature.HasField('version') else None, diff --git a/cli/cros/cros_payload_unittest.py b/cli/cros/cros_payload_unittest.py index f8fd78d20..36f4749bd 100644 --- a/cli/cros/cros_payload_unittest.py +++ b/cli/cros/cros_payload_unittest.py @@ -93,19 +93,32 @@ class FakeManifest(object): """Fake HasField method based on the python members.""" return hasattr(self, field_name) and getattr(self, field_name) is not None +class FakeHeader(object): + """Fake payload header for testing.""" + + def __init__(self, version, manifest_len, metadata_signature_len): + self.version = version + self.manifest_len = manifest_len + self.metadata_signature_len = metadata_signature_len + + @property + def size(self): + return (20 if self.version == cros_payload.MAJOR_PAYLOAD_VERSION_CHROMEOS + else 24) + + class FakePayload(object): """Fake payload for testing.""" def __init__(self, major_version): - FakeHeader = collections.namedtuple('FakeHeader', - ['version', 'manifest_len']) - self._header = FakeHeader(major_version, 222) + self._header = FakeHeader(major_version, 222, 0) self.header = None self._manifest = FakeManifest(major_version) self.manifest = None self._blobs = {} - self._signatures = update_metadata_pb2.Signatures() + self._payload_signatures = update_metadata_pb2.Signatures() + self._metadata_signatures = update_metadata_pb2.Signatures() def Init(self): """Fake Init that sets header and manifest. @@ -126,15 +139,28 @@ class FakePayload(object): 'actual: %d)' % (len(blob), length)) return blob - def AddSignature(self, **kwargs): - new_signature = self._signatures.signatures.add() + @staticmethod + def _AddSignatureToProto(proto, **kwargs): + """Add a new Signature element to the passed proto.""" + new_signature = proto.signatures.add() for key, val in kwargs.iteritems(): setattr(new_signature, key, val) - blob = self._signatures.SerializeToString() + + def AddPayloadSignature(self, **kwargs): + self._AddSignatureToProto(self._payload_signatures, **kwargs) + blob = self._payload_signatures.SerializeToString() self._manifest.signatures_offset = 1234 self._manifest.signatures_size = len(blob) self._blobs[self._manifest.signatures_offset] = blob + def AddMetadataSignature(self, **kwargs): + self._AddSignatureToProto(self._metadata_signatures, **kwargs) + if self._header.metadata_signature_len: + del self._blobs[-self._header.metadata_signature_len] + blob = self._metadata_signatures.SerializeToString() + self._header.metadata_signature_len = len(blob) + self._blobs[-len(blob)] = blob + class PayloadCommandTest(cros_test_lib.MockOutputTestCase): """Test class for our PayloadCommand class.""" @@ -298,7 +324,8 @@ Number of operations: 1 Number of kernel ops: 1 Block size: 4096 Minor version: 4 -No signatures stored in the payload +No metadata signatures stored in the payload +No payload signatures stored in the payload """ self.assertEquals(stdout, expected_out) @@ -307,22 +334,29 @@ No signatures stored in the payload """Verify that the --signatures option shows the present signatures.""" payload_cmd = cros_payload.PayloadCommand( FakeOption(action='show', signatures=True)) - payload = FakePayload(cros_payload.MAJOR_PAYLOAD_VERSION_CHROMEOS) - payload.AddSignature(version=1, data='12345678abcdefgh\x00\x01\x02\x03') - payload.AddSignature(data='I am a signature so access is yes.') + payload = FakePayload(cros_payload.MAJOR_PAYLOAD_VERSION_BRILLO) + payload.AddPayloadSignature(version=1, + data='12345678abcdefgh\x00\x01\x02\x03') + payload.AddPayloadSignature(data='I am a signature so access is yes.') + payload.AddMetadataSignature(data='\x00\x0a\x0c') self.PatchObject(update_payload, 'Payload', return_value=payload) with self.OutputCapturer() as output: payload_cmd.Run() stdout = output.GetStdout() - expected_out = """Payload version: 1 + expected_out = """Payload version: 2 Manifest length: 222 -Number of operations: 1 -Number of kernel ops: 1 +Number of partitions: 2 + Number of "rootfs" ops: 1 + Number of "kernel" ops: 1 Block size: 4096 Minor version: 4 -Signature blob: offset=1234 (64 bytes) +Metadata signatures blob: file_offset=246 (7 bytes) +Metadata signatures: (1 entries) + version=None, hex_data: (3 bytes) + 00 0a 0c | ... +Payload signatures blob: blob_offset=1234 (64 bytes) Payload signatures: (2 entries) version=1, hex_data: (20 bytes) 31 32 33 34 35 36 37 38 61 62 63 64 65 66 67 68 | 12345678abcdefgh |