Change log leaf encoding am: b611df2423 am: d67b07f1c6
Change-Id: I0bfccd26e2df669f793896d1f7f51bfebd3ebee0
diff --git a/Android.bp b/Android.bp
index 19ea97e..6a80a62 100644
--- a/Android.bp
+++ b/Android.bp
@@ -94,7 +94,6 @@
name: "aftl_proto",
srcs: [
"proto/api.proto",
- "proto/aftl.proto",
"proto/crypto/sigpb/sigpb.proto",
"proto/crypto/keyspb/keyspb.proto",
"proto/trillian.proto",
diff --git a/aftltool.py b/aftltool.py
index 192ad9b..613e83b 100755
--- a/aftltool.py
+++ b/aftltool.py
@@ -24,10 +24,11 @@
#
"""Command-line tool for AFTL support for Android Verified Boot images."""
+import abc
import argparse
-import base64
+import enum
import hashlib
-import json
+import io
import multiprocessing
import os
import queue
@@ -46,9 +47,7 @@
# pylint: disable=wrong-import-position,import-error
import avbtool
-import aftl_pb2
import api_pb2
-from crypto.sigpb import sigpb_pb2
# pylint: enable=wrong-import-position,import-error
@@ -350,14 +349,16 @@
log_url_size: Length of the string representing the transparency log URL.
leaf_index: Leaf index in the transparency log representing this entry.
log_root_descriptor_size: Size of the transparency log's SignedLogRoot.
- fw_info_leaf_size: Size of the FirmwareInfo leaf passed to the log.
+ annotation_leaf_size: Size of the SignedVBMetaPrimaryAnnotationLeaf passed
+ to the log.
log_root_sig_size: Size in bytes of the log_root_signature
proof_hash_count: Number of hashes comprising the inclusion proof.
inc_proof_size: The total size of the inclusion proof, in bytes.
log_url: The URL for the transparency log that generated this inclusion
proof.
log_root_descriptor: The data comprising the signed tree head structure.
- fw_info_leaf: The data comprising the FirmwareInfo leaf.
+ annotation_leaf: The data comprising the SignedVBMetaPrimaryAnnotationLeaf
+ leaf.
log_root_signature: The data comprising the log root signature.
proofs: The hashes comprising the inclusion proof.
@@ -370,9 +371,8 @@
'H' # log root signature size
'B' # number of hashes in the inclusion proof
'L') # size of the inclusion proof in bytes
- # These are used to capture the log_url, log_root_descriptor,
- # fw_info leaf, log root signature, and the proofs elements for the
- # encode function.
+ # This header is followed by the log_url, log_root_descriptor,
+ # annotation leaf, log root signature, and the proofs elements.
def __init__(self, data=None):
"""Initializes a new ICP entry object.
@@ -391,7 +391,7 @@
(self._log_url_size_expected,
self.leaf_index,
self._log_root_descriptor_size_expected,
- self._fw_info_leaf_size_expected,
+ self._annotation_leaf_size_expected,
self._log_root_sig_size_expected,
self._proof_hash_count_expected,
self._inc_proof_size_expected) = struct.unpack(self.FORMAT_STRING,
@@ -401,18 +401,20 @@
expected_format_string = '{}s{}s{}s{}s{}s'.format(
self._log_url_size_expected,
self._log_root_descriptor_size_expected,
- self._fw_info_leaf_size_expected,
+ self._annotation_leaf_size_expected,
self._log_root_sig_size_expected,
self._inc_proof_size_expected)
- (log_url, log_root_descriptor_bytes, fw_info_leaf_bytes,
+ (log_url, log_root_descriptor_bytes, annotation_leaf_bytes,
self.log_root_signature, proof_bytes) = struct.unpack(
expected_format_string, data[self.SIZE:self.get_expected_size()])
self.log_url = log_url.decode('ascii')
self.log_root_descriptor = TrillianLogRootDescriptor(
log_root_descriptor_bytes)
- self.fw_info_leaf = FirmwareInfoLeaf(fw_info_leaf_bytes)
+
+ self.annotation_leaf = SignedVBMetaPrimaryAnnotationLeaf.parse(
+ annotation_leaf_bytes)
self.proofs = []
if self._proof_hash_count_expected > 0:
@@ -427,7 +429,7 @@
self.leaf_index = 0
self.log_url = ''
self.log_root_descriptor = TrillianLogRootDescriptor()
- self.fw_info_leaf = FirmwareInfoLeaf()
+ self.annotation_leaf = SignedVBMetaPrimaryAnnotationLeaf()
self.log_root_signature = b''
self.proofs = []
if not self.is_valid():
@@ -448,11 +450,11 @@
return self._log_root_descriptor_size_expected
@property
- def fw_info_leaf_size(self):
- """Gets the size of the fw_info_leaf attribute."""
- if hasattr(self, 'fw_info_leaf'):
- return self.fw_info_leaf.get_expected_size()
- return self._fw_info_leaf_size_expected
+ def annotation_leaf_size(self):
+ """Gets the size of the annotation_leaf attribute."""
+ if hasattr(self, 'annotation_leaf'):
+ return self.annotation_leaf.get_expected_size()
+ return self._annotation_leaf_size_expected
@property
def log_root_sig_size(self):
@@ -490,7 +492,7 @@
if not transparency_log_pub_key:
return False
- leaf_hash = rfc6962_hash_leaf(self.fw_info_leaf.encode())
+ leaf_hash = rfc6962_hash_leaf(self.annotation_leaf.encode())
calc_root = root_from_icp(self.leaf_index,
self.log_root_descriptor.tree_size,
self.proofs,
@@ -513,7 +515,7 @@
Returns:
True if the inclusion proof validates and the vbmeta hash of the given
- VBMeta image matches the one in the fw_info_leaf; otherwise False.
+ VBMeta image matches the one in the annotation leaf; otherwise False.
"""
if not vbmeta_image:
return False
@@ -524,13 +526,13 @@
# Validates the inclusion proof and then compare the calculated vbmeta_hash
# against the one in the inclusion proof.
return (self.verify_icp(transparency_log_pub_key)
- and self.fw_info_leaf.vbmeta_hash == vbmeta_hash)
+ and self.annotation_leaf.annotation.vbmeta_hash == vbmeta_hash)
def encode(self):
- """Serializes the header |SIZE| and data to a bytearray().
+ """Serializes the header |SIZE| and data to bytes.
Returns:
- A bytearray() with the encoded header.
+ bytes with the encoded header.
Raises:
AftlError: If invalid entry structure.
@@ -543,7 +545,7 @@
self.FORMAT_STRING,
self.log_url_size,
self.log_root_descriptor_size,
- self.fw_info_leaf_size,
+ self.annotation_leaf_size,
self.log_root_sig_size,
self.inc_proof_size)
@@ -552,30 +554,31 @@
return struct.pack(expected_format_string,
self.log_url_size, self.leaf_index,
- self.log_root_descriptor_size, self.fw_info_leaf_size,
+ self.log_root_descriptor_size, self.annotation_leaf_size,
self.log_root_sig_size, self.proof_hash_count,
self.inc_proof_size, self.log_url.encode('ascii'),
self.log_root_descriptor.encode(),
- self.fw_info_leaf.encode(),
+ self.annotation_leaf.encode(),
self.log_root_signature,
proof_bytes)
- def translate_response(self, log_url, afi_response):
- """Translates an AddFirmwareInfoResponse object to an AftlIcpEntry.
+ def translate_response(self, log_url, avbm_response):
+ """Translates an AddVBMetaResponse object to an AftlIcpEntry.
Arguments:
log_url: String representing the transparency log URL.
- afi_response: The AddFirmwareResponse object to translate.
+ avbm_response: The AddVBMetaResponse object to translate.
"""
self.log_url = log_url
- # Deserializes from AddFirmwareInfoResponse.
- self.leaf_index = afi_response.fw_info_proof.proof.leaf_index
- self.log_root_descriptor = TrillianLogRootDescriptor(
- afi_response.fw_info_proof.sth.log_root)
- self.fw_info_leaf = FirmwareInfoLeaf(afi_response.fw_info_leaf)
- self.log_root_signature = afi_response.fw_info_proof.sth.log_root_signature
- self.proofs = afi_response.fw_info_proof.proof.hashes
+ # Deserializes from AddVBMetaResponse.
+ proof = avbm_response.annotation_proof
+ self.leaf_index = proof.proof.leaf_index
+ self.log_root_descriptor = TrillianLogRootDescriptor(proof.sth.log_root)
+ self.annotation_leaf = SignedVBMetaPrimaryAnnotationLeaf.parse(
+ avbm_response.annotation_leaf)
+ self.log_root_signature = proof.sth.log_root_signature
+ self.proofs = proof.proof.hashes
def get_expected_size(self):
"""Gets the expected size of the full entry out of the header.
@@ -584,7 +587,7 @@
The expected size of the AftlIcpEntry from the header.
"""
return (self.SIZE + self.log_url_size + self.log_root_descriptor_size +
- self.fw_info_leaf_size + self.log_root_sig_size +
+ self.annotation_leaf_size + self.log_root_sig_size +
self.inc_proof_size)
def is_valid(self):
@@ -604,9 +607,9 @@
sys.stderr.write('ICP entry: invalid TrillianLogRootDescriptor.\n')
return False
- if (not self.fw_info_leaf or
- not isinstance(self.fw_info_leaf, FirmwareInfoLeaf)):
- sys.stderr.write('ICP entry: invalid FirmwareInfo.\n')
+ if (not self.annotation_leaf or
+ not isinstance(self.annotation_leaf, Leaf)):
+ sys.stderr.write('ICP entry: invalid Leaf.\n')
return False
return True
@@ -626,7 +629,7 @@
o.write(' ' * 29)
o.write('{}\n'.format(proof_hash.hex()))
self.log_root_descriptor.print_desc(o)
- self.fw_info_leaf.print_desc(o)
+ self.annotation_leaf.print_desc(o)
class TrillianLogRootDescriptor(object):
@@ -793,139 +796,268 @@
o.write(fmt.format(i, 'Metadata:', self.metadata.hex()))
-class FirmwareInfoLeaf(object):
- """A class representing the FirmwareInfo leaf.
+def tls_decode_bytes(byte_size, stream):
+ """Decodes a variable-length vector.
- AFTL returns the fw_info_leaf as a JSON blob and this class is able to
- parse the blog and provide necessary attributes needed for validation.
+ In the TLS presentation language, a variable-length vector is a pair
+ (size, value). |size| describes the size of the |value| to read
+ in bytes. All values are encoded in big-endian.
+ See https://tools.ietf.org/html/rfc8446#section-3 for more details.
+
+ Arguments:
+ byte_size: A format character as described in the struct module
+ which describes the expected length of the size. For
+ instance, "B", "H", "L" or "Q".
+ stream: a BytesIO which contains the value to decode.
+
+ Returns:
+ A bytes containing the value decoded.
+
+ Raises:
+ AftlError: If |byte_size| is not a known format character, or if not
+ enough data is available to decode the size or the value.
+ """
+ byte_size_format = "!" + byte_size
+ try:
+ byte_size_length = struct.calcsize(byte_size_format)
+ except struct.error:
+ raise AftlError("Invalid byte_size character: {}. It must be a "
+ "format supported by struct.".format(byte_size))
+ try:
+ value_size = struct.unpack(byte_size_format,
+ stream.read(byte_size_length))[0]
+ except struct.error:
+ raise AftlError("Not enough data to read size: {}".format(byte_size))
+ value = stream.read(value_size)
+ if value_size != len(value):
+ raise AftlError("Not enough data to read value: "
+ "{} != {}".format(value_size, len(value)))
+ return value
+
+def tls_encode_bytes(byte_size, value, stream):
+ """Encodes a variable-length vector.
+
+ In the TLS presentation language, a variable-length vector is a pair
+ (size, value). |size| describes the size of the |value| to read
+ in bytes. All values are encoded in big-endian.
+ See https://tools.ietf.org/html/rfc8446#section-3 for more details.
+
+ Arguments:
+ byte_size: A format character as described in the struct module
+ which describes the expected length of the size. For
+ instance, "B", "H", "L" or "Q".
+ value: the value to encode. The length of |value| must be
+ representable with |byte_size|.
+ stream: a BytesIO to which the value is encoded to.
+
+ Raises:
+ AftlError: If |byte_size| is not a known format character, or if
+ |value|'s length cannot be represent with |byte_size|.
+ """
+ byte_size_format = "!" + byte_size
+ try:
+ stream.write(struct.pack(byte_size_format, len(value)))
+ except struct.error:
+ # Whether byte_size is invalid or not large enough to represent value,
+ # struct returns an struct.error exception. Instead of matching on the
+ # exception message, capture both cases in a generic message.
+ raise AftlError("Invalid byte_size to store {} bytes".format(len(value)))
+ stream.write(value)
+
+class HashAlgorithm(enum.Enum):
+ SHA256 = 0
+
+class SignatureAlgorithm(enum.Enum):
+ RSA = 0
+ ECDSA = 1
+
+class Signature(object):
+ """Represents a signature of some data.
+
+ It is usually made using a manufacturer key and used to sign part of a leaf
+ that belongs to the transparency log. The encoding of this structure must
+ match the server expectation.
Attributes:
- vbmeta_hash: This is the SHA256 hash of vbmeta.
- version_incremental: Subcomponent of the build fingerprint as defined at
- https://source.android.com/compatibility/android-cdd#3_2_2_build_parameters.
- For example, a Pixel device with the following build fingerprint
- google/crosshatch/crosshatch:9/PQ3A.190605.003/5524043:user/release-keys,
- would have 5524043 for the version incremental.
- platform_key: Public key of the platform. This is the same key used to sign
- the vbmeta.
- manufacturer_key_hash: SHA256 of the manufacturer public key (DER-encoded,
- x509 subjectPublicKeyInfo format). The public key MUST already be in the
- list of root keys known and trusted by the AFTL.
- description: Free form description field. It can be used to annotate this
- message with further context on the build (e.g., carrier specific build).
+ hash_algorithm: the HashAlgorithm used for the signature.
+ signature_algorithm: the SignatureAlgorithm used.
+ signature: the raw signature in bytes.
"""
+ FORMAT_STRING = ('!B' # Hash algorithm
+ 'B' # Signing algorithm
+ )
+ # Followed by the raw signature, encoded as a TLS variable-length vector
+ # which size is represented using 2 bytes.
- def __init__(self, data=None):
- """Initializes a new FirmwareInfoLeaf descriptor."""
- if data:
- # We have to preserve the original fw_info_leaf bytes in order to preserve
- # hash equivalence with what is stored in the Trillian log and matches up
- # with the proofs.
- self._fw_info_leaf_bytes = data
+ def __init__(self, hash_algorithm=HashAlgorithm.SHA256,
+ signature_algorithm=SignatureAlgorithm.RSA, signature=b''):
+ self.hash_algorithm = hash_algorithm
+ self.signature_algorithm = signature_algorithm
+ self.signature = signature
- # Deserialize the JSON blob and keep only the FirmwareInfo parts.
- try:
- fw_info_leaf = json.loads(self._fw_info_leaf_bytes)
- self._fw_info_leaf_dict = (
- fw_info_leaf['Value']['FwInfo']['info']['info'])
- except (ValueError, KeyError) as e:
- raise AftlError('Invalid structure for FirmwareInfoLeaf: {}'.format(e))
- else:
- self._fw_info_leaf_bytes = b''
- self._fw_info_leaf_dict = dict()
-
- if not self.is_valid():
- raise AftlError('Invalid structure for FirmwareInfoLeaf.')
-
- @property
- def vbmeta_hash(self):
- """Gets the vbmeta_hash attribute."""
- return self._lookup_base64_attribute('vbmeta_hash')
-
- @property
- def version_incremental(self):
- """Gets the version_incremental attribute."""
- return self._fw_info_leaf_dict.get('version_incremental')
-
- @property
- def platform_key(self):
- """Gets the platform key attribute."""
- return self._lookup_base64_attribute('platform_key')
-
- @property
- def manufacturer_key_hash(self):
- """Gets the manufacturer_key_hash attribute."""
- return self._lookup_base64_attribute('manufacturer_key_hash')
-
- @property
- def description(self):
- """Gets the description attribute."""
- return self._fw_info_leaf_dict.get('description')
-
- def _lookup_base64_attribute(self, key):
- """Looks up an attribute that is Base64 encoded and decodes it.
+ @classmethod
+ def parse(cls, stream):
+ """Parses a TLS-encoded structure and returns a new Signature.
Arguments:
- key: The name of the attribute to look up.
+ stream: a BytesIO to read the signature from.
Returns:
- The attribute value or None if not defined.
+ A new Signature object.
+
+ Raises:
+ AftlError: If the hash algorithm or signature algorithm value is
+ unknown; or if the decoding failed.
"""
- result = self._fw_info_leaf_dict.get(key)
- if result:
- result = base64.b64decode(result)
- return result
+ data_length = struct.calcsize(cls.FORMAT_STRING)
+ (hash_algorithm, signature_algorithm) = struct.unpack(
+ cls.FORMAT_STRING, stream.read(data_length))
+ try:
+ hash_algorithm = HashAlgorithm(hash_algorithm)
+ except ValueError:
+ raise AftlError('unknown hash algorithm: {}'.format(hash_algorithm))
+ try:
+ signature_algorithm = SignatureAlgorithm(signature_algorithm)
+ except ValueError:
+ raise AftlError('unknown signature algorithm: {}'.format(
+ signature_algorithm))
+ signature = tls_decode_bytes('H', stream)
+ return Signature(hash_algorithm, signature_algorithm, signature)
def get_expected_size(self):
- """Gets the expected size of the JSON-serialized FirmwareInfoLeaf.
+ """Returns the size of the encoded Signature."""
+ return struct.calcsize(self.FORMAT_STRING) + \
+ struct.calcsize('H') + len(self.signature)
+
+ def encode(self, stream):
+ """Encodes the Signature.
+
+ Arguments:
+ stream: a BytesIO to which the signature is written.
+ """
+ stream.write(struct.pack(self.FORMAT_STRING, self.hash_algorithm.value,
+ self.signature_algorithm.value))
+ tls_encode_bytes('H', self.signature, stream)
+
+class VBMetaPrimaryAnnotation(object):
+ """An annotation that contains metadata about a VBMeta image.
+
+ Attributes:
+ vbmeta_hash: the SHA256 of the VBMeta it references.
+ version_incremental: the version incremental of the build, as string.
+ manufacturer_key_hash: the hash of the manufacturer key that will
+ sign this annotation.
+ description: a free-form field.
+ """
+
+ def __init__(self, vbmeta_hash=b'', version_incremental='',
+ manufacturer_key_hash=b'', description=''):
+ """Default constructor."""
+ self.vbmeta_hash = vbmeta_hash
+ self.version_incremental = version_incremental
+ self.manufacturer_key_hash = manufacturer_key_hash
+ self.description = description
+
+ @classmethod
+ def parse(cls, stream):
+ """Parses a VBMetaPrimaryAnnotation from data.
+
+ Arguments:
+ stream: an io.BytesIO to decode the annotation from.
Returns:
- The expected size of the FirmwareInfo leaf in byte or 0 if not initalized.
- """
- if not self._fw_info_leaf_bytes:
- return 0
- return len(self._fw_info_leaf_bytes)
+ A new VBMetaPrimaryAnnotation.
- def encode(self):
- """Serializes the FirmwareInfoLeaf.
+ Raises:
+ AftlError: If an error occured while parsing the annotation.
+ """
+ vbmeta_hash = tls_decode_bytes("B", stream)
+ version_incremental = tls_decode_bytes("B", stream)
+ try:
+ version_incremental = version_incremental.decode("ascii")
+ except UnicodeError:
+ raise AftlError('Failed to convert version incremental to an ASCII'
+ 'string')
+ manufacturer_key_hash = tls_decode_bytes("B", stream)
+ description = tls_decode_bytes("H", stream)
+ try:
+ description = description.decode("utf-8")
+ except UnicodeError:
+ raise AftlError('Failed to convert description to an UTF-8 string')
+ return cls(vbmeta_hash, version_incremental, manufacturer_key_hash,
+ description)
+
+ def sign(self, manufacturer_key_path, signing_helper=None,
+ signing_helper_with_files=None):
+ """Signs the annotation.
+
+ Arguments:
+ manufacturer_key_path: Path to key used to sign messages sent to the
+ transparency log servers.
+ signing_helper: Program which signs a hash and returns a signature.
+ signing_helper_with_files: Same as signing_helper but uses files instead.
Returns:
- A bytearray() with the JSON-serialized FirmwareInfoLeaf.
- """
- return self._fw_info_leaf_bytes
+ A new SignedVBMetaPrimaryAnnotation.
- def is_valid(self):
- """Ensures that values in the descritor are sane.
-
- Returns:
- True if the values are sane; otherwise False.
+ Raises:
+ AftlError: If an error occured while signing the annotation.
"""
- # Checks that the decode fw_info_leaf at max contains values defined in the
- # FirmwareInfo proto buf.
- expected_fields = set(aftl_pb2.FirmwareInfo()
- .DESCRIPTOR.fields_by_name.keys())
- actual_fields = set(self._fw_info_leaf_dict.keys())
- if actual_fields.issubset(expected_fields):
- return True
- return False
+ # AFTL supports SHA256_RSA4096 for now, more will be available.
+ algorithm_name = 'SHA256_RSA4096'
+ encoded_leaf = io.BytesIO()
+ self.encode(encoded_leaf)
+ try:
+ rsa_key = avbtool.RSAPublicKey(manufacturer_key_path)
+ raw_signature = rsa_key.sign(algorithm_name, encoded_leaf.getvalue(),
+ signing_helper, signing_helper_with_files)
+ except avbtool.AvbError as e:
+ raise AftlError('Failed to sign VBMetaPrimaryAnnotation with '
+ '--manufacturer_key: {}'.format(e))
+ signature = Signature(hash_algorithm=HashAlgorithm.SHA256,
+ signature_algorithm=SignatureAlgorithm.RSA,
+ signature=raw_signature)
+ return SignedVBMetaPrimaryAnnotation(signature=signature, annotation=self)
+
+ def encode(self, stream):
+ """Encodes the VBMetaPrimaryAnnotation.
+
+ Arguments:
+ stream: a BytesIO to which the signature is written.
+
+ Raises:
+ AftlError: If the encoding failed.
+ """
+ tls_encode_bytes("B", self.vbmeta_hash, stream)
+ try:
+ tls_encode_bytes("B", self.version_incremental.encode("ascii"), stream)
+ except UnicodeError:
+ raise AftlError('Unable to encode version incremental to ASCII')
+ tls_encode_bytes("B", self.manufacturer_key_hash, stream)
+ try:
+ tls_encode_bytes("H", self.description.encode("utf-8"), stream)
+ except UnicodeError:
+ raise AftlError('Unable to encode description to UTF-8')
+
+ def get_expected_size(self):
+ """Returns the size of the encoded annotation."""
+ b = io.BytesIO()
+ self.encode(b)
+ return len(b.getvalue())
def print_desc(self, o):
- """Print the FirmwareInfoLeaf.
+ """Print the VBMetaPrimaryAnnotation.
Arguments:
o: The object to write the output to.
"""
- o.write(' Firmware Info Leaf:\n')
- # The order of the fields is based on the definition in
- # proto.aftl_pb2.FirmwareInfo.
- i = ' ' * 6
+ o.write(' VBMeta Primary Annotation:\n')
+ i = ' ' * 8
fmt = '{}{:23}{}\n'
if self.vbmeta_hash:
o.write(fmt.format(i, 'VBMeta hash:', self.vbmeta_hash.hex()))
if self.version_incremental:
o.write(fmt.format(i, 'Version incremental:', self.version_incremental))
- if self.platform_key:
- o.write(fmt.format(i, 'Platform key:', self.platform_key))
if self.manufacturer_key_hash:
o.write(fmt.format(i, 'Manufacturer key hash:',
self.manufacturer_key_hash.hex()))
@@ -933,6 +1065,244 @@
o.write(fmt.format(i, 'Description:', self.description))
+class SignedVBMetaPrimaryAnnotation(object):
+ """A Signed VBMetaPrimaryAnnotation.
+
+ Attributes:
+ signature: a Signature.
+ annotation: a VBMetaPrimaryAnnotation.
+ """
+
+ def __init__(self, signature=None, annotation=None):
+ """Default constructor."""
+ if not signature:
+ signature = Signature()
+ self.signature = signature
+ if not annotation:
+ annotation = VBMetaPrimaryAnnotation()
+ self.annotation = annotation
+
+ @classmethod
+ def parse(cls, stream):
+ """Parses a signed annotation."""
+ signature = Signature.parse(stream)
+ annotation = VBMetaPrimaryAnnotation.parse(stream)
+ return cls(signature, annotation)
+
+ def get_expected_size(self):
+ """Returns the size of the encoded signed annotation."""
+ return self.signature.get_expected_size() + \
+ self.annotation.get_expected_size()
+
+ def encode(self, stream):
+ """Encodes the SignedVBMetaPrimaryAnnotation.
+
+ Arguments:
+ stream: a BytesIO to which the object is written.
+
+ Raises:
+ AftlError: If the encoding failed.
+ """
+ self.signature.encode(stream)
+ self.annotation.encode(stream)
+
+ def print_desc(self, o):
+ """Prints the annotation.
+
+ Arguments:
+ o: The object to write the output to.
+ """
+ self.annotation.print_desc(o)
+
+class Leaf(abc.ABC):
+ """An abstract class to represent the leaves in the transparency log."""
+ FORMAT_STRING = ('!B' # Version
+ 'Q' # Timestamp
+ 'B' # LeafType
+ )
+
+ class LeafType(enum.Enum):
+ VBMetaType = 0
+ SignedVBMetaPrimaryAnnotationType = 1
+
+ def __init__(self, version=1, timestamp=0, leaf_type=LeafType.VBMetaType):
+ """Build a new leaf."""
+ self.version = version
+ self.timestamp = timestamp
+ self.leaf_type = leaf_type
+
+ @classmethod
+ def _parse_header(cls, stream):
+ """Parses the header of a leaf.
+
+ This is called with the parse method of the subclasses.
+
+ Arguments:
+ stream: a BytesIO to read the header from.
+
+ Returns:
+ A tuple (version, timestamp, leaf_type).
+
+ Raises:
+ AftlError: If the header cannot be decoded; or if the leaf type is
+ unknown.
+ """
+ data_length = struct.calcsize(cls.FORMAT_STRING)
+ try:
+ (version, timestamp, leaf_type) = struct.unpack(
+ cls.FORMAT_STRING, stream.read(data_length))
+ except struct.error:
+ raise AftlError("Not enough data to parse leaf header")
+ try:
+ leaf_type = cls.LeafType(leaf_type)
+ except ValueError:
+ raise AftlError("Unknown leaf type: {}".format(leaf_type))
+ return version, timestamp, leaf_type
+
+ @classmethod
+ @abc.abstractmethod
+ def parse(cls, data):
+ """Parses a leaf and returned a new object.
+
+ This abstract method must be implemented by the subclass. It may use
+ _parse_header to parse the common fields.
+
+ Arguments:
+ data: a bytes-like object.
+
+ Returns:
+ An object of the type of the particular subclass.
+
+ Raises:
+ AftlError: If the leaf type is incorrect; or if the decoding failed.
+ """
+
+ @abc.abstractmethod
+ def encode(self):
+ """Encodes a leaf.
+
+ This abstract method must be implemented by the subclass. It may use
+ _encode_header to encode the common fields.
+
+ Returns:
+ A bytes with the encoded leaf.
+
+ Raises:
+ AftlError: If the encoding failed.
+ """
+
+ def _get_expected_header_size(self):
+ """Returns the size of the leaf header."""
+ return struct.calcsize(self.FORMAT_STRING)
+
+ def _encode_header(self, stream):
+ """Encodes the header of the leaf.
+
+ This method is called by the encode method in the subclass.
+
+ Arguments:
+ stream: a BytesIO to which the object is written.
+
+ Raises:
+ AftlError: If the encoding failed.
+ """
+ try:
+ stream.write(struct.pack(self.FORMAT_STRING, self.version, self.timestamp,
+ self.leaf_type.value))
+ except struct.error:
+ raise AftlError('Unable to encode the leaf header')
+
+ def print_desc(self, o):
+ """Prints the leaf header.
+
+ Arguments:
+ o: The object to write the output to.
+ """
+ i = ' ' * 6
+ fmt = '{}{:23}{}\n'
+ o.write(fmt.format(i, 'Version:', self.version))
+ o.write(fmt.format(i, 'Timestamp:', self.timestamp))
+ o.write(fmt.format(i, 'Type:', self.leaf_type))
+
+
+class SignedVBMetaPrimaryAnnotationLeaf(Leaf):
+ """A Signed VBMetaPrimaryAnnotation leaf."""
+
+ def __init__(self, version=1, timestamp=0,
+ signed_vbmeta_primary_annotation=None):
+ """Builds a new Signed VBMeta Primary Annotation leaf."""
+ super(SignedVBMetaPrimaryAnnotationLeaf, self).__init__(
+ version=version, timestamp=timestamp,
+ leaf_type=self.LeafType.SignedVBMetaPrimaryAnnotationType)
+ if not signed_vbmeta_primary_annotation:
+ signed_vbmeta_primary_annotation = SignedVBMetaPrimaryAnnotation()
+ self.signed_vbmeta_primary_annotation = signed_vbmeta_primary_annotation
+
+ @property
+ def annotation(self):
+ """Returns the VBMetaPrimaryAnnotation contained in the leaf."""
+ return self.signed_vbmeta_primary_annotation.annotation
+
+ @property
+ def signature(self):
+ """Returns the Signature contained in the leaf."""
+ return self.signed_vbmeta_primary_annotation.signature
+
+ @classmethod
+ def parse(cls, data):
+ """Parses an encoded contained in data.
+
+ Arguments:
+ data: a bytes-like object.
+
+ Returns:
+ A SignedVBMetaPrimaryAnnotationLeaf.
+
+ Raises:
+ AftlError if the leaf type is incorrect; or if the decoding failed.
+ """
+ encoded_leaf = io.BytesIO(data)
+ version, timestamp, leaf_type = Leaf._parse_header(encoded_leaf)
+ if leaf_type != Leaf.LeafType.SignedVBMetaPrimaryAnnotationType:
+ raise AftlError("Incorrect leaf type")
+ signed_annotation = SignedVBMetaPrimaryAnnotation.parse(encoded_leaf)
+ return cls(version=version, timestamp=timestamp,
+ signed_vbmeta_primary_annotation=signed_annotation)
+
+ def get_expected_size(self):
+ """Returns the size of the leaf."""
+ size = self._get_expected_header_size()
+ if self.signed_vbmeta_primary_annotation:
+ size += self.signed_vbmeta_primary_annotation.get_expected_size()
+ return size
+
+ def encode(self):
+ """Encodes the leaf.
+
+ Returns:
+ bytes which contains the encoded leaf.
+
+ Raises:
+ AftlError: If the encoding failed.
+ """
+ stream = io.BytesIO()
+ self._encode_header(stream)
+ self.signed_vbmeta_primary_annotation.encode(stream)
+ return stream.getvalue()
+
+ def print_desc(self, o):
+ """Prints the leaf.
+
+ Arguments:
+ o: The object to write the output to.
+ """
+ i = ' ' * 4
+ fmt = '{}{:25}{}\n'
+ o.write(fmt.format(i, 'Leaf:', ''))
+ super(SignedVBMetaPrimaryAnnotationLeaf, self).print_desc(o)
+ self.signed_vbmeta_primary_annotation.print_desc(o)
+
+
class AftlImage(object):
"""A class for the AFTL image, which contains the transparency log ICPs.
@@ -1087,40 +1457,40 @@
else:
self.timeout = None
- def add_firmware_info(self, request):
- """Calls the AddFirmwareInfo RPC on the AFTL server.
+ def add_vbmeta(self, request):
+ """Calls the AddVBMeta RPC on the AFTL server.
Arguments:
- request: A AddFirmwareInfoRequest message.
+ request: An AddVBMetaRequest message.
Returns:
- An AddFirmwareInfoReponse message.
+ An AddVBMetaResponse message.
Raises:
AftlError: If grpc or the proto modules cannot be loaded, if there is an
error communicating with the log.
"""
raise NotImplementedError(
- 'AddFirmwareInfo() needs to be implemented by subclass.')
+ 'add_vbmeta() needs to be implemented by subclass.')
class AftlGrpcCommunication(AftlCommunication):
"""Class that implements GRPC communication to the AFTL server."""
- def add_firmware_info(self, request):
- """Calls the AddFirmwareInfo RPC on the AFTL server.
+ def add_vbmeta(self, request):
+ """Calls the AddVBMeta RPC on the AFTL server.
Arguments:
- request: A AddFirmwareInfoRequest message.
+ request: An AddVBMetaRequest message.
Returns:
- An AddFirmwareInfoReponse message.
+ An AddVBMetaResponse message.
Raises:
AftlError: If grpc or the proto modules cannot be loaded, if there is an
error communicating with the log.
"""
- # Import grpc now to avoid global dependencies as it otherwise breakes
+ # Import grpc now to avoid global dependencies as it otherwise breaks
# running unittest with atest.
try:
import grpc # pylint: disable=import-outside-toplevel
@@ -1145,8 +1515,8 @@
'with domain {}.\n'.format(
self.transparency_log_config.target))
try:
- response = stub.AddFirmwareInfo(request, timeout=self.timeout,
- metadata=metadata)
+ response = stub.AddVBMeta(request, timeout=self.timeout,
+ metadata=metadata)
except grpc.RpcError as e:
raise AftlError('Error: grpc failure ({})'.format(e))
return response
@@ -1340,34 +1710,26 @@
# Calculate the hash of the manufacturer key data.
m_key_hash = hashlib.sha256(manufacturer_key_data).digest()
- # Create an AddFirmwareInfoRequest protobuf for transmission to AFTL.
- fw_info = aftl_pb2.FirmwareInfo(vbmeta_hash=vbmeta_hash,
- version_incremental=version_inc,
- manufacturer_key_hash=m_key_hash)
- signed_fw_info = b''
- # AFTL supports SHA256_RSA4096 for now, more will be available.
- algorithm_name = 'SHA256_RSA4096'
- try:
- rsa_key = avbtool.RSAPublicKey(manufacturer_key_path)
- signed_fw_info = rsa_key.sign(algorithm_name, fw_info.SerializeToString(),
- signing_helper, signing_helper_with_files)
- except avbtool.AvbError as e:
- raise AftlError('Failed to sign FirmwareInfo with '
- '--manufacturer_key: {}'.format(e))
- fw_info_sig = sigpb_pb2.DigitallySigned(
- hash_algorithm='SHA256',
- signature_algorithm='RSA',
- signature=signed_fw_info)
+ # Build VBMetaPrimaryAnnotation with that data.
+ annotation = VBMetaPrimaryAnnotation(
+ vbmeta_hash=vbmeta_hash, version_incremental=version_inc,
+ manufacturer_key_hash=m_key_hash)
- sfw_info = aftl_pb2.SignedFirmwareInfo(info=fw_info,
- info_signature=fw_info_sig)
- request = api_pb2.AddFirmwareInfoRequest(
- vbmeta=vbmeta_image, fw_info=sfw_info)
+ # Sign annotation and add it to the request.
+ signed_annotation = annotation.sign(
+ manufacturer_key_path, signing_helper=signing_helper,
+ signing_helper_with_files=signing_helper_with_files)
- # Submit signed FirmwareInfo to the server.
+ encoded_signed_annotation = io.BytesIO()
+ signed_annotation.encode(encoded_signed_annotation)
+ request = api_pb2.AddVBMetaRequest(
+ vbmeta=vbmeta_image,
+ signed_vbmeta_primary_annotation=encoded_signed_annotation.getvalue())
+
+ # Submit signed VBMeta annotation to the server.
if not aftl_comms:
aftl_comms = AftlGrpcCommunication(transparency_log_config, timeout)
- response = aftl_comms.add_firmware_info(request)
+ response = aftl_comms.add_vbmeta(request)
# Return an AftlIcpEntry representing this response.
icp_entry = AftlIcpEntry()
@@ -1870,14 +2232,14 @@
sub_parser.set_defaults(func=self.load_test_aftl)
args = parser.parse_args(argv[1:])
- try:
- success = args.func(args)
- except AttributeError:
+ if not 'func' in args:
# This error gets raised when the command line tool is called without any
# arguments. It mimics the original Python 2 behavior.
parser.print_usage()
print('aftltool: error: too few arguments')
sys.exit(2)
+ try:
+ success = args.func(args)
except AftlError as e:
# Signals to calling tools that an unhandled exception occured.
sys.stderr.write('Unhandled AftlError occured: {}\n'.format(e))
diff --git a/aftltool_test.py b/aftltool_test.py
index 006deb9..5fe9446 100755
--- a/aftltool_test.py
+++ b/aftltool_test.py
@@ -25,7 +25,6 @@
"""Unit tests for aftltool."""
import argparse
-import base64
import binascii
import io
import os
@@ -47,6 +46,107 @@
# TODO(b/149307145): Remove workaround once the referenced bug is fixed.
TEST_EXEC_PATH = os.path.dirname(os.path.realpath(__file__))
+class TlsDataTest(unittest.TestCase):
+
+ def test_decode(self):
+ data = io.BytesIO(b'\x01\x02')
+ value = aftltool.tls_decode_bytes('B', data)
+ self.assertEqual(value, b'\x02')
+ self.assertEqual(data.read(), b'')
+
+ data = io.BytesIO(b'\x00\x01\x03\xff')
+ value = aftltool.tls_decode_bytes('H', data)
+ self.assertEqual(value, b'\x03')
+ self.assertEqual(data.read(), b'\xff')
+
+ data = io.BytesIO(b'\x00\x00\x00\x02\x04\x05\xff\xff')
+ value = aftltool.tls_decode_bytes('L', data)
+ self.assertEqual(value, b'\x04\x05')
+ self.assertEqual(data.read(), b'\xff\xff')
+
+ def test_decode_invalid(self):
+ # Insufficient data for reading the size.
+ with self.assertRaises(aftltool.AftlError):
+ aftltool.tls_decode_bytes('B', io.BytesIO(b''))
+
+ # Invalid byte_size character.
+ with self.assertRaises(aftltool.AftlError):
+ aftltool.tls_decode_bytes('/o/', io.BytesIO(b'\x01\x02\xff'))
+
+ # Insufficient data for reading the value.
+ with self.assertRaises(aftltool.AftlError):
+ aftltool.tls_decode_bytes('B', io.BytesIO(b'\x01'))
+
+ def test_encode(self):
+ stream = io.BytesIO()
+ aftltool.tls_encode_bytes('B', b'\x01\x02\x03\x04', stream)
+ self.assertEqual(stream.getvalue(), b'\x04\x01\x02\x03\x04')
+
+ stream = io.BytesIO()
+ aftltool.tls_encode_bytes('H', b'\x01\x02\x03\x04', stream)
+ self.assertEqual(stream.getvalue(), b'\x00\x04\x01\x02\x03\x04')
+
+ def test_encode_invalid(self):
+ # Byte size is not large enough to encode the value.
+ stream = io.BytesIO()
+ with self.assertRaises(aftltool.AftlError):
+ aftltool.tls_encode_bytes('B', b'\x01'*256, stream)
+
+ # Invalid byte_size character.
+ stream = io.BytesIO()
+ with self.assertRaises(aftltool.AftlError):
+ aftltool.tls_encode_bytes('/o/', b'\x01\x02', stream)
+
+
+class VBMetaPrimaryAnnotationTest(unittest.TestCase):
+
+ def test_decode(self):
+ stream = io.BytesIO(b'\x00\x00\x00\x00\x00')
+ anno = aftltool.VBMetaPrimaryAnnotation.parse(stream)
+ self.assertEqual(anno.vbmeta_hash, b'')
+ self.assertEqual(anno.version_incremental, '')
+ self.assertEqual(anno.manufacturer_key_hash, b'')
+ self.assertEqual(anno.description, '')
+
+ def test_encode(self):
+ stream = io.BytesIO()
+ anno = aftltool.VBMetaPrimaryAnnotation()
+ anno.encode(stream)
+ self.assertEqual(stream.getvalue(), b'\x00\x00\x00\x00\x00')
+
+ def test_encode_invalid(self):
+ stream = io.BytesIO()
+ anno = aftltool.VBMetaPrimaryAnnotation()
+ # Version incremental should be ASCII only.
+ anno.version_incremental = 'ā'
+ with self.assertRaises(aftltool.AftlError):
+ anno.encode(stream)
+
+
+class SignedVBMetaAnnotationLeafTest(unittest.TestCase):
+
+ def test_encode(self):
+ leaf = aftltool.SignedVBMetaPrimaryAnnotationLeaf()
+ self.assertEqual(leaf.encode(),
+ b'\x01' # Version
+ b'\x00\x00\x00\x00\x00\x00\x00\x00' # Timestamp
+ b'\x01' + # Leaf Type
+ b'\x00' * 4 + # Empty Signature
+ b'\x00' * 5) # Empty Annotation
+
+ def test_encode_invalid_type(self):
+ # The version field must be a 1-byte integer.
+ leaf = aftltool.SignedVBMetaPrimaryAnnotationLeaf()
+ leaf.version = 'x'
+ with self.assertRaises(aftltool.AftlError):
+ leaf.encode()
+
+ def test_encode_invalid_size(self):
+ leaf = aftltool.SignedVBMetaPrimaryAnnotationLeaf()
+ leaf.version = 256
+ with self.assertRaises(aftltool.AftlError):
+ leaf.encode()
+
class AftltoolTestCase(unittest.TestCase):
@@ -99,6 +199,28 @@
b'' # metadata (empty)
)
+ # Test Annotation #1
+ anno_1 = aftltool.VBMetaPrimaryAnnotation(vbmeta_hash=b'w'*32,
+ version_incremental='x'*5,
+ manufacturer_key_hash=b'y'*32,
+ description='z'*51)
+ signed_anno_1 = aftltool.SignedVBMetaPrimaryAnnotation(annotation=anno_1)
+
+ self.test_anno_1 = aftltool.SignedVBMetaPrimaryAnnotationLeaf(
+ signed_vbmeta_primary_annotation=signed_anno_1)
+ self.test_anno_1_bytes = (
+ b'\x01' # version
+ b'\x00\x00\x00\x00\x00\x00\x00\x00' # timestamp
+ b'\x01' # leaf_type
+ b'\x00' # hash_algorithm
+ b'\x00' # signature_algorithm
+ + b'\x00\x00' # signature
+ + b'\x20' + b'w' * 32 # vbmeta_hash
+ + b'\x05' + b'x' * 5 # version_incremental
+ + b'\x20' + b'y' * 32 # manufacturer_key_hash
+ + b'\x00\x33' + b'z' * 51 # description
+ )
+
# Fill each structure with an easily observable pattern for easy validation.
self.test_proof_hashes_1 = []
self.test_proof_hashes_1.append(b'b' * 32)
@@ -110,6 +232,7 @@
self.test_entry_1 = aftltool.AftlIcpEntry()
self.test_entry_1.log_url = self.test_tl_url_1
self.test_entry_1.leaf_index = 1
+ self.test_entry_1.annotation_leaf = self.test_anno_1
self.test_entry_1.log_root_descriptor = self.test_sth_1
self.test_entry_1.proofs = self.test_proof_hashes_1
self.test_entry_1.log_root_signature = b'g' * 512
@@ -118,12 +241,13 @@
b'\x00\x00\x00\x1b' # Transparency log url size.
b'\x00\x00\x00\x00\x00\x00\x00\x01' # Leaf index.
b'\x00\x00\x00\x3d' # Log root descriptor size.
- b'\x00\x00\x00\x00' # Firmware info leaf size.
+ b'\x00\x00\x00\x8b' # Annotation leaf size.
b'\x02\x00' # Log root signature size.
b'\x04' # Number of hashes in ICP.
b'\x00\x00\x00\x80' # Size of ICP in bytes.
+ self.test_tl_url_1.encode('ascii') # Transparency log url.
+ self.test_sth_1_bytes
+ + self.test_anno_1_bytes
+ b'g' * 512 # Log root signature.
+ b'b' * 32 # Hashes...
+ b'c' * 32
@@ -161,6 +285,7 @@
self.test_entry_2 = aftltool.AftlIcpEntry()
self.test_entry_2.log_url = self.test_tl_url_2
self.test_entry_2.leaf_index = 2
+ self.test_entry_2.annotation_leaf = self.test_anno_1
self.test_entry_2.log_root_descriptor = self.test_sth_2
self.test_entry_2.log_root_signature = b'd' * 512
self.test_entry_2.proofs = self.test_proof_hashes_2
@@ -169,12 +294,13 @@
b'\x00\x00\x00\x1a' # Transparency log url size.
b'\x00\x00\x00\x00\x00\x00\x00\x02' # Leaf index.
b'\x00\x00\x00\x3f' # Log root descriptor size.
- b'\x00\x00\x00\x00' # Firmware info leaf size.
+ b'\x00\x00\x00\x8b' # Annotation leaf size.
b'\x02\x00' # Log root signature size.
b'\x02' # Number of hashes in ICP.
b'\x00\x00\x00\x40' # Size of ICP in bytes.
+ self.test_tl_url_2.encode('ascii') # Transparency log url.
+ self.test_sth_2_bytes # Log root
+ + self.test_anno_1_bytes
+ b'd' * 512 # Log root signature.
+ b'g' * 32 # Hashes...
+ b'h' * 32)
@@ -188,61 +314,88 @@
b'AFTL' # Magic.
+ struct.pack('!L', avbtool.AVB_VERSION_MAJOR) # Major version.
+ struct.pack('!L', avbtool.AVB_VERSION_MINOR) # Minor version.
- + b'\x00\x00\x05\xb9' # Image size.
+ + b'\x00\x00\x06\xcf' # Image size.
b'\x00\x02' # Number of ICP entries.
+ self.test_entry_1_bytes
+ self.test_entry_2_bytes)
- # pylint: disable=no-member
- self.test_afi_resp = api_pb2.AddFirmwareInfoResponse()
- self.test_afi_resp.fw_info_proof.proof.leaf_index = 6263
+ self.test_avbm_resp = api_pb2.AddVBMetaResponse()
+ self.test_avbm_resp.annotation_proof.proof.leaf_index = 9127
hashes = [
- '3ad99869646980c0a51d637a9791f892d12e0bc83f6bac5d305a9e289e7f7e8b',
- '2e5c664d2aee64f71cb4d292e787d0eae7ca9ed80d1e08abb41d26baca386c05',
- 'a671dd99f8d97e9155cc2f0a9dc776a112a5ec5b821ec71571bb258ac790717a',
- '78046b839595e4e49ad4b0c73f92bf4803aacd4a3351181086509d057ef0d7a9',
- 'c0a7e013f03e7c69e9402070e113dadb345868cf144ccb174fabc384b5605abf',
- 'dc36e5dbe36abe9f4ad10f14170aa0148b6fe3fcaba9df43deaf4dede01b02e8',
- 'b063e7fb665370a361718208756c363dc5206e2e9af9b4d847d81289cdae30de',
- 'a69ea5ba88a221103636d3f4245c800570eb86ad9276121481521f97d0a04a81']
+ '61076ca285b4982669e67757f55682ddc43ab5c11ba671260f82a8efa8831f94',
+ '89c2fbcc58da25a65ce5e9b4fb22aaf208b20601f0bc023f73f05d35bc1f3bac',
+ '75d26b5f754b4bed332a3ce2a2bfea0334706a974b7e00ee663f0279fa8b446e',
+ 'e1cd9c96feb893b5ef7771e424ac1c6c47509c2b98bc578d22ad07369c9641aa',
+ 'e83e0e4dd352b1670a55f93f88781a73bb41efcadb9927399f59459dfa14bc40',
+ '8d5d25996117c88655d66f685baa3c94390867a040507b10587b17fbe92b496a',
+ '5de4c627e9ca712f207d6056f56f0d3286ed4a5381ed7f3cc1aa470217734138',
+ '19acfdb424d7fe28d1f850c76302f78f9a50146a5b9c65f9fdfbbc0173fd6993']
for h in hashes:
- self.test_afi_resp.fw_info_proof.proof.hashes.append(
+ self.test_avbm_resp.annotation_proof.proof.hashes.append(
binascii.unhexlify(h))
- self.test_afi_resp.fw_info_proof.sth.key_hint = binascii.unhexlify(
+ self.test_avbm_resp.annotation_proof.sth.key_hint = binascii.unhexlify(
'5af859abce8fe1ea')
- self.test_afi_resp.fw_info_proof.sth.log_root = binascii.unhexlify(
- '000100000000000018782053b182b55dc1377197c938637f50093131daea4'
- 'd0696b1eae5b8a014bfde884a15edb28f1fc7954400000000000013a50000'
+ self.test_avbm_resp.annotation_proof.sth.log_root = binascii.unhexlify(
+ '0001'
+ '00000000000023a8'
+ '20'
+ '9a5f71340f8dc98bdc6320f976dda5f34db8554cb273ba5ab60f1697c519d6f6'
+ '1609ae15024774b1'
+ '0000000000001e5a'
+ '0000'
)
- self.test_afi_resp.fw_info_proof.sth.log_root_signature = (
+ self.test_avbm_resp.annotation_proof.sth.log_root_signature = (
binascii.unhexlify(
- 'c264bc7986a1cf56364ca4dd04989f45515cb8764d05b4fb2b880172585ea404'
- '2105f95a0e0471fb6e0f8c762b14b2e526fb78eaddcc61484917795a12f6ab3b'
- '557b5571d492d07d7950595f9ad8647a606c7c633f4697c5eb59c272aeca0419'
- '397c70a3b9b51537537c4ea6b49d356110e70a9286902f814cc6afbeafe612e4'
- '9e180146140e902bdd9e9dae66b37b4943150a9571949027a648db88a4eea3ad'
- 'f930b4fa6a183e97b762ab0e55a3a26aa6b0fd44d30531e2541ecb94bf645e62'
- '59e8e3151e7c3b51a09fe24557ce2fd2c0ecdada7ce99c390d2ef10e5d075801'
- '7c10d49c55cdee930959cc35f0104e04f296591eeb5defbc9ebb237da7b204ca'
- 'a4608cb98d6bc3a01f18585a04441caf8ec7a35aa2d35f7483b92b14fd0f4a41'
- '3a91133545579309adc593222ca5032a103b00d8fcaea911936dbec11349e4dd'
- '419b091ea7d1130570d70e2589dd9445fd77fd7492507e1c87736847b9741cc6'
- '236868af42558ff6e833e12010c8ede786e43ada40ff488f5f1870d1619887d7'
- '66a24ad0a06a47cc14e2f7db07361be191172adf3155f49713807c7c265f5a84'
- '040fc84246ccf7913e44721f0043cea05ee774e457e13206775eee992620c3f9'
- 'd2b2584f58aac19e4afe35f0a17df699c45729f94101083f9fc4302659a7e6e0'
- 'e7eb36f8d1ca0be2c9010160d329bd2d17bb707b010fdd63c30b667a0b886cf9'
+ '7c37903cc76e8689a6b31da9ad56c3daeb6194029510297cc7d147278390da33'
+ '09c4d9eb1f6be0cdcd1de5315b0b3b573cc9fcd8620d3fab956abbe3c597a572'
+ '46e5a5d277c4cc4b590872d0292fa64e1d3285626b1dedeb00b6aa0a7a0717c0'
+ '7d4c89b68fda9091be06180be1369675a7c4ce7f42cca133ef0daf8dcc5ba1ee'
+ '930cef6dcb71b0a7690446e19661c8e18c089a5d6f6fc9299a0592efb33a4db5'
+ '4c640027fa4f0ad0009f8bf75ec5fc17e0fa1091fabe74fe52738443745066ab'
+ '48f99b297809b863c01016abda17a2479fce91f9929c60bc2ce15e474204fc5a'
+ '8e79b2190aadb7c149671e8c76a4da506860f8d6020fb2eaabfee025cc267bad'
+ '3c8257186c8aaf1da9eefe50cae4b3e8deb66033ebc4bfcda2b317f9e7d2dd78'
+ 'b47f2d86795815d82058ad4cba8fc7983a3bbf843e9b8c7ec7f1ae137be6848d'
+ '03c76eefdac40ce5e66cc23d9f3e79ad87acbe7ec0c0bb419a7d368ae1e73c85'
+ '742871f847bde69c871e8797638e0e270282fb058ef1cbcba52aded9dcc8249b'
+ '38fbed8424c33b8cfcde4f49797c64dda8d089d73b84062602fd41c66091543c'
+ 'e13c18cfa7f8300530ad4b7adb8924bbb86d17bcc5f1d3d74c522a7dcc8c3c1f'
+ '28a999f2fe1bfe5520c66f93f7c90996dc7f52e62dd95ace9ceace90324c3040'
+ '669b7f5aeb5c5a53f217f1de46e32f80d0aaaf7d9cc9d0e8f8fd7026c612103a'
)
)
- self.test_afi_resp.fw_info_leaf = (
- b'{\"timestamp\":{\"seconds\":1580115370,\"nanos\":621454825},\"Va'
- b'lue\":{\"FwInfo\":{\"info\":{\"info\":{\"vbmeta_hash\":\"ViNzEQS'
- b'/oc/bJ13yl40fk/cvXw90bxHQbzCRxgHDIGc=\",\"version_incremental\":'
- b'\"1\",\"manufacturer_key_hash\":\"yBCrUOdjvaAh4git5EgqWa5neegUao'
- b'XeLlB67+N8ObY=\"}}}}}')
- self.test_fw_info_leaf = aftltool.FirmwareInfoLeaf(
- self.test_afi_resp.fw_info_leaf)
+ anno = aftltool.VBMetaPrimaryAnnotation(
+ vbmeta_hash=bytes.fromhex(
+ '5623731104bfa1cfdb275df2978d1f93f72f5f0f746f11d06f3091c601c32067'),
+ version_incremental='only_for_testing',
+ manufacturer_key_hash=bytes.fromhex(
+ '83ab3b109b73a1d32dce4153a2de57a1a0485052db8364f3180d98614749d7f7'))
+ raw_signature = bytes.fromhex(
+ '6a523021bc5b933bb58c38c8238be3a5fe1166002f5df8b77dee9dd22d353595'
+ 'be7996656d3824ebf4e1411a05ee3652d64669d3d62b167d3290dbdf4f2741ba'
+ '4b6472e1bd71fc1860465fdcdca1ff08c4ab0420d7dcbf4ad144f64e211d8f92'
+ '081ba51192358e2478195e573d000282423b23e6dd945069907dcf11520ff11a'
+ '250e26643b820f8a5d80ccfe7d5d84f58e549cd05630f2254ade8edc88d9aa8a'
+ 'ec2089f84643854e1f265a4f746598ce4cae529c4eaa637f6e35fa1d1da9254e'
+ 'ec8dfede7a4313f7b151547dcdde98782ce6fb3149326ee5b8e750813d3fd37a'
+ '738fe92f6111bf0dff4091769e216b842980e05716f2e50268a7dcca430e175e'
+ '711f80e41a1a28f20635741ac11a56f97492d30db6d1955a827daf8e83faebe5'
+ 'a96e18a13c558ae561a02c90982514c853db0296c2e791e68b77c30e6232a3b7'
+ 'ed355441d4706277f33a01735f56cb8279336491731939691683f96f1c3e3183'
+ 'a0b77510d6ff0199b7688902044829793106546fd6fd4a5294d63c31c91256ad'
+ 'f7be6d053e77875698ad32ffaaeaac5d54b432e537f72549d2543072ae35578f'
+ '138d82afcadd668511ba276ce02b6f9c18ef3b6f2f6ae0d123e9f8cb930f21a9'
+ 'c49a6d9e95de741c7860593a956735e1b77e9851ecb1f6572abf6e2c8ba15085'
+ 'e37e0f7bab0a30d108b997ed5edd74cf7f89cf082590a6f0af7a3a1f68c0077a')
+ signature = aftltool.Signature(signature=raw_signature)
+ signed_anno = aftltool.SignedVBMetaPrimaryAnnotation(annotation=anno,
+ signature=signature)
+ leaf = aftltool.SignedVBMetaPrimaryAnnotationLeaf(
+ timestamp=1587991742919072870,
+ signed_vbmeta_primary_annotation=signed_anno).encode()
+ self.test_avbm_resp.annotation_leaf = leaf
+
def tearDown(self):
"""Tears down the test bed for the unit tests."""
@@ -448,56 +601,6 @@
# Valid image but checked with empty list of keys.
self.assertFalse(desc.verify_vbmeta_image(vbmeta_image, []))
- def test_verify_vbmeta_image_with_2_icp_from_different_logs(self):
- """Tests the verify_vbmeta_image method."""
- # Valid vbmeta image without footer with 2 ICPs from different logs.
- tool = aftltool.Aftl()
- image_path = self.get_testdata_path(
- 'aftltool/aftl_output_vbmeta_with_2_icp_different_logs.img')
- vbmeta_image, _ = tool.get_vbmeta_image(image_path)
- desc = tool.get_aftl_image(image_path)
-
- # Valid image checked against log keys from both logs.
- self.assertTrue(desc.verify_vbmeta_image(
- vbmeta_image, [
- self.get_testdata_path('aftltool/aftl_pubkey_1.pub'),
- self.get_testdata_path('aftltool/aftl_pubkey_2.pub')
- ]))
-
- # Valid image checked with one of the keys with an invalid file path.
- self.assertFalse(desc.verify_vbmeta_image(
- vbmeta_image, [
- self.get_testdata_path('aftltool/aftl_pubkey_1.pub'),
- self.get_testdata_path('non_existent_blabli')
- ]))
-
- # Valid image checked with one of the keys being a invalid key.
- self.assertFalse(desc.verify_vbmeta_image(
- vbmeta_image, [
- self.get_testdata_path('aftltool/aftl_pubkey_1.pub'),
- self.get_testdata_path('large_blob.bin')
- ]))
-
- # Valid image checked with one of the keys being None.
- self.assertFalse(desc.verify_vbmeta_image(
- vbmeta_image, [
- self.get_testdata_path('aftltool/aftl_pubkey_1.pub'),
- None
- ]))
-
- # Valid vbmeta image checked against only one of the log keys.
- self.assertFalse(desc.verify_vbmeta_image(
- vbmeta_image, [self.get_testdata_path('aftltool/aftl_pubkey_1.pub')]))
- self.assertFalse(desc.verify_vbmeta_image(
- vbmeta_image, [self.get_testdata_path('aftltool/aftl_pubkey_2.pub')]))
-
- # Valid image checked with invalid key.
- self.assertFalse(desc.verify_vbmeta_image(
- vbmeta_image, [self.get_testdata_path('large_blob.bin')]))
-
- # Valid image but checked with empty list of keys.
- self.assertFalse(desc.verify_vbmeta_image(vbmeta_image, []))
-
def test_encode(self):
"""Tests encode method."""
desc_bytes = self.test_aftl_desc.encode()
@@ -649,7 +752,7 @@
self.assertEqual(entry.log_url_size, 0)
self.assertEqual(entry.leaf_index, 0)
self.assertEqual(entry.log_root_descriptor_size, 29)
- self.assertEqual(entry.fw_info_leaf_size, 0)
+ self.assertEqual(entry.annotation_leaf_size, 19)
self.assertEqual(entry.log_root_sig_size, 0)
self.assertEqual(entry.proof_hash_count, 0)
self.assertEqual(entry.inc_proof_size, 0)
@@ -663,7 +766,7 @@
entry = aftltool.AftlIcpEntry(self.test_entry_1_bytes)
self.assertEqual(entry.log_url_size, len(self.test_tl_url_1))
self.assertEqual(entry.leaf_index, 1)
- self.assertEqual(entry.fw_info_leaf_size, 0)
+ self.assertEqual(entry.annotation_leaf_size, 139)
self.assertEqual(entry.log_root_sig_size, 512)
self.assertEqual(entry.proof_hash_count, len(self.test_proof_hashes_1))
self.assertEqual(entry.inc_proof_size, 128)
@@ -680,11 +783,11 @@
"""Tests get_expected_size method."""
# Default record.
entry = aftltool.AftlIcpEntry()
- self.assertEqual(entry.get_expected_size(), 56)
+ self.assertEqual(entry.get_expected_size(), 75)
self.assertEqual(entry.get_expected_size(), len(entry.encode()))
# Test record.
- self.assertEqual(self.test_entry_1.get_expected_size(), 755)
+ self.assertEqual(self.test_entry_1.get_expected_size(), 894)
self.assertEqual(self.test_entry_1.get_expected_size(),
len(self.test_entry_1.encode()))
@@ -717,15 +820,17 @@
def test_translate_response(self):
"""Tests translate_response method."""
entry = aftltool.AftlIcpEntry()
- entry.translate_response('aftl-test.foo.bar:80', self.test_afi_resp)
+ entry.translate_response('aftl-test.foo.bar:80', self.test_avbm_resp)
self.assertEqual(entry.log_url, 'aftl-test.foo.bar:80')
- self.assertEqual(entry.leaf_index, 6263)
+ self.assertEqual(entry.leaf_index, 9127)
self.assertEqual(entry.log_root_descriptor.encode(),
- self.test_afi_resp.fw_info_proof.sth.log_root)
- self.assertEqual(entry.log_root_signature,
- self.test_afi_resp.fw_info_proof.sth.log_root_signature)
- self.assertEqual(entry.proofs,
- self.test_afi_resp.fw_info_proof.proof.hashes)
+ self.test_avbm_resp.annotation_proof.sth.log_root)
+ self.assertEqual(
+ entry.log_root_signature,
+ self.test_avbm_resp.annotation_proof.sth.log_root_signature)
+ self.assertEqual(
+ entry.proofs,
+ self.test_avbm_resp.annotation_proof.proof.hashes)
def test_verify_icp(self):
"""Tests verify_icp method."""
@@ -735,17 +840,18 @@
# Valid ICP.
entry = aftltool.AftlIcpEntry()
- entry.translate_response(self.test_tl_url_1, self.test_afi_resp)
+ entry.translate_response(self.test_tl_url_1, self.test_avbm_resp)
self.assertTrue(entry.verify_icp(key_file.name))
- # Invalid ICP where fw_info_leaf is not matching up with proofs.
+ # Invalid ICP where annotation_leaf is not matching up with proofs.
# pylint: disable=protected-access
entry = aftltool.AftlIcpEntry()
- entry.translate_response(self.test_tl_url_1, self.test_afi_resp)
- fw_info_leaf_bytes = entry.fw_info_leaf._fw_info_leaf_bytes.replace(
- b'ViNzEQS', b'1234567')
- entry.fw_info_leaf._fw_info_leaf_bytes = fw_info_leaf_bytes
- self.assertFalse(entry.verify_icp(key_file.name))
+ entry.translate_response(self.test_tl_url_1, self.test_avbm_resp)
+ vbmeta_hash = entry.annotation_leaf.annotation.vbmeta_hash
+ vbmeta_hash = vbmeta_hash.replace(b"\x56\x23\x73\x11",
+ b"\x00\x00\x00\x00")
+ entry.annotation_leaf.annotation.vbmeta_hash = vbmeta_hash
+ self.assertFalse(entry.verify_icp(key_file))
def test_verify_vbmeta_image(self):
"""Tests the verify_vbmeta_image method."""
@@ -995,94 +1101,54 @@
self.assertIn('Metadata:', desc)
-class FirmwareInfoLeafTest(AftltoolTestCase):
- """Test suite for testing the FirmwareInfoLeaf."""
+class SignedVBMetaPrimaryAnnotationLeafTest(AftltoolTestCase):
+ """Test suite for testing the Leaf."""
def test__init__(self):
"""Tests constructor and properties methods."""
# Calls constructor without data.
- leaf = aftltool.FirmwareInfoLeaf()
- self.assertTrue(leaf.is_valid())
- self.assertEqual(leaf.vbmeta_hash, None)
- self.assertEqual(leaf.version_incremental, None)
- self.assertEqual(leaf.platform_key, None)
- self.assertEqual(leaf.manufacturer_key_hash, None)
- self.assertEqual(leaf.description, None)
+ leaf = aftltool.SignedVBMetaPrimaryAnnotationLeaf()
+ self.assertEqual(leaf.version, 1)
+ self.assertEqual(leaf.timestamp, 0)
+ self.assertEqual(leaf.signature.signature, b'')
+ self.assertEqual(leaf.annotation.vbmeta_hash, b'')
+ self.assertEqual(leaf.annotation.description, '')
- # Calls constructor with data.
- leaf = aftltool.FirmwareInfoLeaf(self.test_afi_resp.fw_info_leaf)
- self.assertTrue(leaf.is_valid())
- self.assertEqual(
- leaf.vbmeta_hash,
- base64.b64decode('ViNzEQS/oc/bJ13yl40fk/cvXw90bxHQbzCRxgHDIGc='))
- self.assertEqual(leaf.version_incremental, '1')
- self.assertEqual(leaf.platform_key, None)
- self.assertEqual(
- leaf.manufacturer_key_hash,
- base64.b64decode('yBCrUOdjvaAh4git5EgqWa5neegUaoXeLlB67+N8ObY='))
- self.assertEqual(leaf.description, None)
+ def test_parse(self):
+ # Calls parse with valid data.
+ leaf = aftltool.SignedVBMetaPrimaryAnnotationLeaf.parse(
+ self.test_anno_1_bytes)
+ self.assertEqual(leaf.annotation.vbmeta_hash, b'w'*32)
+ self.assertEqual(leaf.annotation.version_incremental, 'x'*5)
+ self.assertEqual(leaf.annotation.manufacturer_key_hash, b'y'*32)
+ self.assertEqual(leaf.annotation.description, 'z'*51)
- # Calls constructor with invalid JSON data.
+ # Calls parse with invalid data.
with self.assertRaises(aftltool.AftlError):
- leaf = aftltool.FirmwareInfoLeaf('Invalid JSON.')
+ leaf = aftltool.SignedVBMetaPrimaryAnnotationLeaf.parse(b'Invalid data')
def test_get_expected_size(self):
"""Tests get_expected_size method."""
# Calls constructor without data.
- leaf = aftltool.FirmwareInfoLeaf()
- self.assertEqual(leaf.get_expected_size(), 0)
+ leaf = aftltool.SignedVBMetaPrimaryAnnotationLeaf()
+ self.assertEqual(leaf.get_expected_size(), 19)
# Calls constructor with data.
- leaf = aftltool.FirmwareInfoLeaf(self.test_afi_resp.fw_info_leaf)
+ leaf = aftltool.SignedVBMetaPrimaryAnnotationLeaf.parse(
+ self.test_anno_1_bytes)
self.assertEqual(leaf.get_expected_size(),
- len(self.test_afi_resp.fw_info_leaf))
+ len(self.test_anno_1_bytes))
def test_encode(self):
"""Tests encode method."""
- # Calls constructor without data.
- leaf = aftltool.FirmwareInfoLeaf()
- self.assertEqual(leaf.encode(), b'')
-
# Calls constructor with data.
- self.assertEqual(self.test_fw_info_leaf.encode(),
- self.test_afi_resp.fw_info_leaf)
-
- def test_is_valid(self):
- """Tests is_valid method."""
- # Calls constructor without data.
- leaf = aftltool.FirmwareInfoLeaf()
- self.assertTrue(leaf.is_valid())
-
- # Calls constructor with data.
- self.assertTrue(self.test_fw_info_leaf.is_valid())
-
- # Incorrect name for Value key.
- invalid_value_key_name = (
- b'{\"timestamp\":{\"seconds\":1580115370,\"nanos\":621454825},\"In'
- b'val\":{\"FwInfo\":{\"info\":{\"info\":{\"vbmeta_hash\":\"ViNzEQS'
- b'/oc/bJ13yl40fk/cvXw90bxHQbzCRxgHDIGc=\",\"version_incremental\":'
- b'\"1\",\"manufacturer_key_hash\":\"yBCrUOdjvaAh4git5EgqWa5neegUao'
- b'XeLlB67+N8ObY=\"}}}}}')
-
- with self.assertRaises(aftltool.AftlError):
- aftltool.FirmwareInfoLeaf(invalid_value_key_name)
-
- # Within Firmware Info having a field which does not exist in
- # proto.aftl_pb2.FirmwareInfo.
- invalid_fields = (
- b'{\"timestamp\":{\"seconds\":1580115370,\"nanos\":621454825},\"Va'
- b'lue\":{\"FwInfo\":{\"info\":{\"info\":{\"invalid_field\":\"ViNzEQS'
- b'/oc/bJ13yl40fk/cvXw90bxHQbzCRxgHDIGc=\",\"version_incremental\":'
- b'\"1\",\"manufacturer_key_hash\":\"yBCrUOdjvaAh4git5EgqWa5neegUao'
- b'XeLlB67+N8ObY=\"}}}}}')
-
- with self.assertRaises(aftltool.AftlError):
- aftltool.FirmwareInfoLeaf(invalid_fields)
+ self.assertEqual(self.test_anno_1.encode(),
+ self.test_anno_1_bytes)
def test_print_desc(self):
"""Tests print_desc method."""
buf = io.StringIO()
- self.test_fw_info_leaf.print_desc(buf)
+ self.test_anno_1.print_desc(buf)
desc = buf.getvalue()
# Cursory check whether the printed description contains something useful.
@@ -1098,7 +1164,7 @@
Arguments:
transparency_log_config: An aftltool.TransparencyLogConfig instance.
- canned_response: AddFirmwareInfoResponse to return or the Exception to
+ canned_response: AddVBMetaResponse to return or the Exception to
raise.
"""
super(AftlMockCommunication, self).__init__(transparency_log_config,
@@ -1106,7 +1172,7 @@
self.request = None
self.canned_response = canned_response
- def add_firmware_info(self, request):
+ def add_vbmeta(self, request):
"""Records the request and returns the canned response."""
self.request = request
@@ -1122,7 +1188,7 @@
"""Initializes the object.
Arguments:
- canned_response: AddFirmwareInfoResponse to return or the Exception to
+ canned_response: AddVBMetaResponse to return or the Exception to
raise.
"""
self.mock_canned_response = canned_response
@@ -1284,30 +1350,36 @@
def test_request_inclusion_proof(self):
"""Tests the request_inclusion_proof method."""
# Always work with a mock independent if run as unit or integration tests.
- aftl = AftlMock(self.test_afi_resp)
+ aftl = AftlMock(self.test_avbm_resp)
icp = aftl.request_inclusion_proof(
self.transparency_log_config, b'a' * 1024, '1',
self.get_testdata_path('testkey_rsa4096.pem'), None, None, None)
self.assertEqual(icp.leaf_index,
- self.test_afi_resp.fw_info_proof.proof.leaf_index)
+ self.test_avbm_resp.annotation_proof.proof.leaf_index)
self.assertEqual(icp.proof_hash_count,
- len(self.test_afi_resp.fw_info_proof.proof.hashes))
+ len(self.test_avbm_resp.annotation_proof.proof.hashes))
self.assertEqual(icp.log_url, self.aftl_host)
self.assertEqual(
icp.log_root_descriptor.root_hash, binascii.unhexlify(
- '53b182b55dc1377197c938637f50093131daea4d0696b1eae5b8a014bfde884a'))
+ '9a5f71340f8dc98bdc6320f976dda5f34db8554cb273ba5ab60f1697c519d6f6'))
- self.assertEqual(icp.fw_info_leaf.version_incremental, '1')
+ self.assertEqual(icp.annotation_leaf.annotation.version_incremental,
+ 'only_for_testing')
# To calculate the hash of the a RSA key use the following command:
# openssl rsa -in test/data/testkey_rsa4096.pem -pubout \
# -outform DER | sha256sum
- self.assertEqual(icp.fw_info_leaf.manufacturer_key_hash, base64.b64decode(
- 'yBCrUOdjvaAh4git5EgqWa5neegUaoXeLlB67+N8ObY='))
+ self.assertEqual(
+ icp.annotation_leaf.annotation.manufacturer_key_hash,
+ bytes.fromhex(
+ "83ab3b109b73a1d32dce4153a2de57a1a0485052db8364f3180d98614749d7f7"))
- self.assertEqual(icp.log_root_signature,
- self.test_afi_resp.fw_info_proof.sth.log_root_signature)
- self.assertEqual(icp.proofs, self.test_afi_resp.fw_info_proof.proof.hashes)
+ self.assertEqual(
+ icp.log_root_signature,
+ self.test_avbm_resp.annotation_proof.sth.log_root_signature)
+ self.assertEqual(
+ icp.proofs,
+ self.test_avbm_resp.annotation_proof.proof.hashes)
# pylint: disable=no-member
def test_request_inclusion_proof_failure(self):
@@ -1323,7 +1395,7 @@
def test_request_inclusion_proof_manuf_key_not_4096(self):
"""Tests request_inclusion_proof with manufacturing key not of size 4096."""
# Always work with a mock independent if run as unit or integration tests.
- aftl = AftlMock(self.test_afi_resp)
+ aftl = AftlMock(self.test_avbm_resp)
with self.assertRaises(aftltool.AftlError) as e:
aftl.request_inclusion_proof(
self.transparency_log_config, b'a' * 1024, 'version_inc',
@@ -1332,7 +1404,7 @@
def test_make_and_verify_icp_with_1_log(self):
"""Tests make_icp_from_vbmeta, verify_image_icp & info_image_icp."""
- aftl = self.get_aftl_implementation(self.test_afi_resp)
+ aftl = self.get_aftl_implementation(self.test_avbm_resp)
# Make a VBmeta image with ICP.
with tempfile.NamedTemporaryFile('wb+') as output_file:
@@ -1357,7 +1429,7 @@
def test_make_and_verify_icp_with_2_logs(self):
"""Tests make_icp_from_vbmeta, verify_image_icp & info_image_icp."""
- aftl = self.get_aftl_implementation(self.test_afi_resp)
+ aftl = self.get_aftl_implementation(self.test_avbm_resp)
# Reconfigures default parameters with two transparency logs.
self.make_icp_default_params['transparency_log_configs'] = [
@@ -1388,10 +1460,10 @@
def test_info_image_icp(self):
"""Tests info_image_icp with vbmeta image with 2 ICP."""
# Always work with a mock independent if run as unit or integration tests.
- aftl = AftlMock(self.test_afi_resp)
+ aftl = AftlMock(self.test_avbm_resp)
image_path = self.get_testdata_path(
- 'aftltool/aftl_output_vbmeta_with_2_icp_different_logs.img')
+ 'aftltool/aftl_output_vbmeta_with_2_icp_same_log.img')
self.info_icp_default_params['vbmeta_image_path'] = image_path
# Verifies the generated image.
@@ -1401,7 +1473,7 @@
def test_info_image_icp_fail(self):
"""Tests info_image_icp with invalid vbmeta image."""
# Always work with a mock independent if run as unit or integration tests.
- aftl = AftlMock(self.test_afi_resp)
+ aftl = AftlMock(self.test_avbm_resp)
image_path = self.get_testdata_path('large_blob.bin')
self.info_icp_default_params['vbmeta_image_path'] = image_path
@@ -1413,34 +1485,18 @@
def test_verify_image_icp(self):
"""Tets verify_image_icp with 2 ICP with all matching log keys."""
# Always work with a mock independent if run as unit or integration tests.
- aftl = AftlMock(self.test_afi_resp)
+ aftl = AftlMock(self.test_avbm_resp)
image_path = self.get_testdata_path(
- 'aftltool/aftl_output_vbmeta_with_2_icp_different_logs.img')
+ 'aftltool/aftl_output_vbmeta_with_2_icp_same_log.img')
self.verify_icp_default_params['vbmeta_image_path'] = image_path
self.verify_icp_default_params['transparency_log_pub_keys'] = [
self.get_testdata_path('aftltool/aftl_pubkey_1.pub'),
- self.get_testdata_path('aftltool/aftl_pubkey_2.pub')
]
result = aftl.verify_image_icp(**self.verify_icp_default_params)
self.assertTrue(result)
- def test_verify_image_icp_failure(self):
- """Tests verify_image_icp with 2 ICP but only one matching log key."""
- # Always work with a mock independent if run as unit or integration tests.
- aftl = AftlMock(self.test_afi_resp)
-
- image_path = self.get_testdata_path(
- 'aftltool/aftl_output_vbmeta_with_2_icp_different_logs.img')
- self.verify_icp_default_params['vbmeta_image_path'] = image_path
- self.verify_icp_default_params['transparency_log_pub_keys'] = [
- self.get_testdata_path('aftltool/aftl_pubkey_1.pub')
- ]
-
- result = aftl.verify_image_icp(**self.verify_icp_default_params)
- self.assertFalse(result)
-
def test_make_icp_with_invalid_grpc_service(self):
"""Tests make_icp_from_vbmeta command with a host not supporting GRPC."""
aftl = self.get_aftl_implementation(aftltool.AftlError('Comms error'))
@@ -1468,7 +1524,7 @@
def test_load_test_single_process_single_submission(self):
"""Tests load_test_aftl command with 1 process which does 1 submission."""
- aftl = self.get_aftl_implementation(self.test_afi_resp)
+ aftl = self.get_aftl_implementation(self.test_avbm_resp)
with tempfile.TemporaryDirectory() as tmp_dir:
self.load_test_aftl_default_params[
@@ -1485,7 +1541,7 @@
def test_load_test_multi_process_multi_submission(self):
"""Tests load_test_aftl command with 2 processes and 2 submissions each."""
- aftl = self.get_aftl_implementation(self.test_afi_resp)
+ aftl = self.get_aftl_implementation(self.test_avbm_resp)
self.load_test_aftl_default_params['process_count'] = 2
self.load_test_aftl_default_params['submission_count'] = 2
diff --git a/proto/README.md b/proto/README.md
index eb3966c..ee64b01 100644
--- a/proto/README.md
+++ b/proto/README.md
@@ -2,27 +2,20 @@
---
This directory contains the proto definitions required to communicate with an
-AFTL server. Two (api.proto and aftl.proto) contain the definitions of the
-protos needed to communicate with the AFTL Trillian personality. The remainder
-are dependencies. The original repos and purpose for each proto file are as
+AFTL server. The original repos and purpose for each proto file are as
follows:
-* aftl.proto
- <!-- TODO(danielaustin): Add detailed message descriptions. -->
- Contains messages used by the AFTL frontend and the Trillian log.
* api.proto
- <!-- TODO(danielaustin): Add detailed message descriptions. -->
- Contains the messages to communicate through the AFTL personality.
+ Contains the messages to communicate with the AFTL personality.
* crypto/keyspb/keyspb.proto
From https://github.com/google/trillian
Dependency of trillian.proto
Contains the PublicKey message definition used by Tree.
* crypto/sigpb/sigpb.proto
From https://github.com/google/trillian
- Dependency of trillian.proto and aftl.proto
+ Dependency of trillian.proto
For trillian.proto, contains the DigitallySigned message used by Tree and
- SignedEntryTimestamp. For aftl.proto, contains the DigitallySigned message
- used by SignedFirmwareInfo.
+ SignedEntryTimestamp.
* trillian.proto
From https://github.com/google/trillian
Dependency of aftl.proto
diff --git a/proto/aftl.proto b/proto/aftl.proto
deleted file mode 100644
index 41f1148..0000000
--- a/proto/aftl.proto
+++ /dev/null
@@ -1,112 +0,0 @@
-// Copyright 2019 Google LLC
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-syntax = "proto3";
-
-package aftl;
-option go_package = "proto";
-
-import "trillian.proto";
-import "crypto/sigpb/sigpb.proto";
-import "google/protobuf/timestamp.proto";
-
-// These messages are used both by the frontend API and the Trillian log.
-message FirmwareInfo {
- // This is the SHA256 hash of vbmeta.
- bytes vbmeta_hash = 1;
-
- // Subcomponent of the build fingerprint as defined at
- // https://source.android.com/compatibility/android-cdd#3_2_2_build_parameters.
- // For example, a Pixel device with the following build fingerprint
- // google/crosshatch/crosshatch:9/PQ3A.190605.003/5524043:user/release-keys,
- // would have 5524043 for the version incremental.
- string version_incremental = 2;
-
- // Public key of the platform. This is the same key used to sign the vbmeta.
- bytes platform_key = 3;
-
- // SHA256 of the manufacturer public key (DER-encoded, x509
- // subjectPublicKeyInfo format). The public key MUST already be in the list
- // of root keys known and trusted by the AFTL.
- // Internal: This field is required to be able to identify which manufacturer
- // this request is coming from.
- bytes manufacturer_key_hash = 4;
-
- // Free form description field. It can be used to annotate this message with
- // further context on the build (e.g., carrier specific build).
- string description = 5;
-}
-
-message SignedFirmwareInfo {
- FirmwareInfo info = 1;
-
- // Signature of the info field, using manufacturer_pub_key.
- // For the signature, info is first serialized to JSON. It is not
- // expected to be able to reconstruct the info field from scratch.
- // When verifying the inclusion proof associated with the info, it is
- // expected that the leaf is provided.
- sigpb.DigitallySigned info_signature = 2;
-}
-
-message FirmwareImageInfo {
- // This is the SHA256 hash of vbmeta.
- bytes vbmeta_hash = 1;
-
- // SHA256 hash of the complete binary image. In case of Pixel, this would be
- // the hash of the ZIP file that is offered for download at:
- // https://developers.google.com/android/images
- bytes hash = 2;
-
- // Build fingerprint, e.g. in case of Pixel
- // google/crosshatch/crosshatch:9/PQ3A.190605.003/5524043:user/release-keys
- // See https://source.android.com/compatibility/android-cdd.html#3_2_2_build_parameters
- // for the expected format of this field.
- string build_fingerprint = 3;
-}
-
-message SignedFirmwareImageInfo {
- FirmwareImageInfo image_info = 1;
- sigpb.DigitallySigned image_info_signature = 2;
-}
-
-
-message InclusionProof {
- trillian.Proof proof = 1;
- trillian.SignedLogRoot sth = 2;
-}
-
-// Trillian-specific data types
-message Leaf {
- int32 version = 1;
-
- // Timestamp when the entry was added to the log.
- google.protobuf.Timestamp timestamp = 2;
-
- oneof value {
- bytes vbmeta = 3;
- FirmwareInfoAnnotation fw_info = 4;
- FirmwareImageInfoAnnotation fw_image_info = 5;
- }
-}
-
-message FirmwareInfoAnnotation {
- SignedFirmwareInfo info = 1;
-}
-
-message FirmwareImageInfoAnnotation {
- SignedFirmwareImageInfo info = 1;
-
- // URL of the firmware image in the Cloud Storage bucket populated by AFTL.
- string url = 2;
-}
diff --git a/proto/aftl_pb2.py b/proto/aftl_pb2.py
deleted file mode 100644
index ed811ae..0000000
--- a/proto/aftl_pb2.py
+++ /dev/null
@@ -1,469 +0,0 @@
-# -*- coding: utf-8 -*-
-# Generated by the protocol buffer compiler. DO NOT EDIT!
-# source: aftl.proto
-
-import sys
-_b=sys.version_info[0]<3 and (lambda x:x) or (lambda x:x.encode('latin1'))
-from google.protobuf import descriptor as _descriptor
-from google.protobuf import message as _message
-from google.protobuf import reflection as _reflection
-from google.protobuf import symbol_database as _symbol_database
-# @@protoc_insertion_point(imports)
-
-_sym_db = _symbol_database.Default()
-
-
-import trillian_pb2 as trillian__pb2
-from crypto.sigpb import sigpb_pb2 as crypto_dot_sigpb_dot_sigpb__pb2
-from google.protobuf import timestamp_pb2 as google_dot_protobuf_dot_timestamp__pb2
-
-
-DESCRIPTOR = _descriptor.FileDescriptor(
- name='aftl.proto',
- package='aftl',
- syntax='proto3',
- serialized_options=_b('Z\005proto'),
- serialized_pb=_b('\n\naftl.proto\x12\x04\x61\x66tl\x1a\x0etrillian.proto\x1a\x18\x63rypto/sigpb/sigpb.proto\x1a\x1fgoogle/protobuf/timestamp.proto\"\x8a\x01\n\x0c\x46irmwareInfo\x12\x13\n\x0bvbmeta_hash\x18\x01 \x01(\x0c\x12\x1b\n\x13version_incremental\x18\x02 \x01(\t\x12\x14\n\x0cplatform_key\x18\x03 \x01(\x0c\x12\x1d\n\x15manufacturer_key_hash\x18\x04 \x01(\x0c\x12\x13\n\x0b\x64\x65scription\x18\x05 \x01(\t\"f\n\x12SignedFirmwareInfo\x12 \n\x04info\x18\x01 \x01(\x0b\x32\x12.aftl.FirmwareInfo\x12.\n\x0einfo_signature\x18\x02 \x01(\x0b\x32\x16.sigpb.DigitallySigned\"Q\n\x11\x46irmwareImageInfo\x12\x13\n\x0bvbmeta_hash\x18\x01 \x01(\x0c\x12\x0c\n\x04hash\x18\x02 \x01(\x0c\x12\x19\n\x11\x62uild_fingerprint\x18\x03 \x01(\t\"|\n\x17SignedFirmwareImageInfo\x12+\n\nimage_info\x18\x01 \x01(\x0b\x32\x17.aftl.FirmwareImageInfo\x12\x34\n\x14image_info_signature\x18\x02 \x01(\x0b\x32\x16.sigpb.DigitallySigned\"V\n\x0eInclusionProof\x12\x1e\n\x05proof\x18\x01 \x01(\x0b\x32\x0f.trillian.Proof\x12$\n\x03sth\x18\x02 \x01(\x0b\x32\x17.trillian.SignedLogRoot\"\xce\x01\n\x04Leaf\x12\x0f\n\x07version\x18\x01 \x01(\x05\x12-\n\ttimestamp\x18\x02 \x01(\x0b\x32\x1a.google.protobuf.Timestamp\x12\x10\n\x06vbmeta\x18\x03 \x01(\x0cH\x00\x12/\n\x07\x66w_info\x18\x04 \x01(\x0b\x32\x1c.aftl.FirmwareInfoAnnotationH\x00\x12:\n\rfw_image_info\x18\x05 \x01(\x0b\x32!.aftl.FirmwareImageInfoAnnotationH\x00\x42\x07\n\x05value\"@\n\x16\x46irmwareInfoAnnotation\x12&\n\x04info\x18\x01 \x01(\x0b\x32\x18.aftl.SignedFirmwareInfo\"W\n\x1b\x46irmwareImageInfoAnnotation\x12+\n\x04info\x18\x01 \x01(\x0b\x32\x1d.aftl.SignedFirmwareImageInfo\x12\x0b\n\x03url\x18\x02 \x01(\tB\x07Z\x05protob\x06proto3')
- ,
- dependencies=[trillian__pb2.DESCRIPTOR,crypto_dot_sigpb_dot_sigpb__pb2.DESCRIPTOR,google_dot_protobuf_dot_timestamp__pb2.DESCRIPTOR,])
-
-
-
-
-_FIRMWAREINFO = _descriptor.Descriptor(
- name='FirmwareInfo',
- full_name='aftl.FirmwareInfo',
- filename=None,
- file=DESCRIPTOR,
- containing_type=None,
- fields=[
- _descriptor.FieldDescriptor(
- name='vbmeta_hash', full_name='aftl.FirmwareInfo.vbmeta_hash', index=0,
- number=1, type=12, cpp_type=9, label=1,
- has_default_value=False, default_value=_b(""),
- message_type=None, enum_type=None, containing_type=None,
- is_extension=False, extension_scope=None,
- serialized_options=None, file=DESCRIPTOR),
- _descriptor.FieldDescriptor(
- name='version_incremental', full_name='aftl.FirmwareInfo.version_incremental', index=1,
- number=2, type=9, cpp_type=9, label=1,
- has_default_value=False, default_value=_b("").decode('utf-8'),
- message_type=None, enum_type=None, containing_type=None,
- is_extension=False, extension_scope=None,
- serialized_options=None, file=DESCRIPTOR),
- _descriptor.FieldDescriptor(
- name='platform_key', full_name='aftl.FirmwareInfo.platform_key', index=2,
- number=3, type=12, cpp_type=9, label=1,
- has_default_value=False, default_value=_b(""),
- message_type=None, enum_type=None, containing_type=None,
- is_extension=False, extension_scope=None,
- serialized_options=None, file=DESCRIPTOR),
- _descriptor.FieldDescriptor(
- name='manufacturer_key_hash', full_name='aftl.FirmwareInfo.manufacturer_key_hash', index=3,
- number=4, type=12, cpp_type=9, label=1,
- has_default_value=False, default_value=_b(""),
- message_type=None, enum_type=None, containing_type=None,
- is_extension=False, extension_scope=None,
- serialized_options=None, file=DESCRIPTOR),
- _descriptor.FieldDescriptor(
- name='description', full_name='aftl.FirmwareInfo.description', index=4,
- number=5, type=9, cpp_type=9, label=1,
- has_default_value=False, default_value=_b("").decode('utf-8'),
- message_type=None, enum_type=None, containing_type=None,
- is_extension=False, extension_scope=None,
- serialized_options=None, file=DESCRIPTOR),
- ],
- extensions=[
- ],
- nested_types=[],
- enum_types=[
- ],
- serialized_options=None,
- is_extendable=False,
- syntax='proto3',
- extension_ranges=[],
- oneofs=[
- ],
- serialized_start=96,
- serialized_end=234,
-)
-
-
-_SIGNEDFIRMWAREINFO = _descriptor.Descriptor(
- name='SignedFirmwareInfo',
- full_name='aftl.SignedFirmwareInfo',
- filename=None,
- file=DESCRIPTOR,
- containing_type=None,
- fields=[
- _descriptor.FieldDescriptor(
- name='info', full_name='aftl.SignedFirmwareInfo.info', index=0,
- number=1, type=11, cpp_type=10, label=1,
- has_default_value=False, default_value=None,
- message_type=None, enum_type=None, containing_type=None,
- is_extension=False, extension_scope=None,
- serialized_options=None, file=DESCRIPTOR),
- _descriptor.FieldDescriptor(
- name='info_signature', full_name='aftl.SignedFirmwareInfo.info_signature', index=1,
- number=2, type=11, cpp_type=10, label=1,
- has_default_value=False, default_value=None,
- message_type=None, enum_type=None, containing_type=None,
- is_extension=False, extension_scope=None,
- serialized_options=None, file=DESCRIPTOR),
- ],
- extensions=[
- ],
- nested_types=[],
- enum_types=[
- ],
- serialized_options=None,
- is_extendable=False,
- syntax='proto3',
- extension_ranges=[],
- oneofs=[
- ],
- serialized_start=236,
- serialized_end=338,
-)
-
-
-_FIRMWAREIMAGEINFO = _descriptor.Descriptor(
- name='FirmwareImageInfo',
- full_name='aftl.FirmwareImageInfo',
- filename=None,
- file=DESCRIPTOR,
- containing_type=None,
- fields=[
- _descriptor.FieldDescriptor(
- name='vbmeta_hash', full_name='aftl.FirmwareImageInfo.vbmeta_hash', index=0,
- number=1, type=12, cpp_type=9, label=1,
- has_default_value=False, default_value=_b(""),
- message_type=None, enum_type=None, containing_type=None,
- is_extension=False, extension_scope=None,
- serialized_options=None, file=DESCRIPTOR),
- _descriptor.FieldDescriptor(
- name='hash', full_name='aftl.FirmwareImageInfo.hash', index=1,
- number=2, type=12, cpp_type=9, label=1,
- has_default_value=False, default_value=_b(""),
- message_type=None, enum_type=None, containing_type=None,
- is_extension=False, extension_scope=None,
- serialized_options=None, file=DESCRIPTOR),
- _descriptor.FieldDescriptor(
- name='build_fingerprint', full_name='aftl.FirmwareImageInfo.build_fingerprint', index=2,
- number=3, type=9, cpp_type=9, label=1,
- has_default_value=False, default_value=_b("").decode('utf-8'),
- message_type=None, enum_type=None, containing_type=None,
- is_extension=False, extension_scope=None,
- serialized_options=None, file=DESCRIPTOR),
- ],
- extensions=[
- ],
- nested_types=[],
- enum_types=[
- ],
- serialized_options=None,
- is_extendable=False,
- syntax='proto3',
- extension_ranges=[],
- oneofs=[
- ],
- serialized_start=340,
- serialized_end=421,
-)
-
-
-_SIGNEDFIRMWAREIMAGEINFO = _descriptor.Descriptor(
- name='SignedFirmwareImageInfo',
- full_name='aftl.SignedFirmwareImageInfo',
- filename=None,
- file=DESCRIPTOR,
- containing_type=None,
- fields=[
- _descriptor.FieldDescriptor(
- name='image_info', full_name='aftl.SignedFirmwareImageInfo.image_info', index=0,
- number=1, type=11, cpp_type=10, label=1,
- has_default_value=False, default_value=None,
- message_type=None, enum_type=None, containing_type=None,
- is_extension=False, extension_scope=None,
- serialized_options=None, file=DESCRIPTOR),
- _descriptor.FieldDescriptor(
- name='image_info_signature', full_name='aftl.SignedFirmwareImageInfo.image_info_signature', index=1,
- number=2, type=11, cpp_type=10, label=1,
- has_default_value=False, default_value=None,
- message_type=None, enum_type=None, containing_type=None,
- is_extension=False, extension_scope=None,
- serialized_options=None, file=DESCRIPTOR),
- ],
- extensions=[
- ],
- nested_types=[],
- enum_types=[
- ],
- serialized_options=None,
- is_extendable=False,
- syntax='proto3',
- extension_ranges=[],
- oneofs=[
- ],
- serialized_start=423,
- serialized_end=547,
-)
-
-
-_INCLUSIONPROOF = _descriptor.Descriptor(
- name='InclusionProof',
- full_name='aftl.InclusionProof',
- filename=None,
- file=DESCRIPTOR,
- containing_type=None,
- fields=[
- _descriptor.FieldDescriptor(
- name='proof', full_name='aftl.InclusionProof.proof', index=0,
- number=1, type=11, cpp_type=10, label=1,
- has_default_value=False, default_value=None,
- message_type=None, enum_type=None, containing_type=None,
- is_extension=False, extension_scope=None,
- serialized_options=None, file=DESCRIPTOR),
- _descriptor.FieldDescriptor(
- name='sth', full_name='aftl.InclusionProof.sth', index=1,
- number=2, type=11, cpp_type=10, label=1,
- has_default_value=False, default_value=None,
- message_type=None, enum_type=None, containing_type=None,
- is_extension=False, extension_scope=None,
- serialized_options=None, file=DESCRIPTOR),
- ],
- extensions=[
- ],
- nested_types=[],
- enum_types=[
- ],
- serialized_options=None,
- is_extendable=False,
- syntax='proto3',
- extension_ranges=[],
- oneofs=[
- ],
- serialized_start=549,
- serialized_end=635,
-)
-
-
-_LEAF = _descriptor.Descriptor(
- name='Leaf',
- full_name='aftl.Leaf',
- filename=None,
- file=DESCRIPTOR,
- containing_type=None,
- fields=[
- _descriptor.FieldDescriptor(
- name='version', full_name='aftl.Leaf.version', index=0,
- number=1, type=5, cpp_type=1, label=1,
- has_default_value=False, default_value=0,
- message_type=None, enum_type=None, containing_type=None,
- is_extension=False, extension_scope=None,
- serialized_options=None, file=DESCRIPTOR),
- _descriptor.FieldDescriptor(
- name='timestamp', full_name='aftl.Leaf.timestamp', index=1,
- number=2, type=11, cpp_type=10, label=1,
- has_default_value=False, default_value=None,
- message_type=None, enum_type=None, containing_type=None,
- is_extension=False, extension_scope=None,
- serialized_options=None, file=DESCRIPTOR),
- _descriptor.FieldDescriptor(
- name='vbmeta', full_name='aftl.Leaf.vbmeta', index=2,
- number=3, type=12, cpp_type=9, label=1,
- has_default_value=False, default_value=_b(""),
- message_type=None, enum_type=None, containing_type=None,
- is_extension=False, extension_scope=None,
- serialized_options=None, file=DESCRIPTOR),
- _descriptor.FieldDescriptor(
- name='fw_info', full_name='aftl.Leaf.fw_info', index=3,
- number=4, type=11, cpp_type=10, label=1,
- has_default_value=False, default_value=None,
- message_type=None, enum_type=None, containing_type=None,
- is_extension=False, extension_scope=None,
- serialized_options=None, file=DESCRIPTOR),
- _descriptor.FieldDescriptor(
- name='fw_image_info', full_name='aftl.Leaf.fw_image_info', index=4,
- number=5, type=11, cpp_type=10, label=1,
- has_default_value=False, default_value=None,
- message_type=None, enum_type=None, containing_type=None,
- is_extension=False, extension_scope=None,
- serialized_options=None, file=DESCRIPTOR),
- ],
- extensions=[
- ],
- nested_types=[],
- enum_types=[
- ],
- serialized_options=None,
- is_extendable=False,
- syntax='proto3',
- extension_ranges=[],
- oneofs=[
- _descriptor.OneofDescriptor(
- name='value', full_name='aftl.Leaf.value',
- index=0, containing_type=None, fields=[]),
- ],
- serialized_start=638,
- serialized_end=844,
-)
-
-
-_FIRMWAREINFOANNOTATION = _descriptor.Descriptor(
- name='FirmwareInfoAnnotation',
- full_name='aftl.FirmwareInfoAnnotation',
- filename=None,
- file=DESCRIPTOR,
- containing_type=None,
- fields=[
- _descriptor.FieldDescriptor(
- name='info', full_name='aftl.FirmwareInfoAnnotation.info', index=0,
- number=1, type=11, cpp_type=10, label=1,
- has_default_value=False, default_value=None,
- message_type=None, enum_type=None, containing_type=None,
- is_extension=False, extension_scope=None,
- serialized_options=None, file=DESCRIPTOR),
- ],
- extensions=[
- ],
- nested_types=[],
- enum_types=[
- ],
- serialized_options=None,
- is_extendable=False,
- syntax='proto3',
- extension_ranges=[],
- oneofs=[
- ],
- serialized_start=846,
- serialized_end=910,
-)
-
-
-_FIRMWAREIMAGEINFOANNOTATION = _descriptor.Descriptor(
- name='FirmwareImageInfoAnnotation',
- full_name='aftl.FirmwareImageInfoAnnotation',
- filename=None,
- file=DESCRIPTOR,
- containing_type=None,
- fields=[
- _descriptor.FieldDescriptor(
- name='info', full_name='aftl.FirmwareImageInfoAnnotation.info', index=0,
- number=1, type=11, cpp_type=10, label=1,
- has_default_value=False, default_value=None,
- message_type=None, enum_type=None, containing_type=None,
- is_extension=False, extension_scope=None,
- serialized_options=None, file=DESCRIPTOR),
- _descriptor.FieldDescriptor(
- name='url', full_name='aftl.FirmwareImageInfoAnnotation.url', index=1,
- number=2, type=9, cpp_type=9, label=1,
- has_default_value=False, default_value=_b("").decode('utf-8'),
- message_type=None, enum_type=None, containing_type=None,
- is_extension=False, extension_scope=None,
- serialized_options=None, file=DESCRIPTOR),
- ],
- extensions=[
- ],
- nested_types=[],
- enum_types=[
- ],
- serialized_options=None,
- is_extendable=False,
- syntax='proto3',
- extension_ranges=[],
- oneofs=[
- ],
- serialized_start=912,
- serialized_end=999,
-)
-
-_SIGNEDFIRMWAREINFO.fields_by_name['info'].message_type = _FIRMWAREINFO
-_SIGNEDFIRMWAREINFO.fields_by_name['info_signature'].message_type = crypto_dot_sigpb_dot_sigpb__pb2._DIGITALLYSIGNED
-_SIGNEDFIRMWAREIMAGEINFO.fields_by_name['image_info'].message_type = _FIRMWAREIMAGEINFO
-_SIGNEDFIRMWAREIMAGEINFO.fields_by_name['image_info_signature'].message_type = crypto_dot_sigpb_dot_sigpb__pb2._DIGITALLYSIGNED
-_INCLUSIONPROOF.fields_by_name['proof'].message_type = trillian__pb2._PROOF
-_INCLUSIONPROOF.fields_by_name['sth'].message_type = trillian__pb2._SIGNEDLOGROOT
-_LEAF.fields_by_name['timestamp'].message_type = google_dot_protobuf_dot_timestamp__pb2._TIMESTAMP
-_LEAF.fields_by_name['fw_info'].message_type = _FIRMWAREINFOANNOTATION
-_LEAF.fields_by_name['fw_image_info'].message_type = _FIRMWAREIMAGEINFOANNOTATION
-_LEAF.oneofs_by_name['value'].fields.append(
- _LEAF.fields_by_name['vbmeta'])
-_LEAF.fields_by_name['vbmeta'].containing_oneof = _LEAF.oneofs_by_name['value']
-_LEAF.oneofs_by_name['value'].fields.append(
- _LEAF.fields_by_name['fw_info'])
-_LEAF.fields_by_name['fw_info'].containing_oneof = _LEAF.oneofs_by_name['value']
-_LEAF.oneofs_by_name['value'].fields.append(
- _LEAF.fields_by_name['fw_image_info'])
-_LEAF.fields_by_name['fw_image_info'].containing_oneof = _LEAF.oneofs_by_name['value']
-_FIRMWAREINFOANNOTATION.fields_by_name['info'].message_type = _SIGNEDFIRMWAREINFO
-_FIRMWAREIMAGEINFOANNOTATION.fields_by_name['info'].message_type = _SIGNEDFIRMWAREIMAGEINFO
-DESCRIPTOR.message_types_by_name['FirmwareInfo'] = _FIRMWAREINFO
-DESCRIPTOR.message_types_by_name['SignedFirmwareInfo'] = _SIGNEDFIRMWAREINFO
-DESCRIPTOR.message_types_by_name['FirmwareImageInfo'] = _FIRMWAREIMAGEINFO
-DESCRIPTOR.message_types_by_name['SignedFirmwareImageInfo'] = _SIGNEDFIRMWAREIMAGEINFO
-DESCRIPTOR.message_types_by_name['InclusionProof'] = _INCLUSIONPROOF
-DESCRIPTOR.message_types_by_name['Leaf'] = _LEAF
-DESCRIPTOR.message_types_by_name['FirmwareInfoAnnotation'] = _FIRMWAREINFOANNOTATION
-DESCRIPTOR.message_types_by_name['FirmwareImageInfoAnnotation'] = _FIRMWAREIMAGEINFOANNOTATION
-_sym_db.RegisterFileDescriptor(DESCRIPTOR)
-
-FirmwareInfo = _reflection.GeneratedProtocolMessageType('FirmwareInfo', (_message.Message,), {
- 'DESCRIPTOR' : _FIRMWAREINFO,
- '__module__' : 'aftl_pb2'
- # @@protoc_insertion_point(class_scope:aftl.FirmwareInfo)
- })
-_sym_db.RegisterMessage(FirmwareInfo)
-
-SignedFirmwareInfo = _reflection.GeneratedProtocolMessageType('SignedFirmwareInfo', (_message.Message,), {
- 'DESCRIPTOR' : _SIGNEDFIRMWAREINFO,
- '__module__' : 'aftl_pb2'
- # @@protoc_insertion_point(class_scope:aftl.SignedFirmwareInfo)
- })
-_sym_db.RegisterMessage(SignedFirmwareInfo)
-
-FirmwareImageInfo = _reflection.GeneratedProtocolMessageType('FirmwareImageInfo', (_message.Message,), {
- 'DESCRIPTOR' : _FIRMWAREIMAGEINFO,
- '__module__' : 'aftl_pb2'
- # @@protoc_insertion_point(class_scope:aftl.FirmwareImageInfo)
- })
-_sym_db.RegisterMessage(FirmwareImageInfo)
-
-SignedFirmwareImageInfo = _reflection.GeneratedProtocolMessageType('SignedFirmwareImageInfo', (_message.Message,), {
- 'DESCRIPTOR' : _SIGNEDFIRMWAREIMAGEINFO,
- '__module__' : 'aftl_pb2'
- # @@protoc_insertion_point(class_scope:aftl.SignedFirmwareImageInfo)
- })
-_sym_db.RegisterMessage(SignedFirmwareImageInfo)
-
-InclusionProof = _reflection.GeneratedProtocolMessageType('InclusionProof', (_message.Message,), {
- 'DESCRIPTOR' : _INCLUSIONPROOF,
- '__module__' : 'aftl_pb2'
- # @@protoc_insertion_point(class_scope:aftl.InclusionProof)
- })
-_sym_db.RegisterMessage(InclusionProof)
-
-Leaf = _reflection.GeneratedProtocolMessageType('Leaf', (_message.Message,), {
- 'DESCRIPTOR' : _LEAF,
- '__module__' : 'aftl_pb2'
- # @@protoc_insertion_point(class_scope:aftl.Leaf)
- })
-_sym_db.RegisterMessage(Leaf)
-
-FirmwareInfoAnnotation = _reflection.GeneratedProtocolMessageType('FirmwareInfoAnnotation', (_message.Message,), {
- 'DESCRIPTOR' : _FIRMWAREINFOANNOTATION,
- '__module__' : 'aftl_pb2'
- # @@protoc_insertion_point(class_scope:aftl.FirmwareInfoAnnotation)
- })
-_sym_db.RegisterMessage(FirmwareInfoAnnotation)
-
-FirmwareImageInfoAnnotation = _reflection.GeneratedProtocolMessageType('FirmwareImageInfoAnnotation', (_message.Message,), {
- 'DESCRIPTOR' : _FIRMWAREIMAGEINFOANNOTATION,
- '__module__' : 'aftl_pb2'
- # @@protoc_insertion_point(class_scope:aftl.FirmwareImageInfoAnnotation)
- })
-_sym_db.RegisterMessage(FirmwareImageInfoAnnotation)
-
-
-DESCRIPTOR._options = None
-# @@protoc_insertion_point(module_scope)
diff --git a/proto/aftl_pb2_grpc.py b/proto/aftl_pb2_grpc.py
deleted file mode 100644
index a894352..0000000
--- a/proto/aftl_pb2_grpc.py
+++ /dev/null
@@ -1,3 +0,0 @@
-# Generated by the gRPC Python protocol compiler plugin. DO NOT EDIT!
-import grpc
-
diff --git a/proto/api.proto b/proto/api.proto
index 4c66333..e22ae47 100644
--- a/proto/api.proto
+++ b/proto/api.proto
@@ -1,4 +1,4 @@
-// Copyright 2019 Google LLC
+// Copyright 2019-2020 Google LLC
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
@@ -17,27 +17,35 @@
package aftl;
option go_package = "proto";
-import "aftl.proto";
+import "trillian.proto";
-message AddFirmwareInfoRequest {
+message InclusionProof {
+ trillian.Proof proof = 1;
+ trillian.SignedLogRoot sth = 2;
+}
+
+message AddVBMetaRequest {
// VBMeta structure as described in
// https://android.googlesource.com/platform/external/avb/+/master/README.md.
// In case of chained partitions, each VBMeta is added via a separate call.
// The default size for gRPC payload is about 4MB. We expect vbmeta to be
- // in the order of 1kB.
+ // in the order of 64kB.
bytes vbmeta = 1;
- SignedFirmwareInfo fw_info = 2;
+ // Serialized SignedVBMetaPrimaryAnnotation. This annotation contains the hash
+ // of the vbmeta structure. It is signed using the manufacturer key.
+ // See types/types.go.
+ bytes signed_vbmeta_primary_annotation = 2;
}
-message AddFirmwareInfoResponse {
+message AddVBMetaResponse {
// Inclusion proof and the leaf that was added to the log, which contains
- // information on the firmware.
+ // the annotation on VBMeta.
// It is required to have the complete leaf to validate the inclusion proof.
// For on-device verification, only these first 2 fields are required to
// validate the inclusion.
- InclusionProof fw_info_proof = 1;
- bytes fw_info_leaf = 2;
+ InclusionProof annotation_proof = 1;
+ bytes annotation_leaf = 2;
// Inclusion proof and leaf that was added to the log, which contains the full
// vbmeta partition.
@@ -47,12 +55,13 @@
bytes vbmeta_leaf = 4;
}
-message AddFirmwareImageRequest {
+message AnnotateVBMetaWithBuildRequest {
+ // Serialized SignedVBMetaBuildAnnotation. This annotation contains the hash
+ // of the full build image. See types/types.go.
+ bytes signed_vbmeta_build_annotation = 1;
- SignedFirmwareImageInfo fw_image_info = 1;
-
- // Bytes of the binary images. These are not signed as their final
- // hash value is already signed in fw_image_info.hash
+ // Bytes of the binary images. The hash value of the concatenation of these
+ // chunk is contained in SignedVBMetaBuildAnnotation.
// This is ignored if any of the requests origin_url is set.
bytes image_chunk = 2;
@@ -61,14 +70,13 @@
string origin_url = 3;
}
-message AddFirmwareImageResponse {
-
+message AnnotateVBMetaWithBuildResponse {
// Inclusion proof and leaf for the firmware image. The leaf contains the URL
// where the image was stored.
// It is not required for vendors to keep this information. However, this can
// be used for their records to ensure the correctness of the log.
- InclusionProof fw_image_info_proof = 1;
- Leaf fw_image_info_leaf = 2;
+ InclusionProof annotation_proof = 1;
+ bytes annotation_leaf = 2;
}
service AFTLog {
@@ -76,12 +84,11 @@
// Insert a new VBMeta structure into the log.
// This request will effectively create 2 log entries:
// - VBMeta itself
- // - Vendor annotations, including a reference to the VBMeta leaf.
- rpc AddFirmwareInfo(AddFirmwareInfoRequest) returns (AddFirmwareInfoResponse) {}
+ // - Vendor annotations, which includes a reference to the VBMeta.
+ rpc AddVBMeta(AddVBMetaRequest) returns (AddVBMetaResponse) {}
// Upload (or copy) the complete firmware image.
- rpc AddFirmwareImage(stream AddFirmwareImageRequest) returns (AddFirmwareImageResponse) {}
+ rpc AnnotateVBMetaWithBuild(stream AnnotateVBMetaWithBuildResponse) returns (AnnotateVBMetaWithBuildResponse) {}
- // TODO GetProofByHash, GetSthConsistency, GetEntries, GetRootKeys
+ // TODO(tweek): GetProofByHash, GetSthConsistency, GetEntries, GetRootKeys
}
-
diff --git a/proto/api_pb2.py b/proto/api_pb2.py
index f8f9a01..fbe3bab 100644
--- a/proto/api_pb2.py
+++ b/proto/api_pb2.py
@@ -1,4 +1,3 @@
-# pylint: skip-file
# -*- coding: utf-8 -*-
# Generated by the protocol buffer compiler. DO NOT EDIT!
# source: api.proto
@@ -14,7 +13,7 @@
_sym_db = _symbol_database.Default()
-import aftl_pb2 as aftl__pb2
+import trillian_pb2 as trillian__pb2
DESCRIPTOR = _descriptor.FileDescriptor(
@@ -22,29 +21,29 @@
package='aftl',
syntax='proto3',
serialized_options=_b('Z\005proto'),
- serialized_pb=_b('\n\tapi.proto\x12\x04\x61\x66tl\x1a\naftl.proto\"S\n\x16\x41\x64\x64\x46irmwareInfoRequest\x12\x0e\n\x06vbmeta\x18\x01 \x01(\x0c\x12)\n\x07\x66w_info\x18\x02 \x01(\x0b\x32\x18.aftl.SignedFirmwareInfo\"\x9d\x01\n\x17\x41\x64\x64\x46irmwareInfoResponse\x12+\n\rfw_info_proof\x18\x01 \x01(\x0b\x32\x14.aftl.InclusionProof\x12\x14\n\x0c\x66w_info_leaf\x18\x02 \x01(\x0c\x12*\n\x0cvbmeta_proof\x18\x03 \x01(\x0b\x32\x14.aftl.InclusionProof\x12\x13\n\x0bvbmeta_leaf\x18\x04 \x01(\x0c\"x\n\x17\x41\x64\x64\x46irmwareImageRequest\x12\x34\n\rfw_image_info\x18\x01 \x01(\x0b\x32\x1d.aftl.SignedFirmwareImageInfo\x12\x13\n\x0bimage_chunk\x18\x02 \x01(\x0c\x12\x12\n\norigin_url\x18\x03 \x01(\t\"u\n\x18\x41\x64\x64\x46irmwareImageResponse\x12\x31\n\x13\x66w_image_info_proof\x18\x01 \x01(\x0b\x32\x14.aftl.InclusionProof\x12&\n\x12\x66w_image_info_leaf\x18\x02 \x01(\x0b\x32\n.aftl.Leaf2\xb1\x01\n\x06\x41\x46TLog\x12P\n\x0f\x41\x64\x64\x46irmwareInfo\x12\x1c.aftl.AddFirmwareInfoRequest\x1a\x1d.aftl.AddFirmwareInfoResponse\"\x00\x12U\n\x10\x41\x64\x64\x46irmwareImage\x12\x1d.aftl.AddFirmwareImageRequest\x1a\x1e.aftl.AddFirmwareImageResponse\"\x00(\x01\x42\x07Z\x05protob\x06proto3')
+ serialized_pb=_b('\n\tapi.proto\x12\x04\x61\x66tl\x1a\x0etrillian.proto\"V\n\x0eInclusionProof\x12\x1e\n\x05proof\x18\x01 \x01(\x0b\x32\x0f.trillian.Proof\x12$\n\x03sth\x18\x02 \x01(\x0b\x32\x17.trillian.SignedLogRoot\"L\n\x10\x41\x64\x64VBMetaRequest\x12\x0e\n\x06vbmeta\x18\x01 \x01(\x0c\x12(\n signed_vbmeta_primary_annotation\x18\x02 \x01(\x0c\"\x9d\x01\n\x11\x41\x64\x64VBMetaResponse\x12.\n\x10\x61nnotation_proof\x18\x01 \x01(\x0b\x32\x14.aftl.InclusionProof\x12\x17\n\x0f\x61nnotation_leaf\x18\x02 \x01(\x0c\x12*\n\x0cvbmeta_proof\x18\x03 \x01(\x0b\x32\x14.aftl.InclusionProof\x12\x13\n\x0bvbmeta_leaf\x18\x04 \x01(\x0c\"q\n\x1e\x41nnotateVBMetaWithBuildRequest\x12&\n\x1esigned_vbmeta_build_annotation\x18\x01 \x01(\x0c\x12\x13\n\x0bimage_chunk\x18\x02 \x01(\x0c\x12\x12\n\norigin_url\x18\x03 \x01(\t\"j\n\x1f\x41nnotateVBMetaWithBuildResponse\x12.\n\x10\x61nnotation_proof\x18\x01 \x01(\x0b\x32\x14.aftl.InclusionProof\x12\x17\n\x0f\x61nnotation_leaf\x18\x02 \x01(\x0c\x32\xb5\x01\n\x06\x41\x46TLog\x12>\n\tAddVBMeta\x12\x16.aftl.AddVBMetaRequest\x1a\x17.aftl.AddVBMetaResponse\"\x00\x12k\n\x17\x41nnotateVBMetaWithBuild\x12%.aftl.AnnotateVBMetaWithBuildResponse\x1a%.aftl.AnnotateVBMetaWithBuildResponse\"\x00(\x01\x42\x07Z\x05protob\x06proto3')
,
- dependencies=[aftl__pb2.DESCRIPTOR,])
+ dependencies=[trillian__pb2.DESCRIPTOR,])
-_ADDFIRMWAREINFOREQUEST = _descriptor.Descriptor(
- name='AddFirmwareInfoRequest',
- full_name='aftl.AddFirmwareInfoRequest',
+_INCLUSIONPROOF = _descriptor.Descriptor(
+ name='InclusionProof',
+ full_name='aftl.InclusionProof',
filename=None,
file=DESCRIPTOR,
containing_type=None,
fields=[
_descriptor.FieldDescriptor(
- name='vbmeta', full_name='aftl.AddFirmwareInfoRequest.vbmeta', index=0,
- number=1, type=12, cpp_type=9, label=1,
- has_default_value=False, default_value=_b(""),
+ name='proof', full_name='aftl.InclusionProof.proof', index=0,
+ number=1, type=11, cpp_type=10, label=1,
+ has_default_value=False, default_value=None,
message_type=None, enum_type=None, containing_type=None,
is_extension=False, extension_scope=None,
serialized_options=None, file=DESCRIPTOR),
_descriptor.FieldDescriptor(
- name='fw_info', full_name='aftl.AddFirmwareInfoRequest.fw_info', index=1,
+ name='sth', full_name='aftl.InclusionProof.sth', index=1,
number=2, type=11, cpp_type=10, label=1,
has_default_value=False, default_value=None,
message_type=None, enum_type=None, containing_type=None,
@@ -62,41 +61,79 @@
extension_ranges=[],
oneofs=[
],
- serialized_start=31,
- serialized_end=114,
+ serialized_start=35,
+ serialized_end=121,
)
-_ADDFIRMWAREINFORESPONSE = _descriptor.Descriptor(
- name='AddFirmwareInfoResponse',
- full_name='aftl.AddFirmwareInfoResponse',
+_ADDVBMETAREQUEST = _descriptor.Descriptor(
+ name='AddVBMetaRequest',
+ full_name='aftl.AddVBMetaRequest',
filename=None,
file=DESCRIPTOR,
containing_type=None,
fields=[
_descriptor.FieldDescriptor(
- name='fw_info_proof', full_name='aftl.AddFirmwareInfoResponse.fw_info_proof', index=0,
+ name='vbmeta', full_name='aftl.AddVBMetaRequest.vbmeta', index=0,
+ number=1, type=12, cpp_type=9, label=1,
+ has_default_value=False, default_value=_b(""),
+ message_type=None, enum_type=None, containing_type=None,
+ is_extension=False, extension_scope=None,
+ serialized_options=None, file=DESCRIPTOR),
+ _descriptor.FieldDescriptor(
+ name='signed_vbmeta_primary_annotation', full_name='aftl.AddVBMetaRequest.signed_vbmeta_primary_annotation', index=1,
+ number=2, type=12, cpp_type=9, label=1,
+ has_default_value=False, default_value=_b(""),
+ message_type=None, enum_type=None, containing_type=None,
+ is_extension=False, extension_scope=None,
+ serialized_options=None, file=DESCRIPTOR),
+ ],
+ extensions=[
+ ],
+ nested_types=[],
+ enum_types=[
+ ],
+ serialized_options=None,
+ is_extendable=False,
+ syntax='proto3',
+ extension_ranges=[],
+ oneofs=[
+ ],
+ serialized_start=123,
+ serialized_end=199,
+)
+
+
+_ADDVBMETARESPONSE = _descriptor.Descriptor(
+ name='AddVBMetaResponse',
+ full_name='aftl.AddVBMetaResponse',
+ filename=None,
+ file=DESCRIPTOR,
+ containing_type=None,
+ fields=[
+ _descriptor.FieldDescriptor(
+ name='annotation_proof', full_name='aftl.AddVBMetaResponse.annotation_proof', index=0,
number=1, type=11, cpp_type=10, label=1,
has_default_value=False, default_value=None,
message_type=None, enum_type=None, containing_type=None,
is_extension=False, extension_scope=None,
serialized_options=None, file=DESCRIPTOR),
_descriptor.FieldDescriptor(
- name='fw_info_leaf', full_name='aftl.AddFirmwareInfoResponse.fw_info_leaf', index=1,
+ name='annotation_leaf', full_name='aftl.AddVBMetaResponse.annotation_leaf', index=1,
number=2, type=12, cpp_type=9, label=1,
has_default_value=False, default_value=_b(""),
message_type=None, enum_type=None, containing_type=None,
is_extension=False, extension_scope=None,
serialized_options=None, file=DESCRIPTOR),
_descriptor.FieldDescriptor(
- name='vbmeta_proof', full_name='aftl.AddFirmwareInfoResponse.vbmeta_proof', index=2,
+ name='vbmeta_proof', full_name='aftl.AddVBMetaResponse.vbmeta_proof', index=2,
number=3, type=11, cpp_type=10, label=1,
has_default_value=False, default_value=None,
message_type=None, enum_type=None, containing_type=None,
is_extension=False, extension_scope=None,
serialized_options=None, file=DESCRIPTOR),
_descriptor.FieldDescriptor(
- name='vbmeta_leaf', full_name='aftl.AddFirmwareInfoResponse.vbmeta_leaf', index=3,
+ name='vbmeta_leaf', full_name='aftl.AddVBMetaResponse.vbmeta_leaf', index=3,
number=4, type=12, cpp_type=9, label=1,
has_default_value=False, default_value=_b(""),
message_type=None, enum_type=None, containing_type=None,
@@ -114,34 +151,34 @@
extension_ranges=[],
oneofs=[
],
- serialized_start=117,
- serialized_end=274,
+ serialized_start=202,
+ serialized_end=359,
)
-_ADDFIRMWAREIMAGEREQUEST = _descriptor.Descriptor(
- name='AddFirmwareImageRequest',
- full_name='aftl.AddFirmwareImageRequest',
+_ANNOTATEVBMETAWITHBUILDREQUEST = _descriptor.Descriptor(
+ name='AnnotateVBMetaWithBuildRequest',
+ full_name='aftl.AnnotateVBMetaWithBuildRequest',
filename=None,
file=DESCRIPTOR,
containing_type=None,
fields=[
_descriptor.FieldDescriptor(
- name='fw_image_info', full_name='aftl.AddFirmwareImageRequest.fw_image_info', index=0,
- number=1, type=11, cpp_type=10, label=1,
- has_default_value=False, default_value=None,
+ name='signed_vbmeta_build_annotation', full_name='aftl.AnnotateVBMetaWithBuildRequest.signed_vbmeta_build_annotation', index=0,
+ number=1, type=12, cpp_type=9, label=1,
+ has_default_value=False, default_value=_b(""),
message_type=None, enum_type=None, containing_type=None,
is_extension=False, extension_scope=None,
serialized_options=None, file=DESCRIPTOR),
_descriptor.FieldDescriptor(
- name='image_chunk', full_name='aftl.AddFirmwareImageRequest.image_chunk', index=1,
+ name='image_chunk', full_name='aftl.AnnotateVBMetaWithBuildRequest.image_chunk', index=1,
number=2, type=12, cpp_type=9, label=1,
has_default_value=False, default_value=_b(""),
message_type=None, enum_type=None, containing_type=None,
is_extension=False, extension_scope=None,
serialized_options=None, file=DESCRIPTOR),
_descriptor.FieldDescriptor(
- name='origin_url', full_name='aftl.AddFirmwareImageRequest.origin_url', index=2,
+ name='origin_url', full_name='aftl.AnnotateVBMetaWithBuildRequest.origin_url', index=2,
number=3, type=9, cpp_type=9, label=1,
has_default_value=False, default_value=_b("").decode('utf-8'),
message_type=None, enum_type=None, containing_type=None,
@@ -159,29 +196,29 @@
extension_ranges=[],
oneofs=[
],
- serialized_start=276,
- serialized_end=396,
+ serialized_start=361,
+ serialized_end=474,
)
-_ADDFIRMWAREIMAGERESPONSE = _descriptor.Descriptor(
- name='AddFirmwareImageResponse',
- full_name='aftl.AddFirmwareImageResponse',
+_ANNOTATEVBMETAWITHBUILDRESPONSE = _descriptor.Descriptor(
+ name='AnnotateVBMetaWithBuildResponse',
+ full_name='aftl.AnnotateVBMetaWithBuildResponse',
filename=None,
file=DESCRIPTOR,
containing_type=None,
fields=[
_descriptor.FieldDescriptor(
- name='fw_image_info_proof', full_name='aftl.AddFirmwareImageResponse.fw_image_info_proof', index=0,
+ name='annotation_proof', full_name='aftl.AnnotateVBMetaWithBuildResponse.annotation_proof', index=0,
number=1, type=11, cpp_type=10, label=1,
has_default_value=False, default_value=None,
message_type=None, enum_type=None, containing_type=None,
is_extension=False, extension_scope=None,
serialized_options=None, file=DESCRIPTOR),
_descriptor.FieldDescriptor(
- name='fw_image_info_leaf', full_name='aftl.AddFirmwareImageResponse.fw_image_info_leaf', index=1,
- number=2, type=11, cpp_type=10, label=1,
- has_default_value=False, default_value=None,
+ name='annotation_leaf', full_name='aftl.AnnotateVBMetaWithBuildResponse.annotation_leaf', index=1,
+ number=2, type=12, cpp_type=9, label=1,
+ has_default_value=False, default_value=_b(""),
message_type=None, enum_type=None, containing_type=None,
is_extension=False, extension_scope=None,
serialized_options=None, file=DESCRIPTOR),
@@ -197,49 +234,56 @@
extension_ranges=[],
oneofs=[
],
- serialized_start=398,
- serialized_end=515,
+ serialized_start=476,
+ serialized_end=582,
)
-_ADDFIRMWAREINFOREQUEST.fields_by_name['fw_info'].message_type = aftl__pb2._SIGNEDFIRMWAREINFO
-_ADDFIRMWAREINFORESPONSE.fields_by_name['fw_info_proof'].message_type = aftl__pb2._INCLUSIONPROOF
-_ADDFIRMWAREINFORESPONSE.fields_by_name['vbmeta_proof'].message_type = aftl__pb2._INCLUSIONPROOF
-_ADDFIRMWAREIMAGEREQUEST.fields_by_name['fw_image_info'].message_type = aftl__pb2._SIGNEDFIRMWAREIMAGEINFO
-_ADDFIRMWAREIMAGERESPONSE.fields_by_name['fw_image_info_proof'].message_type = aftl__pb2._INCLUSIONPROOF
-_ADDFIRMWAREIMAGERESPONSE.fields_by_name['fw_image_info_leaf'].message_type = aftl__pb2._LEAF
-DESCRIPTOR.message_types_by_name['AddFirmwareInfoRequest'] = _ADDFIRMWAREINFOREQUEST
-DESCRIPTOR.message_types_by_name['AddFirmwareInfoResponse'] = _ADDFIRMWAREINFORESPONSE
-DESCRIPTOR.message_types_by_name['AddFirmwareImageRequest'] = _ADDFIRMWAREIMAGEREQUEST
-DESCRIPTOR.message_types_by_name['AddFirmwareImageResponse'] = _ADDFIRMWAREIMAGERESPONSE
+_INCLUSIONPROOF.fields_by_name['proof'].message_type = trillian__pb2._PROOF
+_INCLUSIONPROOF.fields_by_name['sth'].message_type = trillian__pb2._SIGNEDLOGROOT
+_ADDVBMETARESPONSE.fields_by_name['annotation_proof'].message_type = _INCLUSIONPROOF
+_ADDVBMETARESPONSE.fields_by_name['vbmeta_proof'].message_type = _INCLUSIONPROOF
+_ANNOTATEVBMETAWITHBUILDRESPONSE.fields_by_name['annotation_proof'].message_type = _INCLUSIONPROOF
+DESCRIPTOR.message_types_by_name['InclusionProof'] = _INCLUSIONPROOF
+DESCRIPTOR.message_types_by_name['AddVBMetaRequest'] = _ADDVBMETAREQUEST
+DESCRIPTOR.message_types_by_name['AddVBMetaResponse'] = _ADDVBMETARESPONSE
+DESCRIPTOR.message_types_by_name['AnnotateVBMetaWithBuildRequest'] = _ANNOTATEVBMETAWITHBUILDREQUEST
+DESCRIPTOR.message_types_by_name['AnnotateVBMetaWithBuildResponse'] = _ANNOTATEVBMETAWITHBUILDRESPONSE
_sym_db.RegisterFileDescriptor(DESCRIPTOR)
-AddFirmwareInfoRequest = _reflection.GeneratedProtocolMessageType('AddFirmwareInfoRequest', (_message.Message,), {
- 'DESCRIPTOR' : _ADDFIRMWAREINFOREQUEST,
+InclusionProof = _reflection.GeneratedProtocolMessageType('InclusionProof', (_message.Message,), {
+ 'DESCRIPTOR' : _INCLUSIONPROOF,
'__module__' : 'api_pb2'
- # @@protoc_insertion_point(class_scope:aftl.AddFirmwareInfoRequest)
+ # @@protoc_insertion_point(class_scope:aftl.InclusionProof)
})
-_sym_db.RegisterMessage(AddFirmwareInfoRequest)
+_sym_db.RegisterMessage(InclusionProof)
-AddFirmwareInfoResponse = _reflection.GeneratedProtocolMessageType('AddFirmwareInfoResponse', (_message.Message,), {
- 'DESCRIPTOR' : _ADDFIRMWAREINFORESPONSE,
+AddVBMetaRequest = _reflection.GeneratedProtocolMessageType('AddVBMetaRequest', (_message.Message,), {
+ 'DESCRIPTOR' : _ADDVBMETAREQUEST,
'__module__' : 'api_pb2'
- # @@protoc_insertion_point(class_scope:aftl.AddFirmwareInfoResponse)
+ # @@protoc_insertion_point(class_scope:aftl.AddVBMetaRequest)
})
-_sym_db.RegisterMessage(AddFirmwareInfoResponse)
+_sym_db.RegisterMessage(AddVBMetaRequest)
-AddFirmwareImageRequest = _reflection.GeneratedProtocolMessageType('AddFirmwareImageRequest', (_message.Message,), {
- 'DESCRIPTOR' : _ADDFIRMWAREIMAGEREQUEST,
+AddVBMetaResponse = _reflection.GeneratedProtocolMessageType('AddVBMetaResponse', (_message.Message,), {
+ 'DESCRIPTOR' : _ADDVBMETARESPONSE,
'__module__' : 'api_pb2'
- # @@protoc_insertion_point(class_scope:aftl.AddFirmwareImageRequest)
+ # @@protoc_insertion_point(class_scope:aftl.AddVBMetaResponse)
})
-_sym_db.RegisterMessage(AddFirmwareImageRequest)
+_sym_db.RegisterMessage(AddVBMetaResponse)
-AddFirmwareImageResponse = _reflection.GeneratedProtocolMessageType('AddFirmwareImageResponse', (_message.Message,), {
- 'DESCRIPTOR' : _ADDFIRMWAREIMAGERESPONSE,
+AnnotateVBMetaWithBuildRequest = _reflection.GeneratedProtocolMessageType('AnnotateVBMetaWithBuildRequest', (_message.Message,), {
+ 'DESCRIPTOR' : _ANNOTATEVBMETAWITHBUILDREQUEST,
'__module__' : 'api_pb2'
- # @@protoc_insertion_point(class_scope:aftl.AddFirmwareImageResponse)
+ # @@protoc_insertion_point(class_scope:aftl.AnnotateVBMetaWithBuildRequest)
})
-_sym_db.RegisterMessage(AddFirmwareImageResponse)
+_sym_db.RegisterMessage(AnnotateVBMetaWithBuildRequest)
+
+AnnotateVBMetaWithBuildResponse = _reflection.GeneratedProtocolMessageType('AnnotateVBMetaWithBuildResponse', (_message.Message,), {
+ 'DESCRIPTOR' : _ANNOTATEVBMETAWITHBUILDRESPONSE,
+ '__module__' : 'api_pb2'
+ # @@protoc_insertion_point(class_scope:aftl.AnnotateVBMetaWithBuildResponse)
+ })
+_sym_db.RegisterMessage(AnnotateVBMetaWithBuildResponse)
DESCRIPTOR._options = None
@@ -250,25 +294,25 @@
file=DESCRIPTOR,
index=0,
serialized_options=None,
- serialized_start=518,
- serialized_end=695,
+ serialized_start=585,
+ serialized_end=766,
methods=[
_descriptor.MethodDescriptor(
- name='AddFirmwareInfo',
- full_name='aftl.AFTLog.AddFirmwareInfo',
+ name='AddVBMeta',
+ full_name='aftl.AFTLog.AddVBMeta',
index=0,
containing_service=None,
- input_type=_ADDFIRMWAREINFOREQUEST,
- output_type=_ADDFIRMWAREINFORESPONSE,
+ input_type=_ADDVBMETAREQUEST,
+ output_type=_ADDVBMETARESPONSE,
serialized_options=None,
),
_descriptor.MethodDescriptor(
- name='AddFirmwareImage',
- full_name='aftl.AFTLog.AddFirmwareImage',
+ name='AnnotateVBMetaWithBuild',
+ full_name='aftl.AFTLog.AnnotateVBMetaWithBuild',
index=1,
containing_service=None,
- input_type=_ADDFIRMWAREIMAGEREQUEST,
- output_type=_ADDFIRMWAREIMAGERESPONSE,
+ input_type=_ANNOTATEVBMETAWITHBUILDRESPONSE,
+ output_type=_ANNOTATEVBMETAWITHBUILDRESPONSE,
serialized_options=None,
),
])
diff --git a/proto/api_pb2_grpc.py b/proto/api_pb2_grpc.py
index b1834c7..d487856 100644
--- a/proto/api_pb2_grpc.py
+++ b/proto/api_pb2_grpc.py
@@ -1,4 +1,3 @@
-# pylint: skip-file
# Generated by the gRPC Python protocol compiler plugin. DO NOT EDIT!
import grpc
@@ -15,15 +14,15 @@
Args:
channel: A grpc.Channel.
"""
- self.AddFirmwareInfo = channel.unary_unary(
- '/aftl.AFTLog/AddFirmwareInfo',
- request_serializer=api__pb2.AddFirmwareInfoRequest.SerializeToString,
- response_deserializer=api__pb2.AddFirmwareInfoResponse.FromString,
+ self.AddVBMeta = channel.unary_unary(
+ '/aftl.AFTLog/AddVBMeta',
+ request_serializer=api__pb2.AddVBMetaRequest.SerializeToString,
+ response_deserializer=api__pb2.AddVBMetaResponse.FromString,
)
- self.AddFirmwareImage = channel.stream_unary(
- '/aftl.AFTLog/AddFirmwareImage',
- request_serializer=api__pb2.AddFirmwareImageRequest.SerializeToString,
- response_deserializer=api__pb2.AddFirmwareImageResponse.FromString,
+ self.AnnotateVBMetaWithBuild = channel.stream_unary(
+ '/aftl.AFTLog/AnnotateVBMetaWithBuild',
+ request_serializer=api__pb2.AnnotateVBMetaWithBuildResponse.SerializeToString,
+ response_deserializer=api__pb2.AnnotateVBMetaWithBuildResponse.FromString,
)
@@ -31,17 +30,17 @@
# missing associated documentation comment in .proto file
pass
- def AddFirmwareInfo(self, request, context):
+ def AddVBMeta(self, request, context):
"""Insert a new VBMeta structure into the log.
This request will effectively create 2 log entries:
- VBMeta itself
- - Vendor annotations, including a reference to the VBMeta leaf.
+ - Vendor annotations, which includes a reference to the VBMeta.
"""
context.set_code(grpc.StatusCode.UNIMPLEMENTED)
context.set_details('Method not implemented!')
raise NotImplementedError('Method not implemented!')
- def AddFirmwareImage(self, request_iterator, context):
+ def AnnotateVBMetaWithBuild(self, request_iterator, context):
"""Upload (or copy) the complete firmware image.
"""
context.set_code(grpc.StatusCode.UNIMPLEMENTED)
@@ -51,15 +50,15 @@
def add_AFTLogServicer_to_server(servicer, server):
rpc_method_handlers = {
- 'AddFirmwareInfo': grpc.unary_unary_rpc_method_handler(
- servicer.AddFirmwareInfo,
- request_deserializer=api__pb2.AddFirmwareInfoRequest.FromString,
- response_serializer=api__pb2.AddFirmwareInfoResponse.SerializeToString,
+ 'AddVBMeta': grpc.unary_unary_rpc_method_handler(
+ servicer.AddVBMeta,
+ request_deserializer=api__pb2.AddVBMetaRequest.FromString,
+ response_serializer=api__pb2.AddVBMetaResponse.SerializeToString,
),
- 'AddFirmwareImage': grpc.stream_unary_rpc_method_handler(
- servicer.AddFirmwareImage,
- request_deserializer=api__pb2.AddFirmwareImageRequest.FromString,
- response_serializer=api__pb2.AddFirmwareImageResponse.SerializeToString,
+ 'AnnotateVBMetaWithBuild': grpc.stream_unary_rpc_method_handler(
+ servicer.AnnotateVBMetaWithBuild,
+ request_deserializer=api__pb2.AnnotateVBMetaWithBuildResponse.FromString,
+ response_serializer=api__pb2.AnnotateVBMetaWithBuildResponse.SerializeToString,
),
}
generic_handler = grpc.method_handlers_generic_handler(
diff --git a/test/data/aftltool/aftl_output_vbmeta_with_1_icp.img b/test/data/aftltool/aftl_output_vbmeta_with_1_icp.img
index 25e0869..74b67bb 100644
--- a/test/data/aftltool/aftl_output_vbmeta_with_1_icp.img
+++ b/test/data/aftltool/aftl_output_vbmeta_with_1_icp.img
Binary files differ
diff --git a/test/data/aftltool/aftl_output_vbmeta_with_2_icp_different_logs.img b/test/data/aftltool/aftl_output_vbmeta_with_2_icp_different_logs.img
deleted file mode 100644
index ad36580..0000000
--- a/test/data/aftltool/aftl_output_vbmeta_with_2_icp_different_logs.img
+++ /dev/null
Binary files differ
diff --git a/test/data/aftltool/aftl_output_vbmeta_with_2_icp_same_log.img b/test/data/aftltool/aftl_output_vbmeta_with_2_icp_same_log.img
index e53178c..2a6368e 100644
--- a/test/data/aftltool/aftl_output_vbmeta_with_2_icp_same_log.img
+++ b/test/data/aftltool/aftl_output_vbmeta_with_2_icp_same_log.img
Binary files differ