Merge "Add ramdisk_available to init_first_stage's deps"
diff --git a/Android.bp b/Android.bp
index 4214f04..6e438d8 100644
--- a/Android.bp
+++ b/Android.bp
@@ -147,81 +147,6 @@
compile_multilib: "first",
}
-python_library_host {
- name: "aftl_proto",
- srcs: [
- "proto/api.proto",
- "proto/crypto/sigpb/sigpb.proto",
- "proto/crypto/keyspb/keyspb.proto",
- "proto/trillian.proto",
- ],
- proto: {
- include_dirs: [
- "external/protobuf/src",
- ],
- local_include_dirs: [
- "proto",
- ],
- canonical_path_from_root: false,
- },
- version: {
- py2: {
- enabled: false,
- },
- py3: {
- enabled: true,
- },
- },
-}
-
-python_binary_host {
- name: "aftltool",
- srcs: [
- "aftltool.py",
- "avbtool.py",
- ],
- libs: [
- "aftl_proto",
- ],
- main: "aftltool.py",
- version: {
- py2: {
- enabled: false,
- },
- py3: {
- enabled: true,
- },
- },
-}
-
-python_test_host {
- name: "aftltool_test",
- main: "aftltool_test.py",
- srcs: [
- "aftltool.py",
- "aftltool_test.py",
- "avbtool.py",
- ],
- libs: [
- "aftl_proto",
- ],
- data: [
- "test/data/**/*.*",
- ],
- test_options: {
- unit_test: true,
- },
- version: {
- py2: {
- enabled: false,
- },
- py3: {
- enabled: true,
- },
- },
-}
-
-// Build libavb - this is a static library that depends
// on only libc and doesn't drag in any other dependencies.
cc_library_static {
name: "libavb",
@@ -304,54 +229,6 @@
srcs: ["libavb_ab/avb_ab_flow.c"],
}
-cc_library_static {
- name: "libavb_aftl",
- defaults: [
- "avb_defaults",
- "avb_sources",
- "avb_crypto_ops_impl_boringssl",
- ],
- host_supported: true,
- recovery_available: true,
- header_libs: ["avb_headers"],
- export_header_lib_headers: ["avb_headers"],
- cflags: [
- "-fno-stack-protector",
- ],
- srcs: [
- "libavb_aftl/avb_aftl_util.c",
- "libavb_aftl/avb_aftl_validate.c",
- "libavb_aftl/avb_aftl_verify.c",
- ],
-}
-
-cc_fuzz {
- name: "libavb_aftl_fuzzer",
- defaults: ["avb_defaults"],
- // The fuzzing entry point is declared and defined in the same file.
- // Overwrite the behaviour introduced by avb_defaults.
- cflags: [
- "-Wno-missing-prototypes",
- ],
- srcs: [
- "test/avb_aftl_fuzz.cc",
- ],
- static_libs: [
- "libavb",
- "libavb_aftl",
- ],
- shared_libs: ["libcrypto"],
- host_supported: true,
- corpus: ["test/corpus/*"],
- fuzz_config: {
- cc: [
- "tweek@google.com",
- "jpm@google.com",
- ],
- componentid: 685985,
- },
-}
-
cc_library_host_static {
name: "libavb_atx_host",
defaults: [
@@ -414,7 +291,6 @@
static_libs: [
"libavb",
"libavb_ab_host",
- "libavb_aftl",
"libavb_atx_host",
"libavb_things_example",
"libgmock_host",
@@ -431,9 +307,6 @@
],
srcs: [
"test/avb_ab_flow_unittest.cc",
- "test/avb_aftl_util_unittest.cc",
- "test/avb_aftl_validate_unittest.cc",
- "test/avb_aftl_verify_unittest.cc",
"test/avb_atx_validate_unittest.cc",
"test/avb_atx_slot_verify_unittest.cc",
"test/avb_crypto_ops_unittest.cc",
diff --git a/README.md b/README.md
index b5ca697..a293cb0 100644
--- a/README.md
+++ b/README.md
@@ -429,7 +429,8 @@
[--calc_max_image_size] \
[--do_not_use_ab] \
[--no_hashtree] \
- [--use_persistent_digest]
+ [--use_persistent_digest] \
+ [--check_at_most_once]
Valid values for `HASH_ALG` above include `sha1`, `sha256`, and `blake2b-256`.
@@ -1119,7 +1120,9 @@
### Version 1.2
-Version 1.2 adds support for the `rollback_index_location` field of the main vbmeta header.
+Version 1.2 adds support for the following:
+* `rollback_index_location` field of the main vbmeta header.
+* `check_at_most_once` parameter of dm-verity in a hashtree descriptor.
### Version 1.1
diff --git a/aftltool b/aftltool
deleted file mode 120000
index 11a8ff9..0000000
--- a/aftltool
+++ /dev/null
@@ -1 +0,0 @@
-aftltool.py
\ No newline at end of file
diff --git a/aftltool.py b/aftltool.py
deleted file mode 100755
index 613e83b..0000000
--- a/aftltool.py
+++ /dev/null
@@ -1,2254 +0,0 @@
-#!/usr/bin/env python3
-
-# Copyright 2020, The Android Open Source Project
-#
-# Permission is hereby granted, free of charge, to any person
-# obtaining a copy of this software and associated documentation
-# files (the "Software"), to deal in the Software without
-# restriction, including without limitation the rights to use, copy,
-# modify, merge, publish, distribute, sublicense, and/or sell copies
-# of the Software, and to permit persons to whom the Software is
-# furnished to do so, subject to the following conditions:
-#
-# The above copyright notice and this permission notice shall be
-# included in all copies or substantial portions of the Software.
-#
-# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
-# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
-# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
-# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
-# BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
-# ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
-# CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
-# SOFTWARE.
-#
-"""Command-line tool for AFTL support for Android Verified Boot images."""
-
-import abc
-import argparse
-import enum
-import hashlib
-import io
-import multiprocessing
-import os
-import queue
-import struct
-import subprocess
-import sys
-import tempfile
-import time
-
-# This is to work around temporarily with the issue that python3 does not permit
-# relative imports anymore going forward. This adds the proto directory relative
-# to the location of aftltool to the sys.path.
-# TODO(b/154068467): Implement proper importing of generated *_pb2 modules.
-EXEC_PATH = os.path.dirname(os.path.realpath(__file__))
-sys.path.append(os.path.join(EXEC_PATH, 'proto'))
-
-# pylint: disable=wrong-import-position,import-error
-import avbtool
-import api_pb2
-# pylint: enable=wrong-import-position,import-error
-
-
-class AftlError(Exception):
- """Application-specific errors.
-
- These errors represent issues for which a stack-trace should not be
- presented.
-
- Attributes:
- message: Error message.
- """
-
- def __init__(self, message):
- Exception.__init__(self, message)
-
-
-def rsa_key_read_pem_bytes(key_path):
- """Reads the bytes out of the passed in PEM file.
-
- Arguments:
- key_path: A string containing the path to the PEM file.
-
- Returns:
- A bytearray containing the DER encoded bytes in the PEM file.
-
- Raises:
- AftlError: If openssl cannot decode the PEM file.
- """
- # Use openssl to decode the PEM file.
- args = ['openssl', 'rsa', '-in', key_path, '-pubout', '-outform', 'DER']
- p = subprocess.Popen(args,
- stdin=subprocess.PIPE,
- stdout=subprocess.PIPE,
- stderr=subprocess.PIPE)
- (pout, perr) = p.communicate()
- retcode = p.wait()
- if retcode != 0:
- raise AftlError('Error decoding: {}'.format(perr))
- return pout
-
-
-def check_signature(log_root, log_root_sig,
- transparency_log_pub_key):
- """Validates the signature provided by the transparency log.
-
- Arguments:
- log_root: The transparency log_root data structure.
- log_root_sig: The signature of the transparency log_root data structure.
- transparency_log_pub_key: The file path to the transparency log public key.
-
- Returns:
- True if the signature check passes, otherwise False.
- """
-
- logsig_tmp = tempfile.NamedTemporaryFile()
- logsig_tmp.write(log_root_sig)
- logsig_tmp.flush()
- logroot_tmp = tempfile.NamedTemporaryFile()
- logroot_tmp.write(log_root)
- logroot_tmp.flush()
-
- p = subprocess.Popen(['openssl', 'dgst', '-sha256', '-verify',
- transparency_log_pub_key,
- '-signature', logsig_tmp.name, logroot_tmp.name],
- stdin=subprocess.PIPE,
- stdout=subprocess.PIPE,
- stderr=subprocess.PIPE)
-
- p.communicate()
- retcode = p.wait()
- if not retcode:
- return True
- return False
-
-
-# AFTL Merkle Tree Functionality
-def rfc6962_hash_leaf(leaf):
- """RFC6962 hashing function for hashing leaves of a Merkle tree.
-
- Arguments:
- leaf: A bytearray containing the Merkle tree leaf to be hashed.
-
- Returns:
- A bytearray containing the RFC6962 SHA256 hash of the leaf.
- """
- hasher = hashlib.sha256()
- # RFC6962 states a '0' byte should be prepended to the data.
- # This is done in conjunction with the '1' byte for non-leaf
- # nodes for 2nd preimage attack resistance.
- hasher.update(b'\x00')
- hasher.update(leaf)
- return hasher.digest()
-
-
-def rfc6962_hash_children(l, r):
- """Calculates the inner Merkle tree node hash of child nodes l and r.
-
- Arguments:
- l: A bytearray containing the left child node to be hashed.
- r: A bytearray containing the right child node to be hashed.
-
- Returns:
- A bytearray containing the RFC6962 SHA256 hash of 1|l|r.
- """
- hasher = hashlib.sha256()
- # RFC6962 states a '1' byte should be prepended to the concatenated data.
- # This is done in conjunction with the '0' byte for leaf
- # nodes for 2nd preimage attack resistance.
- hasher.update(b'\x01')
- hasher.update(l)
- hasher.update(r)
- return hasher.digest()
-
-
-def chain_border_right(seed, proof):
- """Computes a subtree hash along the left-side tree border.
-
- Arguments:
- seed: A bytearray containing the starting hash.
- proof: A list of bytearrays representing the hashes in the inclusion proof.
-
- Returns:
- A bytearray containing the left-side subtree hash.
- """
- for h in proof:
- seed = rfc6962_hash_children(h, seed)
- return seed
-
-
-def chain_inner(seed, proof, leaf_index):
- """Computes a subtree hash on or below the tree's right border.
-
- Arguments:
- seed: A bytearray containing the starting hash.
- proof: A list of bytearrays representing the hashes in the inclusion proof.
- leaf_index: The current leaf index.
-
- Returns:
- A bytearray containing the subtree hash.
- """
- for i, h in enumerate(proof):
- if leaf_index >> i & 1 == 0:
- seed = rfc6962_hash_children(seed, h)
- else:
- seed = rfc6962_hash_children(h, seed)
- return seed
-
-
-def root_from_icp(leaf_index, tree_size, proof, leaf_hash):
- """Calculates the expected Merkle tree root hash.
-
- Arguments:
- leaf_index: The current leaf index.
- tree_size: The number of nodes in the Merkle tree.
- proof: A list of bytearrays containing the inclusion proof.
- leaf_hash: A bytearray containing the initial leaf hash.
-
- Returns:
- A bytearray containing the calculated Merkle tree root hash.
-
- Raises:
- AftlError: If invalid parameters are passed in.
- """
- if leaf_index < 0:
- raise AftlError('Invalid leaf_index value: {}'.format(leaf_index))
- if tree_size < 0:
- raise AftlError('Invalid tree_size value: {}'.format(tree_size))
- if leaf_index >= tree_size:
- err_str = 'leaf_index cannot be equal or larger than tree_size: {}, {}'
- raise AftlError(err_str.format(leaf_index, tree_size))
- if proof is None:
- raise AftlError('Inclusion proof not provided.')
- if leaf_hash is None:
- raise AftlError('No leaf hash provided.')
- # Calculate the point to split the proof into two parts.
- # The split is where the paths to leaves diverge.
- inner = (leaf_index ^ (tree_size - 1)).bit_length()
- result = chain_inner(leaf_hash, proof[:inner], leaf_index)
- result = chain_border_right(result, proof[inner:])
- return result
-
-
-class AftlImageHeader(object):
- """A class for representing the AFTL image header.
-
- Attributes:
- magic: Magic for identifying the AftlImage.
- required_icp_version_major: The major version of AVB that wrote the entry.
- required_icp_version_minor: The minor version of AVB that wrote the entry.
- aftl_image_size: Total size of the AftlImage.
- icp_count: Number of inclusion proofs represented in this structure.
- """
-
- SIZE = 18 # The size of the structure, in bytes
- MAGIC = b'AFTL'
- FORMAT_STRING = ('!4s2L' # magic, major & minor version.
- 'L' # AFTL image size.
- 'H') # number of inclusion proof entries.
-
- def __init__(self, data=None):
- """Initializes a new AftlImageHeader object.
-
- Arguments:
- data: If not None, must be a bytearray of size |SIZE|.
-
- Raises:
- AftlError: If invalid structure for AftlImageHeader.
- """
- assert struct.calcsize(self.FORMAT_STRING) == self.SIZE
-
- if data:
- (self.magic, self.required_icp_version_major,
- self.required_icp_version_minor, self.aftl_image_size,
- self.icp_count) = struct.unpack(self.FORMAT_STRING, data)
- else:
- self.magic = self.MAGIC
- self.required_icp_version_major = avbtool.AVB_VERSION_MAJOR
- self.required_icp_version_minor = avbtool.AVB_VERSION_MINOR
- self.aftl_image_size = self.SIZE
- self.icp_count = 0
- if not self.is_valid():
- raise AftlError('Invalid structure for AftlImageHeader.')
-
- def encode(self):
- """Serializes the AftlImageHeader |SIZE| to bytes.
-
- Returns:
- The encoded AftlImageHeader as bytes.
-
- Raises:
- AftlError: If invalid structure for AftlImageHeader.
- """
- if not self.is_valid():
- raise AftlError('Invalid structure for AftlImageHeader')
- return struct.pack(self.FORMAT_STRING, self.magic,
- self.required_icp_version_major,
- self.required_icp_version_minor,
- self.aftl_image_size,
- self.icp_count)
-
- def is_valid(self):
- """Ensures that values in the AftlImageHeader are sane.
-
- Returns:
- True if the values in the AftlImageHeader are sane, False otherwise.
- """
- if self.magic != AftlImageHeader.MAGIC:
- sys.stderr.write(
- 'AftlImageHeader: magic value mismatch: {}\n'
- .format(repr(self.magic)))
- return False
-
- if self.required_icp_version_major > avbtool.AVB_VERSION_MAJOR:
- sys.stderr.write('AftlImageHeader: major version mismatch: {}\n'.format(
- self.required_icp_version_major))
- return False
-
- if self.required_icp_version_minor > avbtool.AVB_VERSION_MINOR:
- sys.stderr.write('AftlImageHeader: minor version mismatch: {}\n'.format(
- self.required_icp_version_minor))
- return False
-
- if self.aftl_image_size < self.SIZE:
- sys.stderr.write('AftlImageHeader: Invalid AFTL image size: {}\n'.format(
- self.aftl_image_size))
- return False
-
- if self.icp_count < 0 or self.icp_count > 65535:
- sys.stderr.write(
- 'AftlImageHeader: ICP entry count out of range: {}\n'.format(
- self.icp_count))
- return False
- return True
-
- def print_desc(self, o):
- """Print the AftlImageHeader.
-
- Arguments:
- o: The object to write the output to.
- """
- o.write(' AFTL image header:\n')
- i = ' ' * 4
- fmt = '{}{:25}{}\n'
- o.write(fmt.format(i, 'Major version:', self.required_icp_version_major))
- o.write(fmt.format(i, 'Minor version:', self.required_icp_version_minor))
- o.write(fmt.format(i, 'Image size:', self.aftl_image_size))
- o.write(fmt.format(i, 'ICP entries count:', self.icp_count))
-
-
-class AftlIcpEntry(object):
- """A class for the transparency log inclusion proof entries.
-
- The data that represents each of the components of the ICP entry are stored
- immediately following the ICP entry header. The format is log_url,
- SignedLogRoot, and inclusion proof hashes.
-
- Attributes:
- 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.
- 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.
- 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.
-
- """
- SIZE = 27 # The size of the structure, in bytes
- FORMAT_STRING = ('!L' # transparency log server url size
- 'Q' # leaf index
- 'L' # log root descriptor size
- 'L' # firmware info leaf size
- 'H' # log root signature size
- 'B' # number of hashes in the inclusion proof
- 'L') # size of the inclusion proof in bytes
- # 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.
-
- Arguments:
- data: If not None, must be a bytearray of size >= |SIZE|.
-
- Raises:
- AftlError: If data does not represent a well-formed AftlIcpEntry.
- """
- # Assert the header structure is of a sane size.
- assert struct.calcsize(self.FORMAT_STRING) == self.SIZE
-
- if data:
- # Deserialize the header from the data.
- (self._log_url_size_expected,
- self.leaf_index,
- self._log_root_descriptor_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,
- data[0:self.SIZE])
-
- # Deserialize ICP entry components from the data.
- expected_format_string = '{}s{}s{}s{}s{}s'.format(
- self._log_url_size_expected,
- self._log_root_descriptor_size_expected,
- self._annotation_leaf_size_expected,
- self._log_root_sig_size_expected,
- self._inc_proof_size_expected)
-
- (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.annotation_leaf = SignedVBMetaPrimaryAnnotationLeaf.parse(
- annotation_leaf_bytes)
-
- self.proofs = []
- if self._proof_hash_count_expected > 0:
- proof_idx = 0
- hash_size = (self._inc_proof_size_expected
- // self._proof_hash_count_expected)
- for _ in range(self._proof_hash_count_expected):
- proof = proof_bytes[proof_idx:(proof_idx+hash_size)]
- self.proofs.append(proof)
- proof_idx += hash_size
- else:
- self.leaf_index = 0
- self.log_url = ''
- self.log_root_descriptor = TrillianLogRootDescriptor()
- self.annotation_leaf = SignedVBMetaPrimaryAnnotationLeaf()
- self.log_root_signature = b''
- self.proofs = []
- if not self.is_valid():
- raise AftlError('Invalid structure for AftlIcpEntry')
-
- @property
- def log_url_size(self):
- """Gets the size of the log_url attribute."""
- if hasattr(self, 'log_url'):
- return len(self.log_url)
- return self._log_url_size_expected
-
- @property
- def log_root_descriptor_size(self):
- """Gets the size of the log_root_descriptor attribute."""
- if hasattr(self, 'log_root_descriptor'):
- return self.log_root_descriptor.get_expected_size()
- return self._log_root_descriptor_size_expected
-
- @property
- 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):
- """Gets the size of the log_root signature."""
- if hasattr(self, 'log_root_signature'):
- return len(self.log_root_signature)
- return self._log_root_sig_size_expected
-
- @property
- def proof_hash_count(self):
- """Gets the number of proof hashes."""
- if hasattr(self, 'proofs'):
- return len(self.proofs)
- return self._proof_hash_count_expected
-
- @property
- def inc_proof_size(self):
- """Gets the total size of the proof hashes in bytes."""
- if hasattr(self, 'proofs'):
- result = 0
- for proof in self.proofs:
- result += len(proof)
- return result
- return self._inc_proof_size_expected
-
- def verify_icp(self, transparency_log_pub_key):
- """Verifies the contained inclusion proof given the public log key.
-
- Arguments:
- transparency_log_pub_key: The path to the trusted public key for the log.
-
- Returns:
- True if the calculated signature matches AftlIcpEntry's. False otherwise.
- """
- if not transparency_log_pub_key:
- return False
-
- 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,
- leaf_hash)
- if ((calc_root == self.log_root_descriptor.root_hash) and
- check_signature(
- self.log_root_descriptor.encode(),
- self.log_root_signature,
- transparency_log_pub_key)):
- return True
- return False
-
- def verify_vbmeta_image(self, vbmeta_image, transparency_log_pub_key):
- """Verify the inclusion proof for the given VBMeta image.
-
- Arguments:
- vbmeta_image: A bytearray with the VBMeta image.
- transparency_log_pub_key: File path to the PEM file containing the trusted
- transparency log public key.
-
- Returns:
- True if the inclusion proof validates and the vbmeta hash of the given
- VBMeta image matches the one in the annotation leaf; otherwise False.
- """
- if not vbmeta_image:
- return False
-
- # Calculate the hash of the vbmeta image.
- vbmeta_hash = hashlib.sha256(vbmeta_image).digest()
-
- # 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.annotation_leaf.annotation.vbmeta_hash == vbmeta_hash)
-
- def encode(self):
- """Serializes the header |SIZE| and data to bytes.
-
- Returns:
- bytes with the encoded header.
-
- Raises:
- AftlError: If invalid entry structure.
- """
- proof_bytes = bytearray()
- if not self.is_valid():
- raise AftlError('Invalid AftlIcpEntry structure')
-
- expected_format_string = '{}{}s{}s{}s{}s{}s'.format(
- self.FORMAT_STRING,
- self.log_url_size,
- self.log_root_descriptor_size,
- self.annotation_leaf_size,
- self.log_root_sig_size,
- self.inc_proof_size)
-
- for proof in self.proofs:
- proof_bytes.extend(proof)
-
- return struct.pack(expected_format_string,
- self.log_url_size, self.leaf_index,
- 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.annotation_leaf.encode(),
- self.log_root_signature,
- proof_bytes)
-
- def translate_response(self, log_url, avbm_response):
- """Translates an AddVBMetaResponse object to an AftlIcpEntry.
-
- Arguments:
- log_url: String representing the transparency log URL.
- avbm_response: The AddVBMetaResponse object to translate.
- """
- self.log_url = log_url
-
- # 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.
-
- Returns:
- The expected size of the AftlIcpEntry from the header.
- """
- return (self.SIZE + self.log_url_size + self.log_root_descriptor_size +
- self.annotation_leaf_size + self.log_root_sig_size +
- self.inc_proof_size)
-
- def is_valid(self):
- """Ensures that values in an AftlIcpEntry structure are sane.
-
- Returns:
- True if the values in the AftlIcpEntry are sane, False otherwise.
- """
- if self.leaf_index < 0:
- sys.stderr.write('ICP entry: leaf index out of range: '
- '{}.\n'.format(self.leaf_index))
- return False
-
- if (not self.log_root_descriptor or
- not isinstance(self.log_root_descriptor, TrillianLogRootDescriptor) or
- not self.log_root_descriptor.is_valid()):
- sys.stderr.write('ICP entry: invalid TrillianLogRootDescriptor.\n')
- return False
-
- if (not self.annotation_leaf or
- not isinstance(self.annotation_leaf, Leaf)):
- sys.stderr.write('ICP entry: invalid Leaf.\n')
- return False
- return True
-
- def print_desc(self, o):
- """Print the ICP entry.
-
- Arguments:
- o: The object to write the output to.
- """
- i = ' ' * 4
- fmt = '{}{:25}{}\n'
- o.write(fmt.format(i, 'Transparency Log:', self.log_url))
- o.write(fmt.format(i, 'Leaf index:', self.leaf_index))
- o.write(' ICP hashes: ')
- for i, proof_hash in enumerate(self.proofs):
- if i != 0:
- o.write(' ' * 29)
- o.write('{}\n'.format(proof_hash.hex()))
- self.log_root_descriptor.print_desc(o)
- self.annotation_leaf.print_desc(o)
-
-
-class TrillianLogRootDescriptor(object):
- """A class representing the Trillian log_root descriptor.
-
- Taken from Trillian definitions:
- https://github.com/google/trillian/blob/master/trillian.proto#L255
-
- Attributes:
- version: The version number of the descriptor. Currently only version=1 is
- supported.
- tree_size: The size of the tree.
- root_hash_size: The size of the root hash in bytes. Valid values are between
- 0 and 128.
- root_hash: The root hash as bytearray().
- timestamp: The timestamp in nanoseconds.
- revision: The revision number as long.
- metadata_size: The size of the metadata in bytes. Valid values are between
- 0 and 65535.
- metadata: The metadata as bytearray().
- """
- FORMAT_STRING_PART_1 = ('!H' # version
- 'Q' # tree_size
- 'B' # root_hash_size
- )
-
- FORMAT_STRING_PART_2 = ('!Q' # timestamp
- 'Q' # revision
- 'H' # metadata_size
- )
-
- def __init__(self, data=None):
- """Initializes a new TrillianLogRoot descriptor."""
- if data:
- # Parses first part of the log_root descriptor.
- data_length = struct.calcsize(self.FORMAT_STRING_PART_1)
- (self.version, self.tree_size, self.root_hash_size) = struct.unpack(
- self.FORMAT_STRING_PART_1, data[0:data_length])
- data = data[data_length:]
-
- # Parses the root_hash bytes if the size indicates existance.
- if self.root_hash_size > 0:
- self.root_hash = data[0:self.root_hash_size]
- data = data[self.root_hash_size:]
- else:
- self.root_hash = b''
-
- # Parses second part of the log_root descriptor.
- data_length = struct.calcsize(self.FORMAT_STRING_PART_2)
- (self.timestamp, self.revision, self.metadata_size) = struct.unpack(
- self.FORMAT_STRING_PART_2, data[0:data_length])
- data = data[data_length:]
-
- # Parses the metadata if the size indicates existance.
- if self.metadata_size > 0:
- self.metadata = data[0:self.metadata_size]
- else:
- self.metadata = b''
- else:
- self.version = 1
- self.tree_size = 0
- self.root_hash_size = 0
- self.root_hash = b''
- self.timestamp = 0
- self.revision = 0
- self.metadata_size = 0
- self.metadata = b''
-
- if not self.is_valid():
- raise AftlError('Invalid structure for TrillianLogRootDescriptor.')
-
- def get_expected_size(self):
- """Calculates the expected size of the TrillianLogRootDescriptor.
-
- Returns:
- The expected size of the TrillianLogRootDescriptor.
- """
- return (struct.calcsize(self.FORMAT_STRING_PART_1) + self.root_hash_size +
- struct.calcsize(self.FORMAT_STRING_PART_2) + self.metadata_size)
-
- def encode(self):
- """Serializes the TrillianLogDescriptor to a bytearray().
-
- Returns:
- A bytearray() with the encoded header.
-
- Raises:
- AftlError: If invalid entry structure.
- """
- if not self.is_valid():
- raise AftlError('Invalid structure for TrillianLogRootDescriptor.')
-
- expected_format_string = '{}{}s{}{}s'.format(
- self.FORMAT_STRING_PART_1,
- self.root_hash_size,
- self.FORMAT_STRING_PART_2[1:],
- self.metadata_size)
-
- return struct.pack(expected_format_string,
- self.version, self.tree_size, self.root_hash_size,
- self.root_hash, self.timestamp, self.revision,
- self.metadata_size, self.metadata)
-
- def is_valid(self):
- """Ensures that values in the descritor are sane.
-
- Returns:
- True if the values are sane; otherwise False.
- """
- cls = self.__class__.__name__
- if self.version != 1:
- sys.stderr.write('{}: Bad version value {}.\n'.format(cls, self.version))
- return False
- if self.tree_size < 0:
- sys.stderr.write('{}: Bad tree_size value {}.\n'.format(cls,
- self.tree_size))
- return False
- if self.root_hash_size < 0 or self.root_hash_size > 128:
- sys.stderr.write('{}: Bad root_hash_size value {}.\n'.format(
- cls, self.root_hash_size))
- return False
- if len(self.root_hash) != self.root_hash_size:
- sys.stderr.write('{}: root_hash_size {} does not match with length of '
- 'root_hash {}.\n'.format(cls, self.root_hash_size,
- len(self.root_hash)))
- return False
- if self.timestamp < 0:
- sys.stderr.write('{}: Bad timestamp value {}.\n'.format(cls,
- self.timestamp))
- return False
- if self.revision < 0:
- sys.stderr.write('{}: Bad revision value {}.\n'.format(cls,
- self.revision))
- return False
- if self.metadata_size < 0 or self.metadata_size > 65535:
- sys.stderr.write('{}: Bad metadatasize value {}.\n'.format(
- cls, self.metadata_size))
- return False
- if len(self.metadata) != self.metadata_size:
- sys.stderr.write('{}: metadata_size {} does not match with length of'
- 'metadata {}.\n'.format(cls, self.metadata_size,
- len(self.metadata)))
- return False
- return True
-
- def print_desc(self, o):
- """Print the TrillianLogRootDescriptor.
-
- Arguments:
- o: The object to write the output to.
- """
- o.write(' Log Root Descriptor:\n')
- i = ' ' * 6
- fmt = '{}{:23}{}\n'
- o.write(fmt.format(i, 'Version:', self.version))
- o.write(fmt.format(i, 'Tree size:', self.tree_size))
- o.write(fmt.format(i, 'Root hash size:', self.root_hash_size))
- if self.root_hash_size > 0:
- o.write(fmt.format(i, 'Root hash:', self.root_hash.hex()))
- o.write(fmt.format(i, 'Timestamp (ns):', self.timestamp))
- o.write(fmt.format(i, 'Revision:', self.revision))
- o.write(fmt.format(i, 'Metadata size:', self.metadata_size))
- if self.metadata_size > 0:
- o.write(fmt.format(i, 'Metadata:', self.metadata.hex()))
-
-
-def tls_decode_bytes(byte_size, stream):
- """Decodes 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".
- 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:
- 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, hash_algorithm=HashAlgorithm.SHA256,
- signature_algorithm=SignatureAlgorithm.RSA, signature=b''):
- self.hash_algorithm = hash_algorithm
- self.signature_algorithm = signature_algorithm
- self.signature = signature
-
- @classmethod
- def parse(cls, stream):
- """Parses a TLS-encoded structure and returns a new Signature.
-
- Arguments:
- stream: a BytesIO to read the signature from.
-
- Returns:
- A new Signature object.
-
- Raises:
- AftlError: If the hash algorithm or signature algorithm value is
- unknown; or if the decoding failed.
- """
- 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):
- """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:
- A new VBMetaPrimaryAnnotation.
-
- 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 new SignedVBMetaPrimaryAnnotation.
-
- Raises:
- AftlError: If an error occured while signing the annotation.
- """
- # 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 VBMetaPrimaryAnnotation.
-
- Arguments:
- o: The object to write the output to.
- """
- 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.manufacturer_key_hash:
- o.write(fmt.format(i, 'Manufacturer key hash:',
- self.manufacturer_key_hash.hex()))
- if self.description:
- 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.
-
- This encapsulates an AFTL ICP section with all information required to
- validate an inclusion proof.
-
- Attributes:
- image_header: A header for the section.
- icp_entries: A list of AftlIcpEntry objects representing the inclusion
- proofs.
- """
-
- def __init__(self, data=None):
- """Initializes a new AftlImage section.
-
- Arguments:
- data: If not None, must be a bytearray representing an AftlImage.
-
- Raises:
- AftlError: If the data does not represent a well-formed AftlImage.
- """
- if data:
- image_header_bytes = data[0:AftlImageHeader.SIZE]
- self.image_header = AftlImageHeader(image_header_bytes)
- if not self.image_header.is_valid():
- raise AftlError('Invalid AftlImageHeader.')
- icp_count = self.image_header.icp_count
-
- # Jump past the header for entry deserialization.
- icp_index = AftlImageHeader.SIZE
- # Validate each entry.
- self.icp_entries = []
- # add_icp_entry() updates entries and header, so set header count to
- # compensate.
- self.image_header.icp_count = 0
- for i in range(icp_count):
- # Get the entry header from the AftlImage.
- cur_icp_entry = AftlIcpEntry(data[icp_index:])
- cur_icp_entry_size = cur_icp_entry.get_expected_size()
- # Now validate the entry structure.
- if not cur_icp_entry.is_valid():
- raise AftlError('Validation of ICP entry {} failed.'.format(i))
- self.add_icp_entry(cur_icp_entry)
- icp_index += cur_icp_entry_size
- else:
- self.image_header = AftlImageHeader()
- self.icp_entries = []
- if not self.is_valid():
- raise AftlError('Invalid AftlImage.')
-
- def add_icp_entry(self, icp_entry):
- """Adds a new AftlIcpEntry to the AftlImage, updating fields as needed.
-
- Arguments:
- icp_entry: An AftlIcpEntry structure.
- """
- self.icp_entries.append(icp_entry)
- self.image_header.icp_count += 1
- self.image_header.aftl_image_size += icp_entry.get_expected_size()
-
- def verify_vbmeta_image(self, vbmeta_image, transparency_log_pub_keys):
- """Verifies the contained inclusion proof given the public log key.
-
- Arguments:
- vbmeta_image: The vbmeta_image that should be verified against the
- inclusion proof.
- transparency_log_pub_keys: List of paths to PEM files containing trusted
- public keys that correspond with the transparency_logs.
-
- Returns:
- True if all the inclusion proofs in the AfltDescriptor validate, are
- signed by one of the give transparency log public keys; otherwise false.
- """
- if not transparency_log_pub_keys or not self.icp_entries:
- return False
-
- icp_verified = 0
- for icp_entry in self.icp_entries:
- verified = False
- for pub_key in transparency_log_pub_keys:
- if icp_entry.verify_vbmeta_image(vbmeta_image, pub_key):
- verified = True
- break
- if verified:
- icp_verified += 1
- return icp_verified == len(self.icp_entries)
-
- def encode(self):
- """Serialize the AftlImage to a bytearray().
-
- Returns:
- A bytearray() with the encoded AFTL image.
-
- Raises:
- AftlError: If invalid AFTL image structure.
- """
- # The header and entries are guaranteed to be valid when encode is called.
- # Check the entire structure as a whole.
- if not self.is_valid():
- raise AftlError('Invalid AftlImage structure.')
-
- aftl_image = bytearray()
- aftl_image.extend(self.image_header.encode())
- for icp_entry in self.icp_entries:
- aftl_image.extend(icp_entry.encode())
- return aftl_image
-
- def is_valid(self):
- """Ensures that values in the AftlImage are sane.
-
- Returns:
- True if the values in the AftlImage are sane, False otherwise.
- """
- if not self.image_header.is_valid():
- return False
-
- if self.image_header.icp_count != len(self.icp_entries):
- return False
-
- for icp_entry in self.icp_entries:
- if not icp_entry.is_valid():
- return False
- return True
-
- def print_desc(self, o):
- """Print the AFTL image.
-
- Arguments:
- o: The object to write the output to.
- """
- o.write('Android Firmware Transparency Image:\n')
- self.image_header.print_desc(o)
- for i, icp_entry in enumerate(self.icp_entries):
- o.write(' Entry #{}:\n'.format(i + 1))
- icp_entry.print_desc(o)
-
-
-class AftlCommunication(object):
- """Class to abstract the communication layer with the transparency log."""
-
- def __init__(self, transparency_log_config, timeout):
- """Initializes the object.
-
- Arguments:
- transparency_log_config: A TransparencyLogConfig instance.
- timeout: Duration in seconds before requests to the AFTL times out. A
- value of 0 or None means there will be no timeout.
- """
- self.transparency_log_config = transparency_log_config
- if timeout:
- self.timeout = timeout
- else:
- self.timeout = None
-
- def add_vbmeta(self, request):
- """Calls the AddVBMeta RPC on the AFTL server.
-
- Arguments:
- request: An AddVBMetaRequest message.
-
- Returns:
- 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(
- 'add_vbmeta() needs to be implemented by subclass.')
-
-
-class AftlGrpcCommunication(AftlCommunication):
- """Class that implements GRPC communication to the AFTL server."""
-
- def add_vbmeta(self, request):
- """Calls the AddVBMeta RPC on the AFTL server.
-
- Arguments:
- request: An AddVBMetaRequest message.
-
- Returns:
- 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 breaks
- # running unittest with atest.
- try:
- import grpc # pylint: disable=import-outside-toplevel
- from proto import api_pb2_grpc # pylint: disable=import-outside-toplevel
- except ImportError as e:
- err_str = 'grpc can be installed with python pip install grpcio.\n'
- raise AftlError('Failed to import module: ({}).\n{}'.format(e, err_str))
-
- # Set up the gRPC channel with the transparency log.
- sys.stdout.write('Preparing to request inclusion proof from {}. This could '
- 'take ~30 seconds for the process to complete.\n'.format(
- self.transparency_log_config.target))
- channel = grpc.insecure_channel(self.transparency_log_config.target)
- stub = api_pb2_grpc.AFTLogStub(channel)
-
- metadata = []
- if self.transparency_log_config.api_key:
- metadata.append(('x-api-key', self.transparency_log_config.api_key))
-
- # Attempt to transmit to the transparency log.
- sys.stdout.write('ICP is about to be requested from transparency log '
- 'with domain {}.\n'.format(
- self.transparency_log_config.target))
- try:
- response = stub.AddVBMeta(request, timeout=self.timeout,
- metadata=metadata)
- except grpc.RpcError as e:
- raise AftlError('Error: grpc failure ({})'.format(e))
- return response
-
-
-class Aftl(avbtool.Avb):
- """Business logic for aftltool command-line tool."""
-
- def get_vbmeta_image(self, image_filename):
- """Gets the VBMeta struct bytes from image.
-
- Arguments:
- image_filename: Image file to get information from.
-
- Returns:
- A tuple with following elements:
- 1. A bytearray with the vbmeta structure or None if the file does not
- contain a VBMeta structure.
- 2. The VBMeta image footer.
- """
- # Reads and parses the vbmeta image.
- try:
- image = avbtool.ImageHandler(image_filename, read_only=True)
- except (IOError, ValueError) as e:
- sys.stderr.write('The image does not contain a valid VBMeta structure: '
- '{}.\n'.format(e))
- return None, None
-
- try:
- (footer, header, _, _) = self._parse_image(image)
- except avbtool.AvbError as e:
- sys.stderr.write('The image cannot be parsed: {}.\n'.format(e))
- return None, None
-
- # Seeks for the start of the vbmeta image and calculates its size.
- offset = 0
- if footer:
- offset = footer.vbmeta_offset
- vbmeta_image_size = (offset + header.SIZE
- + header.authentication_data_block_size
- + header.auxiliary_data_block_size)
-
- # Reads the vbmeta image bytes.
- try:
- image.seek(offset)
- except RuntimeError as e:
- sys.stderr.write('Given vbmeta image offset is invalid: {}.\n'.format(e))
- return None, None
- return image.read(vbmeta_image_size), footer
-
- def get_aftl_image(self, image_filename):
- """Gets the AftlImage from image.
-
- Arguments:
- image_filename: Image file to get information from.
-
- Returns:
- An AftlImage or None if the file does not contain a AftlImage.
- """
- # Reads the vbmeta image bytes.
- vbmeta_image, _ = self.get_vbmeta_image(image_filename)
- if not vbmeta_image:
- return None
-
- try:
- image = avbtool.ImageHandler(image_filename, read_only=True)
- except ValueError as e:
- sys.stderr.write('The image does not contain a valid VBMeta structure: '
- '{}.\n'.format(e))
- return None
-
- # Seeks for the start of the AftlImage.
- try:
- image.seek(len(vbmeta_image))
- except RuntimeError as e:
- sys.stderr.write('Given AftlImage image offset is invalid: {}.\n'
- .format(e))
- return None
-
- # Parses the header for the AftlImage size.
- tmp_header_bytes = image.read(AftlImageHeader.SIZE)
- if not tmp_header_bytes or len(tmp_header_bytes) != AftlImageHeader.SIZE:
- sys.stderr.write('This image does not contain an AftlImage.\n')
- return None
-
- try:
- tmp_header = AftlImageHeader(tmp_header_bytes)
- except AftlError as e:
- sys.stderr.write('This image does not contain a valid AftlImage: '
- '{}.\n'.format(e))
- return None
-
- # Resets to the beginning of the AftlImage.
- try:
- image.seek(len(vbmeta_image))
- except RuntimeError as e:
- sys.stderr.write('Given AftlImage image offset is invalid: {}.\n'
- .format(e))
- return None
-
- # Parses the full AftlImage.
- aftl_image_bytes = image.read(tmp_header.aftl_image_size)
- aftl_image = None
- try:
- aftl_image = AftlImage(aftl_image_bytes)
- except AftlError as e:
- sys.stderr.write('The image does not contain a valid AftlImage: '
- '{}.\n'.format(e))
- return aftl_image
-
- def info_image_icp(self, vbmeta_image_path, output):
- """Implements the 'info_image_icp' command.
-
- Arguments:
- vbmeta_image_path: Image file to get information from.
- output: Output file to write human-readable information to (file object).
-
- Returns:
- True if the given image has an AftlImage and could successfully
- be processed; otherwise False.
- """
- aftl_image = self.get_aftl_image(vbmeta_image_path)
- if not aftl_image:
- return False
- aftl_image.print_desc(output)
- return True
-
- def verify_image_icp(self, vbmeta_image_path, transparency_log_pub_keys,
- output):
- """Implements the 'verify_image_icp' command.
-
- Arguments:
- vbmeta_image_path: Image file to get information from.
- transparency_log_pub_keys: List of paths to PEM files containing trusted
- public keys that correspond with the transparency_logs.
- output: Output file to write human-readable information to (file object).
-
- Returns:
- True if for the given image the inclusion proof validates; otherwise
- False.
- """
- vbmeta_image, _ = self.get_vbmeta_image(vbmeta_image_path)
- aftl_image = self.get_aftl_image(vbmeta_image_path)
- if not aftl_image or not vbmeta_image:
- return False
- verified = aftl_image.verify_vbmeta_image(vbmeta_image,
- transparency_log_pub_keys)
- if not verified:
- output.write('The inclusion proofs for the image do not validate.\n')
- return False
- output.write('The inclusion proofs for the image successfully validate.\n')
- return True
-
- def request_inclusion_proof(self, transparency_log_config, vbmeta_image,
- version_inc, manufacturer_key_path,
- signing_helper, signing_helper_with_files,
- timeout, aftl_comms=None):
- """Packages and sends a request to the specified transparency log.
-
- Arguments:
- transparency_log_config: A TransparencyLogConfig instance.
- vbmeta_image: A bytearray with the VBMeta image.
- version_inc: Subcomponent of the build fingerprint.
- 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.
- timeout: Duration in seconds before requests to the transparency log
- timeout.
- aftl_comms: A subclass of the AftlCommunication class. The default is
- to use AftlGrpcCommunication.
-
- Returns:
- An AftlIcpEntry with the inclusion proof for the log entry.
-
- Raises:
- AftlError: If grpc or the proto modules cannot be loaded, if there is an
- error communicating with the log, if the manufacturer_key_path
- cannot be decoded, or if the log submission cannot be signed.
- """
- # Calculate the hash of the vbmeta image.
- vbmeta_hash = hashlib.sha256(vbmeta_image).digest()
-
- # Extract the key data from the PEM file if of size 4096.
- manufacturer_key = avbtool.RSAPublicKey(manufacturer_key_path)
- if manufacturer_key.num_bits != 4096:
- raise AftlError('Manufacturer keys not of size 4096: {}'.format(
- manufacturer_key.num_bits))
- manufacturer_key_data = rsa_key_read_pem_bytes(manufacturer_key_path)
-
- # Calculate the hash of the manufacturer key data.
- m_key_hash = hashlib.sha256(manufacturer_key_data).digest()
-
- # Build VBMetaPrimaryAnnotation with that data.
- annotation = VBMetaPrimaryAnnotation(
- vbmeta_hash=vbmeta_hash, version_incremental=version_inc,
- manufacturer_key_hash=m_key_hash)
-
- # 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)
-
- 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_vbmeta(request)
-
- # Return an AftlIcpEntry representing this response.
- icp_entry = AftlIcpEntry()
- icp_entry.translate_response(transparency_log_config.target, response)
- return icp_entry
-
- def make_icp_from_vbmeta(self, vbmeta_image_path, output,
- signing_helper, signing_helper_with_files,
- version_incremental, transparency_log_configs,
- manufacturer_key, padding_size, timeout):
- """Generates a vbmeta image with inclusion proof given a vbmeta image.
-
- The AftlImage contains the information required to validate an inclusion
- proof for a specific vbmeta image. It consists of a header (struct
- AftlImageHeader) and zero or more entry structures (struct AftlIcpEntry)
- that contain the vbmeta leaf hash, tree size, root hash, inclusion proof
- hashes, and the signature for the root hash.
-
- The vbmeta image, its hash, the version_incremental part of the build
- fingerprint, and the hash of the manufacturer key are sent to the
- transparency log, with the message signed by the manufacturer key.
- An inclusion proof is calculated and returned. This inclusion proof is
- then packaged in an AftlImage structure. The existing vbmeta data is
- copied to a new file, appended with the AftlImage data, and written to
- output. Validation of the inclusion proof does not require
- communication with the transparency log.
-
- Arguments:
- vbmeta_image_path: Path to a vbmeta image file.
- output: File to write the results to.
- signing_helper: Program which signs a hash and returns a signature.
- signing_helper_with_files: Same as signing_helper but uses files instead.
- version_incremental: A string representing the subcomponent of the
- build fingerprint used to identify the vbmeta in the transparency log.
- transparency_log_configs: List of TransparencyLogConfig used to request
- the inclusion proofs.
- manufacturer_key: Path to PEM file containting the key file used to sign
- messages sent to the transparency log servers.
- padding_size: If not 0, pads output so size is a multiple of the number.
- timeout: Duration in seconds before requests to the AFTL times out. A
- value of 0 or None means there will be no timeout.
-
- Returns:
- True if the inclusion proofs could be fetched from the transparency log
- servers and could be successfully validated; otherwise False.
- """
- # Retrieves vbmeta structure from given partition image.
- vbmeta_image, footer = self.get_vbmeta_image(vbmeta_image_path)
-
- # Fetches inclusion proofs for vbmeta structure from all transparency logs.
- aftl_image = AftlImage()
- for log_config in transparency_log_configs:
- try:
- icp_entry = self.request_inclusion_proof(log_config, vbmeta_image,
- version_incremental,
- manufacturer_key,
- signing_helper,
- signing_helper_with_files,
- timeout)
- if not icp_entry.verify_vbmeta_image(vbmeta_image, log_config.pub_key):
- sys.stderr.write('The inclusion proof from {} could not be verified.'
- '\n'.format(log_config.target))
- aftl_image.add_icp_entry(icp_entry)
- except AftlError as e:
- # The inclusion proof request failed. Continue and see if others will.
- sys.stderr.write('Requesting inclusion proof failed: {}.\n'.format(e))
- continue
-
- # Checks that the resulting AftlImage is sane.
- if aftl_image.image_header.icp_count != len(transparency_log_configs):
- sys.stderr.write('Valid inclusion proofs could only be retrieved from {} '
- 'out of {} transparency logs.\n'
- .format(aftl_image.image_header.icp_count,
- len(transparency_log_configs)))
- return False
- if not aftl_image.is_valid():
- sys.stderr.write('Resulting AftlImage structure is malformed.\n')
- return False
- keys = [log.pub_key for log in transparency_log_configs]
- if not aftl_image.verify_vbmeta_image(vbmeta_image, keys):
- sys.stderr.write('Resulting AftlImage inclusion proofs do not '
- 'validate.\n')
- return False
-
- # Writes original VBMeta image, followed by the AftlImage into the output.
- if footer: # Checks if it is a chained partition.
- # TODO(b/147217370): Determine the best way to handle chained partitions
- # like the system.img. Currently, we only put the main vbmeta.img in the
- # transparency log.
- sys.stderr.write('Image has a footer and ICP for this format is not '
- 'implemented.\n')
- return False
-
- output.seek(0)
- output.write(vbmeta_image)
- encoded_aftl_image = aftl_image.encode()
- output.write(encoded_aftl_image)
-
- if padding_size > 0:
- total_image_size = len(vbmeta_image) + len(encoded_aftl_image)
- padded_size = avbtool.round_to_multiple(total_image_size, padding_size)
- padding_needed = padded_size - total_image_size
- output.write('\0' * padding_needed)
-
- sys.stdout.write('VBMeta image with AFTL image successfully created.\n')
- return True
-
- def _load_test_process_function(self, vbmeta_image_path,
- transparency_log_config,
- manufacturer_key,
- process_number, submission_count,
- preserve_icp_images, timeout, result_queue):
- """Function to be used by multiprocessing.Process.
-
- Arguments:
- vbmeta_image_path: Path to a vbmeta image file.
- transparency_log_config: A TransparencyLogConfig instance used to request
- an inclusion proof.
- manufacturer_key: Path to PEM file containting the key file used to sign
- messages sent to the transparency log servers.
- process_number: The number of the processes executing the function.
- submission_count: Number of total submissions to perform per
- process_count.
- preserve_icp_images: Boolean to indicate if the generated vbmeta image
- files with inclusion proofs should be preserved in the temporary
- directory.
- timeout: Duration in seconds before requests to the AFTL times out. A
- value of 0 or None means there will be no timeout.
- result_queue: Multiprocessing.Queue object for posting execution results.
- """
- for count in range(0, submission_count):
- version_incremental = 'aftl_load_testing_{}_{}'.format(process_number,
- count)
- output_file = os.path.join(tempfile.gettempdir(),
- '{}_icp.img'.format(version_incremental))
- output = open(output_file, 'wb')
-
- # Instrumented section.
- start_time = time.time()
- result = self.make_icp_from_vbmeta(
- vbmeta_image_path=vbmeta_image_path,
- output=output,
- signing_helper=None,
- signing_helper_with_files=None,
- version_incremental=version_incremental,
- transparency_log_configs=[transparency_log_config],
- manufacturer_key=manufacturer_key,
- padding_size=0,
- timeout=timeout)
- end_time = time.time()
-
- output.close()
- if not preserve_icp_images:
- os.unlink(output_file)
-
- # Puts the result onto the result queue.
- execution_time = end_time - start_time
- result_queue.put((start_time, end_time, execution_time,
- version_incremental, result))
-
- def load_test_aftl(self, vbmeta_image_path, output, transparency_log_config,
- manufacturer_key,
- process_count, submission_count, stats_filename,
- preserve_icp_images, timeout):
- """Performs multi-threaded load test on a given AFTL and prints stats.
-
- Arguments:
- vbmeta_image_path: Path to a vbmeta image file.
- output: File to write the report to.
- transparency_log_config: A TransparencyLogConfig used to request an
- inclusion proof.
- manufacturer_key: Path to PEM file containting the key file used to sign
- messages sent to the transparency log servers.
- process_count: Number of processes used for parallel testing.
- submission_count: Number of total submissions to perform per
- process_count.
- stats_filename: Path to the stats file to write the raw execution data to.
- If None, it will be written to the temp directory.
- preserve_icp_images: Boolean to indicate if the generated vbmeta
- image files with inclusion proofs should preserved.
- timeout: Duration in seconds before requests to the AFTL times out. A
- value of 0 or None means there will be no timeout.
-
- Returns:
- True if the load tested succeeded without errors; otherwise False.
- """
- if process_count < 1 or submission_count < 1:
- sys.stderr.write('Values for --processes/--submissions '
- 'must be at least 1.\n')
- return False
-
- if not stats_filename:
- stats_filename = os.path.join(
- tempfile.gettempdir(),
- 'load_test_p{}_s{}.csv'.format(process_count, submission_count))
-
- stats_file = None
- try:
- stats_file = open(stats_filename, 'wt')
- stats_file.write('start_time,end_time,execution_time,version_incremental,'
- 'result\n')
- except IOError as e:
- sys.stderr.write('Could not open stats file {}: {}.\n'
- .format(stats_file, e))
- return False
-
- # Launch all the processes with their workloads.
- result_queue = multiprocessing.Queue()
- processes = set()
- execution_times = []
- results = []
- for i in range(0, process_count):
- p = multiprocessing.Process(
- target=self._load_test_process_function,
- args=(vbmeta_image_path, transparency_log_config,
- manufacturer_key, i, submission_count,
- preserve_icp_images, timeout, result_queue))
- p.start()
- processes.add(p)
-
- while processes:
- # Processes the results queue and writes these to a stats file.
- try:
- (start_time, end_time, execution_time, version_incremental,
- result) = result_queue.get(timeout=1)
- stats_file.write('{},{},{},{},{}\n'.format(start_time, end_time,
- execution_time,
- version_incremental, result))
- execution_times.append(execution_time)
- results.append(result)
- except queue.Empty:
- pass
-
- # Checks if processes are still alive; if not clean them up. join() would
- # have been nicer but we want to continously stream out the stats to file.
- for p in processes.copy():
- if not p.is_alive():
- processes.remove(p)
-
- # Prepares stats.
- executions = sorted(execution_times)
- execution_count = len(execution_times)
- median = 0
-
- # pylint: disable=old-division
- if execution_count % 2 == 0:
- median = (executions[execution_count // 2 - 1]
- + executions[execution_count // 2]) / 2
- else:
- median = executions[execution_count // 2]
-
- # Outputs the stats report.
- o = output
- o.write('Load testing results:\n')
- o.write(' Processes: {}\n'.format(process_count))
- o.write(' Submissions per process: {}\n'.format(submission_count))
- o.write('\n')
- o.write(' Submissions:\n')
- o.write(' Total: {}\n'.format(len(executions)))
- o.write(' Succeeded: {}\n'.format(results.count(True)))
- o.write(' Failed: {}\n'.format(results.count(False)))
- o.write('\n')
- o.write(' Submission execution durations:\n')
- o.write(' Average: {:.2f} sec\n'.format(
- sum(execution_times) / execution_count))
- o.write(' Median: {:.2f} sec\n'.format(median))
- o.write(' Min: {:.2f} sec\n'.format(min(executions)))
- o.write(' Max: {:.2f} sec\n'.format(max(executions)))
-
- # Close the stats file.
- stats_file.close()
- if results.count(False):
- return False
- return True
-
-
-class TransparencyLogConfig(object):
- """Class that gathers the fields representing a transparency log.
-
- Attributes:
- target: The hostname and port of the server in hostname:port format.
- pub_key: A PEM file that contains the public key of the transparency
- log server.
- api_key: The API key to use to interact with the transparency log
- server.
- """
-
- @staticmethod
- def from_argument(arg):
- """Build an object from a command line argument string.
-
- Arguments:
- arg: The transparency log as passed in the command line argument.
- It must be in the format: host:port,key_file[,api_key].
-
- Returns:
- The TransparencyLogConfig instance.
-
- Raises:
- argparse.ArgumentTypeError: If the format of arg is invalid.
- """
- api_key = None
- try:
- target, pub_key, *rest = arg.split(",", maxsplit=2)
- except ValueError:
- raise argparse.ArgumentTypeError("incorrect format for transparency log "
- "server, expected "
- "host:port,publickey_file.")
- if not target:
- raise argparse.ArgumentTypeError("incorrect format for transparency log "
- "server: host:port cannot be empty.")
- if not pub_key:
- raise argparse.ArgumentTypeError("incorrect format for transparency log "
- "server: publickey_file cannot be "
- "empty.")
- if rest:
- api_key = rest[0]
- return TransparencyLogConfig(target, pub_key, api_key)
-
- def __init__(self, target, pub_key, api_key=None):
- """Initializes a new TransparencyLogConfig object."""
- self.target = target
- self.pub_key = pub_key
- self.api_key = api_key
-
-
-class AftlTool(avbtool.AvbTool):
- """Object for aftltool command-line tool."""
-
- def __init__(self):
- """Initializer method."""
- self.aftl = Aftl()
- super(AftlTool, self).__init__()
-
- def make_icp_from_vbmeta(self, args):
- """Implements the 'make_icp_from_vbmeta' sub-command."""
- args = self._fixup_common_args(args)
- return self.aftl.make_icp_from_vbmeta(args.vbmeta_image_path,
- args.output,
- args.signing_helper,
- args.signing_helper_with_files,
- args.version_incremental,
- args.transparency_log_servers,
- args.manufacturer_key,
- args.padding_size,
- args.timeout)
-
- def info_image_icp(self, args):
- """Implements the 'info_image_icp' sub-command."""
- return self.aftl.info_image_icp(args.vbmeta_image_path.name, args.output)
-
- def verify_image_icp(self, args):
- """Implements the 'verify_image_icp' sub-command."""
- return self.aftl.verify_image_icp(args.vbmeta_image_path.name,
- args.transparency_log_pub_keys,
- args.output)
-
- def load_test_aftl(self, args):
- """Implements the 'load_test_aftl' sub-command."""
- return self.aftl.load_test_aftl(args.vbmeta_image_path,
- args.output,
- args.transparency_log_server,
- args.manufacturer_key,
- args.processes,
- args.submissions,
- args.stats_file,
- args.preserve_icp_images,
- args.timeout)
-
- def run(self, argv):
- """Command-line processor.
-
- Arguments:
- argv: Pass sys.argv from main.
- """
- parser = argparse.ArgumentParser()
- subparsers = parser.add_subparsers(title='subcommands')
-
- # Command: make_icp_from_vbmeta
- sub_parser = subparsers.add_parser('make_icp_from_vbmeta',
- help='Makes an ICP enhanced vbmeta image'
- ' from an existing vbmeta image.')
- sub_parser.add_argument('--output',
- help='Output file name.',
- type=argparse.FileType('wb'),
- default=sys.stdout)
- sub_parser.add_argument('--vbmeta_image_path',
- help='Path to a generate vbmeta image file.',
- required=True)
- sub_parser.add_argument('--version_incremental',
- help='Current build ID.',
- required=True)
- sub_parser.add_argument('--manufacturer_key',
- help='Path to the PEM file containing the '
- 'manufacturer key for use with the log.',
- required=True)
- sub_parser.add_argument('--transparency_log_servers',
- help='List of transparency log servers in '
- 'host:port,publickey_file[,api_key] format. The '
- 'publickey_file must be in the PEM format.',
- nargs='+', type=TransparencyLogConfig.from_argument)
- sub_parser.add_argument('--padding_size',
- metavar='NUMBER',
- help='If non-zero, pads output with NUL bytes so '
- 'its size is a multiple of NUMBER (default: 0)',
- type=avbtool.parse_number,
- default=0)
- sub_parser.add_argument('--timeout',
- metavar='SECONDS',
- help='Timeout in seconds for transparency log '
- 'requests (default: 600 sec). A value of 0 means '
- 'no timeout.',
- type=avbtool.parse_number,
- default=600)
- self._add_common_args(sub_parser)
- sub_parser.set_defaults(func=self.make_icp_from_vbmeta)
-
- # Command: info_image_icp
- sub_parser = subparsers.add_parser(
- 'info_image_icp',
- help='Show information about AFTL ICPs in vbmeta or footer.')
- sub_parser.add_argument('--vbmeta_image_path',
- help='Path to vbmeta image for AFTL information.',
- type=argparse.FileType('rb'),
- required=True)
- sub_parser.add_argument('--output',
- help='Write info to file',
- type=argparse.FileType('wt'),
- default=sys.stdout)
- sub_parser.set_defaults(func=self.info_image_icp)
-
- # Arguments for verify_image_icp.
- sub_parser = subparsers.add_parser(
- 'verify_image_icp',
- help='Verify AFTL ICPs in vbmeta or footer.')
-
- sub_parser.add_argument('--vbmeta_image_path',
- help='Image to verify the inclusion proofs.',
- type=argparse.FileType('rb'),
- required=True)
- sub_parser.add_argument('--transparency_log_pub_keys',
- help='Paths to PEM files containing transparency '
- 'log server key(s). This must not be None.',
- nargs='*',
- required=True)
- sub_parser.add_argument('--output',
- help='Write info to file',
- type=argparse.FileType('wt'),
- default=sys.stdout)
- sub_parser.set_defaults(func=self.verify_image_icp)
-
- # Command: load_test_aftl
- sub_parser = subparsers.add_parser(
- 'load_test_aftl',
- help='Perform load testing against one AFTL log server. Note: This MUST'
- ' not be performed against a production system.')
- sub_parser.add_argument('--vbmeta_image_path',
- help='Path to a generate vbmeta image file.',
- required=True)
- sub_parser.add_argument('--output',
- help='Write report to file.',
- type=argparse.FileType('wt'),
- default=sys.stdout)
- sub_parser.add_argument('--manufacturer_key',
- help='Path to the PEM file containing the '
- 'manufacturer key for use with the log.',
- required=True)
- sub_parser.add_argument('--transparency_log_server',
- help='Transparency log server to test against in '
- 'host:port,publickey_file[,api_key] format. The '
- 'publickey_file must be in the PEM format.',
- required=True,
- type=TransparencyLogConfig.from_argument)
- sub_parser.add_argument('--processes',
- help='Number of parallel processes to use for '
- 'testing (default: 1).',
- type=avbtool.parse_number,
- default=1)
- sub_parser.add_argument('--submissions',
- help='Number of submissions to perform against the '
- 'log per process (default: 1).',
- type=avbtool.parse_number,
- default=1)
- sub_parser.add_argument('--stats_file',
- help='Path to the stats file to write the raw '
- 'execution data to (Default: '
- 'load_test_p[processes]_s[submissions].csv.')
- sub_parser.add_argument('--preserve_icp_images',
- help='Boolean flag to indicate if the generated '
- 'vbmeta image files with inclusion proofs should '
- 'preserved.',
- action='store_true')
- sub_parser.add_argument('--timeout',
- metavar='SECONDS',
- help='Timeout in seconds for transparency log '
- 'requests (default: 0). A value of 0 means '
- 'no timeout.',
- type=avbtool.parse_number,
- default=0)
- sub_parser.set_defaults(func=self.load_test_aftl)
-
- args = parser.parse_args(argv[1:])
- 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))
- sys.exit(2)
-
- if not success:
- # Signals to calling tools that the command has failed.
- sys.exit(1)
-
-if __name__ == '__main__':
- tool = AftlTool()
- tool.run(sys.argv)
diff --git a/aftltool_integration_test.py b/aftltool_integration_test.py
deleted file mode 100755
index 814631b..0000000
--- a/aftltool_integration_test.py
+++ /dev/null
@@ -1,82 +0,0 @@
-#!/usr/bin/env python3
-
-# Copyright 2019, The Android Open Source Project
-#
-# Permission is hereby granted, free of charge, to any person
-# obtaining a copy of this software and associated documentation
-# files (the "Software"), to deal in the Software without
-# restriction, including without limitation the rights to use, copy,
-# modify, merge, publish, distribute, sublicense, and/or sell copies
-# of the Software, and to permit persons to whom the Software is
-# furnished to do so, subject to the following conditions:
-#
-# The above copyright notice and this permission notice shall be
-# included in all copies or substantial portions of the Software.
-#
-# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
-# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
-# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
-# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
-# BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
-# ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
-# CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
-# SOFTWARE.
-#
-"""Integration tests for the avbtool with an actual AFTL.
-
-The test cases directly interact with a transparency log. However,
-before using this script the following environment variables
-need to be set:
-
- AFTL_HOST: host:port of the transparency log to test with.
- AFTL_PUBKEY: Transparency log public key in PEM format.
- AFTL_APIKEY: If the transparency log requires an API key to submit data,
- this should be the complete key.
- AFTL_VBMETA_IMAGE: VBMeta image that should be used for submission to AFTL.
- AFTL_MANUFACTURER_KEY: Manufacturer signing key used to sign submissions
- to the transparency log in PEM format.
-"""
-
-import os
-import unittest
-
-import aftltool
-import aftltool_test
-
-
-class AftlIntegrationTest(aftltool_test.AftlTest):
- """Test suite for integration testing aftltool with an actual AFTL.
-
- Note: The actual testcases are implemented are implemented as part of the
- super class. This class only contains the configuration for running the unit
- tests against as a live log as a means of integration testing.
- """
-
- def set_up_environment(self):
- """Sets up the environment for integration testing with actual AFTL."""
- self.aftl_host = os.environ.get('AFTL_HOST')
- self.aftl_pubkey = os.environ.get('AFTL_PUBKEY')
- self.aftl_apikey = os.environ.get('AFTL_APIKEY')
- self.vbmeta_image = os.environ.get('AFTL_VBMETA_IMAGE')
- self.manufacturer_key = os.environ.get('AFTL_MANUFACTURER_KEY')
-
- if (not self.aftl_host or not self.aftl_pubkey or not self.vbmeta_image
- or not self.manufacturer_key):
- self.fail('Environment variables not correctly set up. See description of'
- ' this test case for details')
-
- def get_aftl_implementation(self, canned_response):
- """Retrieves an instance if aftltool.Aftl for integration testing.
-
- Arguments:
- canned_response: Since we are using the actual implementation and not a
- mock this gets ignored.
-
- Returns:
- An instance of aftltool.Aftl()
- """
- return aftltool.Aftl()
-
-
-if __name__ == '__main__':
- unittest.main(verbosity=2)
diff --git a/aftltool_test.py b/aftltool_test.py
deleted file mode 100755
index 7c8c205..0000000
--- a/aftltool_test.py
+++ /dev/null
@@ -1,1609 +0,0 @@
-#!/usr/bin/env python3
-
-# Copyright 2019, The Android Open Source Project
-#
-# Permission is hereby granted, free of charge, to any person
-# obtaining a copy of this software and associated documentation
-# files (the "Software"), to deal in the Software without
-# restriction, including without limitation the rights to use, copy,
-# modify, merge, publish, distribute, sublicense, and/or sell copies
-# of the Software, and to permit persons to whom the Software is
-# furnished to do so, subject to the following conditions:
-#
-# The above copyright notice and this permission notice shall be
-# included in all copies or substantial portions of the Software.
-#
-# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
-# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
-# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
-# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
-# BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
-# ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
-# CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
-# SOFTWARE.
-#
-"""Unit tests for aftltool."""
-
-import argparse
-import binascii
-import io
-import os
-import struct
-import sys
-import tempfile
-import unittest
-
-import aftltool
-import avbtool
-
-# pylint: disable=import-error
-import api_pb2
-# pylint: enable=import-error
-
-
-# Workaround for b/149307145 in order to pick up the test data from the right
-# location independent where the script is called from.
-# 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):
-
- def setUp(self):
- """Sets up the test bed for the unit tests."""
- super(AftltoolTestCase, self).setUp()
-
- # Redirects the stderr to /dev/null when running the unittests. The reason
- # is that soong interprets any output on stderr as an error and marks the
- # unit test as failed although the test itself succeeded.
- self.stderr = sys.stderr
- self.null = open(os.devnull, 'wt')
- sys.stderr = self.null
-
- # AFTL public key.
- self.test_aftl_pub_key = (
- '-----BEGIN PUBLIC KEY-----\n'
- 'MIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEA4ilqCNsenNA013iCdwgD\n'
- 'YPxZ853nbHG9lMBp9boXiwRcqT/8bUKHIL7YX5z7s+QoRYVY3rkMKppRabclXzyx\n'
- 'H59YnPMaU4uv7NqwWzjgaZo7E+vo7IF+KBjV3cJulId5Av0yIYUCsrwd7MpGtWdC\n'
- 'Q3S+7Vd4zwzCKEhcvliNIhnNlp1U3wNkPCxOyCAsMEn6k8O5ar12ke5TvxDv15db\n'
- 'rPDeHh8G2OYWoCkWL+lSN35L2kOJqKqVbLKWrrOd96RCYrrtbPCi580OADJRcUlG\n'
- 'lgcjwmNwmypBWvQMZ6ITj0P0ksHnl1zZz1DE2rXe1goLI1doghb5KxLaezlR8c2C\n'
- 'E3w/uo9KJgNmNgUVzzqZZ6FE0moyIDNOpP7KtZAL0DvEZj6jqLbB0ccPQElrg52m\n'
- 'Dv2/A3nYSr0mYBKeskT4+Bg7PGgoC8p7WyLSxMyzJEDYdtrj9OFx6eZaA23oqTQx\n'
- 'k3Qq5H8RfNBeeSUEeKF7pKH/7gyqZ2bNzBFMA2EBZgBozwRfaeN/HCv3qbaCnwvu\n'
- '6caacmAsK+RxiYxSL1QsJqyhCWWGxVyenmxdc1KG/u5ypi7OIioztyzR3t2tAzD3\n'
- 'Nb+2t8lgHBRxbV24yiPlnvPmB1ZYEctXnlRR9Evpl1o9xA9NnybPHKr9rozN39CZ\n'
- 'V/USB8K6ao1y5xPZxa8CZksCAwEAAQ==\n'
- '-----END PUBLIC KEY-----\n')
-
- # Test AftlIcpEntry #1
- self.test_tl_url_1 = 'aftl-test-server.google.com'
-
- self.test_sth_1 = aftltool.TrillianLogRootDescriptor()
- self.test_sth_1.tree_size = 2
- self.test_sth_1.root_hash_size = 32
- self.test_sth_1.root_hash = b'f' * 32
- self.test_sth_1.timestamp = 0x1234567890ABCDEF
- self.test_sth_1.revision = 0xFEDCBA0987654321
-
- self.test_sth_1_bytes = (
- b'\x00\x01' # version
- b'\x00\x00\x00\x00\x00\x00\x00\x02' # tree_size
- b'\x20' # root_hash_size
- + b'f' * 32 + # root_hash
- b'\x12\x34\x56\x78\x90\xAB\xCD\xEF' # timestamp
- b'\xFE\xDC\xBA\x09\x87\x65\x43\x21' # revision
- b'\x00\x00' # metadata_size
- 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)
- self.test_proof_hashes_1.append(b'c' * 32)
- self.test_proof_hashes_1.append(b'd' * 32)
- self.test_proof_hashes_1.append(b'e' * 32)
-
- # Valid test AftlIcpEntry #1.
- 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
-
- self.test_entry_1_bytes = (
- 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\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
- + b'd' * 32
- + b'e' * 32)
-
- # Valid test AftlIcpEntry #2.
- self.test_tl_url_2 = 'aftl-test-server.google.ch'
-
- self.test_sth_2 = aftltool.TrillianLogRootDescriptor()
- self.test_sth_2.tree_size = 4
- self.test_sth_2.root_hash_size = 32
- self.test_sth_2.root_hash = b'e' * 32
- self.test_sth_2.timestamp = 6
- self.test_sth_2.revision = 7
- self.test_sth_2.metadata_size = 2
- self.test_sth_2.metadata = b'12'
-
- self.test_sth_2_bytes = (
- b'\x00\x01' # version
- b'\x00\x00\x00\x00\x00\x00\x00\x04' # tree_size
- b'\x20' # root_hash_size
- + b'e' * 32 + # root_hash
- b'\x00\x00\x00\x00\x00\x00\x00\x06' # timestamp
- b'\x00\x00\x00\x00\x00\x00\x00\x07' # revision
- b'\x00\x02' # metadata_size
- b'12' # metadata
- )
-
- # Fill each structure with an easily observable pattern for easy validation.
- self.test_proof_hashes_2 = []
- self.test_proof_hashes_2.append(b'g' * 32)
- self.test_proof_hashes_2.append(b'h' * 32)
-
- 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
-
- self.test_entry_2_bytes = (
- 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\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)
-
- # Valid test AftlImage made out of AftlEntry #1 and #2.
- self.test_aftl_desc = aftltool.AftlImage()
- self.test_aftl_desc.add_icp_entry(self.test_entry_1)
- self.test_aftl_desc.add_icp_entry(self.test_entry_2)
-
- self.test_expected_aftl_image_bytes = (
- b'AFTL' # Magic.
- + struct.pack('!L', avbtool.AVB_VERSION_MAJOR) # Major version.
- + struct.pack('!L', avbtool.AVB_VERSION_MINOR) # Minor version.
- + b'\x00\x00\x06\xcf' # Image size.
- b'\x00\x02' # Number of ICP entries.
- + self.test_entry_1_bytes
- + self.test_entry_2_bytes)
-
- self.test_avbm_resp = api_pb2.AddVBMetaResponse()
- self.test_avbm_resp.annotation_proof.proof.leaf_index = 9127
- hashes = [
- '61076ca285b4982669e67757f55682ddc43ab5c11ba671260f82a8efa8831f94',
- '89c2fbcc58da25a65ce5e9b4fb22aaf208b20601f0bc023f73f05d35bc1f3bac',
- '75d26b5f754b4bed332a3ce2a2bfea0334706a974b7e00ee663f0279fa8b446e',
- 'e1cd9c96feb893b5ef7771e424ac1c6c47509c2b98bc578d22ad07369c9641aa',
- 'e83e0e4dd352b1670a55f93f88781a73bb41efcadb9927399f59459dfa14bc40',
- '8d5d25996117c88655d66f685baa3c94390867a040507b10587b17fbe92b496a',
- '5de4c627e9ca712f207d6056f56f0d3286ed4a5381ed7f3cc1aa470217734138',
- '19acfdb424d7fe28d1f850c76302f78f9a50146a5b9c65f9fdfbbc0173fd6993']
- for h in hashes:
- self.test_avbm_resp.annotation_proof.proof.hashes.append(
- binascii.unhexlify(h))
- self.test_avbm_resp.annotation_proof.sth.key_hint = binascii.unhexlify(
- '5af859abce8fe1ea')
- self.test_avbm_resp.annotation_proof.sth.log_root = binascii.unhexlify(
- '0001'
- '00000000000023a8'
- '20'
- '9a5f71340f8dc98bdc6320f976dda5f34db8554cb273ba5ab60f1697c519d6f6'
- '1609ae15024774b1'
- '0000000000001e5a'
- '0000'
- )
- self.test_avbm_resp.annotation_proof.sth.log_root_signature = (
- binascii.unhexlify(
- '7c37903cc76e8689a6b31da9ad56c3daeb6194029510297cc7d147278390da33'
- '09c4d9eb1f6be0cdcd1de5315b0b3b573cc9fcd8620d3fab956abbe3c597a572'
- '46e5a5d277c4cc4b590872d0292fa64e1d3285626b1dedeb00b6aa0a7a0717c0'
- '7d4c89b68fda9091be06180be1369675a7c4ce7f42cca133ef0daf8dcc5ba1ee'
- '930cef6dcb71b0a7690446e19661c8e18c089a5d6f6fc9299a0592efb33a4db5'
- '4c640027fa4f0ad0009f8bf75ec5fc17e0fa1091fabe74fe52738443745066ab'
- '48f99b297809b863c01016abda17a2479fce91f9929c60bc2ce15e474204fc5a'
- '8e79b2190aadb7c149671e8c76a4da506860f8d6020fb2eaabfee025cc267bad'
- '3c8257186c8aaf1da9eefe50cae4b3e8deb66033ebc4bfcda2b317f9e7d2dd78'
- 'b47f2d86795815d82058ad4cba8fc7983a3bbf843e9b8c7ec7f1ae137be6848d'
- '03c76eefdac40ce5e66cc23d9f3e79ad87acbe7ec0c0bb419a7d368ae1e73c85'
- '742871f847bde69c871e8797638e0e270282fb058ef1cbcba52aded9dcc8249b'
- '38fbed8424c33b8cfcde4f49797c64dda8d089d73b84062602fd41c66091543c'
- 'e13c18cfa7f8300530ad4b7adb8924bbb86d17bcc5f1d3d74c522a7dcc8c3c1f'
- '28a999f2fe1bfe5520c66f93f7c90996dc7f52e62dd95ace9ceace90324c3040'
- '669b7f5aeb5c5a53f217f1de46e32f80d0aaaf7d9cc9d0e8f8fd7026c612103a'
- )
- )
-
- 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."""
- # Reconnects stderr back to the normal stderr; see setUp() for details.
- sys.stderr = self.stderr
- self.null.close()
-
- super(AftltoolTestCase, self).tearDown()
-
- def get_testdata_path(self, relative_path):
- """Retrieves the absolute path for testdata given the relative path.
-
- Arguments:
- relative_path: The relative path to the testdata in the testdata
- directory.
-
- Returns:
- The absolute path to the testdata.
- """
- rel_path_parts = ['test', 'data']
- rel_path_parts.extend(relative_path.split(os.path.sep))
- return os.path.join(TEST_EXEC_PATH, *rel_path_parts)
-
-
-class AftltoolTest(AftltoolTestCase):
-
- def test_merkle_root_hash(self):
- """Tests validation of inclusion proof and the merkle tree calculations.
-
- The test vectors have been taken from the Trillian tests:
- https://github.com/google/trillian/blob/v1.3.3/merkle/log_verifier_test.go
- """
-
- inclusion_proofs = [
- (1,
- 8,
- [
- binascii.unhexlify('96a296d224f285c67bee93c30f8a3091'
- '57f0daa35dc5b87e410b78630a09cfc7'),
- binascii.unhexlify('5f083f0a1a33ca076a95279832580db3'
- 'e0ef4584bdff1f54c8a360f50de3031e'),
- binascii.unhexlify('6b47aaf29ee3c2af9af889bc1fb9254d'
- 'abd31177f16232dd6aab035ca39bf6e4')
- ]),
- (6,
- 8,
- [
- binascii.unhexlify('bc1a0643b12e4d2d7c77918f44e0f4f7'
- '9a838b6cf9ec5b5c283e1f4d88599e6b'),
- binascii.unhexlify('ca854ea128ed050b41b35ffc1b87b8eb'
- '2bde461e9e3b5596ece6b9d5975a0ae0'),
- binascii.unhexlify('d37ee418976dd95753c1c73862b9398f'
- 'a2a2cf9b4ff0fdfe8b30cd95209614b7')
- ]),
- (3,
- 3,
- [
- binascii.unhexlify('fac54203e7cc696cf0dfcb42c92a1d9d'
- 'baf70ad9e621f4bd8d98662f00e3c125')
- ]),
- (2,
- 5,
- [
- binascii.unhexlify('6e340b9cffb37a989ca544e6bb780a2c'
- '78901d3fb33738768511a30617afa01d'),
- binascii.unhexlify('5f083f0a1a33ca076a95279832580db3'
- 'e0ef4584bdff1f54c8a360f50de3031e'),
- binascii.unhexlify('bc1a0643b12e4d2d7c77918f44e0f4f7'
- '9a838b6cf9ec5b5c283e1f4d88599e6b')
- ]
- )
- ]
-
- leaves = [
- binascii.unhexlify(''),
- binascii.unhexlify('00'),
- binascii.unhexlify('10'),
- binascii.unhexlify('2021'),
- binascii.unhexlify('3031'),
- binascii.unhexlify('40414243'),
- binascii.unhexlify('5051525354555657'),
- binascii.unhexlify('606162636465666768696a6b6c6d6e6f'),
- ]
-
- roots = [
- binascii.unhexlify('6e340b9cffb37a989ca544e6bb780a2c'
- '78901d3fb33738768511a30617afa01d'),
- binascii.unhexlify('fac54203e7cc696cf0dfcb42c92a1d9d'
- 'baf70ad9e621f4bd8d98662f00e3c125'),
- binascii.unhexlify('aeb6bcfe274b70a14fb067a5e5578264'
- 'db0fa9b51af5e0ba159158f329e06e77'),
- binascii.unhexlify('d37ee418976dd95753c1c73862b9398f'
- 'a2a2cf9b4ff0fdfe8b30cd95209614b7'),
- binascii.unhexlify('4e3bbb1f7b478dcfe71fb631631519a3'
- 'bca12c9aefca1612bfce4c13a86264d4'),
- binascii.unhexlify('76e67dadbcdf1e10e1b74ddc608abd2f'
- '98dfb16fbce75277b5232a127f2087ef'),
- binascii.unhexlify('ddb89be403809e325750d3d263cd7892'
- '9c2942b7942a34b77e122c9594a74c8c'),
- binascii.unhexlify('5dc9da79a70659a9ad559cb701ded9a2'
- 'ab9d823aad2f4960cfe370eff4604328'),
- ]
-
- for icp in inclusion_proofs:
- leaf_id = icp[0] - 1
- leaf_hash = aftltool.rfc6962_hash_leaf(leaves[leaf_id])
- root_hash = aftltool.root_from_icp(leaf_id, icp[1], icp[2], leaf_hash)
- self.assertEqual(root_hash, roots[icp[1] -1])
-
-
-class AftlImageTest(AftltoolTestCase):
-
- def test__init__(self):
- """Tests the constructor."""
- # Calls constructor without data.
- d = aftltool.AftlImage()
- self.assertIsInstance(d.image_header, aftltool.AftlImageHeader)
- self.assertEqual(d.image_header.icp_count, 0)
- self.assertEqual(d.icp_entries, [])
- self.assertTrue(d.is_valid())
-
- # Calls constructor with data.
- d = aftltool.AftlImage(self.test_expected_aftl_image_bytes)
- self.assertIsInstance(d.image_header, aftltool.AftlImageHeader)
- self.assertEqual(d.image_header.icp_count, 2)
- self.assertEqual(len(d.icp_entries), 2)
- for entry in d.icp_entries:
- self.assertIsInstance(entry, aftltool.AftlIcpEntry)
- self.assertTrue(d.is_valid())
-
- def test_add_icp_entry(self):
- """Tests the add_icp_entry method."""
- d = aftltool.AftlImage()
-
- # Adds 1st ICP.
- d.add_icp_entry(self.test_entry_1)
- self.assertEqual(d.image_header.icp_count, 1)
- self.assertEqual(len(d.icp_entries), 1)
- self.assertTrue(d.is_valid())
-
- # Adds 2nd ICP.
- d.add_icp_entry(self.test_entry_2)
- self.assertEqual(d.image_header.icp_count, 2)
- self.assertEqual(len(d.icp_entries), 2)
- self.assertTrue(d.is_valid())
-
- def test_verify_vbmeta_image_with_1_icp(self):
- """Tests the verify_vbmeta_image method."""
- # Valid vbmeta image without footer with 1 ICP.
- tool = aftltool.Aftl()
- image_path = self.get_testdata_path(
- 'aftl_output_vbmeta_with_1_icp.img')
- vbmeta_image, _ = tool.get_vbmeta_image(image_path)
- desc = tool.get_aftl_image(image_path)
-
- # Valid image checked against correct log key.
- self.assertTrue(desc.verify_vbmeta_image(
- vbmeta_image, [self.get_testdata_path('aftl_pubkey_1.pem')]))
-
- # Valid image checked with a key from another log.
- self.assertFalse(desc.verify_vbmeta_image(
- vbmeta_image, [self.get_testdata_path('testkey_rsa4096_pub.pem')]))
-
- # Valid image checked with non existed key file path.
- self.assertFalse(desc.verify_vbmeta_image(
- vbmeta_image, [self.get_testdata_path('non_existent_blabli')]))
-
- # Valid image checked with an invalid key.
- self.assertFalse(desc.verify_vbmeta_image(
- vbmeta_image, [self.get_testdata_path('large_blob.bin')]))
-
- # Valid image checked with empty list of keys.
- self.assertFalse(desc.verify_vbmeta_image(vbmeta_image, []))
-
- # Valid image checked with empty list of keys.
- self.assertFalse(desc.verify_vbmeta_image(vbmeta_image, None))
-
- def test_verify_vbmeta_image_with_2_icp_from_same_log(self):
- """Tests the verify_vbmeta_image method."""
- # Valid vbmeta image without footer with 2 ICPs from same log.
- tool = aftltool.Aftl()
- image_path = self.get_testdata_path(
- 'aftl_output_vbmeta_with_2_icp_same_log.img')
- vbmeta_image, _ = tool.get_vbmeta_image(image_path)
- desc = tool.get_aftl_image(image_path)
-
- # Valid image checked against correct log key.
- self.assertTrue(desc.verify_vbmeta_image(
- vbmeta_image, [self.get_testdata_path('aftl_pubkey_1.pem')]))
-
- # Valid vbmeta image checked with key from another log.
- self.assertFalse(desc.verify_vbmeta_image(
- vbmeta_image, [self.get_testdata_path('testkey_rsa4096_pub.pem')]))
-
- # Valid image checked with non existed key file path.
- self.assertFalse(desc.verify_vbmeta_image(
- vbmeta_image, [self.get_testdata_path('non_existent_blabli')]))
-
- # 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()
- self.assertEqual(desc_bytes, self.test_expected_aftl_image_bytes)
-
- def test_is_valid(self):
- """Tests is_valid method."""
- d = aftltool.AftlImage()
- d.add_icp_entry(self.test_entry_1)
- d.add_icp_entry(self.test_entry_2)
-
- # Force invalid ICP header.
- old_magic = d.image_header.magic
- d.image_header.magic = b'YOLO'
- self.assertFalse(d.is_valid())
- d.image_header.magic = old_magic
- self.assertTrue(d.is_valid())
-
- # Force count mismatch between header and actual entries.
- old_icp_count = d.image_header.icp_count
- d.image_header.icp_count = 1
- self.assertFalse(d.is_valid())
- d.image_header.icp_count = old_icp_count
- self.assertTrue(d.is_valid())
-
- # Force invalid ICP entry.
- old_leaf_index = d.icp_entries[0].leaf_index
- d.icp_entries[0].leaf_index = -10
- self.assertFalse(d.is_valid())
- d.icp_entries[0].leaf_index = old_leaf_index
- self.assertTrue(d.is_valid())
-
- def test_print_desc(self):
- """Tests print_desc method."""
- buf = io.StringIO()
- self.test_aftl_desc.print_desc(buf)
- desc = buf.getvalue()
-
- # Cursory check whether the printed description contains something useful.
- self.assertGreater(len(desc), 0)
- self.assertIn('Log Root Descriptor:', desc)
-
-
-class AftlImageHeaderTest(AftltoolTestCase):
- """Test suite for testing the AftlImageHeader descriptor."""
-
- def setUp(self):
- """Sets up the test bed for the unit tests."""
- super(AftlImageHeaderTest, self).setUp()
-
- self.test_header_valid = aftltool.AftlImageHeader()
- self.test_header_valid.icp_count = 1
-
- self.test_header_invalid = aftltool.AftlImageHeader()
- self.test_header_invalid.icp_count = -34
-
- self.test_header_bytes = (
- b'AFTL' # Magic.
- + struct.pack('!L', avbtool.AVB_VERSION_MAJOR) # Major version.
- + struct.pack('!L', avbtool.AVB_VERSION_MINOR) # Minor version.
- + b'\x00\x00\x00\x12' # Image size.
- b'\x00\x01') # Number of ICP entries.
-
- def test__init__(self):
- """Tests constructor."""
-
- # Calls constructor without data.
- header = aftltool.AftlImageHeader()
- self.assertEqual(header.magic, b'AFTL')
- self.assertEqual(header.required_icp_version_major,
- avbtool.AVB_VERSION_MAJOR)
- self.assertEqual(header.required_icp_version_minor,
- avbtool.AVB_VERSION_MINOR)
- self.assertEqual(header.aftl_image_size, aftltool.AftlImageHeader.SIZE)
- self.assertEqual(header.icp_count, 0)
- self.assertTrue(header.is_valid())
-
- # Calls constructor with data.
- header = aftltool.AftlImageHeader(self.test_header_bytes)
- self.assertEqual(header.magic, b'AFTL')
- self.assertEqual(header.required_icp_version_major,
- avbtool.AVB_VERSION_MAJOR)
- self.assertEqual(header.required_icp_version_minor,
- avbtool.AVB_VERSION_MINOR)
- self.assertEqual(header.aftl_image_size, aftltool.AftlImageHeader.SIZE)
- self.assertTrue(header.icp_count, 1)
- self.assertTrue(header.is_valid())
-
- def test_encode(self):
- """Tests encode method."""
- # Valid header.
- header_bytes = self.test_header_valid.encode()
- self.assertEqual(header_bytes, self.test_header_bytes)
-
- # Invalid header
- with self.assertRaises(aftltool.AftlError):
- header_bytes = self.test_header_invalid.encode()
-
- def test_is_valid(self):
- """Tests is_valid method."""
- # Valid default record.
- header = aftltool.AftlImageHeader()
- self.assertTrue(header.is_valid())
-
- # Invalid magic.
- header = aftltool.AftlImageHeader()
- header.magic = b'YOLO'
- self.assertFalse(header.is_valid())
-
- # Valid ICP count.
- self.assertTrue(self.test_header_valid.is_valid())
-
- # Invalid ICP count.
- self.assertFalse(self.test_header_invalid.is_valid())
-
- header = aftltool.AftlImageHeader()
- header.icp_count = 10000000
- self.assertFalse(header.is_valid())
-
- # Invalid ICP major version.
- header = aftltool.AftlImageHeader()
- header.required_icp_version_major = avbtool.AVB_VERSION_MAJOR + 1
- self.assertFalse(header.is_valid())
-
- # Invalid ICP minor version.
- header = aftltool.AftlImageHeader()
- header.required_icp_version_minor = avbtool.AVB_VERSION_MINOR + 1
- self.assertFalse(header.is_valid())
-
- def test_print_desc(self):
- """Tests print_desc method."""
- buf = io.StringIO()
- self.test_header_valid.print_desc(buf)
- desc = buf.getvalue()
-
- # Cursory check whether the printed description contains something useful.
- self.assertGreater(len(desc), 0)
- self.assertIn('Major version:', desc)
-
-
-class AftlIcpEntryTest(AftltoolTestCase):
- """Test suite for testing the AftlIcpEntry descriptor."""
-
- def test__init__and_properties(self):
- """Tests constructor and properties methods."""
-
- # Calls constructor without data.
- entry = aftltool.AftlIcpEntry()
- self.assertEqual(entry.log_url_size, 0)
- self.assertEqual(entry.leaf_index, 0)
- self.assertEqual(entry.log_root_descriptor_size, 29)
- 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)
- self.assertEqual(entry.log_url, '')
- self.assertIsInstance(entry.log_root_descriptor,
- aftltool.TrillianLogRootDescriptor)
- self.assertEqual(entry.proofs, [])
- self.assertTrue(entry.is_valid())
-
- # Calls constructor with data.
- 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.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)
- self.assertEqual(entry.log_url, self.test_tl_url_1)
- self.assertEqual(entry.proofs, self.test_proof_hashes_1)
- self.assertTrue(entry.is_valid())
-
- def test_encode(self):
- """Tests encode method."""
- entry_bytes = self.test_entry_1.encode()
- self.assertEqual(entry_bytes, self.test_entry_1_bytes)
-
- def test_get_expected_size(self):
- """Tests get_expected_size method."""
- # Default record.
- entry = aftltool.AftlIcpEntry()
- 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(), 894)
- self.assertEqual(self.test_entry_1.get_expected_size(),
- len(self.test_entry_1.encode()))
-
- def test_is_valid(self):
- """Tests is_valid method."""
- # Valid default record.
- entry = aftltool.AftlIcpEntry()
- entry.leaf_index = 2
- entry.log_url = self.test_tl_url_1
- entry.set_log_root_descriptor = self.test_sth_1
- entry.proofs = self.test_proof_hashes_1
- self.assertTrue(entry.is_valid())
-
- # Invalid leaf index.
- entry = aftltool.AftlIcpEntry()
- entry.leaf_index = -1
- self.assertFalse(entry.is_valid())
-
- # Invalid log_root_descriptor
- entry = aftltool.AftlIcpEntry()
- entry.log_root_descriptor = None
- self.assertFalse(entry.is_valid())
-
- entry.log_root_descriptor = b''
- self.assertFalse(entry.is_valid())
-
- entry.log_root_descriptor = b'blabli'
- self.assertFalse(entry.is_valid())
-
- def test_translate_response(self):
- """Tests translate_response method."""
- entry = aftltool.AftlIcpEntry()
- 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, 9127)
- self.assertEqual(entry.log_root_descriptor.encode(),
- 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."""
- with tempfile.NamedTemporaryFile('wt+') as key_file:
- key_file.write(self.test_aftl_pub_key)
- key_file.flush()
-
- # Valid ICP.
- entry = aftltool.AftlIcpEntry()
- entry.translate_response(self.test_tl_url_1, self.test_avbm_resp)
- self.assertTrue(entry.verify_icp(key_file.name))
-
- # 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_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."""
- # Valid vbmeta image without footer with 1 ICP.
- tool = aftltool.Aftl()
- image_path = self.get_testdata_path(
- 'aftl_output_vbmeta_with_1_icp.img')
- vbmeta_image, _ = tool.get_vbmeta_image(image_path)
- desc = tool.get_aftl_image(image_path)
-
- # Checks that there is 1 ICP.
- self.assertEqual(desc.image_header.icp_count, 1)
- entry = desc.icp_entries[0]
-
- # Valid vbmeta image checked with correct log key.
- self.assertTrue(entry.verify_vbmeta_image(
- vbmeta_image, self.get_testdata_path('aftl_pubkey_1.pem')))
-
- # Valid vbmeta image checked with public key of another log.
- self.assertFalse(entry.verify_vbmeta_image(
- vbmeta_image, self.get_testdata_path('testkey_rsa4096_pub.pem')))
-
- # Valid vbmeta image checked with invalid key.
- self.assertFalse(entry.verify_vbmeta_image(
- vbmeta_image, self.get_testdata_path('large_blob.bin')))
-
- # Valid vbmeta image checked with no key.
- self.assertFalse(entry.verify_vbmeta_image(vbmeta_image, None))
-
- def test_verify_invalid_vbmeta_image(self):
- """Tests the verify_vbmeta_image method."""
- # Valid vbmeta image without footer with 1 ICP.
- tool = aftltool.Aftl()
- image_path = self.get_testdata_path(
- 'aftl_output_vbmeta_with_1_icp.img')
- vbmeta_image, _ = tool.get_vbmeta_image(image_path)
- desc = tool.get_aftl_image(image_path)
-
- self.assertEqual(desc.image_header.icp_count, 1)
- entry = desc.icp_entries[0]
-
- # Modify vbmeta image to become invalid
- vbmeta_image = b'A' * len(vbmeta_image)
-
- # Invalid vbmeta image checked with correct log key.
- self.assertFalse(entry.verify_vbmeta_image(
- vbmeta_image, self.get_testdata_path('aftl_pubkey_1.pem')))
-
- # Invalid vbmeta image checked with invalid key.
- self.assertFalse(entry.verify_vbmeta_image(
- vbmeta_image, self.get_testdata_path('large_blob.bin')))
-
- # Valid vbmeta image checked with no key.
- self.assertFalse(entry.verify_vbmeta_image(vbmeta_image, None))
-
- # None image checked with a key.
- self.assertFalse(entry.verify_vbmeta_image(
- None, self.get_testdata_path('aftl_pubkey_1.pem')))
-
- def test_print_desc(self):
- """Tests print_desc method."""
- buf = io.StringIO()
- self.test_entry_1.print_desc(buf)
- desc = buf.getvalue()
-
- # Cursory check whether the printed description contains something useful.
- self.assertGreater(len(desc), 0)
- self.assertIn('ICP hashes:', desc)
-
-
-class TrillianLogRootDescriptorTest(AftltoolTestCase):
- """Test suite for testing the TrillianLogRootDescriptor descriptor."""
-
- def setUp(self):
- """Sets up the test bed for the unit tests."""
- super(TrillianLogRootDescriptorTest, self).setUp()
-
- # Creates basic log root without metadata fields.
- base_log_root = (
- '0001' # version
- '00000000000002e5' # tree_size
- '20' # root_hash_size
- '2d614759ad408a111a3351c0cb33c099' # root_hash
- '422c30a5c5104788a343332bde2b387b'
- '15e1c97e3b4bd239' # timestamp
- '00000000000002e4' # revision
- )
-
- # Create valid log roots with metadata fields w/ and w/o metadata.
- self.test_log_root_bytes_wo_metadata = binascii.unhexlify(
- base_log_root + '0000')
- self.test_log_root_bytes_with_metadata = binascii.unhexlify(
- base_log_root + '00023132')
-
- def test__init__(self):
- """Tests constructor."""
- # Calls constructor without data.
- d = aftltool.TrillianLogRootDescriptor()
- self.assertTrue(d.is_valid())
- self.assertEqual(d.version, 1)
- self.assertEqual(d.tree_size, 0)
- self.assertEqual(d.root_hash_size, 0)
- self.assertEqual(d.root_hash, b'')
- self.assertEqual(d.timestamp, 0)
- self.assertEqual(d.revision, 0)
- self.assertEqual(d.metadata_size, 0)
- self.assertEqual(d.metadata, b'')
-
- # Calls constructor with log_root w/o metadata
- d = aftltool.TrillianLogRootDescriptor(self.test_log_root_bytes_wo_metadata)
- self.assertTrue(d.is_valid())
- self.assertEqual(d.version, 1)
- self.assertEqual(d.tree_size, 741)
- self.assertEqual(d.root_hash_size, 32)
- self.assertEqual(d.root_hash,
- binascii.unhexlify('2d614759ad408a111a3351c0cb33c099'
- '422c30a5c5104788a343332bde2b387b'))
- self.assertEqual(d.timestamp, 1576762888554271289)
- self.assertEqual(d.revision, 740)
- self.assertEqual(d.metadata_size, 0)
- self.assertEqual(d.metadata, b'')
-
- # Calls constructor with log_root with metadata
- d = aftltool.TrillianLogRootDescriptor(
- self.test_log_root_bytes_with_metadata)
- self.assertEqual(d.metadata_size, 2)
- self.assertEqual(d.metadata, b'12')
-
- def test_get_expected_size(self):
- """Tests get_expected_size method."""
- # Default constructor.
- d = aftltool.TrillianLogRootDescriptor()
- self.assertEqual(d.get_expected_size(), 11 + 18)
-
- # Log root without metadata.
- d = aftltool.TrillianLogRootDescriptor(self.test_log_root_bytes_wo_metadata)
- self.assertEqual(d.get_expected_size(), 11 + 18 + 32)
-
- # Log root with metadata.
- d = aftltool.TrillianLogRootDescriptor(
- self.test_log_root_bytes_with_metadata)
- self.assertEqual(d.get_expected_size(), 11 + 18 + 32 + 2)
-
- def test_encode(self):
- """Tests encode method."""
- # Log root from default constructor.
- d = aftltool.TrillianLogRootDescriptor()
- expected_bytes = (
- '0001' # version
- '0000000000000000' # tree_size
- '00' # root_hash_size
- '' # root_hash (empty)
- '0000000000000000' # timestamp
- '0000000000000000' # revision
- '0000' # metadata size
- '' # metadata (empty)
- )
- self.assertEqual(d.encode(), binascii.unhexlify(expected_bytes))
-
- # Log root without metadata.
- d = aftltool.TrillianLogRootDescriptor(self.test_log_root_bytes_wo_metadata)
- self.assertEqual(d.encode(), self.test_log_root_bytes_wo_metadata)
-
- # Log root with metadata.
- d = aftltool.TrillianLogRootDescriptor(
- self.test_log_root_bytes_with_metadata)
- self.assertEqual(d.encode(), self.test_log_root_bytes_with_metadata)
-
- def test_is_valid(self):
- """Tests is_valid method."""
- d = aftltool.TrillianLogRootDescriptor()
- self.assertTrue(d.is_valid())
-
- # Invalid version.
- d = aftltool.TrillianLogRootDescriptor()
- d.version = 2
- self.assertFalse(d.is_valid())
-
- # Invalid tree_size.
- d = aftltool.TrillianLogRootDescriptor()
- d.tree_size = -1
- self.assertFalse(d.is_valid())
-
- # Invalid root_hash_size.
- d = aftltool.TrillianLogRootDescriptor()
- d.root_hash_size = -1
- self.assertFalse(d.is_valid())
- d.root_hash_size = 300
- self.assertFalse(d.is_valid())
-
- # Invalid/valid root_hash_size / root_hash combination.
- d = aftltool.TrillianLogRootDescriptor()
- d.root_hash_size = 4
- d.root_hash = b'123'
- self.assertFalse(d.is_valid())
- d.root_hash = b'1234'
- self.assertTrue(d.is_valid())
-
- # Invalid timestamp.
- d = aftltool.TrillianLogRootDescriptor()
- d.timestamp = -1
- self.assertFalse(d.is_valid())
-
- # Invalid revision.
- d = aftltool.TrillianLogRootDescriptor()
- d.revision = -1
- self.assertFalse(d.is_valid())
-
- # Invalid metadata_size.
- d = aftltool.TrillianLogRootDescriptor()
- d.metadata_size = -1
- self.assertFalse(d.is_valid())
- d.metadata_size = 70000
- self.assertFalse(d.is_valid())
-
- # Invalid/valid metadata_size / metadata combination.
- d = aftltool.TrillianLogRootDescriptor()
- d.metadata_size = 4
- d.metadata = b'123'
- self.assertFalse(d.is_valid())
- d.metadata = b'1234'
- self.assertTrue(d.is_valid())
-
- def test_print_desc(self):
- """Tests print_desc method."""
- # Log root without metadata
- buf = io.StringIO()
- d = aftltool.TrillianLogRootDescriptor(self.test_log_root_bytes_wo_metadata)
- d.print_desc(buf)
- desc = buf.getvalue()
-
- # Cursory check whether the printed description contains something useful.
- self.assertGreater(len(desc), 0)
- self.assertIn('Version:', desc)
- self.assertNotIn('Metadata:', desc)
-
- # Log root with metadata
- buf = io.StringIO()
- d = aftltool.TrillianLogRootDescriptor(
- self.test_log_root_bytes_with_metadata)
- d.print_desc(buf)
- desc = buf.getvalue()
-
- # Cursory check whether the printed description contains something useful.
- self.assertGreater(len(desc), 0)
- self.assertIn('Version:', desc)
- self.assertIn('Metadata:', desc)
-
-
-class SignedVBMetaPrimaryAnnotationLeafTest(AftltoolTestCase):
- """Test suite for testing the Leaf."""
-
- def test__init__(self):
- """Tests constructor and properties methods."""
- # Calls constructor without data.
- 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, '')
-
- 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 parse with invalid data.
- with self.assertRaises(aftltool.AftlError):
- leaf = aftltool.SignedVBMetaPrimaryAnnotationLeaf.parse(b'Invalid data')
-
- def test_get_expected_size(self):
- """Tests get_expected_size method."""
- # Calls constructor without data.
- leaf = aftltool.SignedVBMetaPrimaryAnnotationLeaf()
- self.assertEqual(leaf.get_expected_size(), 19)
-
- # Calls constructor with data.
- leaf = aftltool.SignedVBMetaPrimaryAnnotationLeaf.parse(
- self.test_anno_1_bytes)
- self.assertEqual(leaf.get_expected_size(),
- len(self.test_anno_1_bytes))
-
- def test_encode(self):
- """Tests encode method."""
- # Calls constructor with data.
- 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_anno_1.print_desc(buf)
- desc = buf.getvalue()
-
- # Cursory check whether the printed description contains something useful.
- self.assertGreater(len(desc), 0)
- self.assertIn('VBMeta hash:', desc)
-
-
-class AftlMockCommunication(aftltool.AftlCommunication):
- """Testing Mock implementation of AftlCommunication."""
-
- def __init__(self, transparency_log_config, canned_response):
- """Initializes the object.
-
- Arguments:
- transparency_log_config: An aftltool.TransparencyLogConfig instance.
- canned_response: AddVBMetaResponse to return or the Exception to
- raise.
- """
- super(AftlMockCommunication, self).__init__(transparency_log_config,
- timeout=None)
- self.request = None
- self.canned_response = canned_response
-
- def add_vbmeta(self, request):
- """Records the request and returns the canned response."""
- self.request = request
-
- if isinstance(self.canned_response, aftltool.AftlError):
- raise self.canned_response
- return self.canned_response
-
-
-class AftlMock(aftltool.Aftl):
- """Mock for aftltool.Aftl to mock the communication piece."""
-
- def __init__(self, canned_response):
- """Initializes the object.
-
- Arguments:
- canned_response: AddVBMetaResponse to return or the Exception to
- raise.
- """
- self.mock_canned_response = canned_response
-
- def request_inclusion_proof(self, transparency_log_config, vbmeta_image,
- version_inc, manufacturer_key_path,
- signing_helper, signing_helper_with_files,
- timeout, aftl_comms=None):
- """Mocked request_inclusion_proof function."""
- aftl_comms = AftlMockCommunication(transparency_log_config,
- self.mock_canned_response)
- return super(AftlMock, self).request_inclusion_proof(
- transparency_log_config, vbmeta_image, version_inc,
- manufacturer_key_path, signing_helper, signing_helper_with_files,
- timeout, aftl_comms=aftl_comms)
-
-
-class AftlTestCase(AftltoolTestCase):
-
- def setUp(self):
- """Sets up the test bed for the unit tests."""
- super(AftlTestCase, self).setUp()
-
- # Sets up the member variables which are then configured by
- # set_up_environment() in the subclasses.
- self.aftl_host = None
- self.aftl_pubkey = None
- self.aftl_apikey = None
- self.vbmeta_image = None
- self.manufacturer_key = None
- self.set_up_environment()
-
- self.transparency_log_config = aftltool.TransparencyLogConfig(
- self.aftl_host, self.aftl_pubkey, self.aftl_apikey)
-
- self.make_icp_default_params = {
- 'vbmeta_image_path': self.vbmeta_image,
- 'output': None,
- 'signing_helper': None,
- 'signing_helper_with_files': None,
- 'version_incremental': '1',
- 'transparency_log_configs': [self.transparency_log_config],
- 'manufacturer_key': self.manufacturer_key,
- 'padding_size': 0,
- 'timeout': None
- }
-
- self.info_icp_default_params = {
- 'vbmeta_image_path': None,
- 'output': io.StringIO()
- }
-
- self.verify_icp_default_params = {
- 'vbmeta_image_path': None,
- 'transparency_log_pub_keys': [self.aftl_pubkey],
- 'output': io.StringIO()
- }
-
- self.load_test_aftl_default_params = {
- 'vbmeta_image_path': self.vbmeta_image,
- 'output': io.StringIO(),
- 'transparency_log_config': self.transparency_log_config,
- 'manufacturer_key': self.manufacturer_key,
- 'process_count': 1,
- 'submission_count': 1,
- 'stats_filename': None,
- 'preserve_icp_images': False,
- 'timeout': None
- }
-
- def set_up_environment(self):
- """Sets up member variables for the particular test environment.
-
- This allows to have different settings and mocking for unit tests and
- integration tests.
- """
- raise NotImplementedError('set_up_environment() needs to be implemented '
- 'by subclass.')
-
- def get_aftl_implementation(self, canned_response):
- """Gets the aftltool.Aftl implementation used for testing.
-
- This allows to have different Aftl implementations for unit tests and
- integration tests.
-
- Arguments:
- canned_response: Since we are using the actual implementation and not a
- mock this gets ignored.
-
- Raises:
- NotImplementedError if subclass is not implementing the method.
- """
- raise NotImplementedError('get_aftl_implementation() needs to be'
- 'implemented by subclass.')
-
-
-class AftlTest(AftlTestCase):
-
- def set_up_environment(self):
- """Sets up the environment for unit testing without networking."""
- self.aftl_host = 'test.foo.bar:9000'
- self.aftl_pubkey = self.get_testdata_path('aftl_pubkey_1.pem')
- self.vbmeta_image = self.get_testdata_path('aftl_input_vbmeta.img')
- self.manufacturer_key = self.get_testdata_path('testkey_rsa4096.pem')
-
- def get_aftl_implementation(self, canned_response):
- """Retrieves the AftlMock for unit testing without networking."""
- return AftlMock(canned_response)
-
- def test_get_vbmeta_image(self):
- """Tests the get_vbmeta_image method."""
- tool = aftltool.Aftl()
-
- # Valid vbmeta image without footer and AftlImage.
- image, footer = tool.get_vbmeta_image(
- self.get_testdata_path('aftl_input_vbmeta.img'))
- self.assertIsNotNone(image)
- self.assertEqual(len(image), 4352)
- self.assertIsNone(footer)
-
- # Valid vbmeta image without footer but with AftlImage.
- image, footer = tool.get_vbmeta_image(
- self.get_testdata_path('aftl_output_vbmeta_with_1_icp.img'))
- self.assertIsNotNone(image)
- self.assertEqual(len(image), 4352)
- self.assertIsNone(footer)
-
- # Invalid vbmeta image.
- image, footer = tool.get_vbmeta_image(
- self.get_testdata_path('large_blob.bin'))
- self.assertIsNone(image)
- self.assertIsNone(footer)
-
- # Invalid file path.
- image, footer = tool.get_vbmeta_image(
- self.get_testdata_path('blabli_not_existing_file'))
- self.assertIsNone(image)
- self.assertIsNone(footer)
-
- def test_get_aftl_image(self):
- """Tests the get_aftl_image method."""
- tool = aftltool.Aftl()
-
- # Valid vbmeta image without footer with AftlImage.
- desc = tool.get_aftl_image(
- self.get_testdata_path('aftl_output_vbmeta_with_1_icp.img'))
- self.assertIsInstance(desc, aftltool.AftlImage)
-
- # Valid vbmeta image without footer and AftlImage.
- desc = tool.get_aftl_image(
- self.get_testdata_path('aftl_input_vbmeta.img'))
- self.assertIsNone(desc)
-
- # Invalid vbmeta image.
- desc = tool.get_aftl_image(self.get_testdata_path('large_blob.bin'))
- self.assertIsNone(desc)
-
- # pylint: disable=no-member
- 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_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_avbm_resp.annotation_proof.proof.leaf_index)
- self.assertEqual(icp.proof_hash_count,
- 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(
- '9a5f71340f8dc98bdc6320f976dda5f34db8554cb273ba5ab60f1697c519d6f6'))
-
- 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.annotation_leaf.annotation.manufacturer_key_hash,
- bytes.fromhex(
- "83ab3b109b73a1d32dce4153a2de57a1a0485052db8364f3180d98614749d7f7"))
-
- 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):
- """Tests the request_inclusion_proof method in case of a comms problem."""
- # Always work with a mock independent if run as unit or integration tests.
- aftl = AftlMock(aftltool.AftlError('Comms error'))
-
- with self.assertRaises(aftltool.AftlError):
- aftl.request_inclusion_proof(
- self.transparency_log_config, b'a' * 1024, 'version_inc',
- self.get_testdata_path('testkey_rsa4096.pem'), None, None, None)
-
- 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_avbm_resp)
- with self.assertRaises(aftltool.AftlError) as e:
- aftl.request_inclusion_proof(
- self.transparency_log_config, b'a' * 1024, 'version_inc',
- self.get_testdata_path('testkey_rsa2048.pem'), None, None, None)
- self.assertIn('not of size 4096: 2048', str(e.exception))
-
- 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_avbm_resp)
-
- # Make a VBmeta image with ICP.
- with tempfile.NamedTemporaryFile('wb+') as output_file:
- self.make_icp_default_params['output'] = output_file
- result = aftl.make_icp_from_vbmeta(**self.make_icp_default_params)
- output_file.flush()
- self.assertTrue(result)
-
- # Checks that there is 1 ICP.
- aftl_image = aftl.get_aftl_image(output_file.name)
- self.assertEqual(aftl_image.image_header.icp_count, 1)
-
- # Verifies the generated image.
- self.verify_icp_default_params['vbmeta_image_path'] = output_file.name
- result = aftl.verify_image_icp(**self.verify_icp_default_params)
- self.assertTrue(result)
-
- # Prints the image details.
- self.info_icp_default_params['vbmeta_image_path'] = output_file.name
- result = aftl.info_image_icp(**self.info_icp_default_params)
- self.assertTrue(result)
-
- 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_avbm_resp)
-
- # Reconfigures default parameters with two transparency logs.
- self.make_icp_default_params['transparency_log_configs'] = [
- self.transparency_log_config, self.transparency_log_config]
-
- # Make a VBmeta image with ICP.
- with tempfile.NamedTemporaryFile('wb+') as output_file:
- self.make_icp_default_params['output'] = output_file
- result = aftl.make_icp_from_vbmeta(
- **self.make_icp_default_params)
- output_file.flush()
- self.assertTrue(result)
-
- # Checks that there are 2 ICPs.
- aftl_image = aftl.get_aftl_image(output_file.name)
- self.assertEqual(aftl_image.image_header.icp_count, 2)
-
- # Verifies the generated image.
- self.verify_icp_default_params['vbmeta_image_path'] = output_file.name
- result = aftl.verify_image_icp(**self.verify_icp_default_params)
- self.assertTrue(result)
-
- # Prints the image details.
- self.info_icp_default_params['vbmeta_image_path'] = output_file.name
- result = aftl.info_image_icp(**self.info_icp_default_params)
- self.assertTrue(result)
-
- 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_avbm_resp)
-
- image_path = self.get_testdata_path(
- 'aftl_output_vbmeta_with_2_icp_same_log.img')
- self.info_icp_default_params['vbmeta_image_path'] = image_path
-
- # Verifies the generated image.
- result = aftl.info_image_icp(**self.info_icp_default_params)
- self.assertTrue(result)
-
- 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_avbm_resp)
-
- image_path = self.get_testdata_path('large_blob.bin')
- self.info_icp_default_params['vbmeta_image_path'] = image_path
-
- # Verifies the generated image.
- result = aftl.info_image_icp(**self.info_icp_default_params)
- self.assertFalse(result)
-
- 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_avbm_resp)
-
- image_path = self.get_testdata_path(
- '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('aftl_pubkey_1.pem'),
- ]
-
- result = aftl.verify_image_icp(**self.verify_icp_default_params)
- self.assertTrue(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'))
- self.make_icp_default_params[
- 'transparency_log_configs'][0].target = 'www.google.com:80'
- with tempfile.NamedTemporaryFile('wb+') as output_file:
- self.make_icp_default_params['output'] = output_file
- result = aftl.make_icp_from_vbmeta(
- **self.make_icp_default_params)
- self.assertFalse(result)
-
- def test_make_icp_grpc_timeout(self):
- """Tests make_icp_from_vbmeta command when running into GRPC timeout."""
- aftl = self.get_aftl_implementation(aftltool.AftlError('Comms error'))
-
- # The timeout is set to 1 second which is way below the minimum processing
- # time of the transparency log per load test results in b/139407814#2 where
- # it was 3.43 seconds.
- self.make_icp_default_params['timeout'] = 1
- with tempfile.NamedTemporaryFile('wb+') as output_file:
- self.make_icp_default_params['output'] = output_file
- result = aftl.make_icp_from_vbmeta(
- **self.make_icp_default_params)
- self.assertFalse(result)
-
- 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_avbm_resp)
-
- with tempfile.TemporaryDirectory() as tmp_dir:
- self.load_test_aftl_default_params[
- 'stats_filename'] = os.path.join(tmp_dir, 'load_test.csv')
- result = aftl.load_test_aftl(**self.load_test_aftl_default_params)
- self.assertTrue(result)
-
- output = self.load_test_aftl_default_params['output'].getvalue()
- self.assertRegex(output, 'Succeeded:.+?1\n')
- self.assertRegex(output, 'Failed:.+?0\n')
-
- self.assertTrue(os.path.exists(
- self.load_test_aftl_default_params['stats_filename']))
-
- 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_avbm_resp)
-
- self.load_test_aftl_default_params['process_count'] = 2
- self.load_test_aftl_default_params['submission_count'] = 2
- with tempfile.TemporaryDirectory() as tmp_dir:
- self.load_test_aftl_default_params[
- 'stats_filename'] = os.path.join(tmp_dir, 'load_test.csv')
- result = aftl.load_test_aftl(**self.load_test_aftl_default_params)
- self.assertTrue(result)
-
- output = self.load_test_aftl_default_params['output'].getvalue()
- self.assertRegex(output, 'Succeeded:.+?4\n')
- self.assertRegex(output, 'Failed:.+?0\n')
-
- self.assertTrue(os.path.exists(
- self.load_test_aftl_default_params['stats_filename']))
-
- def test_load_test_invalid_grpc_service(self):
- """Tests load_test_aftl command with a host that does not support GRPC."""
- aftl = self.get_aftl_implementation(aftltool.AftlError('Comms error'))
-
- self.load_test_aftl_default_params[
- 'transparency_log_config'].target = 'www.google.com:80'
- result = aftl.load_test_aftl(**self.load_test_aftl_default_params)
- self.assertFalse(result)
-
- output = self.load_test_aftl_default_params['output'].getvalue()
- self.assertRegex(output, 'Succeeded:.+?0\n')
- self.assertRegex(output, 'Failed:.+?1\n')
-
- def test_load_test_grpc_timeout(self):
- """Tests load_test_aftl command when running into timeout."""
- aftl = self.get_aftl_implementation(aftltool.AftlError('Comms error'))
-
- self.load_test_aftl_default_params['timeout'] = 1
- result = aftl.load_test_aftl(**self.load_test_aftl_default_params)
- self.assertFalse(result)
-
- output = self.load_test_aftl_default_params['output'].getvalue()
- self.assertRegex(output, 'Succeeded:.+?0\n')
- self.assertRegex(output, 'Failed:.+?1\n')
-
-
-class TransparencyLogConfigTestCase(unittest.TestCase):
-
- def test_from_argument(self):
- log = aftltool.TransparencyLogConfig.from_argument(
- "example.com:8080,mykey.pub")
- self.assertEqual(log.target, "example.com:8080")
- self.assertEqual(log.pub_key, "mykey.pub")
-
- with self.assertRaises(argparse.ArgumentTypeError):
- aftltool.TransparencyLogConfig.from_argument("example.com:8080,")
-
- with self.assertRaises(argparse.ArgumentTypeError):
- aftltool.TransparencyLogConfig.from_argument(",")
-
- def test_from_argument_with_api_key(self):
- log = aftltool.TransparencyLogConfig.from_argument(
- "example.com:8080,mykey.pub,Aipl29gj3x9")
- self.assertEqual(log.target, "example.com:8080")
- self.assertEqual(log.pub_key, "mykey.pub")
- self.assertEqual(log.api_key, "Aipl29gj3x9")
-
-if __name__ == '__main__':
- unittest.main(verbosity=2)
diff --git a/avbtool.py b/avbtool.py
index 8647b29..3967651 100755
--- a/avbtool.py
+++ b/avbtool.py
@@ -342,6 +342,7 @@
exponent: The key exponent.
modulus: The key modulus.
num_bits: The key size.
+ key_path: The path to a key file.
"""
MODULUS_PREFIX = b'modulus='
@@ -900,7 +901,7 @@
Arguments:
num_bytes: Size in number of bytes of the DONT_CARE chunk.
- Raises
+ Raises:
OSError: If ImageHandler was initialized in read-only mode.
"""
assert num_bytes % self.block_size == 0
@@ -937,7 +938,7 @@
Arguments:
data: Data to append as bytes.
- Raises
+ Raises:
OSError: If ImageHandler was initialized in read-only mode.
"""
assert len(data) % self.block_size == 0
@@ -974,7 +975,7 @@
fill_data: Fill data to append - must be four bytes.
size: Number of chunk - must be a multiple of four and the block size.
- Raises
+ Raises:
OSError: If ImageHandler was initialized in read-only mode.
"""
assert len(fill_data) == 4
@@ -1259,7 +1260,7 @@
Raises:
LookupError: If the given descriptor is malformed.
"""
- super(AvbPropertyDescriptor, self).__init__(None)
+ super().__init__(None)
assert struct.calcsize(self.FORMAT_STRING) == self.SIZE
if data:
@@ -1273,7 +1274,8 @@
try:
self.key = data[self.SIZE:(self.SIZE + key_size)].decode('utf-8')
except UnicodeDecodeError as e:
- raise LookupError('Key cannot be decoded as UTF-8: {}.'.format(e))
+ raise LookupError('Key cannot be decoded as UTF-8: {}.'
+ .format(e)) from e
self.value = data[(self.SIZE + key_size + 1):(self.SIZE + key_size + 1 +
value_size)]
else:
@@ -1377,6 +1379,9 @@
'L' + # flags
str(RESERVED) + 's') # reserved
+ FLAGS_DO_NOT_USE_AB = (1 << 0)
+ FLAGS_CHECK_AT_MOST_ONCE = (1 << 1)
+
def __init__(self, data=None):
"""Initializes a new hashtree descriptor.
@@ -1386,7 +1391,7 @@
Raises:
LookupError: If the given descriptor is malformed.
"""
- super(AvbHashtreeDescriptor, self).__init__(None)
+ super().__init__(None)
assert struct.calcsize(self.FORMAT_STRING) == self.SIZE
if data:
@@ -1410,7 +1415,7 @@
].decode('utf-8')
except UnicodeDecodeError as e:
raise LookupError('Partition name cannot be decoded as UTF-8: {}.'
- .format(e))
+ .format(e)) from e
o += partition_name_len
self.salt = data[(self.SIZE + o):(self.SIZE + o + salt_len)]
o += salt_len
@@ -1582,7 +1587,7 @@
Raises:
LookupError: If the given descriptor is malformed.
"""
- super(AvbHashDescriptor, self).__init__(None)
+ super().__init__(None)
assert struct.calcsize(self.FORMAT_STRING) == self.SIZE
if data:
@@ -1603,7 +1608,7 @@
].decode('utf-8')
except UnicodeDecodeError as e:
raise LookupError('Partition name cannot be decoded as UTF-8: {}.'
- .format(e))
+ .format(e)) from e
o += partition_name_len
self.salt = data[(self.SIZE + o):(self.SIZE + o + salt_len)]
o += salt_len
@@ -1720,7 +1725,7 @@
Raises:
LookupError: If the given descriptor is malformed.
"""
- super(AvbKernelCmdlineDescriptor, self).__init__(None)
+ super().__init__(None)
assert struct.calcsize(self.FORMAT_STRING) == self.SIZE
if data:
@@ -1737,7 +1742,7 @@
self.SIZE:(self.SIZE + kernel_cmdline_length)].decode('utf-8')
except UnicodeDecodeError as e:
raise LookupError('Kernel command-line cannot be decoded as UTF-8: {}.'
- .format(e))
+ .format(e)) from e
else:
self.flags = 0
self.kernel_cmdline = ''
@@ -1835,7 +1840,7 @@
].decode('utf-8')
except UnicodeDecodeError as e:
raise LookupError('Partition name cannot be decoded as UTF-8: {}.'
- .format(e))
+ .format(e)) from e
o += partition_name_len
self.public_key = data[(self.SIZE + o):(self.SIZE + o + public_key_len)]
@@ -2468,8 +2473,8 @@
o.write(' Metadata version: {}\n'.format(version))
def print_atx_certificate(cert):
- version, public_key, subject, usage, key_version, _signature = \
- struct.unpack('<I1032s32s32sQ512s', cert)
+ version, public_key, subject, usage, key_version, _ = (
+ struct.unpack('<I1032s32s32sQ512s', cert))
o.write(' Version: {}\n'.format(version))
o.write(' Public key (sha1): {}\n'.format(
hashlib.sha1(public_key).hexdigest()))
@@ -2832,7 +2837,11 @@
c += ' {}'.format(ht.root_digest.hex()) # root_digest
c += ' {}'.format(ht.salt.hex()) # salt
if ht.fec_num_roots > 0:
- c += ' 10' # number of optional args
+ if ht.flags & AvbHashtreeDescriptor.FLAGS_CHECK_AT_MOST_ONCE:
+ c += ' 11' # number of optional args
+ c += ' check_at_most_once'
+ else:
+ c += ' 10' # number of optional args
c += ' $(ANDROID_VERITY_MODE)'
c += ' ignore_zero_blocks'
c += ' use_fec_from_device PARTUUID=$(ANDROID_SYSTEM_PARTUUID)'
@@ -2843,7 +2852,11 @@
c += ' fec_blocks {}'.format(ht.fec_offset // ht.data_block_size)
c += ' fec_start {}'.format(ht.fec_offset // ht.data_block_size)
else:
- c += ' 2' # number of optional args
+ if ht.flags & AvbHashtreeDescriptor.FLAGS_CHECK_AT_MOST_ONCE:
+ c += ' 3' # number of optional args
+ c += ' check_at_most_once'
+ else:
+ c += ' 2' # number of optional args
c += ' $(ANDROID_VERITY_MODE)'
c += ' ignore_zero_blocks'
c += '" root=/dev/dm-0'
@@ -3025,8 +3038,9 @@
"""
try:
alg = ALGORITHMS[algorithm_name]
- except KeyError:
- raise AvbError('Unknown algorithm with name {}'.format(algorithm_name))
+ except KeyError as e:
+ raise AvbError('Unknown algorithm with name {}'
+ .format(algorithm_name)) from e
if not descriptors:
descriptors = []
@@ -3313,7 +3327,7 @@
except Exception as e:
# Truncate back to original size, then re-raise.
image.truncate(original_image_size)
- raise AvbError('Appending VBMeta image failed: {}.'.format(e))
+ raise AvbError('Appending VBMeta image failed: {}.'.format(e)) from e
def add_hash_footer(self, image_filename, partition_size, partition_name,
hash_algorithm, salt, chain_partitions, algorithm_name,
@@ -3514,7 +3528,7 @@
except Exception as e:
# Truncate back to original size, then re-raise.
image.truncate(original_image_size)
- raise AvbError('Adding hash_footer failed: {}.'.format(e))
+ raise AvbError('Adding hash_footer failed: {}.'.format(e)) from e
def add_hashtree_footer(self, image_filename, partition_size, partition_name,
generate_fec, fec_num_roots, hash_algorithm,
@@ -3532,7 +3546,7 @@
output_vbmeta_image, do_not_append_vbmeta_image,
print_required_libavb_version,
use_persistent_root_digest, do_not_use_ab,
- no_hashtree):
+ no_hashtree, check_at_most_once):
"""Implements the 'add_hashtree_footer' command.
See https://gitlab.com/cryptsetup/cryptsetup/wikis/DMVerity for
@@ -3576,13 +3590,15 @@
use_persistent_root_digest: Use a persistent root digest on device.
do_not_use_ab: The partition does not use A/B.
no_hashtree: Do not append hashtree. Set size in descriptor as zero.
+ check_at_most_once: Set to verify data blocks only the first time they
+ are read from the data device.
Raises:
AvbError: If an argument is incorrect or adding the hashtree footer
failed.
"""
required_libavb_version_minor = 0
- if use_persistent_root_digest or do_not_use_ab:
+ if use_persistent_root_digest or do_not_use_ab or check_at_most_once:
required_libavb_version_minor = 1
if rollback_index_location > 0:
required_libavb_version_minor = 2
@@ -3713,9 +3729,11 @@
ht_desc.partition_name = partition_name
ht_desc.salt = salt
if do_not_use_ab:
- ht_desc.flags |= 1 # AVB_HASHTREE_DESCRIPTOR_FLAGS_DO_NOT_USE_AB
+ ht_desc.flags |= AvbHashtreeDescriptor.FLAGS_DO_NOT_USE_AB
if not use_persistent_root_digest:
ht_desc.root_digest = root_digest
+ if check_at_most_once:
+ ht_desc.flags |= AvbHashtreeDescriptor.FLAGS_CHECK_AT_MOST_ONCE
# Write the hash tree
padding_needed = (round_to_multiple(len(hash_tree), image.block_size) -
@@ -3788,7 +3806,7 @@
except Exception as e:
# Truncate back to original size, then re-raise.
image.truncate(original_image_size)
- raise AvbError('Adding hashtree_footer failed: {}.'.format(e))
+ raise AvbError('Adding hashtree_footer failed: {}.'.format(e)) from e
def make_atx_certificate(self, output, authority_key_path, subject_key_path,
subject_key_version, subject,
@@ -4040,7 +4058,8 @@
fec_tmpfile.name],
stderr=open(os.devnull, 'wb'))
except subprocess.CalledProcessError as e:
- raise ValueError('Execution of \'fec\' tool failed: {}.'.format(e))
+ raise ValueError('Execution of \'fec\' tool failed: {}.'
+ .format(e)) from e
fec_data = fec_tmpfile.read()
footer_size = struct.calcsize(FEC_FOOTER_FORMAT)
@@ -4404,6 +4423,9 @@
sub_parser.add_argument('--no_hashtree',
action='store_true',
help='Do not append hashtree')
+ sub_parser.add_argument('--check_at_most_once',
+ action='store_true',
+ help='Set to verify data block only once')
self._add_common_args(sub_parser)
self._add_common_footer_args(sub_parser)
sub_parser.set_defaults(func=self.add_hashtree_footer)
@@ -4784,7 +4806,8 @@
args.print_required_libavb_version,
args.use_persistent_digest,
args.do_not_use_ab,
- args.no_hashtree)
+ args.no_hashtree,
+ args.check_at_most_once)
def erase_footer(self, args):
"""Implements the 'erase_footer' sub-command."""
diff --git a/docs/aftl-architecture.png b/docs/aftl-architecture.png
deleted file mode 100644
index 5526f92..0000000
--- a/docs/aftl-architecture.png
+++ /dev/null
Binary files differ
diff --git a/docs/aftl-boot-flow.png b/docs/aftl-boot-flow.png
deleted file mode 100644
index f724808..0000000
--- a/docs/aftl-boot-flow.png
+++ /dev/null
Binary files differ
diff --git a/docs/aftl-image-location.png b/docs/aftl-image-location.png
deleted file mode 100644
index 0e609d7..0000000
--- a/docs/aftl-image-location.png
+++ /dev/null
Binary files differ
diff --git a/docs/aftl-image-structure.png b/docs/aftl-image-structure.png
deleted file mode 100644
index 2487314..0000000
--- a/docs/aftl-image-structure.png
+++ /dev/null
Binary files differ
diff --git a/libavb/avb_hashtree_descriptor.h b/libavb/avb_hashtree_descriptor.h
index d0f7e2c..6595f46 100644
--- a/libavb/avb_hashtree_descriptor.h
+++ b/libavb/avb_hashtree_descriptor.h
@@ -40,9 +40,12 @@
* AVB_HASHTREE_DESCRIPTOR_FLAGS_DO_NOT_USE_AB: Do not apply the default A/B
* partition logic to this partition. This is intentionally a negative boolean
* because A/B should be both the default and most used in practice.
+ * AVB_HASHTREE_DESCRIPTOR_FLAGS_CHECK_AT_MOST_ONCE: supports to validate hashes
+ * at most once in DM-Verity.
*/
typedef enum {
AVB_HASHTREE_DESCRIPTOR_FLAGS_DO_NOT_USE_AB = (1 << 0),
+ AVB_HASHTREE_DESCRIPTOR_FLAGS_CHECK_AT_MOST_ONCE = (1 << 1),
} AvbHashtreeDescriptorFlags;
/* A descriptor containing information about a dm-verity hashtree.
diff --git a/libavb_aftl/README.md b/libavb_aftl/README.md
deleted file mode 100644
index abf2636..0000000
--- a/libavb_aftl/README.md
+++ /dev/null
@@ -1,305 +0,0 @@
-# Android Firmware Transparency Log 1.0
----
-
-This repository contains tools and libraries for working with the Android
-Firmware Transparency Log components of Android Verified Boot. AFTL will be
-used to refer to these components.
-
-[TOC]
-
-# What is it?
-
-The Android Firmware Transparency Log (AFTL) is an implementation of binary
-transparency that leverages cryptographic proofs of inclusion of build images
-using a public append-only ledger. The device manufacturer stores these
-cryptographic proofs, called inclusion proofs, on-device to allow for offline
-validation of the build during system update and device boot. This ensures that
-only a publicly known build is running on the device. Furthermore, it allows
-device manufacturers and other interested parties to audit the information in
-the log to detect unexpected or malicious uses of the publisher's signing keys.
-
-
-## System overview
-
-An AFTL can be implemented using a
-[Trillian](https://github.com/google/trillian) instance which manages a Merkle
-tree with build metadata (particularly the [VBMeta
-struct](https://android.googlesource.com/platform/external/avb/+/refs/heads/master#The-VBMeta-struct))
-and keeps a repository of other data that were made transparent.
-
-![Android Firmware Transparency Log system overview](../docs/aftl-architecture.png)
-
-As part of the finalizing step in the build process the `aftltool` reaches out
-to the **AFTL personality** to submit a manufacturer-signed message (containing
-VBMeta struct and other metadata) to the AFTL. Then the AFTL personality
-submits that data to Trillian to incorporate it into the Merkle tree. After
-integration into the log, the AFTL personality returns the inclusion proof back
-to the `aftltool`, which in turn incorporates the inclusion proof with the
-VBMeta image.
-
-The AFTL uses two sets of keys for authentication and validation, the
-transparency log key and the manufacturer key.
-
-* **Transparency log key:** Used by Trillian to sign inclusion proofs. The
- public key is embedded with the device for on-device for validation.
-* **Manufacturer key:** Used by OEMs or other build providers to sign
- submissions sent to the log. This ensures that malicious entries posing as a
- valid OEM entry cannot be provided to the log. For the log to authenticate
- messages, the manufacturer key must be shared out-of-band with the AFTL prior
- to submission.
-
-## The AftlImage struct
-
-The central data structure used for AFTL validation is the `AftlImage` struct.
-The structure is saved on the vbmeta partition, right after the
-`AvbVBMetaImage` struct, as illustrated below.
-
-![Overview of the AftlImage structure](../docs/aftl-image-location.png)
-
-This structure contains the `AftlImageHeader` header that describes the number
-of inclusion proofs (`AftlIcpEntry`) represented by this structure. Each
-inclusion proof has associated metadata, such as the transparency log URL. A
-high-level description of the structures is given below. See
-[aftltool](https://android.googlesource.com/platform/external/avb/+/refs/heads/master/aftltool.py)
-and
-[libavb_aftl](https://android.googlesource.com/platform/external/avb/+/refs/heads/master/libavb_aftl/)
-for more details.
-
-
-![Overview of AftlIcpHeader and AftlIcpEntry](../docs/aftl-image-structure.png)
-
-Each `AftlIcpEntry` structure contains the information required to validate an
-inclusion proof from a specific transparency log server for a given [VBMeta
-structure](https://android.googlesource.com/platform/external/avb/+/master#the-vbmeta-struct)
-given the corresponding transparency log public key. The inclusion proof
-validation process is described in the [inclusion proofs](#inclusion-proofs)
-section of this document.
-
-*Note*: A single `AftlImage` can have multiple inclusion proofs from different
-transparency logs. This allows the device manufacturer to not rely on a single
-transparency log, and ensures that the builds represented by the VBMeta
-structure are deemed transparent in multiple disparate jurisdictions.
-
-## Inclusion proofs
-
-An inclusion proof allows a user to prove that a specific VBMeta structure is
-included in a transparency log. An inclusion proof consists of three parts:
-
-* A `SignedVBMetaPrimaryAnnotation` structure containing the hash of the
-VBMeta structure (and other build meta information) that is signed with the
-manufacturer key.
-* A set of sibling node hashes (`Proof`) in a Merkle tree on the path from the
-leaf node in question, which represents the logged annotation, to the root
-node.
-* A `TrillianLogRootDescriptor` structure containing the log's root hash,
-along with related metadata, which is signed by the transparency log’s private
-key.
-
-Validation of an inclusion proof can be performed with the following steps,
-which are implemented in both `aftltool` and `libavb_aftl`.
-
-1. Calculate the hash of the VBMeta structure stored on the device.
-1. Determine if the hash matches the hash stored in the
-`SignedVBMetaPrimaryAnnotation` structure inside the `AftlImage` on device. If
-it does, continue validation.
-1. Given the set of hashes provided from the transparency log as part of the
-inclusion proof, attempt to recalculate the root hash. Details of the process
-can be found [here](https://www.certificate-transparency.org/log-proofs-work)
-in the Merkle Audit Proofs section.
-1. Check the calculated root hash against the log's root hash from the
-inclusion proof. If it matches, continue validation.
-1. Finally, verify the log root signature given the calculated root hash and
-the public key of the transparency log that is stored on device. If the
-signature is valid, the inclusion proof is valid.
-
-# Tools and libraries
-
-This section contains information about the tools and libraries added to AVB
-repository or modified to include AFTL support.
-
-## aftltool and libavb\_aftl
-
-The main purpose of
-[aftltool](https://android.googlesource.com/platform/external/avb/+/refs/heads/master/aftltool.py)
-is to add an inclusion proof to an existing `vbmeta.img` to be used
-for transparency checks at boot or system update time. This enhanced image is
-stored in the `vbmeta` partition or in the `vbmeta_a` and
-`vbmeta_b` slots when using A/B and will still be of minimal size
-(for out-of-band updates). Creation, query, and verification tasks can be
-performed with `aftltool`.
-
-In addition to the `aftltool`, the
-[libavb](https://android.googlesource.com/platform/external/avb/+/master/libavb/)
-library comes with an extension called
-[libavb\_aftl](https://android.googlesource.com/platform/external/avb/+/master/libavb_aftl/).
-This component performs all verification on the device side related to AFTL and
-inclusion proofs. That is, it loads the `vbmeta` partition, checks
-the VBMeta structure signature, walks through each inclusion proof stored in
-the `AftlImage`, and validates them against a trusted transparency
-log key stored on the device.
-
-This library is intended to be used in both the boot loader and inside Android
-as part of the OTA client. The main entry point for verification is
-`aftl_slot_verify()`, which is intended to be called after `vbmeta`
-verification is done via `avb_slot_verify()`.
-
-## Files and directories
-
-* `libavb_aftl/`
- + An implementation of AFTL inclusion proof validation. This
- code is designed to be highly portable so it can be used in as many contexts
- as possible. This code requires a C99-compliant C compiler. Only the content
- declared in `libavb_aftl.h` is considered public. The other files are
- considered internal to the implementation and may change without notice.
-* `libavb_aftl/README.md`
- + This document.
-* `test/`
- + Unit tests for `libavb_aftl.`
-* `test/data/`
- + Test data for the `aftltool` and `libavb_aftl` unit tests.
-* `aftltool`
- + A symlink to `aftltool.py`.
-* `aftltool.py`
- + A tool written in Python for working with images related to AFTL.
-* `Android.bp`
- + Build rules for `aftltool`, `libavb_aftl` (a static library
- for use on the device), host-side libraries (for unit tests), and unit
- tests.
-* `aftltool_test.py`
- + Source-code for `aftltool` related unit tests.
-* `aftltool_integration_test.py`
- + Source-code for `aftltool` related integration tests against
- a live transparency log.
-
-## Portability
-
-The `libavb_aftl` code is intended to be used in bootloaders in devices that
-will load Android or other operating systems. The suggested approach is to copy
-the appropriate header and C files mentioned in the previous section into the
-boot loader and integrate as appropriate. The library is intended to be highly
-portable, working on both little and big endian architectures, as well as
-32-bit and 64-bit variants of each. It is also intended to work in environments
-without the standard C library and runtime.
-
-As in libavb, if the `AVB_ENABLE_DEBUG` preprocessor symbol is set, the code
-will include useful debug information and run-time checks.
-
-## Versioning and compatibility
-
-The `libavb_aftl` library follows the [versioning of
-libavb](https://android.googlesource.com/platform/external/avb/+/master#Versioning-and-Compatibility).
-
-## Using aftltool
-
-The content for the vbmeta partition is assumed to have been generated
-previously using `avbtool`. Instructions can be found in the
-[README.md](https://android.googlesource.com/platform/external/avb/+/master/README.md)
-for libavb. After the VBMeta partition is generated, it can be extended with
-inclusion proofs from transparency logs in the following manner:
-
-
-```
-aftltool make_icp_from_vbmeta \
- --vbmeta_image_path /path/to/image.bin \
- --output OUTPUT \
- [--signing_helper /path/to/external/signer] \
- [--signing_helper_with_files /path/to/external/signer_with_files] \
- --version_incremental STR \
- --transparency_log_servers host:port,/path/to/log_key.pub \
- --manufacturer_key /path/to/priv_key \
- [--padding_size NUM]
-```
-
-The
-[version\_incremental](https://developer.android.com/reference/android/os/Build.VERSION#INCREMENTAL)
-is a part of the build fingerprint which allows for tagging the transparency
-log entry for easier tracking.
-
-An example of how to use the `make_icp_from_vbmeta` command is as follows:
-
-```
-aftltool make_icp_from_vbmeta \
- --vbmeta_image_path ./vbmeta.img \
- --output ./vbmeta_icp.img \
- --version_incremental 99999999 \
- --transparency_log_servers \
- log.aftl-android.com:9000,/aftl-log-rsa-pub.pem \
- --manufacturer_key ./manufacturer-rsa.pem \
- --algorithm SHA256_RSA4096 \
- --padding 4096
-```
-
-The AFTL information can be viewed in a human readable format in the following
-manner:
-
-```
-aftltool info_image_icp \
- --vbmeta_image_path /path/to/image.bin \
- [--output OUTPUT]
-```
-
-An example using `info_image_icp` is as follows:
-
-```
-aftltool info_image_icp --vbmeta_image_path ./vbmeta.img
-```
-
-Verification of an AFTL enhanced vbmeta image can be performed with the
-following command:
-
-```
-aftltool verify_image_icp \
- --vbmeta_image_path /path/to/image.bin \
- --transparency_log_pub_keys [TRANSPARENCY_LOG_PUB_KEYS [TRANSPARENCY_LOG_PUB_KEYS ...]]
-[--output OUTPUT]
-```
-
-An example using `verify_image_icp` is as follows:
-
-```
-aftltool verify_image_icp --vbmeta_image_path ./vbmeta.img --transparency_log_pub_keys ./log_pub_key.pem
-```
-
-More information on the options can be found using `aftltool --help`.
-
-# Build system integration
-
-AFTL modifications only will work if AVB is enabled in the build. In Android,
-AVB is enabled in an `Android.mk` file by the `BOARD_AVB_ENABLE` variable as
-described in the AVB
-[README.md](https://android.googlesource.com/platform/external/avb/#Build-System-Integration).
-
-When calling the
-[sign\_target\_files\_apks.py](https://android.googlesource.com/platform/build/+/master/tools/releasetools/sign_target_files_apks.py)
-script, the following parameters must be set:
-
-* `--aftl_tool_path`, the location of aftltool.py
-* `--aftl_server`, the address of the transparency log
-* `--aftl_key_path`, which gives the path to the DER encoded transparency log public key
-* `--aftl_manufacturer_key_path`, which gives the path to the DER encoded OEM
- private key. Note: This key is different to the signing key used to sign VBMeta
- structure
-
-Remember that the public part of the transparency log keys need to be available
-to the bootloader of the device to validate the inclusion proofs.
-
-# Device integration
-
-This section discusses recommendations and best practices for integrating
-`libavb` AFTL support with a device boot loader. It's important to emphasize
-that these are just recommendations. Most of these recommendations are the same
-as those for AVB.
-
-## Recommended bootflow
-
-The boot flow should ensure checking of the inclusion proofs independent of the
-unlock state of the device. It is recommended to present the user with a
-warning in case transparency checks fail.
-
-AFTL modifies this flow in the following manner: as soon as a valid OS has been
-found, search for an `AftlImage` for each VBMeta image and validate their
-inclusion proofs (this is done by the `aftl_slot_verify` function). The result
-of the verification can be appended to the kernel command line for further
-processing by the OS.
-
-![Recommended boot flow for a device using AFTL](../docs/aftl-boot-flow.png)
diff --git a/libavb_aftl/avb_aftl_types.h b/libavb_aftl/avb_aftl_types.h
deleted file mode 100644
index 028ffda..0000000
--- a/libavb_aftl/avb_aftl_types.h
+++ /dev/null
@@ -1,206 +0,0 @@
-/*
- * Copyright (C) 2020 The Android Open Source Project
- *
- * Permission is hereby granted, free of charge, to any person
- * obtaining a copy of this software and associated documentation
- * files (the "Software"), to deal in the Software without
- * restriction, including without limitation the rights to use, copy,
- * modify, merge, publish, distribute, sublicense, and/or sell copies
- * of the Software, and to permit persons to whom the Software is
- * furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be
- * included in all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
- * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
- * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
- * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
- * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
- * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
- * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
- * SOFTWARE.
- */
-
-#ifdef AVB_INSIDE_LIBAVB_AFTL_H
-#error "You can't include avb_aftl_types.h in the public header libavb_aftl.h."
-#endif
-
-#ifndef AVB_COMPILATION
-#error "Never include this file, it may only be used from internal avb code."
-#endif
-
-#ifndef AVB_AFTL_TYPES_H_
-#define AVB_AFTL_TYPES_H_
-
-#include <libavb/libavb.h>
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-#define AVB_AFTL_UINT64_MAX 0xfffffffffffffffful
-#define AVB_AFTL_HASH_SIZE 32ul
-#define AVB_AFTL_SIGNATURE_SIZE 512ul
-/* Raw key size used for signature validation. */
-#define AVB_AFTL_PUB_KEY_SIZE 1032ul
-/* Limit AftlImage size to 64KB. */
-#define AVB_AFTL_MAX_AFTL_IMAGE_SIZE 65536ul
-/* Limit version.incremental size to 256 characters. */
-#define AVB_AFTL_MAX_VERSION_INCREMENTAL_SIZE 256ul
-/* AFTL trees require at most 64 hashes to reconstruct the root */
-#define AVB_AFTL_MAX_PROOF_SIZE 64 * AVB_AFTL_HASH_SIZE
-/* Max URL limit. */
-#define AVB_AFTL_MAX_URL_SIZE 2048ul
-/* Minimum valid size for an Annotation leaf. */
-#define AVB_AFTL_MIN_ANNOTATION_SIZE 18ul
-/* Minimum valid size for a TrillianLogRootDescriptor. See the
- TrillianLogRootDescriptor struct for details. The values here cover:
- version: sizeof(uint16_t)
- tree_size: sizeof(uint64_t)
- root_hash_size: sizeof(uint8_t)
- root_hash: AVB_AFTL_HASH_SIZE
- timestamp; sizeof(uint64_t)
- revision; sizeof(uint64_t)
- metadata_size: sizeof(uint16_t)
- metadata is optional, so it's not required for the minimum size. */
-#define AVB_AFTL_MIN_TLRD_SIZE \
- (sizeof(uint16_t) + sizeof(uint64_t) + sizeof(uint8_t) + \
- AVB_AFTL_HASH_SIZE + sizeof(uint64_t) + sizeof(uint64_t) + \
- sizeof(uint16_t))
-/* Minimum valid size for an AftlIcpEntry structure. See the
- AftlIcpEntry struct for details. The values here cover:
- log_url_size: sizeof(uint32_t)
- leaf_index: sizeof(uint64_t)
- log_root_descriptor_size: sizeof(uint32_t)
- annotation_leaf_size: sizeof(uint32_t)
- log_root_sig_size: sizeof(uint32_t)
- proof_hash_count: sizeof(uint8_t)
- inc_proof_size: sizeof(uint32_t)
- log_url: 4 (shortest practical URL)
- log_root_descriptor: AVB_AFTL_MIN_TLRD_SIZE
- annotation_leaf: AVB_AFTL_MIN_ANNOTATION_SIZE
- log_root_signature: AVB_AFTL_SIGNATURE_SIZE
- proofs: AVB_AFTL_HASH_SIZE as there must be at least one hash. */
-#define AVB_AFTL_MIN_AFTL_ICP_ENTRY_SIZE \
- (sizeof(uint32_t) + sizeof(uint64_t) + sizeof(uint32_t) + sizeof(uint32_t) + \
- sizeof(uint32_t) + sizeof(uint8_t) + sizeof(uint32_t) + 4 + \
- AVB_AFTL_MIN_TLRD_SIZE + AVB_AFTL_MIN_ANNOTATION_SIZE + \
- AVB_AFTL_SIGNATURE_SIZE + AVB_AFTL_HASH_SIZE)
-/* The maximum AftlIcpEntrySize is the max AftlImage size minus the size
- of the AftlImageHeader. */
-#define AVB_AFTL_MAX_AFTL_ICP_ENTRY_SIZE \
- (AVB_AFTL_MAX_AFTL_IMAGE_SIZE - sizeof(AftlImageHeader))
-/* The maximum Annotation size is the max AftlImage size minus the
- size of the smallest valid AftlIcpEntry. */
-#define AVB_AFTL_MAX_ANNOTATION_SIZE \
- (AVB_AFTL_MAX_AFTL_IMAGE_SIZE - AVB_AFTL_MIN_AFTL_ICP_ENTRY_SIZE)
-/* The maximum metadata size in a TrillianLogRootDescriptor for AFTL is the
- max AftlImage size minus the smallest valid AftlIcpEntry size. */
-#define AVB_AFTL_MAX_METADATA_SIZE \
- (AVB_AFTL_MAX_AFTL_IMAGE_SIZE - AVB_AFTL_MIN_AFTL_ICP_ENTRY_SIZE)
-/* The maximum TrillianLogRootDescriptor is the size of the smallest valid
-TrillianLogRootDescriptor + the largest possible metadata size. */
-#define AVB_AFTL_MAX_TLRD_SIZE \
- (AVB_AFTL_MIN_TLRD_SIZE + AVB_AFTL_MAX_METADATA_SIZE)
-
-/* Data structure containing a Trillian LogRootDescriptor, from
- https://github.com/google/trillian/blob/master/trillian.proto#L255
- The log_root_signature is calculated over this structure. */
-typedef struct TrillianLogRootDescriptor {
- uint16_t version;
- uint64_t tree_size;
- uint8_t root_hash_size;
- uint8_t* root_hash;
- uint64_t timestamp;
- uint64_t revision;
- uint16_t metadata_size;
- uint8_t* metadata;
-} TrillianLogRootDescriptor;
-
-typedef enum {
- AVB_AFTL_HASH_SHA256,
- _AVB_AFTL_HASH_ALGORITHM_NUM
-} HashAlgorithm;
-
-typedef enum {
- AVB_AFTL_SIGNATURE_RSA, // RSA with PKCS1v15
- AVB_AFTL_SIGNATURE_ECDSA, // ECDSA with P256 curve
- _AVB_AFTL_SIGNATURE_ALGORITHM_NUM
-} SignatureAlgorithm;
-
-/* Data structure containing the signature within a leaf of the VBMeta
- * annotation. This signature is made using the manufacturer key which is
- * generally not available at boot time. Therefore, this structure is not
- * verified by the bootloader. */
-typedef struct {
- uint8_t hash_algorithm;
- uint8_t signature_algorithm;
- uint16_t signature_size;
- uint8_t* signature;
-} Signature;
-
-/* Data structure containing the VBMeta annotation. */
-typedef struct {
- uint8_t vbmeta_hash_size;
- uint8_t* vbmeta_hash;
- uint8_t version_incremental_size;
- uint8_t* version_incremental;
- uint8_t manufacturer_key_hash_size;
- uint8_t* manufacturer_key_hash;
- uint16_t description_size;
- uint8_t* description;
-} VBMetaPrimaryAnnotation;
-
-#define AVB_AFTL_VBMETA_LEAF 0
-#define AVB_AFTL_SIGNED_VBMETA_PRIMARY_ANNOTATION_LEAF 1
-
-/* Data structure containing the leaf that is stored in the
- transparency log. */
-typedef struct {
- uint8_t version;
- uint64_t timestamp;
- uint8_t leaf_type;
- Signature* signature;
- VBMetaPrimaryAnnotation* annotation;
-} SignedVBMetaPrimaryAnnotationLeaf;
-
-/* Data structure containing AFTL inclusion proof data from a single
- transparency log. */
-typedef struct AftlIcpEntry {
- uint32_t log_url_size;
- uint64_t leaf_index;
- uint32_t log_root_descriptor_size;
- uint32_t annotation_leaf_size;
- uint16_t log_root_sig_size;
- uint8_t proof_hash_count;
- uint32_t inc_proof_size;
- uint8_t* log_url;
- TrillianLogRootDescriptor log_root_descriptor;
- uint8_t* log_root_descriptor_raw;
- SignedVBMetaPrimaryAnnotationLeaf* annotation_leaf;
- uint8_t* annotation_leaf_raw;
- uint8_t* log_root_signature;
- uint8_t (*proofs)[AVB_AFTL_HASH_SIZE];
-} AftlIcpEntry;
-
-/* Data structure containing AFTL header information. */
-typedef struct AftlImageHeader {
- uint32_t magic;
- uint32_t required_icp_version_major;
- uint32_t required_icp_version_minor;
- uint32_t image_size; /* Total size of the AftlImage, including this header */
- uint16_t icp_count;
-} AVB_ATTR_PACKED AftlImageHeader;
-
-/* Main data structure for an AFTL image. */
-typedef struct AftlImage {
- AftlImageHeader header;
- AftlIcpEntry** entries;
-} AftlImage;
-
-#ifdef __cplusplus
-}
-#endif
-
-#endif /* AVB_AFTL_TYPES_H_ */
diff --git a/libavb_aftl/avb_aftl_util.c b/libavb_aftl/avb_aftl_util.c
deleted file mode 100644
index f780e82..0000000
--- a/libavb_aftl/avb_aftl_util.c
+++ /dev/null
@@ -1,932 +0,0 @@
-/*
- * Copyright (C) 2020 The Android Open Source Project
- *
- * Permission is hereby granted, free of charge, to any person
- * obtaining a copy of this software and associated documentation
- * files (the "Software"), to deal in the Software without
- * restriction, including without limitation the rights to use, copy,
- * modify, merge, publish, distribute, sublicense, and/or sell copies
- * of the Software, and to permit persons to whom the Software is
- * furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be
- * included in all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
- * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
- * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
- * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
- * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
- * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
- * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
- * SOFTWARE.
- */
-
-#include <libavb/avb_crypto.h>
-#include <libavb/avb_rsa.h>
-#include <libavb/avb_sha.h>
-#include <libavb/avb_util.h>
-
-#include "avb_aftl_types.h"
-#include "avb_aftl_util.h"
-#include "avb_aftl_validate.h"
-
-/* Performs a SHA256 hash operation on data. */
-bool avb_aftl_sha256(uint8_t* data,
- uint64_t length,
- uint8_t hash[AVB_AFTL_HASH_SIZE]) {
- AvbSHA256Ctx context;
- uint8_t* tmp;
-
- if ((data == NULL) && (length != 0)) return false;
-
- avb_sha256_init(&context);
- avb_sha256_update(&context, data, length);
- tmp = avb_sha256_final(&context);
- avb_memcpy(hash, tmp, AVB_AFTL_HASH_SIZE);
- return true;
-}
-
-/* Computes a leaf hash as detailed by https://tools.ietf.org/html/rfc6962. */
-bool avb_aftl_rfc6962_hash_leaf(uint8_t* leaf,
- uint64_t leaf_size,
- uint8_t* hash) {
- uint8_t* buffer;
- bool retval;
-
- avb_assert(leaf != NULL && hash != NULL);
- avb_assert(leaf_size != AVB_AFTL_UINT64_MAX);
-
- buffer = (uint8_t*)avb_malloc(leaf_size + 1);
-
- if (buffer == NULL) {
- avb_error("Allocation failure in avb_aftl_rfc6962_hash_leaf.\n");
- return false;
- }
- /* Prefix the data with a '0' for 2nd preimage attack resistance. */
- buffer[0] = 0;
-
- if (leaf_size > 0) avb_memcpy(buffer + 1, leaf, leaf_size);
-
- retval = avb_aftl_sha256(buffer, leaf_size + 1, hash);
- avb_free(buffer);
- return retval;
-}
-
-/* Computes an inner hash as detailed by https://tools.ietf.org/html/rfc6962. */
-bool avb_aftl_rfc6962_hash_children(uint8_t* left_child,
- uint64_t left_child_size,
- uint8_t* right_child,
- uint64_t right_child_size,
- uint8_t* hash) {
- uint8_t* buffer;
- uint64_t data_size;
- bool retval;
-
- avb_assert(left_child != NULL && right_child != NULL && hash != NULL);
-
- /* Check for integer overflow. */
- avb_assert(left_child_size < AVB_AFTL_UINT64_MAX - right_child_size);
-
- data_size = left_child_size + right_child_size + 1;
- buffer = (uint8_t*)avb_malloc(data_size);
- if (buffer == NULL) {
- avb_error("Allocation failure in avb_aftl_rfc6962_hash_children.\n");
- return false;
- }
-
- /* Prefix the data with '1' for 2nd preimage attack resistance. */
- buffer[0] = 1;
-
- /* Copy the left child data, if it exists. */
- if (left_child_size > 0) avb_memcpy(buffer + 1, left_child, left_child_size);
- /* Copy the right child data, if it exists. */
- if (right_child_size > 0)
- avb_memcpy(buffer + 1 + left_child_size, right_child, right_child_size);
-
- /* Hash the concatenated data and clean up. */
- retval = avb_aftl_sha256(buffer, data_size, hash);
- avb_free(buffer);
- return retval;
-}
-
-/* Computes a subtree hash along tree's right border. */
-bool avb_aftl_chain_border_right(uint8_t* seed,
- uint64_t seed_size,
- uint8_t* proof,
- uint32_t proof_entry_count,
- uint8_t* hash) {
- size_t i;
- uint8_t* tmp_hash;
- uint8_t* tmp = seed;
- bool retval = true;
-
- avb_assert(seed_size == AVB_AFTL_HASH_SIZE);
- avb_assert(seed != NULL && proof != NULL && hash != NULL);
-
- tmp_hash = (uint8_t*)avb_malloc(AVB_AFTL_HASH_SIZE);
- if (tmp_hash == NULL) {
- avb_error("Allocation failure in avb_aftl_chain_border_right.\n");
- return false;
- }
- for (i = 0; i < proof_entry_count; i++) {
- retval = avb_aftl_rfc6962_hash_children(proof + (i * AVB_AFTL_HASH_SIZE),
- AVB_AFTL_HASH_SIZE,
- tmp,
- AVB_AFTL_HASH_SIZE,
- tmp_hash);
- if (!retval) {
- avb_error("Failed to hash Merkle tree children.\n");
- break;
- }
- tmp = tmp_hash;
- }
-
- if (retval) avb_memcpy(hash, tmp, AVB_AFTL_HASH_SIZE);
-
- avb_free(tmp_hash);
- return retval;
-}
-
-/* Computes a subtree hash on or below the tree's right border. */
-bool avb_aftl_chain_inner(uint8_t* seed,
- uint64_t seed_size,
- uint8_t* proof,
- uint32_t proof_entry_count,
- uint64_t leaf_index,
- uint8_t* hash) {
- size_t i;
- uint8_t* tmp_hash;
- uint8_t* tmp = seed;
- bool retval = true;
-
- avb_assert(seed_size == AVB_AFTL_HASH_SIZE);
- avb_assert(seed != NULL && proof != NULL && hash != NULL);
-
- tmp_hash = (uint8_t*)avb_malloc(AVB_AFTL_HASH_SIZE);
- if (tmp_hash == NULL) {
- avb_error("Allocation failure in avb_aftl_chain_inner.\n");
- return false;
- }
- for (i = 0; i < proof_entry_count; i++) {
- if ((leaf_index >> i & 1) == 0) {
- retval = avb_aftl_rfc6962_hash_children(tmp,
- seed_size,
- proof + (i * AVB_AFTL_HASH_SIZE),
- AVB_AFTL_HASH_SIZE,
- tmp_hash);
- } else {
- retval = avb_aftl_rfc6962_hash_children(proof + (i * AVB_AFTL_HASH_SIZE),
- AVB_AFTL_HASH_SIZE,
- tmp,
- seed_size,
- tmp_hash);
- }
- if (!retval) {
- avb_error("Failed to hash Merkle tree children.\n");
- break;
- }
- tmp = tmp_hash;
- }
- if (retval) avb_memcpy(hash, tmp, AVB_AFTL_HASH_SIZE);
- avb_free(tmp_hash);
- return retval;
-}
-
-/* Counts leading zeros. Used in Merkle tree hash validation .*/
-unsigned int avb_aftl_count_leading_zeros(uint64_t val) {
- int r = 0;
- if (val == 0) return 64;
- if (!(val & 0xffffffff00000000u)) {
- val <<= 32;
- r += 32;
- }
- if (!(val & 0xffff000000000000u)) {
- val <<= 16;
- r += 16;
- }
- if (!(val & 0xff00000000000000u)) {
- val <<= 8;
- r += 8;
- }
- if (!(val & 0xf000000000000000u)) {
- val <<= 4;
- r += 4;
- }
- if (!(val & 0xc000000000000000u)) {
- val <<= 2;
- r += 2;
- }
- if (!(val & 0x8000000000000000u)) {
- val <<= 1;
- r += 1;
- }
-
- return r;
-}
-
-/* Calculates the expected Merkle tree hash. */
-bool avb_aftl_root_from_icp(uint64_t leaf_index,
- uint64_t tree_size,
- uint8_t proof[][AVB_AFTL_HASH_SIZE],
- uint32_t proof_entry_count,
- uint8_t* leaf_hash,
- uint64_t leaf_hash_size,
- uint8_t* root_hash) {
- uint64_t inner_proof_size;
- uint64_t border_proof_size;
- size_t i;
- uint8_t hash[AVB_AFTL_HASH_SIZE];
- uint8_t* inner_proof;
- uint8_t* border_proof;
- bool retval;
-
- avb_assert(proof_entry_count != 0);
- avb_assert(leaf_hash_size != 0);
- avb_assert(proof != NULL && leaf_hash != NULL && root_hash != NULL);
-
- /* This cannot overflow. */
- inner_proof_size =
- 64 - avb_aftl_count_leading_zeros(leaf_index ^ (tree_size - 1));
-
- /* Check for integer underflow.*/
- if ((proof_entry_count - inner_proof_size) > proof_entry_count) {
- avb_error("Invalid proof entry count value.\n");
- return false;
- }
- border_proof_size = proof_entry_count - inner_proof_size;
- /* Split the proof into two parts based on the calculated pivot point. */
- inner_proof = (uint8_t*)avb_malloc(inner_proof_size * AVB_AFTL_HASH_SIZE);
- if (inner_proof == NULL) {
- avb_error("Allocation failure in avb_aftl_root_from_icp.\n");
- return false;
- }
- border_proof = (uint8_t*)avb_malloc(border_proof_size * AVB_AFTL_HASH_SIZE);
- if (border_proof == NULL) {
- avb_free(inner_proof);
- avb_error("Allocation failure in avb_aftl_root_from_icp.\n");
- return false;
- }
-
- for (i = 0; i < inner_proof_size; i++) {
- avb_memcpy(
- inner_proof + (AVB_AFTL_HASH_SIZE * i), proof[i], AVB_AFTL_HASH_SIZE);
- }
- for (i = 0; i < border_proof_size; i++) {
- avb_memcpy(border_proof + (AVB_AFTL_HASH_SIZE * i),
- proof[inner_proof_size + i],
- AVB_AFTL_HASH_SIZE);
- }
-
- /* Calculate the root hash and store it in root_hash. */
- retval = avb_aftl_chain_inner(leaf_hash,
- leaf_hash_size,
- inner_proof,
- inner_proof_size,
- leaf_index,
- hash);
- if (retval)
- retval = avb_aftl_chain_border_right(
- hash, AVB_AFTL_HASH_SIZE, border_proof, border_proof_size, root_hash);
-
- if (inner_proof != NULL) avb_free(inner_proof);
- if (border_proof != NULL) avb_free(border_proof);
- return retval;
-}
-
-/* Defines helper functions read_u8, read_u16, read_u32 and read_u64. These
- * functions can be used to read from a |data| stream a |value| of a specific
- * size. The value endianness is converted from big-endian to host. We ensure
- * that the read do not overflow beyond |data_end|. If successful, |data| is
- * brought forward by the size of the value read.
- */
-#define _read_u(fct) \
- { \
- size_t value_size = sizeof(*value); \
- if ((*data + value_size) < *data) return false; \
- if ((*data + value_size) > data_end) return false; \
- avb_memcpy(value, *data, value_size); \
- *value = fct(*value); \
- *data += value_size; \
- return true; \
- }
-static bool read_u8(uint8_t* value, uint8_t** data, uint8_t* data_end) {
- _read_u();
-}
-AVB_ATTR_WARN_UNUSED_RESULT
-static bool read_u16(uint16_t* value, uint8_t** data, uint8_t* data_end) {
- _read_u(avb_be16toh);
-}
-AVB_ATTR_WARN_UNUSED_RESULT
-static bool read_u32(uint32_t* value, uint8_t** data, uint8_t* data_end) {
- _read_u(avb_be32toh);
-}
-AVB_ATTR_WARN_UNUSED_RESULT
-static bool read_u64(uint64_t* value, uint8_t** data, uint8_t* data_end) {
- _read_u(avb_be64toh);
-}
-AVB_ATTR_WARN_UNUSED_RESULT
-
-/* Allocates |value_size| bytes into |value| and copy |value_size| bytes from
- * |data|. Ensure that we don't overflow beyond |data_end|. It is the caller
- * responsibility to avb_free |value|. Advances the |data| pointer pass the
- * value that has been read. Returns false if an overflow would have occurred or
- * if the allocation failed.
- */
-static bool read_mem(uint8_t** value,
- size_t value_size,
- uint8_t** data,
- uint8_t* data_end) {
- if (*data + value_size < *data || *data + value_size > data_end) {
- return false;
- }
- *value = (uint8_t*)avb_calloc(value_size);
- if (!value) {
- return false;
- }
- avb_memcpy(*value, *data, value_size);
- *data += value_size;
- return true;
-}
-
-/* Allocates and populates a TrillianLogRootDescriptor element in an
- AftlIcpEntry from a binary blob.
- The blob is expected to be pointing to the beginning of a
- serialized TrillianLogRootDescriptor element of an AftlIcpEntry.
- The aftl_blob argument is updated to point to the area after the
- TrillianLogRootDescriptor. aftl_blob_remaining gives the amount of the
- aftl_blob that is left to parse. */
-static bool parse_trillian_log_root_descriptor(AftlIcpEntry* icp_entry,
- uint8_t** aftl_blob,
- size_t aftl_blob_remaining) {
- avb_assert(icp_entry);
- avb_assert(aftl_blob);
- uint8_t* blob_end = *aftl_blob + aftl_blob_remaining;
- if (*aftl_blob > blob_end) {
- return false;
- }
-
- /* Copy in the version field from the blob. */
- if (!read_u16(
- &(icp_entry->log_root_descriptor.version), aftl_blob, blob_end)) {
- avb_error("Unable to parse version.\n");
- return false;
- }
-
- /* Copy in the tree size field from the blob. */
- if (!read_u64(
- &(icp_entry->log_root_descriptor.tree_size), aftl_blob, blob_end)) {
- avb_error("Unable to parse tree size.\n");
- return false;
- }
-
- /* Copy in the root hash size field from the blob. */
- if (!read_u8(&(icp_entry->log_root_descriptor.root_hash_size),
- aftl_blob,
- blob_end)) {
- avb_error("Unable to parse root hash size.\n");
- return false;
- }
- if (icp_entry->log_root_descriptor.root_hash_size != AVB_AFTL_HASH_SIZE) {
- avb_error("Invalid root hash size.\n");
- return false;
- }
-
- /* Copy in the root hash from the blob. */
- if (!read_mem(&(icp_entry->log_root_descriptor.root_hash),
- icp_entry->log_root_descriptor.root_hash_size,
- aftl_blob,
- blob_end)) {
- avb_error("Unable to parse root hash.\n");
- return false;
- }
-
- /* Copy in the timestamp field from the blob. */
- if (!read_u64(
- &(icp_entry->log_root_descriptor.timestamp), aftl_blob, blob_end)) {
- avb_error("Unable to parse timestamp.\n");
- return false;
- }
-
- /* Copy in the revision field from the blob. */
- if (!read_u64(
- &(icp_entry->log_root_descriptor.revision), aftl_blob, blob_end)) {
- avb_error("Unable to parse revision.\n");
- return false;
- }
-
- /* Copy in the metadata size field from the blob. */
- if (!read_u16(&(icp_entry->log_root_descriptor.metadata_size),
- aftl_blob,
- blob_end)) {
- avb_error("Unable to parse metadata size.\n");
- return false;
- }
-
- if (icp_entry->log_root_descriptor.metadata_size >
- AVB_AFTL_MAX_METADATA_SIZE) {
- avb_error("Invalid metadata size.\n");
- return false;
- }
-
- /* If it exists, copy in the metadata field from the blob. */
- if (icp_entry->log_root_descriptor.metadata_size > 0) {
- if (!read_mem(&(icp_entry->log_root_descriptor.metadata),
- icp_entry->log_root_descriptor.metadata_size,
- aftl_blob,
- blob_end)) {
- avb_error("Unable to parse metadata.\n");
- return false;
- }
- } else {
- icp_entry->log_root_descriptor.metadata = NULL;
- }
- return true;
-}
-
-/* Parses a Signature from |aftl_blob| into leaf->signature.
- * Returns false if an error occurred during the parsing */
-static bool parse_signature(SignedVBMetaPrimaryAnnotationLeaf* leaf,
- uint8_t** aftl_blob,
- uint8_t* blob_end) {
- Signature* signature = (Signature*)avb_calloc(sizeof(Signature));
- if (!signature) {
- avb_error("Failed to allocate signature.\n");
- return false;
- }
- leaf->signature = signature;
-
- if (!read_u8(&(signature->hash_algorithm), aftl_blob, blob_end)) {
- avb_error("Unable to parse the hash algorithm.\n");
- return false;
- }
- if (signature->hash_algorithm >= _AVB_AFTL_HASH_ALGORITHM_NUM) {
- avb_error("Unexpect hash algorithm in leaf signature.\n");
- return false;
- }
-
- if (!read_u8(&(signature->signature_algorithm), aftl_blob, blob_end)) {
- avb_error("Unable to parse the signature algorithm.\n");
- return false;
- }
- if (signature->signature_algorithm >= _AVB_AFTL_SIGNATURE_ALGORITHM_NUM) {
- avb_error("Unexpect signature algorithm in leaf signature.\n");
- return false;
- }
-
- if (!read_u16(&(signature->signature_size), aftl_blob, blob_end)) {
- avb_error("Unable to parse the signature size.\n");
- return false;
- }
- if (!read_mem(&(signature->signature),
- signature->signature_size,
- aftl_blob,
- blob_end)) {
- avb_error("Unable to parse signature.\n");
- return false;
- }
- return true;
-}
-
-/* Parses an VBMetaPrimaryAnnotation from |aftl_blob| into leaf->annotation.
- * Returns false if an error occurred during the parsing */
-static bool parse_annotation(SignedVBMetaPrimaryAnnotationLeaf* leaf,
- uint8_t** aftl_blob,
- uint8_t* blob_end) {
- VBMetaPrimaryAnnotation* annotation =
- (VBMetaPrimaryAnnotation*)avb_calloc(sizeof(VBMetaPrimaryAnnotation));
- if (!annotation) {
- avb_error("Failed to allocate annotation.\n");
- return false;
- }
- leaf->annotation = annotation;
-
- if (!read_u8(&(annotation->vbmeta_hash_size), aftl_blob, blob_end)) {
- avb_error("Unable to parse VBMeta hash size.\n");
- return false;
- }
- if (annotation->vbmeta_hash_size != AVB_AFTL_HASH_SIZE) {
- avb_error("Unexpected VBMeta hash size.\n");
- return false;
- }
- if (!read_mem(&(annotation->vbmeta_hash),
- annotation->vbmeta_hash_size,
- aftl_blob,
- blob_end)) {
- avb_error("Unable to parse VBMeta hash.\n");
- return false;
- }
-
- if (!read_u8(&(annotation->version_incremental_size), aftl_blob, blob_end)) {
- avb_error("Unable to parse version incremental size.\n");
- return false;
- }
- if (!read_mem(&(annotation->version_incremental),
- annotation->version_incremental_size,
- aftl_blob,
- blob_end)) {
- avb_error("Unable to parse version incremental.\n");
- return false;
- }
-
- if (!read_u8(
- &(annotation->manufacturer_key_hash_size), aftl_blob, blob_end)) {
- avb_error("Unable to parse manufacturer key hash size.\n");
- return false;
- }
- if (!read_mem(&(annotation->manufacturer_key_hash),
- annotation->manufacturer_key_hash_size,
- aftl_blob,
- blob_end)) {
- avb_error("Unable to parse manufacturer key hash.\n");
- return false;
- }
-
- if (!read_u16(&(annotation->description_size), aftl_blob, blob_end)) {
- avb_error("Unable to parse description size.\n");
- return false;
- }
- if (!read_mem(&(annotation->description),
- annotation->description_size,
- aftl_blob,
- blob_end)) {
- avb_error("Unable to parse description.\n");
- return false;
- }
- return true;
-}
-
-/* Allocates and populates a SignedVBMetaPrimaryAnnotationLeaf element in an
- AftlIcpEntry from a binary blob.
- The blob is expected to be pointing to the beginning of a
- serialized SignedVBMetaPrimaryAnnotationLeaf element of an AftlIcpEntry.
- The aftl_blob argument is updated to point to the area after the leaf. */
-static bool parse_annotation_leaf(AftlIcpEntry* icp_entry,
- uint8_t** aftl_blob) {
- SignedVBMetaPrimaryAnnotationLeaf* leaf;
- uint8_t* blob_end = *aftl_blob + icp_entry->annotation_leaf_size;
- if (*aftl_blob > blob_end) {
- return false;
- }
-
- leaf = (SignedVBMetaPrimaryAnnotationLeaf*)avb_calloc(
- sizeof(SignedVBMetaPrimaryAnnotationLeaf));
- if (!leaf) {
- avb_error("Failed to allocate for annotation leaf.\n");
- return false;
- }
- /* The leaf will be free'd within the free_aftl_icp_entry() */
- icp_entry->annotation_leaf = leaf;
- if (!read_u8(&(leaf->version), aftl_blob, blob_end)) {
- avb_error("Unable to parse version.\n");
- return false;
- }
- if (leaf->version != 1) {
- avb_error("Unexpected leaf version.\n");
- return false;
- }
- if (!read_u64(&(leaf->timestamp), aftl_blob, blob_end)) {
- avb_error("Unable to parse timestamp.\n");
- return false;
- }
- if (!read_u8(&(leaf->leaf_type), aftl_blob, blob_end)) {
- avb_error("Unable to parse version.\n");
- return false;
- }
- if (leaf->leaf_type != AVB_AFTL_SIGNED_VBMETA_PRIMARY_ANNOTATION_LEAF) {
- avb_error("Unexpected leaf type.\n");
- return false;
- }
- if (!parse_signature(leaf, aftl_blob, blob_end)) {
- avb_error("Unable to parse signature.\n");
- return false;
- }
- if (!parse_annotation(leaf, aftl_blob, blob_end)) {
- avb_error("Unable to parse annotation.\n");
- return false;
- }
- return true;
-}
-
-/* Allocates and populates an AftlIcpEntry from a binary blob.
- The blob is expected to be pointing to the beginning of a
- serialized AftlIcpEntry structure. */
-AftlIcpEntry* parse_icp_entry(uint8_t** aftl_blob, size_t* remaining_size) {
- AftlIcpEntry* icp_entry;
- uint8_t* blob_start = *aftl_blob;
- uint8_t* blob_end = *aftl_blob + *remaining_size;
- if (*aftl_blob > blob_end) {
- return NULL;
- }
-
- if (*remaining_size < AVB_AFTL_MIN_AFTL_ICP_ENTRY_SIZE) {
- avb_error("Invalid AftlImage\n");
- return NULL;
- }
-
- icp_entry = (AftlIcpEntry*)avb_calloc(sizeof(AftlIcpEntry));
- if (!icp_entry) {
- avb_error("Failure allocating AftlIcpEntry\n");
- return NULL;
- }
-
- /* Copy in the log server URL size field. */
- if (!read_u32(&(icp_entry->log_url_size), aftl_blob, blob_end)) {
- avb_error("Unable to parse log url size.\n");
- avb_free(icp_entry);
- return NULL;
- }
- if (icp_entry->log_url_size > AVB_AFTL_MAX_URL_SIZE) {
- avb_error("Invalid log URL size.\n");
- avb_free(icp_entry);
- return NULL;
- }
- /* Copy in the leaf index field. */
- if (!read_u64(&(icp_entry->leaf_index), aftl_blob, blob_end)) {
- avb_error("Unable to parse leaf_index.\n");
- avb_free(icp_entry);
- return NULL;
- }
- /* Copy in the TrillianLogRootDescriptor size field. */
- if (!read_u32(&(icp_entry->log_root_descriptor_size), aftl_blob, blob_end)) {
- avb_error("Unable to parse log root descriptor size.\n");
- avb_free(icp_entry);
- return NULL;
- }
- if (icp_entry->log_root_descriptor_size < AVB_AFTL_MIN_TLRD_SIZE ||
- icp_entry->log_root_descriptor_size > AVB_AFTL_MAX_TLRD_SIZE) {
- avb_error("Invalid TrillianLogRootDescriptor size.\n");
- avb_free(icp_entry);
- return NULL;
- }
-
- /* Copy in the annotation leaf size field. */
- if (!read_u32(&(icp_entry->annotation_leaf_size), aftl_blob, blob_end)) {
- avb_error("Unable to parse annotation leaf size.\n");
- avb_free(icp_entry);
- return NULL;
- }
- if (icp_entry->annotation_leaf_size == 0 ||
- icp_entry->annotation_leaf_size > AVB_AFTL_MAX_ANNOTATION_SIZE) {
- avb_error("Invalid annotation leaf size.\n");
- avb_free(icp_entry);
- return NULL;
- }
-
- /* Copy the log root signature size field. */
- if (!read_u16(&(icp_entry->log_root_sig_size), aftl_blob, blob_end)) {
- avb_error("Unable to parse log root signature size.\n");
- avb_free(icp_entry);
- return NULL;
- }
- if (icp_entry->log_root_sig_size != AVB_AFTL_SIGNATURE_SIZE) {
- avb_error("Invalid log root signature size.\n");
- avb_free(icp_entry);
- return NULL;
- }
- /* Copy the inclusion proof hash count field. */
- if (!read_u8(&(icp_entry->proof_hash_count), aftl_blob, blob_end)) {
- avb_error("Unable to parse proof hash count.\n");
- avb_free(icp_entry);
- return NULL;
- }
- /* Copy the inclusion proof size field. */
- if (!read_u32(&(icp_entry->inc_proof_size), aftl_blob, blob_end)) {
- avb_error("Unable to parse inclusion proof size.\n");
- avb_free(icp_entry);
- return NULL;
- }
- if ((icp_entry->inc_proof_size !=
- icp_entry->proof_hash_count * AVB_AFTL_HASH_SIZE) ||
- (icp_entry->inc_proof_size > AVB_AFTL_MAX_PROOF_SIZE)) {
- avb_error("Invalid inclusion proof size.\n");
- avb_free(icp_entry);
- return NULL;
- }
- /* Copy in the log server URL from the blob. */
- if (*aftl_blob + icp_entry->log_url_size < *aftl_blob ||
- *aftl_blob + icp_entry->log_url_size > blob_end) {
- avb_error("Invalid AftlImage.\n");
- avb_free(icp_entry);
- return NULL;
- }
- icp_entry->log_url = (uint8_t*)avb_calloc(icp_entry->log_url_size);
- if (!icp_entry->log_url) {
- avb_error("Failure to allocate URL.\n");
- free_aftl_icp_entry(icp_entry);
- return NULL;
- }
- avb_memcpy(icp_entry->log_url, *aftl_blob, icp_entry->log_url_size);
- *aftl_blob += icp_entry->log_url_size;
-
- /* Populate the TrillianLogRootDescriptor elements. */
- if (*aftl_blob + icp_entry->log_root_descriptor_size < *aftl_blob ||
- *aftl_blob + icp_entry->log_root_descriptor_size > blob_end) {
- avb_error("Invalid AftlImage.\n");
- free_aftl_icp_entry(icp_entry);
- return NULL;
- }
- icp_entry->log_root_descriptor_raw =
- (uint8_t*)avb_calloc(icp_entry->log_root_descriptor_size);
- if (!icp_entry->log_root_descriptor_raw) {
- avb_error("Failure to allocate log root descriptor.\n");
- free_aftl_icp_entry(icp_entry);
- return NULL;
- }
- avb_memcpy(icp_entry->log_root_descriptor_raw,
- *aftl_blob,
- icp_entry->log_root_descriptor_size);
- if (!parse_trillian_log_root_descriptor(
- icp_entry, aftl_blob, icp_entry->log_root_descriptor_size)) {
- free_aftl_icp_entry(icp_entry);
- return NULL;
- }
-
- /* Populate the annotation leaf. */
- if (*aftl_blob + icp_entry->annotation_leaf_size < *aftl_blob ||
- *aftl_blob + icp_entry->annotation_leaf_size > blob_end) {
- avb_error("Invalid AftlImage.\n");
- free_aftl_icp_entry(icp_entry);
- return NULL;
- }
- icp_entry->annotation_leaf_raw =
- (uint8_t*)avb_calloc(icp_entry->annotation_leaf_size);
- if (!icp_entry->annotation_leaf_raw) {
- avb_error("Failure to allocate annotation leaf.\n");
- free_aftl_icp_entry(icp_entry);
- return NULL;
- }
- avb_memcpy(icp_entry->annotation_leaf_raw,
- *aftl_blob,
- icp_entry->annotation_leaf_size);
- if (!parse_annotation_leaf(icp_entry, aftl_blob)) {
- free_aftl_icp_entry(icp_entry);
- return NULL;
- }
-
- /* Allocate and copy the log root signature from the blob. */
- if (*aftl_blob + icp_entry->log_root_sig_size < *aftl_blob ||
- *aftl_blob + icp_entry->log_root_sig_size > blob_end) {
- avb_error("Invalid AftlImage.\n");
- free_aftl_icp_entry(icp_entry);
- return NULL;
- }
- icp_entry->log_root_signature =
- (uint8_t*)avb_calloc(icp_entry->log_root_sig_size);
- if (!icp_entry->log_root_signature) {
- avb_error("Failure to allocate log root signature.\n");
- free_aftl_icp_entry(icp_entry);
- return NULL;
- }
- avb_memcpy(
- icp_entry->log_root_signature, *aftl_blob, icp_entry->log_root_sig_size);
- *aftl_blob += icp_entry->log_root_sig_size;
-
- /* Finally, copy the proof hash data from the blob to the AftlImage. */
- if (*aftl_blob + icp_entry->inc_proof_size < *aftl_blob ||
- *aftl_blob + icp_entry->inc_proof_size > blob_end) {
- avb_error("Invalid AftlImage.\n");
- free_aftl_icp_entry(icp_entry);
- return NULL;
- }
- icp_entry->proofs = avb_calloc(icp_entry->inc_proof_size);
- if (!icp_entry->proofs) {
- free_aftl_icp_entry(icp_entry);
- return NULL;
- }
- avb_memcpy(icp_entry->proofs, *aftl_blob, icp_entry->inc_proof_size);
- *aftl_blob += icp_entry->inc_proof_size;
-
- *remaining_size -= *aftl_blob - blob_start;
- return icp_entry;
-}
-
-/* Allocate and parse an AftlImage object out of binary data. */
-AftlImage* parse_aftl_image(uint8_t* aftl_blob, size_t aftl_blob_size) {
- AftlImage* image;
- AftlImageHeader* image_header;
- AftlIcpEntry* entry;
- size_t image_size;
- size_t i;
- size_t remaining_size;
-
- /* Ensure the blob is at least large enough for an AftlImageHeader */
- if (aftl_blob_size < sizeof(AftlImageHeader)) {
- avb_error("Invalid image header.\n");
- return NULL;
- }
- image_header = (AftlImageHeader*)aftl_blob;
- /* Check for the magic value for an AftlImageHeader. */
- if (image_header->magic != AVB_AFTL_MAGIC) {
- avb_error("Invalid magic number\n");
- return NULL;
- }
- /* Extract the size out of the header. */
- image_size = avb_be32toh(image_header->image_size);
- if (image_size < sizeof(AftlImageHeader) ||
- image_size > AVB_AFTL_MAX_AFTL_IMAGE_SIZE) {
- avb_error("Invalid image size.\n");
- return NULL;
- }
- image = (AftlImage*)avb_calloc(sizeof(AftlImage));
- if (!image) {
- avb_error("Failed allocation for AftlImage.\n");
- return NULL;
- }
- /* Copy the header bytes directly from the aftl_blob. */
- avb_memcpy(&(image->header), aftl_blob, sizeof(AftlImageHeader));
- /* Fix endianness. */
- image->header.required_icp_version_major =
- avb_be32toh(image->header.required_icp_version_major);
- image->header.required_icp_version_minor =
- avb_be32toh(image->header.required_icp_version_minor);
- image->header.image_size = avb_be32toh(image->header.image_size);
- image->header.icp_count = avb_be16toh(image->header.icp_count);
- /* Allocate memory for the entry array */
- image->entries = (AftlIcpEntry**)avb_calloc(sizeof(AftlIcpEntry*) *
- image->header.icp_count);
- if (!image->entries) {
- avb_error("Failed allocation for AftlIcpEntry array.\n");
- avb_free(image);
- return NULL;
- }
-
- /* Jump past the header and parse out each AftlIcpEntry. */
- aftl_blob += sizeof(AftlImageHeader);
- remaining_size = aftl_blob_size - sizeof(AftlImageHeader);
- for (i = 0; i < image->header.icp_count && remaining_size > 0; i++) {
- entry = parse_icp_entry(&aftl_blob, &remaining_size);
- if (!entry) {
- free_aftl_image(image);
- return NULL;
- }
- image->entries[i] = entry;
- }
-
- return image;
-}
-
-/* Free an AftlIcpEntry and each allocated sub-element. */
-void free_aftl_icp_entry(AftlIcpEntry* icp_entry) {
- /* Ensure the AftlIcpEntry exists before attempting to free it. */
- if (icp_entry) {
- /* Free the log_url and log_root_signature elements if they exist. */
- if (icp_entry->log_url) avb_free(icp_entry->log_url);
- if (icp_entry->log_root_signature) avb_free(icp_entry->log_root_signature);
- /* Free the annotation elements if they exist. */
- if (icp_entry->annotation_leaf) {
- if (icp_entry->annotation_leaf->signature) {
- if (icp_entry->annotation_leaf->signature->signature) {
- avb_free(icp_entry->annotation_leaf->signature->signature);
- }
- avb_free(icp_entry->annotation_leaf->signature);
- }
- if (icp_entry->annotation_leaf->annotation) {
- if (icp_entry->annotation_leaf->annotation->vbmeta_hash)
- avb_free(icp_entry->annotation_leaf->annotation->vbmeta_hash);
- if (icp_entry->annotation_leaf->annotation->version_incremental)
- avb_free(icp_entry->annotation_leaf->annotation->version_incremental);
- if (icp_entry->annotation_leaf->annotation->manufacturer_key_hash)
- avb_free(
- icp_entry->annotation_leaf->annotation->manufacturer_key_hash);
- if (icp_entry->annotation_leaf->annotation->description)
- avb_free(icp_entry->annotation_leaf->annotation->description);
- avb_free(icp_entry->annotation_leaf->annotation);
- }
- avb_free(icp_entry->annotation_leaf);
- }
- if (icp_entry->annotation_leaf_raw)
- avb_free(icp_entry->annotation_leaf_raw);
- /* Free the TrillianLogRoot elements if they exist. */
- if (icp_entry->log_root_descriptor.metadata)
- avb_free(icp_entry->log_root_descriptor.metadata);
- if (icp_entry->log_root_descriptor.root_hash)
- avb_free(icp_entry->log_root_descriptor.root_hash);
- if (icp_entry->log_root_descriptor_raw)
- avb_free(icp_entry->log_root_descriptor_raw);
- if (icp_entry->proofs) avb_free(icp_entry->proofs);
- /* Finally, free the AftlIcpEntry. */
- avb_free(icp_entry);
- }
-}
-
-/* Free the AftlImage and each allocated sub-element. */
-void free_aftl_image(AftlImage* image) {
- size_t i;
-
- /* Ensure the descriptor exists before attempting to free it. */
- if (!image) {
- return;
- }
- /* Free the entry array. */
- if (image->entries) {
- /* Walk through each entry, freeing each one. */
- for (i = 0; i < image->header.icp_count; i++) {
- if (image->entries[i]) {
- free_aftl_icp_entry(image->entries[i]);
- }
- }
- avb_free(image->entries);
- }
- avb_free(image);
-}
diff --git a/libavb_aftl/avb_aftl_util.h b/libavb_aftl/avb_aftl_util.h
deleted file mode 100644
index db222c3..0000000
--- a/libavb_aftl/avb_aftl_util.h
+++ /dev/null
@@ -1,121 +0,0 @@
-/*
- * Copyright (C) 2020 The Android Open Source Project
- *
- * Permission is hereby granted, free of charge, to any person
- * obtaining a copy of this software and associated documentation
- * files (the "Software"), to deal in the Software without
- * restriction, including without limitation the rights to use, copy,
- * modify, merge, publish, distribute, sublicense, and/or sell copies
- * of the Software, and to permit persons to whom the Software is
- * furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be
- * included in all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
- * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
- * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
- * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
- * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
- * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
- * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
- * SOFTWARE.
- */
-
-#ifdef AVB_INSIDE_LIBAVB_AFTL_H
-#error "You can't include avb_aftl_util.h in the public header libavb_aftl.h."
-#endif
-
-#ifndef AVB_COMPILATION
-#error "Never include this file, it may only be used from internal avb code."
-#endif
-
-#ifndef AVB_AFTL_UTIL_H_
-#define AVB_AFTL_UTIL_H_
-
-#include "avb_aftl_types.h"
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-#define AVB_AFTL_MAGIC 0x4c544641
-#define avb_aftl_member_size(type, member) sizeof(((type*)0)->member)
-
-/* Performs a SHA256 hash operation on data. */
-bool avb_aftl_sha256(
- uint8_t* data, /* Data to be hashed. */
- uint64_t length, /* Size of data. */
- uint8_t hash[AVB_AFTL_HASH_SIZE]); /* Resulting SHA256 hash. */
-
-/* Calculates a SHA256 hash of the TrillianLogRootDescriptor in icp_entry. */
-bool avb_aftl_hash_log_root_descriptor(
- AftlIcpEntry* icp_entry, /* The icp_entry containing the descriptor. */
- uint8_t* hash); /* The resulting hash of the descriptor data. */
-
-/* RFC 6962 Hashing function for leaves of a Merkle tree. */
-bool avb_aftl_rfc6962_hash_leaf(
- uint8_t* leaf, /* The Merkle tree leaf data to be hashed. */
- uint64_t leaf_size, /* Size of the leaf data. */
- uint8_t* hash); /* Resulting RFC 6962 hash of the leaf data. */
-
-/* Computes an inner hash as detailed by https://tools.ietf.org/html/rfc6962. */
-bool avb_aftl_rfc6962_hash_children(
- uint8_t* left_child, /* The left child node data. */
- uint64_t left_child_size, /* Size of the left child node data. */
- uint8_t* right_child, /* The right child node data. */
- uint64_t right_child_size, /* Size of the right child node data. */
- uint8_t
- hash[AVB_AFTL_HASH_SIZE]); /* Resulting RFC 6962 hash of the children.*/
-
-/* Computes a subtree hash along the left-side tree border. */
-bool avb_aftl_chain_border_right(
- uint8_t* seed, /* Data containing the starting hash. */
- uint64_t seed_size, /* Size of the starting hash data. */
- uint8_t* proof, /* The hashes in the inclusion proof. */
- uint32_t proof_entry_count, /* Number of inclusion proof entries. */
- uint8_t* hash); /* Resulting subtree hash. */
-
-/* Computes a subtree hash on or below the tree's right border. */
-bool avb_aftl_chain_inner(
- uint8_t* seed, /* Data containing the starting hash. */
- uint64_t seed_size, /* Size of the starting hash data. */
- uint8_t* proof, /* The hashes in the inclusion proof. */
- uint32_t proof_entry_count, /* Number of inclusion proof entries. */
- uint64_t leaf_index, /* The current Merkle tree leaf index. */
- uint8_t* hash); /* Resulting subtree hash. */
-
-/* Counts leading zeros. Used in Merkle tree hash validation .*/
-unsigned int avb_aftl_count_leading_zeros(
- uint64_t val); /* Value to count leading zeros of. */
-
-/* Calculates the expected Merkle tree hash. */
-bool avb_aftl_root_from_icp(
- uint64_t leaf_index, /* The leaf index in the Merkle tree.*/
- uint64_t tree_size, /* The size of the Merkle tree. */
- uint8_t proof[][AVB_AFTL_HASH_SIZE], /* Inclusion proof hash data. */
- uint32_t proof_entry_count, /* Number of inclusion proof hashes. */
- uint8_t* leaf_hash, /* The leaf hash to prove inclusion of. */
- uint64_t leaf_hash_size, /* Size of the leaf hash. */
- uint8_t* root_hash); /* The resulting tree root hash. */
-
-/* Allocates and populates an AftlImage from a binary blob. */
-AftlImage* parse_aftl_image(uint8_t* aftl_blob, size_t aftl_blob_size);
-
-/* Allocates and populates an AftlIcpEntry and all sub-fields from
- a binary blob. It is assumed that the blob points to an AftlIcpEntry. */
-AftlIcpEntry* parse_icp_entry(uint8_t** aftl_blob, size_t* remaining_size);
-
-/* Frees an AftlIcpEntry and all sub-fields that were previously
- allocated by a call to parse_icp_entry. */
-void free_aftl_icp_entry(AftlIcpEntry* aftl_icp_entry);
-
-/* Frees an AftlImage and all sub-fields that were previously
- allocated by a call to parse_aftl_image. */
-void free_aftl_image(AftlImage* image);
-
-#ifdef __cplusplus
-}
-#endif
-
-#endif /* AVB_AFTL_UTIL_H_ */
diff --git a/libavb_aftl/avb_aftl_validate.c b/libavb_aftl/avb_aftl_validate.c
deleted file mode 100644
index 2d76b2f..0000000
--- a/libavb_aftl/avb_aftl_validate.c
+++ /dev/null
@@ -1,128 +0,0 @@
-/*
- * Copyright (C) 2020 The Android Open Source Project
- *
- * Permission is hereby granted, free of charge, to any person
- * obtaining a copy of this software and associated documentation
- * files (the "Software"), to deal in the Software without
- * restriction, including without limitation the rights to use, copy,
- * modify, merge, publish, distribute, sublicense, and/or sell copies
- * of the Software, and to permit persons to whom the Software is
- * furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be
- * included in all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
- * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
- * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
- * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
- * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
- * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
- * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
- * SOFTWARE.
- */
-
-#include <libavb/avb_crypto.h>
-#include <libavb/avb_rsa.h>
-#include <libavb/avb_sha.h>
-#include <libavb/avb_util.h>
-
-#include "avb_aftl_types.h"
-#include "avb_aftl_util.h"
-#include "avb_aftl_validate.h"
-
-/* Verifies that the logged VBMeta hash matches the one on device. */
-bool avb_aftl_verify_vbmeta_hash(uint8_t* vbmeta,
- size_t vbmeta_size,
- AftlIcpEntry* icp_entry) {
- uint8_t vbmeta_hash[AVB_AFTL_HASH_SIZE];
-
- avb_assert(vbmeta != NULL && icp_entry != NULL);
- if (!avb_aftl_sha256(vbmeta, vbmeta_size, vbmeta_hash)) return false;
-
- /* Only SHA256 hashes are currently supported. If the vbmeta hash
- size is not AVB_AFTL_HASH_SIZE, return false. */
- if (icp_entry->annotation_leaf->annotation->vbmeta_hash_size !=
- AVB_AFTL_HASH_SIZE) {
- avb_error("Invalid VBMeta hash size.\n");
- return false;
- }
-
- /* Return whether the calculated VBMeta hash matches the stored one. */
- return avb_safe_memcmp(vbmeta_hash,
- icp_entry->annotation_leaf->annotation->vbmeta_hash,
- AVB_AFTL_HASH_SIZE) == 0;
-}
-
-/* Verifies the Merkle tree root hash. */
-bool avb_aftl_verify_icp_root_hash(AftlIcpEntry* icp_entry) {
- uint8_t leaf_hash[AVB_AFTL_HASH_SIZE];
- uint8_t result_hash[AVB_AFTL_HASH_SIZE];
-
- avb_assert(icp_entry != NULL);
- /* Calculate the RFC 6962 hash of the seed entry. */
- if (!avb_aftl_rfc6962_hash_leaf(icp_entry->annotation_leaf_raw,
- icp_entry->annotation_leaf_size,
- leaf_hash)) {
- return false;
- }
- /* Calculate the Merkle tree's root hash. */
- if (!avb_aftl_root_from_icp(icp_entry->leaf_index,
- icp_entry->log_root_descriptor.tree_size,
- icp_entry->proofs,
- icp_entry->proof_hash_count,
- leaf_hash,
- AVB_AFTL_HASH_SIZE,
- result_hash))
- return false;
-
- /* Return whether the calculated root hash matches the stored one. */
- return (avb_safe_memcmp(result_hash,
- icp_entry->log_root_descriptor.root_hash,
- AVB_AFTL_HASH_SIZE) == 0);
-}
-
-/* Verifies the log root signature for the transparency log submission. */
-bool avb_aftl_verify_entry_signature(const uint8_t* key,
- size_t key_num_bytes,
- AftlIcpEntry* icp_entry) {
- uint8_t* sig;
- size_t sig_num_bytes;
- uint8_t log_root_hash[AVB_AFTL_HASH_SIZE];
- size_t log_root_hash_num_bytes;
- const AvbAlgorithmData* algorithm_data;
-
- avb_assert(key != NULL && icp_entry != NULL);
-
- /* Extract the log root signature from the AftlIcpEntry. */
- sig = icp_entry->log_root_signature;
- if (sig == NULL) {
- avb_error("Invalid log root signature.\n");
- return false;
- }
- sig_num_bytes = icp_entry->log_root_sig_size;
- log_root_hash_num_bytes = AVB_AFTL_HASH_SIZE;
-
- /* Calculate the SHA256 of the TrillianLogRootDescriptor. */
- if (!avb_aftl_sha256(icp_entry->log_root_descriptor_raw,
- icp_entry->log_root_descriptor_size,
- log_root_hash))
- return false;
-
- /* algorithm_data is used to calculate the padding for signature verification.
- */
- algorithm_data = avb_get_algorithm_data(AVB_ALGORITHM_TYPE_SHA256_RSA4096);
- if (algorithm_data == NULL) {
- avb_error("Failed to get algorithm data.\n");
- return false;
- }
-
- return avb_rsa_verify(key,
- key_num_bytes,
- sig,
- sig_num_bytes,
- log_root_hash,
- log_root_hash_num_bytes,
- algorithm_data->padding,
- algorithm_data->padding_len);
-}
diff --git a/libavb_aftl/avb_aftl_validate.h b/libavb_aftl/avb_aftl_validate.h
deleted file mode 100644
index 4a1ecc8..0000000
--- a/libavb_aftl/avb_aftl_validate.h
+++ /dev/null
@@ -1,59 +0,0 @@
-/*
- * Copyright (C) 2020 The Android Open Source Project
- *
- * Permission is hereby granted, free of charge, to any person
- * obtaining a copy of this software and associated documentation
- * files (the "Software"), to deal in the Software without
- * restriction, including without limitation the rights to use, copy,
- * modify, merge, publish, distribute, sublicense, and/or sell copies
- * of the Software, and to permit persons to whom the Software is
- * furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be
- * included in all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
- * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
- * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
- * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
- * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
- * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
- * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
- * SOFTWARE.
- */
-
-#if !defined(AVB_INSIDE_LIBAVB_AFTL_H) && !defined(AVB_COMPILATION)
-#error "Never include this file directly, include libavb_aftl/libavb_aftl.h."
-#endif
-
-#ifndef AVB_AFTL_VALIDATE_H_
-#define AVB_AFTL_VALIDATE_H_
-
-#include <libavb/libavb.h>
-#include "avb_aftl_types.h"
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-/* Verifies that the logged vbmeta hash matches the one on device. */
-bool avb_aftl_verify_vbmeta_hash(
- uint8_t* vbmeta, /* Buffer containing the vbmeta data. */
- size_t vbmeta_size, /* Size of the vbmeta buffer. */
- AftlIcpEntry* icp_entry); /* Pointer to the AftlIcpEntry to verify. */
-
-/* Verifies the Merkle tree root hash. */
-bool avb_aftl_verify_icp_root_hash(
- AftlIcpEntry* icp_entry); /* Pointer to the AftlIcpEntry to verify. */
-
-/* Verifies the log root signature for the transparency log submission. */
-bool avb_aftl_verify_entry_signature(
- const uint8_t* key, /* Transparency log public key data. */
- size_t key_num_bytes, /* Size of the key data. */
- AftlIcpEntry* icp_entry); /* Pointer to the AftlIcpEntry to verify. */
-
-#ifdef __cplusplus
-}
-#endif
-
-#endif /* AVB_AFTL_VALIDATE_H_ */
diff --git a/libavb_aftl/avb_aftl_verify.c b/libavb_aftl/avb_aftl_verify.c
deleted file mode 100644
index b35e417..0000000
--- a/libavb_aftl/avb_aftl_verify.c
+++ /dev/null
@@ -1,190 +0,0 @@
-/*
- * Copyright (C) 2020 The Android Open Source Project
- *
- * Permission is hereby granted, free of charge, to any person
- * obtaining a copy of this software and associated documentation
- * files (the "Software"), to deal in the Software without
- * restriction, including without limitation the rights to use, copy,
- * modify, merge, publish, distribute, sublicense, and/or sell copies
- * of the Software, and to permit persons to whom the Software is
- * furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be
- * included in all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
- * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
- * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
- * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
- * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
- * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
- * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
- * SOFTWARE.
- */
-
-#include "libavb_aftl/avb_aftl_verify.h"
-
-#include <libavb/avb_cmdline.h>
-#include <libavb/avb_slot_verify.h>
-#include <libavb/avb_util.h>
-
-#include "libavb_aftl/avb_aftl_types.h"
-#include "libavb_aftl/avb_aftl_util.h"
-#include "libavb_aftl/avb_aftl_validate.h"
-
-/* Read the vbmeta partition, after the AvbVBMetaImageHeader structure, to find
- * the AftlImage.
- */
-static AftlSlotVerifyResult avb_aftl_find_aftl_image(AvbOps* ops,
- const char* part_name,
- size_t vbmeta_size,
- uint8_t* out_image_buf,
- size_t* out_image_size) {
- AvbIOResult io_ret;
-
- avb_assert(vbmeta_size <= AVB_AFTL_MAX_AFTL_IMAGE_SIZE);
- io_ret = ops->read_from_partition(ops,
- part_name,
- vbmeta_size /* offset */,
- AVB_AFTL_MAX_AFTL_IMAGE_SIZE - vbmeta_size,
- out_image_buf,
- out_image_size);
- switch (io_ret) {
- case AVB_IO_RESULT_OK:
- break;
- case AVB_IO_RESULT_ERROR_OOM:
- return AFTL_SLOT_VERIFY_RESULT_ERROR_OOM;
- case AVB_IO_RESULT_ERROR_RANGE_OUTSIDE_PARTITION:
- case AVB_IO_RESULT_ERROR_NO_SUCH_PARTITION:
- return AFTL_SLOT_VERIFY_RESULT_ERROR_IMAGE_NOT_FOUND;
- default:
- avb_errorv(
- part_name, ": Error loading AftlImage from partition.\n", NULL);
- return AFTL_SLOT_VERIFY_RESULT_ERROR_IO;
- }
-
- if (*out_image_size < 4 || (out_image_buf[0] != 'A') ||
- (out_image_buf[1] != 'F') || (out_image_buf[2] != 'T') ||
- (out_image_buf[3] != 'L')) {
- avb_errorv(part_name, ": Unexpected AftlImage magic.\n", NULL);
- return AFTL_SLOT_VERIFY_RESULT_ERROR_IMAGE_NOT_FOUND;
- }
-
- return AFTL_SLOT_VERIFY_RESULT_OK;
-}
-
-/* Performs the three validation steps for an AFTL image:
- 1. Ensure the vbmeta image hash matches that in the image.
- 2. Ensure the root hash of the Merkle tree matches that in the image.
- 3. Verify the signature using the transparency log public key.
-*/
-static AftlSlotVerifyResult avb_aftl_verify_image(uint8_t* cur_vbmeta_data,
- size_t cur_vbmeta_size,
- uint8_t* aftl_blob,
- size_t aftl_size,
- uint8_t* key_bytes,
- size_t key_num_bytes) {
- size_t i;
- AftlImage* image;
- AftlSlotVerifyResult result = AFTL_SLOT_VERIFY_RESULT_ERROR_VERIFICATION;
-
- /* Attempt to parse the AftlImage pointed to by aftl_blob. */
- image = parse_aftl_image(aftl_blob, aftl_size);
- if (!image) {
- return AFTL_SLOT_VERIFY_RESULT_ERROR_INVALID_IMAGE;
- }
-
- /* Now that a valid AftlImage has been parsed, attempt to verify
- the inclusion proof(s) in three steps. */
- for (i = 0; i < image->header.icp_count; i++) {
- /* 1. Ensure that the vbmeta hash stored in the AftlIcpEntry matches
- the one that represents the partition. */
- if (!avb_aftl_verify_vbmeta_hash(
- cur_vbmeta_data, cur_vbmeta_size, image->entries[i])) {
- avb_error("AFTL vbmeta hash verification failed.\n");
- result = AFTL_SLOT_VERIFY_RESULT_ERROR_VBMETA_HASH_MISMATCH;
- break;
- }
- /* 2. Ensure that the root hash of the Merkle tree representing
- the transparency log entry matches the one stored in the
- AftlIcpEntry. */
- if (!avb_aftl_verify_icp_root_hash(image->entries[i])) {
- avb_error("AFTL root hash verification failed.\n");
- result = AFTL_SLOT_VERIFY_RESULT_ERROR_TREE_HASH_MISMATCH;
- break;
- }
- /* 3. Verify the signature using the transparency log public
- key stored on device. */
- if (!avb_aftl_verify_entry_signature(
- key_bytes, key_num_bytes, image->entries[i])) {
- avb_error("AFTL signature verification failed on entry.\n");
- result = AFTL_SLOT_VERIFY_RESULT_ERROR_INVALID_PROOF_SIGNATURE;
- break;
- }
- result = AFTL_SLOT_VERIFY_RESULT_OK;
- }
- free_aftl_image(image);
- return result;
-}
-
-AftlSlotVerifyResult aftl_slot_verify(AvbOps* ops,
- AvbSlotVerifyData* slot_verify_data,
- uint8_t* key_bytes,
- size_t key_size) {
- size_t i;
- size_t aftl_image_size;
- size_t vbmeta_size;
- uint8_t* current_aftl_blob;
- char part_name[AVB_PART_NAME_MAX_SIZE];
- char* pname;
- AftlSlotVerifyResult ret = AFTL_SLOT_VERIFY_RESULT_ERROR_VERIFICATION;
-
- avb_assert(slot_verify_data != NULL);
- avb_assert(key_bytes != NULL);
- avb_assert(key_size == AVB_AFTL_PUB_KEY_SIZE);
- if (slot_verify_data->vbmeta_images == NULL) {
- return AFTL_SLOT_VERIFY_RESULT_ERROR_INVALID_ARGUMENT;
- }
-
- current_aftl_blob = avb_malloc(AVB_AFTL_MAX_AFTL_IMAGE_SIZE);
- if (current_aftl_blob == NULL) {
- return AFTL_SLOT_VERIFY_RESULT_ERROR_OOM;
- }
-
- /* Walk through each vbmeta blob in the AvbSlotVerifyData struct. */
- for (i = 0; i < slot_verify_data->num_vbmeta_images; i++) {
- /* Rebuild partition name, appending the suffix */
- pname = slot_verify_data->vbmeta_images[i].partition_name;
- if (!avb_str_concat(part_name,
- sizeof part_name,
- (const char*)pname,
- avb_strlen(pname),
- slot_verify_data->ab_suffix,
- avb_strlen(slot_verify_data->ab_suffix))) {
- avb_error("Partition name and suffix does not fit.\n");
- ret = AFTL_SLOT_VERIFY_RESULT_ERROR_VERIFICATION;
- break;
- }
-
- /* Use the partition info to find the AftlImage */
- vbmeta_size = slot_verify_data->vbmeta_images[i].vbmeta_size;
- ret = avb_aftl_find_aftl_image(
- ops, part_name, vbmeta_size, current_aftl_blob, &aftl_image_size);
- if (ret != AFTL_SLOT_VERIFY_RESULT_OK) {
- avb_errorv(part_name, ": Unable to find the AftlImage.\n", NULL);
- break;
- }
-
- /* Validate the AFTL image in the vbmeta image. */
- ret = avb_aftl_verify_image(slot_verify_data->vbmeta_images[i].vbmeta_data,
- vbmeta_size,
- current_aftl_blob,
- aftl_image_size,
- key_bytes,
- key_size);
- if (ret != AVB_SLOT_VERIFY_RESULT_OK) break;
- }
-
- avb_free(current_aftl_blob);
- return ret;
-}
diff --git a/libavb_aftl/avb_aftl_verify.h b/libavb_aftl/avb_aftl_verify.h
deleted file mode 100644
index 7c6799f..0000000
--- a/libavb_aftl/avb_aftl_verify.h
+++ /dev/null
@@ -1,106 +0,0 @@
-/*
- * Copyright (C) 2020 The Android Open Source Project
- *
- * Permission is hereby granted, free of charge, to any person
- * obtaining a copy of this software and associated documentation
- * files (the "Software"), to deal in the Software without
- * restriction, including without limitation the rights to use, copy,
- * modify, merge, publish, distribute, sublicense, and/or sell copies
- * of the Software, and to permit persons to whom the Software is
- * furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be
- * included in all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
- * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
- * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
- * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
- * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
- * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
- * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
- * SOFTWARE.
- */
-#if !defined(AVB_INSIDE_LIBAVB_AFTL_H) && !defined(AVB_COMPILATION)
-#error "Never include this file directly, include libavb_aftl.h instead."
-#endif
-
-#ifndef AVB_AFTL_VERIFY_H_
-#define AVB_AFTL_VERIFY_H_
-
-#include <libavb/libavb.h>
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-typedef enum {
- // When the verification succeeded.
- AFTL_SLOT_VERIFY_RESULT_OK,
-
- // If at some point during the verification, a memory allocation failed. This
- // could be the case when handling a large number of log keys or inclusion
- // proofs.
- AFTL_SLOT_VERIFY_RESULT_ERROR_OOM,
-
- // If at some point during the verification, we were not able to access some
- // devices. This can be the case when reading the AftlImage from the
- // partition.
- AFTL_SLOT_VERIFY_RESULT_ERROR_IO,
-
- // The VBMeta hash in the inclusion proof is not matching the VBMeta image
- // hash.
- AFTL_SLOT_VERIFY_RESULT_ERROR_VBMETA_HASH_MISMATCH,
-
- // The root hash of the reconstructed tree do not match the value contained in
- // the inclusion proof.
- AFTL_SLOT_VERIFY_RESULT_ERROR_TREE_HASH_MISMATCH,
-
- // The inclusion proof signature cannot be verified by the given key.
- AFTL_SLOT_VERIFY_RESULT_ERROR_INVALID_PROOF_SIGNATURE,
-
- // A generic error occurred during the verification.
- AFTL_SLOT_VERIFY_RESULT_ERROR_VERIFICATION,
-
- // At least one of the VBMetas did not have an AftlImage attached.
- AFTL_SLOT_VERIFY_RESULT_ERROR_IMAGE_NOT_FOUND,
-
- // Some content of one of the AFTLImages was found corrupted.
- AFTL_SLOT_VERIFY_RESULT_ERROR_INVALID_IMAGE,
-
- // Returned if the caller passed invalid parameters, for example if the prior
- // call to avb_slot_verify failed.
- AFTL_SLOT_VERIFY_RESULT_ERROR_INVALID_ARGUMENT
-
-} AftlSlotVerifyResult;
-
-/* The entry point of AFTL validation. It uses the AvbSlotVerifyData structure,
- * |slot_verify_data|, generated by a prior call to the avb_slot_verify
- * function, and a transparency log key to validate the inclusion proof(s)
- * attached to each VBMeta images.
- *
- * The caller is responsible for ensuring that the previous call to
- * avb_slot_verify succeeded. If |slot_verify_data| is incomplete or NULL,
- * AFTL_SLOT_VERIFY_RESULT_ERROR_INVALID_ARGUMENT will be returned.
- *
- * The AftlImage structure is located after the VBMetaImage structure. Uses
- * |ops| to read the partition where the VBMeta was loaded from.
- *
- * For each inclusion proof found, the following three validation steps are
- * performed:
- * 1. Match the VBMeta image hash with the hash in the tree leaf.
- * 2. Match the root hash of the Merkle tree with the hash in the proof.
- * 3. Verify the signature of the proof using the transparency log public key.
- * See the definition of AftlSlotVerifyResult for all the possible return
- * values.
- */
-
-AftlSlotVerifyResult aftl_slot_verify(AvbOps* ops,
- AvbSlotVerifyData* slot_verify_data,
- uint8_t* key_bytes,
- size_t key_size);
-#ifdef __cplusplus
-}
-#endif
-
-#endif /* AVB_AFTL_VERIFY_H_ */
diff --git a/libavb_aftl/avb_ops_aftl.h b/libavb_aftl/avb_ops_aftl.h
deleted file mode 100644
index a2f5577..0000000
--- a/libavb_aftl/avb_ops_aftl.h
+++ /dev/null
@@ -1,52 +0,0 @@
-/*
- * Copyright (C) 2020 The Android Open Source Project
- *
- * Permission is hereby granted, free of charge, to any person
- * obtaining a copy of this software and associated documentation
- * files (the "Software"), to deal in the Software without
- * restriction, including without limitation the rights to use, copy,
- * modify, merge, publish, distribute, sublicense, and/or sell copies
- * of the Software, and to permit persons to whom the Software is
- * furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be
- * included in all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
- * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
- * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
- * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
- * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
- * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
- * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
- * SOFTWARE.
- */
-
-#if !defined(AVB_INSIDE_LIBAVB_AFTL_H) && !defined(AVB_COMPILATION)
-#error "Never include this file directly, include libavb_aftl/libavb_aftl.h."
-#endif
-
-#ifndef AVB_AFTL_OPS_H_
-#define AVB_AFTL_OPS_H_
-
-#include <libavb/libavb.h>
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-struct AvbAftlOps;
-typedef struct AvbAftlOps AvbAftlOps;
-
-/* An extension to AvbOps required by the new AFTL validation flow.
- TODO(danielaustin): update the AFTL readme link once it is submitted. */
-struct AvbAftlOps {
- /* Operations from libavb. */
- AvbOps* ops;
-};
-
-#ifdef __cplusplus
-}
-#endif
-
-#endif /* AVB_AFTL_OPS_H_ */
diff --git a/libavb_aftl/libavb_aftl.h b/libavb_aftl/libavb_aftl.h
deleted file mode 100644
index dbf0146..0000000
--- a/libavb_aftl/libavb_aftl.h
+++ /dev/null
@@ -1,38 +0,0 @@
-/*
- * Copyright (C) 2020 The Android Open Source Project
- *
- * Permission is hereby granted, free of charge, to any person
- * obtaining a copy of this software and associated documentation
- * files (the "Software"), to deal in the Software without
- * restriction, including without limitation the rights to use, copy,
- * modify, merge, publish, distribute, sublicense, and/or sell copies
- * of the Software, and to permit persons to whom the Software is
- * furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be
- * included in all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
- * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
- * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
- * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
- * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
- * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
- * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
- * SOFTWARE.
- */
-
-#ifndef LIBAVB_AFTL_H_
-#define LIBAVB_AFTL_H_
-
-
-/* The AVB_INSIDE_LIBAVB_AFTL_H preprocessor symbol is used to enforce
- * library users to include only this file. All public interfaces, and
- * only public interfaces, must be included here.
- */
-
-#define AVB_INSIDE_LIBAVB_AFTL_H
-#include "avb_aftl_verify.h"
-#undef AVB_INSIDE_LIBAVB_AFTL_H
-
-#endif /* LIBAVB_AFTL_H_ */
diff --git a/proto/README.md b/proto/README.md
deleted file mode 100644
index ee64b01..0000000
--- a/proto/README.md
+++ /dev/null
@@ -1,22 +0,0 @@
-# Android Firmware Transparency Log Proto Definitions
----
-
-This directory contains the proto definitions required to communicate with an
-AFTL server. The original repos and purpose for each proto file are as
-follows:
-
-* api.proto
- 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
- For trillian.proto, contains the DigitallySigned message used by Tree and
- SignedEntryTimestamp.
-* trillian.proto
- From https://github.com/google/trillian
- Dependency of aftl.proto
- For aftl.proto, contains message definitions for SignedLogRoot.
diff --git a/proto/__init__.py b/proto/__init__.py
deleted file mode 100644
index e69de29..0000000
--- a/proto/__init__.py
+++ /dev/null
diff --git a/proto/api.proto b/proto/api.proto
deleted file mode 100644
index e22ae47..0000000
--- a/proto/api.proto
+++ /dev/null
@@ -1,94 +0,0 @@
-// 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.
-// 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";
-
-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 64kB.
- bytes vbmeta = 1;
-
- // 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 AddVBMetaResponse {
- // Inclusion proof and the leaf that was added to the log, which contains
- // 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 annotation_proof = 1;
- bytes annotation_leaf = 2;
-
- // Inclusion proof and leaf that was added to the log, which contains the full
- // vbmeta partition.
- // These fields are NOT required for validation but can still be recorded by a
- // vendor to prove that the complete VBMeta was submitted.
- InclusionProof vbmeta_proof = 3;
- bytes vbmeta_leaf = 4;
-}
-
-message AnnotateVBMetaWithBuildRequest {
- // Serialized SignedVBMetaBuildAnnotation. This annotation contains the hash
- // of the full build image. See types/types.go.
- bytes signed_vbmeta_build_annotation = 1;
-
- // 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;
-
- // Origin location of image. It is used to get a copy of the binary image
- // from another server (e.g., Google Cloud Storage).
- string origin_url = 3;
-}
-
-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 annotation_proof = 1;
- bytes annotation_leaf = 2;
-}
-
-service AFTLog {
-
- // Insert a new VBMeta structure into the log.
- // This request will effectively create 2 log entries:
- // - VBMeta itself
- // - Vendor annotations, which includes a reference to the VBMeta.
- rpc AddVBMeta(AddVBMetaRequest) returns (AddVBMetaResponse) {}
-
- // Upload (or copy) the complete firmware image.
- rpc AnnotateVBMetaWithBuild(stream AnnotateVBMetaWithBuildResponse) returns (AnnotateVBMetaWithBuildResponse) {}
-
- // TODO(tweek): GetProofByHash, GetSthConsistency, GetEntries, GetRootKeys
-}
diff --git a/proto/api_pb2.py b/proto/api_pb2.py
deleted file mode 100644
index fbe3bab..0000000
--- a/proto/api_pb2.py
+++ /dev/null
@@ -1,323 +0,0 @@
-# -*- coding: utf-8 -*-
-# Generated by the protocol buffer compiler. DO NOT EDIT!
-# source: api.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
-
-
-DESCRIPTOR = _descriptor.FileDescriptor(
- name='api.proto',
- package='aftl',
- syntax='proto3',
- serialized_options=_b('Z\005proto'),
- 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=[trillian__pb2.DESCRIPTOR,])
-
-
-
-
-_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=35,
- serialized_end=121,
-)
-
-
-_ADDVBMETAREQUEST = _descriptor.Descriptor(
- name='AddVBMetaRequest',
- full_name='aftl.AddVBMetaRequest',
- filename=None,
- file=DESCRIPTOR,
- containing_type=None,
- fields=[
- _descriptor.FieldDescriptor(
- 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='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.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.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,
- 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=202,
- serialized_end=359,
-)
-
-
-_ANNOTATEVBMETAWITHBUILDREQUEST = _descriptor.Descriptor(
- name='AnnotateVBMetaWithBuildRequest',
- full_name='aftl.AnnotateVBMetaWithBuildRequest',
- filename=None,
- file=DESCRIPTOR,
- containing_type=None,
- fields=[
- _descriptor.FieldDescriptor(
- 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.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.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,
- 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=361,
- serialized_end=474,
-)
-
-
-_ANNOTATEVBMETAWITHBUILDRESPONSE = _descriptor.Descriptor(
- name='AnnotateVBMetaWithBuildResponse',
- full_name='aftl.AnnotateVBMetaWithBuildResponse',
- filename=None,
- file=DESCRIPTOR,
- containing_type=None,
- fields=[
- _descriptor.FieldDescriptor(
- 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='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),
- ],
- extensions=[
- ],
- nested_types=[],
- enum_types=[
- ],
- serialized_options=None,
- is_extendable=False,
- syntax='proto3',
- extension_ranges=[],
- oneofs=[
- ],
- serialized_start=476,
- serialized_end=582,
-)
-
-_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)
-
-InclusionProof = _reflection.GeneratedProtocolMessageType('InclusionProof', (_message.Message,), {
- 'DESCRIPTOR' : _INCLUSIONPROOF,
- '__module__' : 'api_pb2'
- # @@protoc_insertion_point(class_scope:aftl.InclusionProof)
- })
-_sym_db.RegisterMessage(InclusionProof)
-
-AddVBMetaRequest = _reflection.GeneratedProtocolMessageType('AddVBMetaRequest', (_message.Message,), {
- 'DESCRIPTOR' : _ADDVBMETAREQUEST,
- '__module__' : 'api_pb2'
- # @@protoc_insertion_point(class_scope:aftl.AddVBMetaRequest)
- })
-_sym_db.RegisterMessage(AddVBMetaRequest)
-
-AddVBMetaResponse = _reflection.GeneratedProtocolMessageType('AddVBMetaResponse', (_message.Message,), {
- 'DESCRIPTOR' : _ADDVBMETARESPONSE,
- '__module__' : 'api_pb2'
- # @@protoc_insertion_point(class_scope:aftl.AddVBMetaResponse)
- })
-_sym_db.RegisterMessage(AddVBMetaResponse)
-
-AnnotateVBMetaWithBuildRequest = _reflection.GeneratedProtocolMessageType('AnnotateVBMetaWithBuildRequest', (_message.Message,), {
- 'DESCRIPTOR' : _ANNOTATEVBMETAWITHBUILDREQUEST,
- '__module__' : 'api_pb2'
- # @@protoc_insertion_point(class_scope:aftl.AnnotateVBMetaWithBuildRequest)
- })
-_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
-
-_AFTLOG = _descriptor.ServiceDescriptor(
- name='AFTLog',
- full_name='aftl.AFTLog',
- file=DESCRIPTOR,
- index=0,
- serialized_options=None,
- serialized_start=585,
- serialized_end=766,
- methods=[
- _descriptor.MethodDescriptor(
- name='AddVBMeta',
- full_name='aftl.AFTLog.AddVBMeta',
- index=0,
- containing_service=None,
- input_type=_ADDVBMETAREQUEST,
- output_type=_ADDVBMETARESPONSE,
- serialized_options=None,
- ),
- _descriptor.MethodDescriptor(
- name='AnnotateVBMetaWithBuild',
- full_name='aftl.AFTLog.AnnotateVBMetaWithBuild',
- index=1,
- containing_service=None,
- input_type=_ANNOTATEVBMETAWITHBUILDRESPONSE,
- output_type=_ANNOTATEVBMETAWITHBUILDRESPONSE,
- serialized_options=None,
- ),
-])
-_sym_db.RegisterServiceDescriptor(_AFTLOG)
-
-DESCRIPTOR.services_by_name['AFTLog'] = _AFTLOG
-
-# @@protoc_insertion_point(module_scope)
diff --git a/proto/api_pb2_grpc.py b/proto/api_pb2_grpc.py
deleted file mode 100644
index d487856..0000000
--- a/proto/api_pb2_grpc.py
+++ /dev/null
@@ -1,66 +0,0 @@
-# Generated by the gRPC Python protocol compiler plugin. DO NOT EDIT!
-import grpc
-
-import api_pb2 as api__pb2
-
-
-class AFTLogStub(object):
- # missing associated documentation comment in .proto file
- pass
-
- def __init__(self, channel):
- """Constructor.
-
- Args:
- channel: A grpc.Channel.
- """
- self.AddVBMeta = channel.unary_unary(
- '/aftl.AFTLog/AddVBMeta',
- request_serializer=api__pb2.AddVBMetaRequest.SerializeToString,
- response_deserializer=api__pb2.AddVBMetaResponse.FromString,
- )
- self.AnnotateVBMetaWithBuild = channel.stream_unary(
- '/aftl.AFTLog/AnnotateVBMetaWithBuild',
- request_serializer=api__pb2.AnnotateVBMetaWithBuildResponse.SerializeToString,
- response_deserializer=api__pb2.AnnotateVBMetaWithBuildResponse.FromString,
- )
-
-
-class AFTLogServicer(object):
- # missing associated documentation comment in .proto file
- pass
-
- 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, 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 AnnotateVBMetaWithBuild(self, request_iterator, context):
- """Upload (or copy) the complete firmware image.
- """
- context.set_code(grpc.StatusCode.UNIMPLEMENTED)
- context.set_details('Method not implemented!')
- raise NotImplementedError('Method not implemented!')
-
-
-def add_AFTLogServicer_to_server(servicer, server):
- rpc_method_handlers = {
- 'AddVBMeta': grpc.unary_unary_rpc_method_handler(
- servicer.AddVBMeta,
- request_deserializer=api__pb2.AddVBMetaRequest.FromString,
- response_serializer=api__pb2.AddVBMetaResponse.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(
- 'aftl.AFTLog', rpc_method_handlers)
- server.add_generic_rpc_handlers((generic_handler,))
diff --git a/proto/crypto/__init__.py b/proto/crypto/__init__.py
deleted file mode 100644
index e69de29..0000000
--- a/proto/crypto/__init__.py
+++ /dev/null
diff --git a/proto/crypto/keyspb/__init__.py b/proto/crypto/keyspb/__init__.py
deleted file mode 100644
index e69de29..0000000
--- a/proto/crypto/keyspb/__init__.py
+++ /dev/null
diff --git a/proto/crypto/keyspb/keyspb.proto b/proto/crypto/keyspb/keyspb.proto
deleted file mode 100644
index 03a8313..0000000
--- a/proto/crypto/keyspb/keyspb.proto
+++ /dev/null
@@ -1,94 +0,0 @@
-// Copyright 2017 Google Inc. All Rights Reserved.
-//
-// 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";
-
-option go_package = "github.com/google/trillian/crypto/keyspb";
-
-package keyspb;
-
-// Specification for a private key.
-message Specification {
- /// ECDSA defines parameters for an ECDSA key.
- message ECDSA {
- // The supported elliptic curves.
- enum Curve {
- DEFAULT_CURVE = 0; // Curve will be chosen by Trillian.
- P256 = 1;
- P384 = 2;
- P521 = 3;
- }
-
- // The elliptic curve to use.
- // Optional. If not set, the default curve will be used.
- Curve curve = 1;
- }
-
- // RSA defines parameters for an RSA key.
- message RSA {
- // Size of the keys in bits. Must be sufficiently large to allow two primes
- // to be generated.
- // Optional. If not set, the key size will be chosen by Trillian.
- int32 bits = 1;
- }
-
- // Ed25519 defines (empty) parameters for an Ed25519 private key.
- message Ed25519 {
- }
-
- // The type of parameters provided determines the algorithm used for the key.
- oneof params {
- // The parameters for an ECDSA key.
- ECDSA ecdsa_params = 1;
-
- // The parameters for an RSA key.
- RSA rsa_params = 2;
-
- // The parameters for an Ed25519 key.
- Ed25519 ed25519_params = 3;
- }
-}
-
-// PEMKeyFile identifies a private key stored in a PEM-encoded file.
-message PEMKeyFile {
- // File path of the private key.
- string path = 1;
-
- // Password for decrypting the private key.
- // If empty, indicates that the private key is not encrypted.
- string password = 2;
-}
-
-// PrivateKey is a private key, used for generating signatures.
-message PrivateKey {
- // The key in DER-encoded form.
- // The specific format (e.g. PKCS8) is not specified.
- bytes der = 1;
-}
-
-// PublicKey is a public key, used for verifying signatures.
-message PublicKey {
- // The key in DER-encoded PKIX form.
- bytes der = 1;
-}
-
-// PKCS11Config identifies a private key accessed using PKCS #11.
-message PKCS11Config {
- // The label of the PKCS#11 token.
- string token_label = 1;
- // The PIN for the specific token.
- string pin = 2;
- // The PEM public key assosciated with the private key to be used.
- string public_key = 3;
-}
diff --git a/proto/crypto/keyspb/keyspb_pb2.py b/proto/crypto/keyspb/keyspb_pb2.py
deleted file mode 100644
index eba4099..0000000
--- a/proto/crypto/keyspb/keyspb_pb2.py
+++ /dev/null
@@ -1,421 +0,0 @@
-# pylint: skip-file
-# -*- coding: utf-8 -*-
-# Generated by the protocol buffer compiler. DO NOT EDIT!
-# source: crypto/keyspb/keyspb.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()
-
-
-
-
-DESCRIPTOR = _descriptor.FileDescriptor(
- name='crypto/keyspb/keyspb.proto',
- package='keyspb',
- syntax='proto3',
- serialized_options=_b('Z(github.com/google/trillian/crypto/keyspb'),
- serialized_pb=_b('\n\x1a\x63rypto/keyspb/keyspb.proto\x12\x06keyspb\"\xcd\x02\n\rSpecification\x12\x33\n\x0c\x65\x63\x64sa_params\x18\x01 \x01(\x0b\x32\x1b.keyspb.Specification.ECDSAH\x00\x12/\n\nrsa_params\x18\x02 \x01(\x0b\x32\x19.keyspb.Specification.RSAH\x00\x12\x37\n\x0e\x65\x64\x32\x35\x35\x31\x39_params\x18\x03 \x01(\x0b\x32\x1d.keyspb.Specification.Ed25519H\x00\x1as\n\x05\x45\x43\x44SA\x12\x30\n\x05\x63urve\x18\x01 \x01(\x0e\x32!.keyspb.Specification.ECDSA.Curve\"8\n\x05\x43urve\x12\x11\n\rDEFAULT_CURVE\x10\x00\x12\x08\n\x04P256\x10\x01\x12\x08\n\x04P384\x10\x02\x12\x08\n\x04P521\x10\x03\x1a\x13\n\x03RSA\x12\x0c\n\x04\x62its\x18\x01 \x01(\x05\x1a\t\n\x07\x45\x64\x32\x35\x35\x31\x39\x42\x08\n\x06params\",\n\nPEMKeyFile\x12\x0c\n\x04path\x18\x01 \x01(\t\x12\x10\n\x08password\x18\x02 \x01(\t\"\x19\n\nPrivateKey\x12\x0b\n\x03\x64\x65r\x18\x01 \x01(\x0c\"\x18\n\tPublicKey\x12\x0b\n\x03\x64\x65r\x18\x01 \x01(\x0c\"D\n\x0cPKCS11Config\x12\x13\n\x0btoken_label\x18\x01 \x01(\t\x12\x0b\n\x03pin\x18\x02 \x01(\t\x12\x12\n\npublic_key\x18\x03 \x01(\tB*Z(github.com/google/trillian/crypto/keyspbb\x06proto3')
-)
-
-
-
-_SPECIFICATION_ECDSA_CURVE = _descriptor.EnumDescriptor(
- name='Curve',
- full_name='keyspb.Specification.ECDSA.Curve',
- filename=None,
- file=DESCRIPTOR,
- values=[
- _descriptor.EnumValueDescriptor(
- name='DEFAULT_CURVE', index=0, number=0,
- serialized_options=None,
- type=None),
- _descriptor.EnumValueDescriptor(
- name='P256', index=1, number=1,
- serialized_options=None,
- type=None),
- _descriptor.EnumValueDescriptor(
- name='P384', index=2, number=2,
- serialized_options=None,
- type=None),
- _descriptor.EnumValueDescriptor(
- name='P521', index=3, number=3,
- serialized_options=None,
- type=None),
- ],
- containing_type=None,
- serialized_options=None,
- serialized_start=274,
- serialized_end=330,
-)
-_sym_db.RegisterEnumDescriptor(_SPECIFICATION_ECDSA_CURVE)
-
-
-_SPECIFICATION_ECDSA = _descriptor.Descriptor(
- name='ECDSA',
- full_name='keyspb.Specification.ECDSA',
- filename=None,
- file=DESCRIPTOR,
- containing_type=None,
- fields=[
- _descriptor.FieldDescriptor(
- name='curve', full_name='keyspb.Specification.ECDSA.curve', index=0,
- number=1, type=14, cpp_type=8, 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),
- ],
- extensions=[
- ],
- nested_types=[],
- enum_types=[
- _SPECIFICATION_ECDSA_CURVE,
- ],
- serialized_options=None,
- is_extendable=False,
- syntax='proto3',
- extension_ranges=[],
- oneofs=[
- ],
- serialized_start=215,
- serialized_end=330,
-)
-
-_SPECIFICATION_RSA = _descriptor.Descriptor(
- name='RSA',
- full_name='keyspb.Specification.RSA',
- filename=None,
- file=DESCRIPTOR,
- containing_type=None,
- fields=[
- _descriptor.FieldDescriptor(
- name='bits', full_name='keyspb.Specification.RSA.bits', 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),
- ],
- extensions=[
- ],
- nested_types=[],
- enum_types=[
- ],
- serialized_options=None,
- is_extendable=False,
- syntax='proto3',
- extension_ranges=[],
- oneofs=[
- ],
- serialized_start=332,
- serialized_end=351,
-)
-
-_SPECIFICATION_ED25519 = _descriptor.Descriptor(
- name='Ed25519',
- full_name='keyspb.Specification.Ed25519',
- filename=None,
- file=DESCRIPTOR,
- containing_type=None,
- fields=[
- ],
- extensions=[
- ],
- nested_types=[],
- enum_types=[
- ],
- serialized_options=None,
- is_extendable=False,
- syntax='proto3',
- extension_ranges=[],
- oneofs=[
- ],
- serialized_start=353,
- serialized_end=362,
-)
-
-_SPECIFICATION = _descriptor.Descriptor(
- name='Specification',
- full_name='keyspb.Specification',
- filename=None,
- file=DESCRIPTOR,
- containing_type=None,
- fields=[
- _descriptor.FieldDescriptor(
- name='ecdsa_params', full_name='keyspb.Specification.ecdsa_params', 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='rsa_params', full_name='keyspb.Specification.rsa_params', 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='ed25519_params', full_name='keyspb.Specification.ed25519_params', 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),
- ],
- extensions=[
- ],
- nested_types=[_SPECIFICATION_ECDSA, _SPECIFICATION_RSA, _SPECIFICATION_ED25519, ],
- enum_types=[
- ],
- serialized_options=None,
- is_extendable=False,
- syntax='proto3',
- extension_ranges=[],
- oneofs=[
- _descriptor.OneofDescriptor(
- name='params', full_name='keyspb.Specification.params',
- index=0, containing_type=None, fields=[]),
- ],
- serialized_start=39,
- serialized_end=372,
-)
-
-
-_PEMKEYFILE = _descriptor.Descriptor(
- name='PEMKeyFile',
- full_name='keyspb.PEMKeyFile',
- filename=None,
- file=DESCRIPTOR,
- containing_type=None,
- fields=[
- _descriptor.FieldDescriptor(
- name='path', full_name='keyspb.PEMKeyFile.path', index=0,
- number=1, 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='password', full_name='keyspb.PEMKeyFile.password', 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=374,
- serialized_end=418,
-)
-
-
-_PRIVATEKEY = _descriptor.Descriptor(
- name='PrivateKey',
- full_name='keyspb.PrivateKey',
- filename=None,
- file=DESCRIPTOR,
- containing_type=None,
- fields=[
- _descriptor.FieldDescriptor(
- name='der', full_name='keyspb.PrivateKey.der', 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),
- ],
- extensions=[
- ],
- nested_types=[],
- enum_types=[
- ],
- serialized_options=None,
- is_extendable=False,
- syntax='proto3',
- extension_ranges=[],
- oneofs=[
- ],
- serialized_start=420,
- serialized_end=445,
-)
-
-
-_PUBLICKEY = _descriptor.Descriptor(
- name='PublicKey',
- full_name='keyspb.PublicKey',
- filename=None,
- file=DESCRIPTOR,
- containing_type=None,
- fields=[
- _descriptor.FieldDescriptor(
- name='der', full_name='keyspb.PublicKey.der', 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),
- ],
- extensions=[
- ],
- nested_types=[],
- enum_types=[
- ],
- serialized_options=None,
- is_extendable=False,
- syntax='proto3',
- extension_ranges=[],
- oneofs=[
- ],
- serialized_start=447,
- serialized_end=471,
-)
-
-
-_PKCS11CONFIG = _descriptor.Descriptor(
- name='PKCS11Config',
- full_name='keyspb.PKCS11Config',
- filename=None,
- file=DESCRIPTOR,
- containing_type=None,
- fields=[
- _descriptor.FieldDescriptor(
- name='token_label', full_name='keyspb.PKCS11Config.token_label', index=0,
- number=1, 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='pin', full_name='keyspb.PKCS11Config.pin', 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='public_key', full_name='keyspb.PKCS11Config.public_key', 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=473,
- serialized_end=541,
-)
-
-_SPECIFICATION_ECDSA.fields_by_name['curve'].enum_type = _SPECIFICATION_ECDSA_CURVE
-_SPECIFICATION_ECDSA.containing_type = _SPECIFICATION
-_SPECIFICATION_ECDSA_CURVE.containing_type = _SPECIFICATION_ECDSA
-_SPECIFICATION_RSA.containing_type = _SPECIFICATION
-_SPECIFICATION_ED25519.containing_type = _SPECIFICATION
-_SPECIFICATION.fields_by_name['ecdsa_params'].message_type = _SPECIFICATION_ECDSA
-_SPECIFICATION.fields_by_name['rsa_params'].message_type = _SPECIFICATION_RSA
-_SPECIFICATION.fields_by_name['ed25519_params'].message_type = _SPECIFICATION_ED25519
-_SPECIFICATION.oneofs_by_name['params'].fields.append(
- _SPECIFICATION.fields_by_name['ecdsa_params'])
-_SPECIFICATION.fields_by_name['ecdsa_params'].containing_oneof = _SPECIFICATION.oneofs_by_name['params']
-_SPECIFICATION.oneofs_by_name['params'].fields.append(
- _SPECIFICATION.fields_by_name['rsa_params'])
-_SPECIFICATION.fields_by_name['rsa_params'].containing_oneof = _SPECIFICATION.oneofs_by_name['params']
-_SPECIFICATION.oneofs_by_name['params'].fields.append(
- _SPECIFICATION.fields_by_name['ed25519_params'])
-_SPECIFICATION.fields_by_name['ed25519_params'].containing_oneof = _SPECIFICATION.oneofs_by_name['params']
-DESCRIPTOR.message_types_by_name['Specification'] = _SPECIFICATION
-DESCRIPTOR.message_types_by_name['PEMKeyFile'] = _PEMKEYFILE
-DESCRIPTOR.message_types_by_name['PrivateKey'] = _PRIVATEKEY
-DESCRIPTOR.message_types_by_name['PublicKey'] = _PUBLICKEY
-DESCRIPTOR.message_types_by_name['PKCS11Config'] = _PKCS11CONFIG
-_sym_db.RegisterFileDescriptor(DESCRIPTOR)
-
-Specification = _reflection.GeneratedProtocolMessageType('Specification', (_message.Message,), {
-
- 'ECDSA' : _reflection.GeneratedProtocolMessageType('ECDSA', (_message.Message,), {
- 'DESCRIPTOR' : _SPECIFICATION_ECDSA,
- '__module__' : 'crypto.keyspb.keyspb_pb2'
- # @@protoc_insertion_point(class_scope:keyspb.Specification.ECDSA)
- })
- ,
-
- 'RSA' : _reflection.GeneratedProtocolMessageType('RSA', (_message.Message,), {
- 'DESCRIPTOR' : _SPECIFICATION_RSA,
- '__module__' : 'crypto.keyspb.keyspb_pb2'
- # @@protoc_insertion_point(class_scope:keyspb.Specification.RSA)
- })
- ,
-
- 'Ed25519' : _reflection.GeneratedProtocolMessageType('Ed25519', (_message.Message,), {
- 'DESCRIPTOR' : _SPECIFICATION_ED25519,
- '__module__' : 'crypto.keyspb.keyspb_pb2'
- # @@protoc_insertion_point(class_scope:keyspb.Specification.Ed25519)
- })
- ,
- 'DESCRIPTOR' : _SPECIFICATION,
- '__module__' : 'crypto.keyspb.keyspb_pb2'
- # @@protoc_insertion_point(class_scope:keyspb.Specification)
- })
-_sym_db.RegisterMessage(Specification)
-_sym_db.RegisterMessage(Specification.ECDSA)
-_sym_db.RegisterMessage(Specification.RSA)
-_sym_db.RegisterMessage(Specification.Ed25519)
-
-PEMKeyFile = _reflection.GeneratedProtocolMessageType('PEMKeyFile', (_message.Message,), {
- 'DESCRIPTOR' : _PEMKEYFILE,
- '__module__' : 'crypto.keyspb.keyspb_pb2'
- # @@protoc_insertion_point(class_scope:keyspb.PEMKeyFile)
- })
-_sym_db.RegisterMessage(PEMKeyFile)
-
-PrivateKey = _reflection.GeneratedProtocolMessageType('PrivateKey', (_message.Message,), {
- 'DESCRIPTOR' : _PRIVATEKEY,
- '__module__' : 'crypto.keyspb.keyspb_pb2'
- # @@protoc_insertion_point(class_scope:keyspb.PrivateKey)
- })
-_sym_db.RegisterMessage(PrivateKey)
-
-PublicKey = _reflection.GeneratedProtocolMessageType('PublicKey', (_message.Message,), {
- 'DESCRIPTOR' : _PUBLICKEY,
- '__module__' : 'crypto.keyspb.keyspb_pb2'
- # @@protoc_insertion_point(class_scope:keyspb.PublicKey)
- })
-_sym_db.RegisterMessage(PublicKey)
-
-PKCS11Config = _reflection.GeneratedProtocolMessageType('PKCS11Config', (_message.Message,), {
- 'DESCRIPTOR' : _PKCS11CONFIG,
- '__module__' : 'crypto.keyspb.keyspb_pb2'
- # @@protoc_insertion_point(class_scope:keyspb.PKCS11Config)
- })
-_sym_db.RegisterMessage(PKCS11Config)
-
-
-DESCRIPTOR._options = None
-# @@protoc_insertion_point(module_scope)
diff --git a/proto/crypto/keyspb/keyspb_pb2_grpc.py b/proto/crypto/keyspb/keyspb_pb2_grpc.py
deleted file mode 100644
index 73636b2..0000000
--- a/proto/crypto/keyspb/keyspb_pb2_grpc.py
+++ /dev/null
@@ -1,4 +0,0 @@
-# pylint: skip-file
-# Generated by the gRPC Python protocol compiler plugin. DO NOT EDIT!
-import grpc
-
diff --git a/proto/crypto/sigpb/__init__.py b/proto/crypto/sigpb/__init__.py
deleted file mode 100644
index e69de29..0000000
--- a/proto/crypto/sigpb/__init__.py
+++ /dev/null
diff --git a/proto/crypto/sigpb/sigpb.proto b/proto/crypto/sigpb/sigpb.proto
deleted file mode 100644
index 3e333d3..0000000
--- a/proto/crypto/sigpb/sigpb.proto
+++ /dev/null
@@ -1,57 +0,0 @@
-// Copyright 2016 Google Inc. All Rights Reserved.
-//
-// 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";
-
-option go_package = "github.com/google/trillian/crypto/sigpb";
-
-package sigpb;
-
-// Protocol buffer encoding of the TLS DigitallySigned type, from RFC 5246 §4.7.
-message DigitallySigned {
- // HashAlgorithm defines the approved methods for object hashing.
- //
- // Supported hash algorithms. The numbering space is the same as for TLS,
- // given in RFC 5246 s7.4.1.4.1 and at:
- // http://www.iana.org/assignments/tls-parameters/tls-parameters.xhtml#tls-parameters-18
- enum HashAlgorithm {
- // No hash algorithm is used.
- NONE = 0;
- // SHA256 is used.
- SHA256 = 4;
- }
-
- // SignatureAlgorithm defines the algorithm used to sign the object.
- //
- // Supported signature algorithms. The numbering space is the same as for TLS,
- // given in RFC 5246 s7.4.1.4.1 and at:
- // http://www.iana.org/assignments/tls-parameters/tls-parameters.xhtml#tls-parameters-16
- enum SignatureAlgorithm {
- // Anonymous signature scheme.
- ANONYMOUS = 0;
- // RSA signature scheme.
- RSA = 1;
- // ECDSA signature scheme.
- ECDSA = 3;
- // Ed25519 signature scheme.
- ED25519 = 7;
- }
-
- // hash_algorithm contains the hash algorithm used.
- HashAlgorithm hash_algorithm = 1;
- // sig_algorithm contains the signing algorithm used.
- SignatureAlgorithm signature_algorithm = 2;
- // signature contains the object signature.
- bytes signature = 3;
-}
diff --git a/proto/crypto/sigpb/sigpb_pb2.py b/proto/crypto/sigpb/sigpb_pb2.py
deleted file mode 100644
index b00d42a..0000000
--- a/proto/crypto/sigpb/sigpb_pb2.py
+++ /dev/null
@@ -1,144 +0,0 @@
-# pylint: skip-file
-# -*- coding: utf-8 -*-
-# Generated by the protocol buffer compiler. DO NOT EDIT!
-# source: crypto/sigpb/sigpb.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()
-
-
-
-
-DESCRIPTOR = _descriptor.FileDescriptor(
- name='crypto/sigpb/sigpb.proto',
- package='sigpb',
- syntax='proto3',
- serialized_options=_b('Z\'github.com/google/trillian/crypto/sigpb'),
- serialized_pb=_b('\n\x18\x63rypto/sigpb/sigpb.proto\x12\x05sigpb\"\x97\x02\n\x0f\x44igitallySigned\x12<\n\x0ehash_algorithm\x18\x01 \x01(\x0e\x32$.sigpb.DigitallySigned.HashAlgorithm\x12\x46\n\x13signature_algorithm\x18\x02 \x01(\x0e\x32).sigpb.DigitallySigned.SignatureAlgorithm\x12\x11\n\tsignature\x18\x03 \x01(\x0c\"%\n\rHashAlgorithm\x12\x08\n\x04NONE\x10\x00\x12\n\n\x06SHA256\x10\x04\"D\n\x12SignatureAlgorithm\x12\r\n\tANONYMOUS\x10\x00\x12\x07\n\x03RSA\x10\x01\x12\t\n\x05\x45\x43\x44SA\x10\x03\x12\x0b\n\x07\x45\x44\x32\x35\x35\x31\x39\x10\x07\x42)Z\'github.com/google/trillian/crypto/sigpbb\x06proto3')
-)
-
-
-
-_DIGITALLYSIGNED_HASHALGORITHM = _descriptor.EnumDescriptor(
- name='HashAlgorithm',
- full_name='sigpb.DigitallySigned.HashAlgorithm',
- filename=None,
- file=DESCRIPTOR,
- values=[
- _descriptor.EnumValueDescriptor(
- name='NONE', index=0, number=0,
- serialized_options=None,
- type=None),
- _descriptor.EnumValueDescriptor(
- name='SHA256', index=1, number=4,
- serialized_options=None,
- type=None),
- ],
- containing_type=None,
- serialized_options=None,
- serialized_start=208,
- serialized_end=245,
-)
-_sym_db.RegisterEnumDescriptor(_DIGITALLYSIGNED_HASHALGORITHM)
-
-_DIGITALLYSIGNED_SIGNATUREALGORITHM = _descriptor.EnumDescriptor(
- name='SignatureAlgorithm',
- full_name='sigpb.DigitallySigned.SignatureAlgorithm',
- filename=None,
- file=DESCRIPTOR,
- values=[
- _descriptor.EnumValueDescriptor(
- name='ANONYMOUS', index=0, number=0,
- serialized_options=None,
- type=None),
- _descriptor.EnumValueDescriptor(
- name='RSA', index=1, number=1,
- serialized_options=None,
- type=None),
- _descriptor.EnumValueDescriptor(
- name='ECDSA', index=2, number=3,
- serialized_options=None,
- type=None),
- _descriptor.EnumValueDescriptor(
- name='ED25519', index=3, number=7,
- serialized_options=None,
- type=None),
- ],
- containing_type=None,
- serialized_options=None,
- serialized_start=247,
- serialized_end=315,
-)
-_sym_db.RegisterEnumDescriptor(_DIGITALLYSIGNED_SIGNATUREALGORITHM)
-
-
-_DIGITALLYSIGNED = _descriptor.Descriptor(
- name='DigitallySigned',
- full_name='sigpb.DigitallySigned',
- filename=None,
- file=DESCRIPTOR,
- containing_type=None,
- fields=[
- _descriptor.FieldDescriptor(
- name='hash_algorithm', full_name='sigpb.DigitallySigned.hash_algorithm', index=0,
- number=1, type=14, cpp_type=8, 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='signature_algorithm', full_name='sigpb.DigitallySigned.signature_algorithm', index=1,
- number=2, type=14, cpp_type=8, 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='signature', full_name='sigpb.DigitallySigned.signature', 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),
- ],
- extensions=[
- ],
- nested_types=[],
- enum_types=[
- _DIGITALLYSIGNED_HASHALGORITHM,
- _DIGITALLYSIGNED_SIGNATUREALGORITHM,
- ],
- serialized_options=None,
- is_extendable=False,
- syntax='proto3',
- extension_ranges=[],
- oneofs=[
- ],
- serialized_start=36,
- serialized_end=315,
-)
-
-_DIGITALLYSIGNED.fields_by_name['hash_algorithm'].enum_type = _DIGITALLYSIGNED_HASHALGORITHM
-_DIGITALLYSIGNED.fields_by_name['signature_algorithm'].enum_type = _DIGITALLYSIGNED_SIGNATUREALGORITHM
-_DIGITALLYSIGNED_HASHALGORITHM.containing_type = _DIGITALLYSIGNED
-_DIGITALLYSIGNED_SIGNATUREALGORITHM.containing_type = _DIGITALLYSIGNED
-DESCRIPTOR.message_types_by_name['DigitallySigned'] = _DIGITALLYSIGNED
-_sym_db.RegisterFileDescriptor(DESCRIPTOR)
-
-DigitallySigned = _reflection.GeneratedProtocolMessageType('DigitallySigned', (_message.Message,), {
- 'DESCRIPTOR' : _DIGITALLYSIGNED,
- '__module__' : 'crypto.sigpb.sigpb_pb2'
- # @@protoc_insertion_point(class_scope:sigpb.DigitallySigned)
- })
-_sym_db.RegisterMessage(DigitallySigned)
-
-
-DESCRIPTOR._options = None
-# @@protoc_insertion_point(module_scope)
diff --git a/proto/crypto/sigpb/sigpb_pb2_grpc.py b/proto/crypto/sigpb/sigpb_pb2_grpc.py
deleted file mode 100644
index 73636b2..0000000
--- a/proto/crypto/sigpb/sigpb_pb2_grpc.py
+++ /dev/null
@@ -1,4 +0,0 @@
-# pylint: skip-file
-# Generated by the gRPC Python protocol compiler plugin. DO NOT EDIT!
-import grpc
-
diff --git a/proto/trillian.proto b/proto/trillian.proto
deleted file mode 100644
index e14522f..0000000
--- a/proto/trillian.proto
+++ /dev/null
@@ -1,316 +0,0 @@
-// Copyright 2016 Google Inc. All Rights Reserved.
-//
-// 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";
-
-option java_multiple_files = true;
-option java_package = "com.google.trillian.proto";
-option java_outer_classname = "TrillianProto";
-option go_package = "github.com/google/trillian";
-
-package trillian;
-
-import "crypto/keyspb/keyspb.proto";
-import "crypto/sigpb/sigpb.proto";
-import "google/protobuf/any.proto";
-import "google/protobuf/duration.proto";
-import "google/protobuf/timestamp.proto";
-
-// LogRootFormat specifies the fields that are covered by the
-// SignedLogRoot signature, as well as their ordering and formats.
-enum LogRootFormat {
- LOG_ROOT_FORMAT_UNKNOWN = 0;
- LOG_ROOT_FORMAT_V1 = 1;
-}
-
-// MapRootFormat specifies the fields that are covered by the
-// SignedMapRoot signature, as well as their ordering and formats.
-enum MapRootFormat {
- MAP_ROOT_FORMAT_UNKNOWN = 0;
- MAP_ROOT_FORMAT_V1 = 1;
-}
-
-// What goes in here?
-// Things which are exposed through the public trillian APIs.
-
-// Defines the way empty / node / leaf hashes are constructed incorporating
-// preimage protection, which can be application specific.
-enum HashStrategy {
- // Hash strategy cannot be determined. Included to enable detection of
- // mismatched proto versions being used. Represents an invalid value.
- UNKNOWN_HASH_STRATEGY = 0;
-
- // Certificate Transparency strategy: leaf hash prefix = 0x00, node prefix =
- // 0x01, empty hash is digest([]byte{}), as defined in the specification.
- RFC6962_SHA256 = 1;
-
- // Sparse Merkle Tree strategy: leaf hash prefix = 0x00, node prefix = 0x01,
- // empty branch is recursively computed from empty leaf nodes.
- // NOT secure in a multi tree environment. For testing only.
- TEST_MAP_HASHER = 2;
-
- // Append-only log strategy where leaf nodes are defined as the ObjectHash.
- // All other properties are equal to RFC6962_SHA256.
- OBJECT_RFC6962_SHA256 = 3;
-
- // The CONIKS sparse tree hasher with SHA512_256 as the hash algorithm.
- CONIKS_SHA512_256 = 4;
-
- // The CONIKS sparse tree hasher with SHA256 as the hash algorithm.
- CONIKS_SHA256 = 5;
-}
-
-// State of the tree.
-enum TreeState {
- // Tree state cannot be determined. Included to enable detection of
- // mismatched proto versions being used. Represents an invalid value.
- UNKNOWN_TREE_STATE = 0;
-
- // Active trees are able to respond to both read and write requests.
- ACTIVE = 1;
-
- // Frozen trees are only able to respond to read requests, writing to a frozen
- // tree is forbidden. Trees should not be frozen when there are entries
- // in the queue that have not yet been integrated. See the DRAINING
- // state for this case.
- FROZEN = 2;
-
- // Deprecated: now tracked in Tree.deleted.
- DEPRECATED_SOFT_DELETED = 3 [deprecated = true];
-
- // Deprecated: now tracked in Tree.deleted.
- DEPRECATED_HARD_DELETED = 4 [deprecated = true];
-
- // A tree that is draining will continue to integrate queued entries.
- // No new entries should be accepted.
- DRAINING = 5;
-}
-
-// Type of the tree.
-enum TreeType {
- // Tree type cannot be determined. Included to enable detection of mismatched
- // proto versions being used. Represents an invalid value.
- UNKNOWN_TREE_TYPE = 0;
-
- // Tree represents a verifiable log.
- LOG = 1;
-
- // Tree represents a verifiable map.
- MAP = 2;
-
- // Tree represents a verifiable pre-ordered log, i.e., a log whose entries are
- // placed according to sequence numbers assigned outside of Trillian.
- PREORDERED_LOG = 3;
-}
-
-// Represents a tree, which may be either a verifiable log or map.
-// Readonly attributes are assigned at tree creation, after which they may not
-// be modified.
-//
-// Note: Many APIs within the rest of the code require these objects to
-// be provided. For safety they should be obtained via Admin API calls and
-// not created dynamically.
-message Tree {
- // ID of the tree.
- // Readonly.
- int64 tree_id = 1;
-
- // State of the tree.
- // Trees are ACTIVE after creation. At any point the tree may transition
- // between ACTIVE, DRAINING and FROZEN states.
- TreeState tree_state = 2;
-
- // Type of the tree.
- // Readonly after Tree creation. Exception: Can be switched from
- // PREORDERED_LOG to LOG if the Tree is and remains in the FROZEN state.
- TreeType tree_type = 3;
-
- // Hash strategy to be used by the tree.
- // Readonly.
- HashStrategy hash_strategy = 4;
-
- // Hash algorithm to be used by the tree.
- // Readonly.
- sigpb.DigitallySigned.HashAlgorithm hash_algorithm = 5;
-
- // Signature algorithm to be used by the tree.
- // Readonly.
- sigpb.DigitallySigned.SignatureAlgorithm signature_algorithm = 6;
-
- reserved 18; // Signature cipher suite (removed)
- reserved 7; // DuplicatePolicy (removed)
-
- // Display name of the tree.
- // Optional.
- string display_name = 8;
-
- // Description of the tree,
- // Optional.
- string description = 9;
-
- reserved 10; // create_time_millis_since_epoch (removed)
- reserved 11; // update_time_millis_since_epoch (removed)
-
- // Identifies the private key used for signing tree heads and entry
- // timestamps.
- // This can be any type of message to accommodate different key management
- // systems, e.g. PEM files, HSMs, etc.
- // Private keys are write-only: they're never returned by RPCs.
- // The private_key message can be changed after a tree is created, but the
- // underlying key must remain the same - this is to enable migrating a key
- // from one provider to another.
- google.protobuf.Any private_key = 12;
-
- // Storage-specific settings.
- // Varies according to the storage implementation backing Trillian.
- google.protobuf.Any storage_settings = 13;
-
- // The public key used for verifying tree heads and entry timestamps.
- // Readonly.
- keyspb.PublicKey public_key = 14;
-
- // Interval after which a new signed root is produced even if there have been
- // no submission. If zero, this behavior is disabled.
- google.protobuf.Duration max_root_duration = 15;
-
- // Time of tree creation.
- // Readonly.
- google.protobuf.Timestamp create_time = 16;
-
- // Time of last tree update.
- // Readonly (automatically assigned on updates).
- google.protobuf.Timestamp update_time = 17;
-
- // If true, the tree has been deleted.
- // Deleted trees may be undeleted during a certain time window, after which
- // they're permanently deleted (and unrecoverable).
- // Readonly.
- bool deleted = 19;
-
- // Time of tree deletion, if any.
- // Readonly.
- google.protobuf.Timestamp delete_time = 20;
-}
-
-message SignedEntryTimestamp {
- int64 timestamp_nanos = 1;
- int64 log_id = 2;
- sigpb.DigitallySigned signature = 3;
-}
-
-// SignedLogRoot represents a commitment by a Log to a particular tree.
-message SignedLogRoot {
- // Deleted: TimestampNanos moved to LogRoot.
- reserved 1;
- // Deleted: RootHash moved to LogRoot.
- reserved 2;
- // Deleted: TreeSize moved to LogRoot.
- reserved 3;
- // Deleted: Signature replaced by LogRootSignature.
- reserved 4;
- // Deleted: LogID is associated with the public key that validates signature.
- reserved 5;
- // Deleted: TreeRevision moved to LogRoot.
- reserved 6;
-
- // key_hint is a hint to identify the public key for signature verification.
- // key_hint is not authenticated and may be incorrect or missing, in which
- // case all known public keys may be used to verify the signature.
- // When directly communicating with a Trillian gRPC server, the key_hint will
- // typically contain the LogID encoded as a big-endian 64-bit integer;
- // however, in other contexts the key_hint is likely to have different
- // contents (e.g. it could be a GUID, a URL + TreeID, or it could be
- // derived from the public key itself).
- bytes key_hint = 7;
-
- // log_root holds the TLS-serialization of the following structure (described
- // in RFC5246 notation): Clients should validate log_root_signature with
- // VerifySignedLogRoot before deserializing log_root.
- // enum { v1(1), (65535)} Version;
- // struct {
- // uint64 tree_size;
- // opaque root_hash<0..128>;
- // uint64 timestamp_nanos;
- // uint64 revision;
- // opaque metadata<0..65535>;
- // } LogRootV1;
- // struct {
- // Version version;
- // select(version) {
- // case v1: LogRootV1;
- // }
- // } LogRoot;
- //
- // A serialized v1 log root will therefore be laid out as:
- //
- // +---+---+---+---+---+---+---+---+---+---+---+---+---+---+-....--+
- // | ver=1 | tree_size |len| root_hashlen |
- // +---+---+---+---+---+---+---+---+---+---+---+---+---+---+-....--+
- //
- // +---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+
- // | timestamp_nanos | revision |
- // +---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+
- //
- // +---+---+---+---+---+-....---+
- // | len | metadata |
- // +---+---+---+---+---+-....---+
- //
- // (with all integers encoded big-endian).
- bytes log_root = 8;
-
- // log_root_signature is the raw signature over log_root.
- bytes log_root_signature = 9;
-}
-
-// SignedMapRoot represents a commitment by a Map to a particular tree.
-message SignedMapRoot {
- reserved 1; // Deprecated: Was timestamp_nanos. Use map_root.
- reserved 2; // Deprecated: Was root_hash. Use map_root.
- reserved 3; // Deprecated: Was MapperMetadata. Use map_root.
- reserved 5; // Deprecated: Was map_id. Use signature.
- reserved 6; // Deprecated: Was map_revision. Use map_root.
- reserved 7; // Deprecated: Was metadata Any. Use map_root.
- reserved 8; // Deprecated: Was metadata bytes. Use map_root.
-
- // map_root holds the TLS-serialization of the following structure (described
- // in RFC5246 notation): Clients should validate signature with
- // VerifySignedMapRoot before deserializing map_root.
- // enum { v1(1), (65535)} Version;
- // struct {
- // opaque root_hash<0..128>;
- // uint64 timestamp_nanos;
- // uint64 revision;
- // opaque metadata<0..65535>;
- // } MapRootV1;
- // struct {
- // Version version;
- // select(version) {
- // case v1: MapRootV1;
- // }
- // } MapRoot;
- bytes map_root = 9;
- // Signature is the raw signature over MapRoot.
- bytes signature = 4;
-}
-
-// Proof holds a consistency or inclusion proof for a Merkle tree, as returned
-// by the API.
-message Proof {
- // leaf_index indicates the requested leaf index when this message is used for
- // a leaf inclusion proof. This field is set to zero when this message is
- // used for a consistency proof.
- int64 leaf_index = 1;
- reserved 2; // Contained internal node details (removed)
- repeated bytes hashes = 3;
-}
diff --git a/proto/trillian_pb2.py b/proto/trillian_pb2.py
deleted file mode 100644
index 4c7ddd6..0000000
--- a/proto/trillian_pb2.py
+++ /dev/null
@@ -1,576 +0,0 @@
-# -*- coding: utf-8 -*-
-# Generated by the protocol buffer compiler. DO NOT EDIT!
-# source: trillian.proto
-
-import sys
-_b=sys.version_info[0]<3 and (lambda x:x) or (lambda x:x.encode('latin1'))
-from google.protobuf.internal import enum_type_wrapper
-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()
-
-
-from crypto.keyspb import keyspb_pb2 as crypto_dot_keyspb_dot_keyspb__pb2
-from crypto.sigpb import sigpb_pb2 as crypto_dot_sigpb_dot_sigpb__pb2
-from google.protobuf import any_pb2 as google_dot_protobuf_dot_any__pb2
-from google.protobuf import duration_pb2 as google_dot_protobuf_dot_duration__pb2
-from google.protobuf import timestamp_pb2 as google_dot_protobuf_dot_timestamp__pb2
-
-
-DESCRIPTOR = _descriptor.FileDescriptor(
- name='trillian.proto',
- package='trillian',
- syntax='proto3',
- serialized_options=_b('\n\031com.google.trillian.protoB\rTrillianProtoP\001Z\032github.com/google/trillian'),
- serialized_pb=_b('\n\x0etrillian.proto\x12\x08trillian\x1a\x1a\x63rypto/keyspb/keyspb.proto\x1a\x18\x63rypto/sigpb/sigpb.proto\x1a\x19google/protobuf/any.proto\x1a\x1egoogle/protobuf/duration.proto\x1a\x1fgoogle/protobuf/timestamp.proto\"\xbb\x05\n\x04Tree\x12\x0f\n\x07tree_id\x18\x01 \x01(\x03\x12\'\n\ntree_state\x18\x02 \x01(\x0e\x32\x13.trillian.TreeState\x12%\n\ttree_type\x18\x03 \x01(\x0e\x32\x12.trillian.TreeType\x12-\n\rhash_strategy\x18\x04 \x01(\x0e\x32\x16.trillian.HashStrategy\x12<\n\x0ehash_algorithm\x18\x05 \x01(\x0e\x32$.sigpb.DigitallySigned.HashAlgorithm\x12\x46\n\x13signature_algorithm\x18\x06 \x01(\x0e\x32).sigpb.DigitallySigned.SignatureAlgorithm\x12\x14\n\x0c\x64isplay_name\x18\x08 \x01(\t\x12\x13\n\x0b\x64\x65scription\x18\t \x01(\t\x12)\n\x0bprivate_key\x18\x0c \x01(\x0b\x32\x14.google.protobuf.Any\x12.\n\x10storage_settings\x18\r \x01(\x0b\x32\x14.google.protobuf.Any\x12%\n\npublic_key\x18\x0e \x01(\x0b\x32\x11.keyspb.PublicKey\x12\x34\n\x11max_root_duration\x18\x0f \x01(\x0b\x32\x19.google.protobuf.Duration\x12/\n\x0b\x63reate_time\x18\x10 \x01(\x0b\x32\x1a.google.protobuf.Timestamp\x12/\n\x0bupdate_time\x18\x11 \x01(\x0b\x32\x1a.google.protobuf.Timestamp\x12\x0f\n\x07\x64\x65leted\x18\x13 \x01(\x08\x12/\n\x0b\x64\x65lete_time\x18\x14 \x01(\x0b\x32\x1a.google.protobuf.TimestampJ\x04\x08\x12\x10\x13J\x04\x08\x07\x10\x08J\x04\x08\n\x10\x0bJ\x04\x08\x0b\x10\x0c\"j\n\x14SignedEntryTimestamp\x12\x17\n\x0ftimestamp_nanos\x18\x01 \x01(\x03\x12\x0e\n\x06log_id\x18\x02 \x01(\x03\x12)\n\tsignature\x18\x03 \x01(\x0b\x32\x16.sigpb.DigitallySigned\"s\n\rSignedLogRoot\x12\x10\n\x08key_hint\x18\x07 \x01(\x0c\x12\x10\n\x08log_root\x18\x08 \x01(\x0c\x12\x1a\n\x12log_root_signature\x18\t \x01(\x0cJ\x04\x08\x01\x10\x02J\x04\x08\x02\x10\x03J\x04\x08\x03\x10\x04J\x04\x08\x04\x10\x05J\x04\x08\x05\x10\x06J\x04\x08\x06\x10\x07\"^\n\rSignedMapRoot\x12\x10\n\x08map_root\x18\t \x01(\x0c\x12\x11\n\tsignature\x18\x04 \x01(\x0cJ\x04\x08\x01\x10\x02J\x04\x08\x02\x10\x03J\x04\x08\x03\x10\x04J\x04\x08\x05\x10\x06J\x04\x08\x06\x10\x07J\x04\x08\x07\x10\x08J\x04\x08\x08\x10\t\"1\n\x05Proof\x12\x12\n\nleaf_index\x18\x01 \x01(\x03\x12\x0e\n\x06hashes\x18\x03 \x03(\x0cJ\x04\x08\x02\x10\x03*D\n\rLogRootFormat\x12\x1b\n\x17LOG_ROOT_FORMAT_UNKNOWN\x10\x00\x12\x16\n\x12LOG_ROOT_FORMAT_V1\x10\x01*D\n\rMapRootFormat\x12\x1b\n\x17MAP_ROOT_FORMAT_UNKNOWN\x10\x00\x12\x16\n\x12MAP_ROOT_FORMAT_V1\x10\x01*\x97\x01\n\x0cHashStrategy\x12\x19\n\x15UNKNOWN_HASH_STRATEGY\x10\x00\x12\x12\n\x0eRFC6962_SHA256\x10\x01\x12\x13\n\x0fTEST_MAP_HASHER\x10\x02\x12\x19\n\x15OBJECT_RFC6962_SHA256\x10\x03\x12\x15\n\x11\x43ONIKS_SHA512_256\x10\x04\x12\x11\n\rCONIKS_SHA256\x10\x05*\x8b\x01\n\tTreeState\x12\x16\n\x12UNKNOWN_TREE_STATE\x10\x00\x12\n\n\x06\x41\x43TIVE\x10\x01\x12\n\n\x06\x46ROZEN\x10\x02\x12\x1f\n\x17\x44\x45PRECATED_SOFT_DELETED\x10\x03\x1a\x02\x08\x01\x12\x1f\n\x17\x44\x45PRECATED_HARD_DELETED\x10\x04\x1a\x02\x08\x01\x12\x0c\n\x08\x44RAINING\x10\x05*G\n\x08TreeType\x12\x15\n\x11UNKNOWN_TREE_TYPE\x10\x00\x12\x07\n\x03LOG\x10\x01\x12\x07\n\x03MAP\x10\x02\x12\x12\n\x0ePREORDERED_LOG\x10\x03\x42H\n\x19\x63om.google.trillian.protoB\rTrillianProtoP\x01Z\x1agithub.com/google/trillianb\x06proto3')
- ,
- dependencies=[crypto_dot_keyspb_dot_keyspb__pb2.DESCRIPTOR,crypto_dot_sigpb_dot_sigpb__pb2.DESCRIPTOR,google_dot_protobuf_dot_any__pb2.DESCRIPTOR,google_dot_protobuf_dot_duration__pb2.DESCRIPTOR,google_dot_protobuf_dot_timestamp__pb2.DESCRIPTOR,])
-
-_LOGROOTFORMAT = _descriptor.EnumDescriptor(
- name='LogRootFormat',
- full_name='trillian.LogRootFormat',
- filename=None,
- file=DESCRIPTOR,
- values=[
- _descriptor.EnumValueDescriptor(
- name='LOG_ROOT_FORMAT_UNKNOWN', index=0, number=0,
- serialized_options=None,
- type=None),
- _descriptor.EnumValueDescriptor(
- name='LOG_ROOT_FORMAT_V1', index=1, number=1,
- serialized_options=None,
- type=None),
- ],
- containing_type=None,
- serialized_options=None,
- serialized_start=1248,
- serialized_end=1316,
-)
-_sym_db.RegisterEnumDescriptor(_LOGROOTFORMAT)
-
-LogRootFormat = enum_type_wrapper.EnumTypeWrapper(_LOGROOTFORMAT)
-_MAPROOTFORMAT = _descriptor.EnumDescriptor(
- name='MapRootFormat',
- full_name='trillian.MapRootFormat',
- filename=None,
- file=DESCRIPTOR,
- values=[
- _descriptor.EnumValueDescriptor(
- name='MAP_ROOT_FORMAT_UNKNOWN', index=0, number=0,
- serialized_options=None,
- type=None),
- _descriptor.EnumValueDescriptor(
- name='MAP_ROOT_FORMAT_V1', index=1, number=1,
- serialized_options=None,
- type=None),
- ],
- containing_type=None,
- serialized_options=None,
- serialized_start=1318,
- serialized_end=1386,
-)
-_sym_db.RegisterEnumDescriptor(_MAPROOTFORMAT)
-
-MapRootFormat = enum_type_wrapper.EnumTypeWrapper(_MAPROOTFORMAT)
-_HASHSTRATEGY = _descriptor.EnumDescriptor(
- name='HashStrategy',
- full_name='trillian.HashStrategy',
- filename=None,
- file=DESCRIPTOR,
- values=[
- _descriptor.EnumValueDescriptor(
- name='UNKNOWN_HASH_STRATEGY', index=0, number=0,
- serialized_options=None,
- type=None),
- _descriptor.EnumValueDescriptor(
- name='RFC6962_SHA256', index=1, number=1,
- serialized_options=None,
- type=None),
- _descriptor.EnumValueDescriptor(
- name='TEST_MAP_HASHER', index=2, number=2,
- serialized_options=None,
- type=None),
- _descriptor.EnumValueDescriptor(
- name='OBJECT_RFC6962_SHA256', index=3, number=3,
- serialized_options=None,
- type=None),
- _descriptor.EnumValueDescriptor(
- name='CONIKS_SHA512_256', index=4, number=4,
- serialized_options=None,
- type=None),
- _descriptor.EnumValueDescriptor(
- name='CONIKS_SHA256', index=5, number=5,
- serialized_options=None,
- type=None),
- ],
- containing_type=None,
- serialized_options=None,
- serialized_start=1389,
- serialized_end=1540,
-)
-_sym_db.RegisterEnumDescriptor(_HASHSTRATEGY)
-
-HashStrategy = enum_type_wrapper.EnumTypeWrapper(_HASHSTRATEGY)
-_TREESTATE = _descriptor.EnumDescriptor(
- name='TreeState',
- full_name='trillian.TreeState',
- filename=None,
- file=DESCRIPTOR,
- values=[
- _descriptor.EnumValueDescriptor(
- name='UNKNOWN_TREE_STATE', index=0, number=0,
- serialized_options=None,
- type=None),
- _descriptor.EnumValueDescriptor(
- name='ACTIVE', index=1, number=1,
- serialized_options=None,
- type=None),
- _descriptor.EnumValueDescriptor(
- name='FROZEN', index=2, number=2,
- serialized_options=None,
- type=None),
- _descriptor.EnumValueDescriptor(
- name='DEPRECATED_SOFT_DELETED', index=3, number=3,
- serialized_options=_b('\010\001'),
- type=None),
- _descriptor.EnumValueDescriptor(
- name='DEPRECATED_HARD_DELETED', index=4, number=4,
- serialized_options=_b('\010\001'),
- type=None),
- _descriptor.EnumValueDescriptor(
- name='DRAINING', index=5, number=5,
- serialized_options=None,
- type=None),
- ],
- containing_type=None,
- serialized_options=None,
- serialized_start=1543,
- serialized_end=1682,
-)
-_sym_db.RegisterEnumDescriptor(_TREESTATE)
-
-TreeState = enum_type_wrapper.EnumTypeWrapper(_TREESTATE)
-_TREETYPE = _descriptor.EnumDescriptor(
- name='TreeType',
- full_name='trillian.TreeType',
- filename=None,
- file=DESCRIPTOR,
- values=[
- _descriptor.EnumValueDescriptor(
- name='UNKNOWN_TREE_TYPE', index=0, number=0,
- serialized_options=None,
- type=None),
- _descriptor.EnumValueDescriptor(
- name='LOG', index=1, number=1,
- serialized_options=None,
- type=None),
- _descriptor.EnumValueDescriptor(
- name='MAP', index=2, number=2,
- serialized_options=None,
- type=None),
- _descriptor.EnumValueDescriptor(
- name='PREORDERED_LOG', index=3, number=3,
- serialized_options=None,
- type=None),
- ],
- containing_type=None,
- serialized_options=None,
- serialized_start=1684,
- serialized_end=1755,
-)
-_sym_db.RegisterEnumDescriptor(_TREETYPE)
-
-TreeType = enum_type_wrapper.EnumTypeWrapper(_TREETYPE)
-LOG_ROOT_FORMAT_UNKNOWN = 0
-LOG_ROOT_FORMAT_V1 = 1
-MAP_ROOT_FORMAT_UNKNOWN = 0
-MAP_ROOT_FORMAT_V1 = 1
-UNKNOWN_HASH_STRATEGY = 0
-RFC6962_SHA256 = 1
-TEST_MAP_HASHER = 2
-OBJECT_RFC6962_SHA256 = 3
-CONIKS_SHA512_256 = 4
-CONIKS_SHA256 = 5
-UNKNOWN_TREE_STATE = 0
-ACTIVE = 1
-FROZEN = 2
-DEPRECATED_SOFT_DELETED = 3
-DEPRECATED_HARD_DELETED = 4
-DRAINING = 5
-UNKNOWN_TREE_TYPE = 0
-LOG = 1
-MAP = 2
-PREORDERED_LOG = 3
-
-
-
-_TREE = _descriptor.Descriptor(
- name='Tree',
- full_name='trillian.Tree',
- filename=None,
- file=DESCRIPTOR,
- containing_type=None,
- fields=[
- _descriptor.FieldDescriptor(
- name='tree_id', full_name='trillian.Tree.tree_id', index=0,
- number=1, type=3, cpp_type=2, 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='tree_state', full_name='trillian.Tree.tree_state', index=1,
- number=2, type=14, cpp_type=8, 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='tree_type', full_name='trillian.Tree.tree_type', index=2,
- number=3, type=14, cpp_type=8, 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='hash_strategy', full_name='trillian.Tree.hash_strategy', index=3,
- number=4, type=14, cpp_type=8, 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='hash_algorithm', full_name='trillian.Tree.hash_algorithm', index=4,
- number=5, type=14, cpp_type=8, 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='signature_algorithm', full_name='trillian.Tree.signature_algorithm', index=5,
- number=6, type=14, cpp_type=8, 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='display_name', full_name='trillian.Tree.display_name', index=6,
- number=8, 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='description', full_name='trillian.Tree.description', index=7,
- number=9, 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='private_key', full_name='trillian.Tree.private_key', index=8,
- number=12, 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='storage_settings', full_name='trillian.Tree.storage_settings', index=9,
- number=13, 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='public_key', full_name='trillian.Tree.public_key', index=10,
- number=14, 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='max_root_duration', full_name='trillian.Tree.max_root_duration', index=11,
- number=15, 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='create_time', full_name='trillian.Tree.create_time', index=12,
- number=16, 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='update_time', full_name='trillian.Tree.update_time', index=13,
- number=17, 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='deleted', full_name='trillian.Tree.deleted', index=14,
- number=19, type=8, cpp_type=7, label=1,
- has_default_value=False, default_value=False,
- message_type=None, enum_type=None, containing_type=None,
- is_extension=False, extension_scope=None,
- serialized_options=None, file=DESCRIPTOR),
- _descriptor.FieldDescriptor(
- name='delete_time', full_name='trillian.Tree.delete_time', index=15,
- number=20, 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=175,
- serialized_end=874,
-)
-
-
-_SIGNEDENTRYTIMESTAMP = _descriptor.Descriptor(
- name='SignedEntryTimestamp',
- full_name='trillian.SignedEntryTimestamp',
- filename=None,
- file=DESCRIPTOR,
- containing_type=None,
- fields=[
- _descriptor.FieldDescriptor(
- name='timestamp_nanos', full_name='trillian.SignedEntryTimestamp.timestamp_nanos', index=0,
- number=1, type=3, cpp_type=2, 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='log_id', full_name='trillian.SignedEntryTimestamp.log_id', index=1,
- number=2, type=3, cpp_type=2, 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='signature', full_name='trillian.SignedEntryTimestamp.signature', 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),
- ],
- extensions=[
- ],
- nested_types=[],
- enum_types=[
- ],
- serialized_options=None,
- is_extendable=False,
- syntax='proto3',
- extension_ranges=[],
- oneofs=[
- ],
- serialized_start=876,
- serialized_end=982,
-)
-
-
-_SIGNEDLOGROOT = _descriptor.Descriptor(
- name='SignedLogRoot',
- full_name='trillian.SignedLogRoot',
- filename=None,
- file=DESCRIPTOR,
- containing_type=None,
- fields=[
- _descriptor.FieldDescriptor(
- name='key_hint', full_name='trillian.SignedLogRoot.key_hint', index=0,
- number=7, 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='log_root', full_name='trillian.SignedLogRoot.log_root', index=1,
- number=8, 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='log_root_signature', full_name='trillian.SignedLogRoot.log_root_signature', index=2,
- number=9, 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=984,
- serialized_end=1099,
-)
-
-
-_SIGNEDMAPROOT = _descriptor.Descriptor(
- name='SignedMapRoot',
- full_name='trillian.SignedMapRoot',
- filename=None,
- file=DESCRIPTOR,
- containing_type=None,
- fields=[
- _descriptor.FieldDescriptor(
- name='map_root', full_name='trillian.SignedMapRoot.map_root', index=0,
- number=9, 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='signature', full_name='trillian.SignedMapRoot.signature', index=1,
- 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),
- ],
- extensions=[
- ],
- nested_types=[],
- enum_types=[
- ],
- serialized_options=None,
- is_extendable=False,
- syntax='proto3',
- extension_ranges=[],
- oneofs=[
- ],
- serialized_start=1101,
- serialized_end=1195,
-)
-
-
-_PROOF = _descriptor.Descriptor(
- name='Proof',
- full_name='trillian.Proof',
- filename=None,
- file=DESCRIPTOR,
- containing_type=None,
- fields=[
- _descriptor.FieldDescriptor(
- name='leaf_index', full_name='trillian.Proof.leaf_index', index=0,
- number=1, type=3, cpp_type=2, 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='hashes', full_name='trillian.Proof.hashes', index=1,
- number=3, type=12, cpp_type=9, label=3,
- has_default_value=False, default_value=[],
- 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=1197,
- serialized_end=1246,
-)
-
-_TREE.fields_by_name['tree_state'].enum_type = _TREESTATE
-_TREE.fields_by_name['tree_type'].enum_type = _TREETYPE
-_TREE.fields_by_name['hash_strategy'].enum_type = _HASHSTRATEGY
-_TREE.fields_by_name['hash_algorithm'].enum_type = crypto_dot_sigpb_dot_sigpb__pb2._DIGITALLYSIGNED_HASHALGORITHM
-_TREE.fields_by_name['signature_algorithm'].enum_type = crypto_dot_sigpb_dot_sigpb__pb2._DIGITALLYSIGNED_SIGNATUREALGORITHM
-_TREE.fields_by_name['private_key'].message_type = google_dot_protobuf_dot_any__pb2._ANY
-_TREE.fields_by_name['storage_settings'].message_type = google_dot_protobuf_dot_any__pb2._ANY
-_TREE.fields_by_name['public_key'].message_type = crypto_dot_keyspb_dot_keyspb__pb2._PUBLICKEY
-_TREE.fields_by_name['max_root_duration'].message_type = google_dot_protobuf_dot_duration__pb2._DURATION
-_TREE.fields_by_name['create_time'].message_type = google_dot_protobuf_dot_timestamp__pb2._TIMESTAMP
-_TREE.fields_by_name['update_time'].message_type = google_dot_protobuf_dot_timestamp__pb2._TIMESTAMP
-_TREE.fields_by_name['delete_time'].message_type = google_dot_protobuf_dot_timestamp__pb2._TIMESTAMP
-_SIGNEDENTRYTIMESTAMP.fields_by_name['signature'].message_type = crypto_dot_sigpb_dot_sigpb__pb2._DIGITALLYSIGNED
-DESCRIPTOR.message_types_by_name['Tree'] = _TREE
-DESCRIPTOR.message_types_by_name['SignedEntryTimestamp'] = _SIGNEDENTRYTIMESTAMP
-DESCRIPTOR.message_types_by_name['SignedLogRoot'] = _SIGNEDLOGROOT
-DESCRIPTOR.message_types_by_name['SignedMapRoot'] = _SIGNEDMAPROOT
-DESCRIPTOR.message_types_by_name['Proof'] = _PROOF
-DESCRIPTOR.enum_types_by_name['LogRootFormat'] = _LOGROOTFORMAT
-DESCRIPTOR.enum_types_by_name['MapRootFormat'] = _MAPROOTFORMAT
-DESCRIPTOR.enum_types_by_name['HashStrategy'] = _HASHSTRATEGY
-DESCRIPTOR.enum_types_by_name['TreeState'] = _TREESTATE
-DESCRIPTOR.enum_types_by_name['TreeType'] = _TREETYPE
-_sym_db.RegisterFileDescriptor(DESCRIPTOR)
-
-Tree = _reflection.GeneratedProtocolMessageType('Tree', (_message.Message,), {
- 'DESCRIPTOR' : _TREE,
- '__module__' : 'trillian_pb2'
- # @@protoc_insertion_point(class_scope:trillian.Tree)
- })
-_sym_db.RegisterMessage(Tree)
-
-SignedEntryTimestamp = _reflection.GeneratedProtocolMessageType('SignedEntryTimestamp', (_message.Message,), {
- 'DESCRIPTOR' : _SIGNEDENTRYTIMESTAMP,
- '__module__' : 'trillian_pb2'
- # @@protoc_insertion_point(class_scope:trillian.SignedEntryTimestamp)
- })
-_sym_db.RegisterMessage(SignedEntryTimestamp)
-
-SignedLogRoot = _reflection.GeneratedProtocolMessageType('SignedLogRoot', (_message.Message,), {
- 'DESCRIPTOR' : _SIGNEDLOGROOT,
- '__module__' : 'trillian_pb2'
- # @@protoc_insertion_point(class_scope:trillian.SignedLogRoot)
- })
-_sym_db.RegisterMessage(SignedLogRoot)
-
-SignedMapRoot = _reflection.GeneratedProtocolMessageType('SignedMapRoot', (_message.Message,), {
- 'DESCRIPTOR' : _SIGNEDMAPROOT,
- '__module__' : 'trillian_pb2'
- # @@protoc_insertion_point(class_scope:trillian.SignedMapRoot)
- })
-_sym_db.RegisterMessage(SignedMapRoot)
-
-Proof = _reflection.GeneratedProtocolMessageType('Proof', (_message.Message,), {
- 'DESCRIPTOR' : _PROOF,
- '__module__' : 'trillian_pb2'
- # @@protoc_insertion_point(class_scope:trillian.Proof)
- })
-_sym_db.RegisterMessage(Proof)
-
-
-DESCRIPTOR._options = None
-_TREESTATE.values_by_name["DEPRECATED_SOFT_DELETED"]._options = None
-_TREESTATE.values_by_name["DEPRECATED_HARD_DELETED"]._options = None
-# @@protoc_insertion_point(module_scope)
diff --git a/proto/trillian_pb2_grpc.py b/proto/trillian_pb2_grpc.py
deleted file mode 100644
index a894352..0000000
--- a/proto/trillian_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/test/avb_aftl_fuzz.cc b/test/avb_aftl_fuzz.cc
deleted file mode 100644
index 89b59d8..0000000
--- a/test/avb_aftl_fuzz.cc
+++ /dev/null
@@ -1,35 +0,0 @@
-/*
- * Copyright (C) 2020 The Android Open Source Project
- *
- * Permission is hereby granted, free of charge, to any person
- * obtaining a copy of this software and associated documentation
- * files (the "Software"), to deal in the Software without
- * restriction, including without limitation the rights to use, copy,
- * modify, merge, publish, distribute, sublicense, and/or sell copies
- * of the Software, and to permit persons to whom the Software is
- * furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be
- * included in all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
- * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
- * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
- * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
- * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
- * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
- * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
- * SOFTWARE.
- */
-
-#include <stddef.h>
-#include <stdint.h>
-
-#include "libavb_aftl/avb_aftl_types.h"
-#include "libavb_aftl/avb_aftl_util.h"
-
-extern "C" int LLVMFuzzerTestOneInput(const char* data, size_t size) {
- AftlImage* image = parse_aftl_image((uint8_t*)data, size);
- free_aftl_image(image);
- return 0;
-}
diff --git a/test/avb_aftl_util_unittest.cc b/test/avb_aftl_util_unittest.cc
deleted file mode 100644
index 33a598c..0000000
--- a/test/avb_aftl_util_unittest.cc
+++ /dev/null
@@ -1,143 +0,0 @@
-/*
- * Copyright (C) 2020 The Android Open Source Project
- *
- * Permission is hereby granted, free of charge, to any person
- * obtaining a copy of this software and associated documentation
- * files (the "Software"), to deal in the Software without
- * restriction, including without limitation the rights to use, copy,
- * modify, merge, publish, distribute, sublicense, and/or sell copies
- * of the Software, and to permit persons to whom the Software is
- * furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be
- * included in all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
- * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
- * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
- * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
- * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
- * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
- * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
- * SOFTWARE.
- */
-
-#include "libavb_aftl/avb_aftl_util.h"
-#include <libavb_aftl/libavb_aftl.h>
-#include "avb_unittest_util.h"
-#include "libavb_aftl/avb_aftl_types.h"
-
-namespace {
-
-/* TODO(b/154115873): These VBMetas are manually generated. We need to implement
- * a mock in aftltool that generates an inclusion proof and call that mock from
- * the unit tests, similarly to what is done with GenerateVBMetaImage. */
-const char kAftlImagePath[] = "test/data/aftl_output_vbmeta_with_1_icp.img";
-const uint64_t kAftlImageOffset = 0x1100;
-const char kAftlImageMultiPath[] =
- "test/data/aftl_output_vbmeta_with_2_icp_same_log.img";
-
-} // namespace
-
-namespace avb {
-/* Extend BaseAvbToolTest to take advantage of common checks and tooling. */
-class AvbAftlUtilTest : public BaseAvbToolTest {
- public:
- AvbAftlUtilTest() {}
- ~AvbAftlUtilTest() {}
- void SetUp() override {
- std::string content;
-
- BaseAvbToolTest::SetUp();
- /* Read in test data from the aftl_image binaries. */
- ASSERT_TRUE(
- base::ReadFileToString(base::FilePath(kAftlImagePath), &content));
- content = content.substr(kAftlImageOffset);
- /* Allocate and populate an AftlImage for testing. */
- aftl_image_ = parse_aftl_image((uint8_t*)content.data(), content.size());
-
- /* Read in test data from the aftl_image file with multiple ICPs. */
- ASSERT_TRUE(
- base::ReadFileToString(base::FilePath(kAftlImageMultiPath), &content));
- content = content.substr(kAftlImageOffset);
- /* Allocate and populate an AftlImage for testing. */
- aftl_image_multi_ =
- parse_aftl_image((uint8_t*)content.data(), content.size());
- }
-
- void TearDown() override {
- free_aftl_image(aftl_image_);
- free_aftl_image(aftl_image_multi_);
- BaseAvbToolTest::TearDown();
- }
-
- void TestAftlImageHeader(AftlImageHeader* aftl_header, uint16_t icp_count) {
- EXPECT_EQ(aftl_header->magic, 0x4c544641ul);
- EXPECT_EQ(aftl_header->required_icp_version_major, 1ul);
- EXPECT_EQ(aftl_header->required_icp_version_minor, 2ul);
- EXPECT_EQ(aftl_header->icp_count, icp_count);
- }
-
- void TestAftlIcpEntry(AftlIcpEntry* icp_entry) {
- /* Test each field in the AftlIcpEntry. */
- EXPECT_GT(icp_entry->log_url_size, 0ul);
- EXPECT_GT(icp_entry->leaf_index, 1ul);
- EXPECT_GT(icp_entry->log_root_descriptor_size, 0ul);
- EXPECT_GT(icp_entry->annotation_leaf_size, 0ul);
- EXPECT_EQ(icp_entry->log_root_sig_size, AVB_AFTL_SIGNATURE_SIZE);
- EXPECT_GT(icp_entry->proof_hash_count, 0ul);
- EXPECT_LT(icp_entry->proof_hash_count, 64ul);
- EXPECT_GT(icp_entry->inc_proof_size, 0ul);
- EXPECT_EQ(mem_to_hexstring(icp_entry->log_url, 8), "6c6f672e656e6470");
- /* Test the TrillianLogRootDescriptor fields. */
- EXPECT_EQ(icp_entry->log_root_descriptor.version, 1ul);
- EXPECT_GT(icp_entry->log_root_descriptor.tree_size, 0ull);
- EXPECT_EQ(icp_entry->log_root_descriptor.root_hash_size,
- AVB_AFTL_HASH_SIZE);
- EXPECT_GT(icp_entry->log_root_descriptor.timestamp, 0ull);
- EXPECT_GT(icp_entry->log_root_descriptor.revision, 0ull);
- EXPECT_EQ(icp_entry->log_root_descriptor.metadata_size, 0);
- /* Test the FirmwareInfo fields. */
- EXPECT_EQ(icp_entry->annotation_leaf->annotation->vbmeta_hash_size,
- AVB_AFTL_HASH_SIZE);
- EXPECT_EQ(icp_entry->proof_hash_count * 32ul, icp_entry->inc_proof_size);
- }
-
- protected:
- AftlImage* aftl_image_;
- AftlImage* aftl_image_multi_;
-};
-
-TEST_F(AvbAftlUtilTest, AftlImageHeaderStructure) {
- AftlImageHeader* header;
- ASSERT_NE(aftl_image_, nullptr);
- header = &(aftl_image_->header);
- ASSERT_NE(header, nullptr);
- TestAftlImageHeader(header, 1);
-}
-
-TEST_F(AvbAftlUtilTest, AftlImageMultipleIcps) {
- AftlImageHeader* header;
- size_t i;
-
- ASSERT_NE(aftl_image_multi_, nullptr);
- header = &(aftl_image_multi_->header);
- ASSERT_NE(header, nullptr);
- TestAftlImageHeader(header, 2);
-
- for (i = 0; i < header->icp_count; i++) {
- ASSERT_NE(aftl_image_multi_->entries[i], nullptr)
- << " Failed at entry " << i;
- TestAftlIcpEntry(aftl_image_multi_->entries[i]);
- }
-}
-
-TEST_F(AvbAftlUtilTest, AftlIcpEntryStructure) {
- AftlIcpEntry* icp_entry;
-
- icp_entry = aftl_image_->entries[0];
- ASSERT_NE(icp_entry, nullptr);
- TestAftlIcpEntry(icp_entry);
-}
-
-} /* namespace avb */
diff --git a/test/avb_aftl_validate_unittest.cc b/test/avb_aftl_validate_unittest.cc
deleted file mode 100644
index 2a78e6a..0000000
--- a/test/avb_aftl_validate_unittest.cc
+++ /dev/null
@@ -1,539 +0,0 @@
-/*
- * Copyright (C) 2020 The Android Open Source Project
- *
- * Permission is hereby granted, free of charge, to any person
- * obtaining a copy of this software and associated documentation
- * files (the "Software"), to deal in the Software without
- * restriction, including without limitation the rights to use, copy,
- * modify, merge, publish, distribute, sublicense, and/or sell copies
- * of the Software, and to permit persons to whom the Software is
- * furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be
- * included in all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
- * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
- * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
- * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
- * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
- * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
- * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
- * SOFTWARE.
- */
-
-#include <gtest/gtest.h>
-
-#include <libavb_aftl/libavb_aftl.h>
-
-#include "avb_unittest_util.h"
-#include "libavb_aftl/avb_aftl_types.h"
-#include "libavb_aftl/avb_aftl_util.h"
-#include "libavb_aftl/avb_aftl_validate.h"
-
-namespace {
-
-/* Public part of testkey_rsa4096.pem, in the AvbRsaPublicKey format. Generated
- * using:
- * $ openssl rsa -in testkey_rsa4096.pem -pubout -out testkey_rsa4096_pub.pem
- * $ avbtool extract_public_key --key testkey_rsa4096_pub.pem --output \
- * testkey_rsa4096_pub.bin.
- */
-const char kKeyBytesPath[] = "test/data/testkey_rsa4096_pub.bin";
-/* Example VBMeta. Its hash should match the value kVBMetaHash defined below. */
-const char kVBMetaPath[] = "test/data/aftl_input_vbmeta.img";
-
-} /* namespace */
-
-namespace avb {
-
-/* Extend BaseAvbToolTest to take advantage of common checks and tooling. */
-class AvbAftlValidateTest : public BaseAvbToolTest {
- public:
- AvbAftlValidateTest() {}
- ~AvbAftlValidateTest() {}
- void SetUp() override {
- /* Generate an artificial inclusion proof with its own annotation. The
- * annotation matches the kVBMetaPath file. It is signed using the
- * testkey_rsa4096.pem key. */
- /* We define the constants below as string literals (to be able to annotate
- * the bytes). We keep their sizes in a separate variable as sizeof will
- * include the final null byte that is automatically appended. */
- const uint8_t kAnnotationLeafHeader[] =
- "\x01" // Version
- "\x00\x00\x00\x00\x00\x00\x00\x00" // Timestamp
- "\x01"; // Leaf Type
- const size_t kAnnotationLeafHeaderSize = sizeof(kAnnotationLeafHeader) - 1;
- const uint8_t kSignature[] =
- "\x00" // Hash Type
- "\x00" // Signature Type
- "\x00"; // Signature size
- const size_t kSignatureSize = sizeof(kSignature) - 1;
- const uint8_t kAnnotationHeader[] = "\x20"; // VBMeta hash size
- const size_t kAnnotationHeaderSize = sizeof(kAnnotationHeader) - 1;
- /* This is the SHA256 hash of the image at kVBMetaPath */
- const uint8_t kVBMetaHash[] =
- "\x34\x1c\x6c\xf2\x4b\xc1\xe6\x4a\xb1\x03\xa0\xee\xe1\x9d\xee\x9c"
- "\x35\x34\xdb\x07\x17\x29\xb4\xad\xd0\xce\xa0\xbd\x52\x92\x54\xec";
- const uint8_t kAnnotationFooter[] =
- "\x03" // Version incremental size
- "123" // Version incremental
- "\x00" // Manufacturer key hash size
- "\x00\x05" // Description size
- "abcde"; // Description
- const size_t kAnnotationFooterSize = sizeof(kAnnotationFooter) - 1;
- const uint8_t kLogRootDescriptorHeader[] =
- "\x00\x01" // Version
- "\x00\x00\x00\x00\x00\x00\x00\x03" // Tree size
- "\x20"; // Root hash size
- const size_t kLogRootDescriptorHeaderSize =
- sizeof(kLogRootDescriptorHeader) - 1;
- const uint8_t kLogRootDescriptorRootHash[] =
- "\x40\x79\x2f\xf1\xcb\xfc\xd1\x8a\x13\x70\x90\xaf\x6a\x16\x4d\xa9"
- "\x36\x80\x99\xb3\xf9\x7f\x99\x13\x3e\x07\xff\xbc\x73\x42\xfc\xc7";
- const uint8_t kLogRootDescriptorFooter[] =
- "\x00\x00\x00\x00\x13\x36\x4b\xff" // Timestamp
- "\x00\x00\x00\x00\x00\x00\x00\x00" // Revision
- "\x00\x00"; // Metadata size
- const size_t kLogRootDescriptorFooterSize =
- sizeof(kLogRootDescriptorFooter) - 1;
- /* Signature of the log root descriptor.
- * $ openssl dgst -sha256 -sign testkey_rsa4096.pem \
- * -out kLogRootHashSignature log_root_descriptor_raw
- * log_root_descriptor_raw is defined as the concatenation:
- * kLogRootDescriptorHeader || kLogRootDescriptorRootHash ||
- * kLogRootDescriptorFooter */
- const uint8_t kLogRootHashSignature[] = {
- 0x55, 0x1d, 0xd3, 0x13, 0x3c, 0x41, 0xde, 0x67, 0x79, 0xf1, 0xc6, 0xad,
- 0x72, 0x10, 0xff, 0xfb, 0x6d, 0xac, 0xc1, 0x1c, 0x06, 0x2a, 0x3e, 0xa8,
- 0xd9, 0xf3, 0x8c, 0x9c, 0x67, 0xbe, 0x1e, 0x8e, 0xe1, 0x02, 0xf6, 0xdb,
- 0xd2, 0x5c, 0x31, 0x4b, 0x26, 0xad, 0x9a, 0xd1, 0xf5, 0x7d, 0xb9, 0x6b,
- 0x4b, 0xf1, 0x7a, 0x89, 0x9d, 0xf0, 0x17, 0xb4, 0xee, 0xb2, 0x08, 0x0d,
- 0xd8, 0x99, 0xac, 0x7b, 0x34, 0x1f, 0xd1, 0x9c, 0x2e, 0x0c, 0xd1, 0xb1,
- 0x42, 0x34, 0xf2, 0x65, 0xbb, 0x79, 0x7a, 0xac, 0x23, 0x37, 0xec, 0xfc,
- 0xff, 0xbf, 0x66, 0x51, 0xed, 0x3e, 0xa7, 0x45, 0x3a, 0xf9, 0x72, 0xaa,
- 0x01, 0x3c, 0xfd, 0x59, 0x01, 0x67, 0x67, 0xb4, 0x57, 0x23, 0xb6, 0x7e,
- 0x59, 0x82, 0xb3, 0x98, 0xa2, 0x57, 0xd4, 0x64, 0x83, 0xaa, 0x02, 0x17,
- 0x87, 0xfd, 0xa2, 0xe2, 0x3b, 0xa8, 0xf5, 0xc2, 0xfb, 0xce, 0x7f, 0x59,
- 0x72, 0x10, 0xc5, 0x11, 0x81, 0x80, 0x20, 0x4a, 0x3e, 0xf9, 0x85, 0x2e,
- 0x44, 0x94, 0x87, 0xec, 0xfa, 0x2e, 0x8f, 0x75, 0x00, 0x6f, 0x52, 0x1b,
- 0x4d, 0x5c, 0xfc, 0xe4, 0x1f, 0xe2, 0x94, 0xbc, 0x8c, 0xe8, 0x7f, 0x74,
- 0x14, 0x2f, 0x66, 0x8e, 0xfb, 0x11, 0x34, 0xde, 0x80, 0x21, 0x92, 0xc3,
- 0x52, 0xa7, 0xf7, 0x5e, 0x49, 0x53, 0x21, 0x7d, 0x8b, 0xa2, 0xcb, 0x84,
- 0x80, 0x64, 0x0d, 0xd7, 0xd0, 0x6d, 0x6f, 0x2a, 0x98, 0x57, 0x3b, 0x95,
- 0xa1, 0x63, 0x39, 0x00, 0x22, 0x9e, 0x5a, 0x75, 0x07, 0x10, 0x1f, 0x7e,
- 0xdb, 0x05, 0x5d, 0x3d, 0x76, 0x75, 0x3c, 0x1a, 0xd4, 0x1e, 0x8d, 0x6e,
- 0xce, 0x57, 0xd6, 0xce, 0x23, 0xc0, 0x23, 0x4c, 0xcb, 0x10, 0xec, 0x59,
- 0x22, 0x64, 0x57, 0x33, 0x1c, 0x3f, 0xa9, 0x43, 0x97, 0xc1, 0xc0, 0x93,
- 0x5a, 0x16, 0x80, 0x51, 0x56, 0x28, 0x98, 0x33, 0xee, 0x1a, 0xf8, 0x38,
- 0x7a, 0xaa, 0xdb, 0x43, 0x39, 0x90, 0x9e, 0x74, 0xb7, 0x9f, 0xfe, 0xa5,
- 0x84, 0x69, 0xf5, 0x77, 0x80, 0x92, 0xec, 0x06, 0x06, 0xe0, 0xd2, 0x98,
- 0x34, 0x66, 0x25, 0xc3, 0x7c, 0x89, 0x78, 0x3a, 0x0b, 0x48, 0x49, 0x37,
- 0x46, 0x07, 0xc4, 0xc8, 0x04, 0x72, 0x45, 0x60, 0x36, 0x98, 0x2d, 0x47,
- 0xfe, 0xba, 0x74, 0xb9, 0xb0, 0xe4, 0xf5, 0x45, 0xa0, 0xfb, 0x4a, 0x53,
- 0xe0, 0x16, 0x6a, 0x6b, 0x82, 0xcc, 0x33, 0x1c, 0x3c, 0x64, 0xe0, 0x90,
- 0x3c, 0x59, 0xfa, 0x04, 0x51, 0xe0, 0xe8, 0xaa, 0xe9, 0x92, 0x43, 0x04,
- 0x2a, 0x49, 0xd4, 0xdf, 0xac, 0x1d, 0x46, 0x44, 0xad, 0x65, 0x62, 0xaf,
- 0x44, 0x16, 0xb0, 0x05, 0x56, 0x2b, 0xa4, 0xad, 0x4c, 0x7e, 0xbd, 0x04,
- 0x95, 0xcb, 0xce, 0x0e, 0xf6, 0xd5, 0x4b, 0x3a, 0xc0, 0xde, 0x1e, 0xf8,
- 0xfa, 0xf5, 0x73, 0x4a, 0x6d, 0xc2, 0x4a, 0xe1, 0xaf, 0xae, 0xd8, 0x31,
- 0x23, 0x16, 0x5d, 0x15, 0x41, 0xe6, 0xbf, 0x4a, 0xe0, 0xf3, 0xdd, 0x74,
- 0x32, 0x96, 0x64, 0x4c, 0x16, 0x7d, 0xd3, 0xad, 0x21, 0x47, 0x2b, 0x17,
- 0xb9, 0xf3, 0x84, 0x38, 0x80, 0x60, 0xb6, 0xcb, 0x24, 0x45, 0x24, 0x90,
- 0x74, 0xe9, 0x50, 0xea, 0x2e, 0x1f, 0xc2, 0x74, 0x36, 0xa2, 0xf5, 0xd7,
- 0x24, 0xb3, 0xa1, 0x1f, 0xd3, 0x39, 0x61, 0x67, 0x37, 0xe4, 0x2a, 0x20,
- 0x67, 0x95, 0x53, 0x9d, 0xd4, 0xdb, 0x4f, 0xa6, 0xb8, 0x7f, 0x91, 0xb2,
- 0xc5, 0x6f, 0x71, 0x3c, 0x86, 0xc8, 0x36, 0x8d, 0xa4, 0x4d, 0x53, 0x6b,
- 0x3f, 0xe6, 0xce, 0xf1, 0x7a, 0xa2, 0x2e, 0x53, 0x80, 0x4c, 0x52, 0x9d,
- 0x3e, 0xd7, 0xec, 0x47, 0x4a, 0xfa, 0x84, 0xa5, 0x9a, 0x2f, 0x7b, 0xfc,
- 0xfc, 0xe8, 0xa4, 0x09, 0xfb, 0xb5, 0xb7, 0xf2};
- BaseAvbToolTest::SetUp();
-
- /* Read in test data from the key and log_sig binaries. */
- ASSERT_TRUE(
- base::ReadFileToString(base::FilePath(kKeyBytesPath), &key_bytes_));
-
- /* Allocate and populate the inclusion proof */
- icp_entry_ = (AftlIcpEntry*)avb_malloc(sizeof(AftlIcpEntry));
- if (!icp_entry_) return;
- icp_entry_->log_root_descriptor.version = 1;
- icp_entry_->log_root_descriptor.tree_size = 3;
- icp_entry_->log_root_descriptor.root_hash_size = AVB_AFTL_HASH_SIZE;
- icp_entry_->log_root_descriptor.timestamp = 322325503;
- icp_entry_->log_root_descriptor.revision = 0;
- icp_entry_->log_root_descriptor.metadata_size = 0;
- icp_entry_->log_root_descriptor.metadata = NULL;
- icp_entry_->log_root_descriptor_size = kLogRootDescriptorHeaderSize +
- AVB_AFTL_HASH_SIZE +
- kLogRootDescriptorFooterSize;
- icp_entry_->log_root_descriptor_raw =
- (uint8_t*)avb_malloc(icp_entry_->log_root_descriptor_size);
- if (!icp_entry_->log_root_descriptor_raw) {
- return;
- }
- memcpy(icp_entry_->log_root_descriptor_raw,
- kLogRootDescriptorHeader,
- kLogRootDescriptorHeaderSize);
- memcpy(icp_entry_->log_root_descriptor_raw + kLogRootDescriptorHeaderSize,
- kLogRootDescriptorRootHash,
- AVB_AFTL_HASH_SIZE);
- memcpy(icp_entry_->log_root_descriptor_raw + kLogRootDescriptorHeaderSize +
- AVB_AFTL_HASH_SIZE,
- kLogRootDescriptorFooter,
- kLogRootDescriptorFooterSize);
- icp_entry_->log_root_descriptor.root_hash =
- (uint8_t*)avb_malloc(AVB_AFTL_HASH_SIZE);
- if (!icp_entry_->log_root_descriptor.root_hash) return;
- /* Copy the hash from within the raw version */
- memcpy(icp_entry_->log_root_descriptor.root_hash,
- kLogRootDescriptorRootHash,
- AVB_AFTL_HASH_SIZE);
- icp_entry_->log_root_sig_size = AVB_AFTL_SIGNATURE_SIZE;
- icp_entry_->log_root_signature =
- (uint8_t*)avb_malloc(AVB_AFTL_SIGNATURE_SIZE);
- memcpy(icp_entry_->log_root_signature,
- kLogRootHashSignature,
- AVB_AFTL_SIGNATURE_SIZE);
-
- /* Allocate the annotation leaf */
- icp_entry_->annotation_leaf_size =
- kAnnotationLeafHeaderSize + kSignatureSize + kAnnotationHeaderSize +
- AVB_AFTL_HASH_SIZE + kAnnotationFooterSize;
- icp_entry_->annotation_leaf =
- (SignedVBMetaPrimaryAnnotationLeaf*)avb_calloc(
- sizeof(SignedVBMetaPrimaryAnnotationLeaf));
- if (!icp_entry_->annotation_leaf) return;
- icp_entry_->annotation_leaf->version = 1;
- icp_entry_->annotation_leaf->timestamp = 0;
- icp_entry_->annotation_leaf->leaf_type =
- AVB_AFTL_SIGNED_VBMETA_PRIMARY_ANNOTATION_LEAF;
- icp_entry_->annotation_leaf->annotation =
- (VBMetaPrimaryAnnotation*)avb_calloc(sizeof(VBMetaPrimaryAnnotation));
- if (!icp_entry_->annotation_leaf->annotation) return;
- icp_entry_->annotation_leaf->annotation->vbmeta_hash_size =
- AVB_AFTL_HASH_SIZE;
- icp_entry_->annotation_leaf->annotation->vbmeta_hash =
- (uint8_t*)avb_calloc(AVB_AFTL_HASH_SIZE);
- if (!icp_entry_->annotation_leaf->annotation->vbmeta_hash) return;
- memcpy(icp_entry_->annotation_leaf->annotation->vbmeta_hash,
- kVBMetaHash,
- AVB_AFTL_HASH_SIZE);
- icp_entry_->annotation_leaf_raw =
- (uint8_t*)avb_calloc(icp_entry_->annotation_leaf_size);
- if (!icp_entry_->annotation_leaf_raw) return;
- memcpy(icp_entry_->annotation_leaf_raw,
- kAnnotationLeafHeader,
- kAnnotationLeafHeaderSize);
- memcpy(icp_entry_->annotation_leaf_raw + kAnnotationLeafHeaderSize,
- kSignature,
- kSignatureSize);
- memcpy(icp_entry_->annotation_leaf_raw + kAnnotationLeafHeaderSize +
- kSignatureSize,
- kAnnotationHeader,
- kAnnotationHeaderSize);
- memcpy(icp_entry_->annotation_leaf_raw + kAnnotationLeafHeaderSize +
- kSignatureSize + kAnnotationHeaderSize,
- kVBMetaHash,
- AVB_AFTL_HASH_SIZE);
- memcpy(icp_entry_->annotation_leaf_raw + kAnnotationLeafHeaderSize +
- kSignatureSize + kAnnotationHeaderSize + AVB_AFTL_HASH_SIZE,
- kAnnotationFooter,
- kAnnotationFooterSize);
-
- icp_entry_->leaf_index = 2;
- icp_entry_->proofs =
- (uint8_t(*)[AVB_AFTL_HASH_SIZE])avb_calloc(AVB_AFTL_HASH_SIZE);
- memcpy(icp_entry_->proofs[0],
- "\xfa\xc5\x42\x03\xe7\xcc\x69\x6c\xf0\xdf\xcb\x42\xc9\x2a\x1d\x9d"
- "\xba\xf7\x0a\xd9\xe6\x21\xf4\xbd\x8d\x98\x66\x2f\x00\xe3\xc1\x25",
- AVB_AFTL_HASH_SIZE);
- icp_entry_->proof_hash_count = 1;
- }
-
- void TearDown() override {
- if (icp_entry_) {
- if (icp_entry_->annotation_leaf_raw)
- avb_free(icp_entry_->annotation_leaf_raw);
- if (icp_entry_->annotation_leaf) {
- if (icp_entry_->annotation_leaf->annotation) {
- if (icp_entry_->annotation_leaf->annotation->vbmeta_hash)
- avb_free(icp_entry_->annotation_leaf->annotation->vbmeta_hash);
- avb_free(icp_entry_->annotation_leaf->annotation);
- }
- avb_free(icp_entry_->annotation_leaf);
- }
- if (icp_entry_->log_root_descriptor.root_hash)
- avb_free(icp_entry_->log_root_descriptor.root_hash);
- if (icp_entry_->log_root_descriptor_raw)
- avb_free(icp_entry_->log_root_descriptor_raw);
- if (icp_entry_->log_root_signature)
- avb_free(icp_entry_->log_root_signature);
- if (icp_entry_->proofs) avb_free(icp_entry_->proofs);
- avb_free(icp_entry_);
- }
- BaseAvbToolTest::TearDown();
- }
-
- protected:
- AftlIcpEntry* icp_entry_;
- std::string key_bytes_;
-};
-
-TEST_F(AvbAftlValidateTest, VerifyEntrySignature) {
- EXPECT_EQ(true,
- avb_aftl_verify_entry_signature(
- (uint8_t*)key_bytes_.data(), key_bytes_.size(), icp_entry_));
-}
-
-TEST_F(AvbAftlValidateTest, VerifyIcpRootHash) {
- EXPECT_EQ(true, avb_aftl_verify_icp_root_hash(icp_entry_));
-}
-
-TEST_F(AvbAftlValidateTest, VerifyVbmetaHash) {
- std::string vbmeta;
- ASSERT_TRUE(base::ReadFileToString(base::FilePath(kVBMetaPath), &vbmeta));
- EXPECT_EQ(true,
- avb_aftl_verify_vbmeta_hash(
- (uint8_t*)vbmeta.data(), vbmeta.size(), icp_entry_));
-}
-
-TEST_F(AvbAftlValidateTest, RootFromIcp) {
- /* Tests from trillian root_from_icp functionality:
- https://github.com/google/trillian/blob/master/merkle/log_verifier_test.go
- */
- uint64_t leaf_index;
- uint64_t tree_size;
- uint8_t proof[3][AVB_AFTL_HASH_SIZE];
- uint8_t leaf_hash[AVB_AFTL_HASH_SIZE];
- uint8_t hash[AVB_AFTL_HASH_SIZE];
-
- leaf_index = 0;
- tree_size = 8;
- avb_aftl_rfc6962_hash_leaf((uint8_t*)"", 0, leaf_hash);
- memcpy(proof[0],
- "\x96\xa2\x96\xd2\x24\xf2\x85\xc6\x7b\xee\x93\xc3\x0f\x8a\x30\x91"
- "\x57\xf0\xda\xa3\x5d\xc5\xb8\x7e\x41\x0b\x78\x63\x0a\x09\xcf\xc7",
- AVB_AFTL_HASH_SIZE);
- memcpy(proof[1],
- "\x5f\x08\x3f\x0a\x1a\x33\xca\x07\x6a\x95\x27\x98\x32\x58\x0d\xb3"
- "\xe0\xef\x45\x84\xbd\xff\x1f\x54\xc8\xa3\x60\xf5\x0d\xe3\x03\x1e",
- AVB_AFTL_HASH_SIZE);
- memcpy(proof[2],
- "\x6b\x47\xaa\xf2\x9e\xe3\xc2\xaf\x9a\xf8\x89\xbc\x1f\xb9\x25\x4d"
- "\xab\xd3\x11\x77\xf1\x62\x32\xdd\x6a\xab\x03\x5c\xa3\x9b\xf6\xe4",
- AVB_AFTL_HASH_SIZE);
- avb_aftl_root_from_icp(
- leaf_index, tree_size, proof, 3, leaf_hash, AVB_AFTL_HASH_SIZE, hash);
- EXPECT_EQ("5dc9da79a70659a9ad559cb701ded9a2ab9d823aad2f4960cfe370eff4604328",
- mem_to_hexstring(hash, AVB_AFTL_HASH_SIZE))
- << "Failed on test #1";
-
- leaf_index = 5;
- tree_size = 8;
- avb_aftl_rfc6962_hash_leaf((uint8_t*)"@ABC", 4, leaf_hash);
- memcpy(proof[0],
- "\xbc\x1a\x06\x43\xb1\x2e\x4d\x2d\x7c\x77\x91\x8f\x44\xe0\xf4\xf7"
- "\x9a\x83\x8b\x6c\xf9\xec\x5b\x5c\x28\x3e\x1f\x4d\x88\x59\x9e\x6b",
- AVB_AFTL_HASH_SIZE);
- memcpy(proof[1],
- "\xca\x85\x4e\xa1\x28\xed\x05\x0b\x41\xb3\x5f\xfc\x1b\x87\xb8\xeb"
- "\x2b\xde\x46\x1e\x9e\x3b\x55\x96\xec\xe6\xb9\xd5\x97\x5a\x0a\xe0",
- AVB_AFTL_HASH_SIZE);
- memcpy(proof[2],
- "\xd3\x7e\xe4\x18\x97\x6d\xd9\x57\x53\xc1\xc7\x38\x62\xb9\x39\x8f"
- "\xa2\xa2\xcf\x9b\x4f\xf0\xfd\xfe\x8b\x30\xcd\x95\x20\x96\x14\xb7",
- AVB_AFTL_HASH_SIZE);
- avb_aftl_root_from_icp(
- leaf_index, tree_size, proof, 3, leaf_hash, AVB_AFTL_HASH_SIZE, hash);
- EXPECT_EQ("5dc9da79a70659a9ad559cb701ded9a2ab9d823aad2f4960cfe370eff4604328",
- mem_to_hexstring(hash, AVB_AFTL_HASH_SIZE))
- << "Failed on test #2";
-
- leaf_index = 2;
- tree_size = 3;
- avb_aftl_rfc6962_hash_leaf((uint8_t*)"\x10", 1, leaf_hash);
- memcpy(proof[0],
- "\xfa\xc5\x42\x03\xe7\xcc\x69\x6c\xf0\xdf\xcb\x42\xc9\x2a\x1d\x9d"
- "\xba\xf7\x0a\xd9\xe6\x21\xf4\xbd\x8d\x98\x66\x2f\x00\xe3\xc1\x25",
- AVB_AFTL_HASH_SIZE);
- avb_aftl_root_from_icp(
- leaf_index, tree_size, proof, 1, leaf_hash, AVB_AFTL_HASH_SIZE, hash);
- EXPECT_EQ("aeb6bcfe274b70a14fb067a5e5578264db0fa9b51af5e0ba159158f329e06e77",
- mem_to_hexstring(hash, AVB_AFTL_HASH_SIZE))
- << "Failed on test #3";
-
- leaf_index = 1;
- tree_size = 5;
- avb_aftl_rfc6962_hash_leaf((uint8_t*)"\x00", 1, leaf_hash);
- memcpy(proof[0],
- "\x6e\x34\x0b\x9c\xff\xb3\x7a\x98\x9c\xa5\x44\xe6\xbb\x78\x0a\x2c"
- "\x78\x90\x1d\x3f\xb3\x37\x38\x76\x85\x11\xa3\x06\x17\xaf\xa0\x1d",
- AVB_AFTL_HASH_SIZE);
- memcpy(proof[1],
- "\x5f\x08\x3f\x0a\x1a\x33\xca\x07\x6a\x95\x27\x98\x32\x58\x0d\xb3"
- "\xe0\xef\x45\x84\xbd\xff\x1f\x54\xc8\xa3\x60\xf5\x0d\xe3\x03\x1e",
- AVB_AFTL_HASH_SIZE);
- memcpy(proof[2],
- "\xbc\x1a\x06\x43\xb1\x2e\x4d\x2d\x7c\x77\x91\x8f\x44\xe0\xf4\xf7"
- "\x9a\x83\x8b\x6c\xf9\xec\x5b\x5c\x28\x3e\x1f\x4d\x88\x59\x9e\x6b",
- AVB_AFTL_HASH_SIZE);
- avb_aftl_root_from_icp(
- leaf_index, tree_size, proof, 3, leaf_hash, AVB_AFTL_HASH_SIZE, hash);
- EXPECT_EQ("4e3bbb1f7b478dcfe71fb631631519a3bca12c9aefca1612bfce4c13a86264d4",
- mem_to_hexstring(hash, AVB_AFTL_HASH_SIZE))
- << "Failed on test #4";
-}
-
-TEST_F(AvbAftlValidateTest, ChainInner) {
- uint8_t hash[AVB_AFTL_HASH_SIZE];
- uint8_t seed[AVB_AFTL_HASH_SIZE];
- uint8_t proof[4][AVB_AFTL_HASH_SIZE];
- uint64_t i;
-
- for (i = 0; i < AVB_AFTL_HASH_SIZE; i++) {
- hash[i] = 0;
- }
-
- memcpy(seed, "1234567890abcdefghijklmnopqrstuv", AVB_AFTL_HASH_SIZE);
- memcpy(proof[0], "abcdefghijklmnopqrstuvwxyz123456", AVB_AFTL_HASH_SIZE);
- avb_aftl_chain_inner(seed, AVB_AFTL_HASH_SIZE, (uint8_t*)proof, 1, 0, hash);
- EXPECT_EQ("9cb6af81b146b6a81d911d26f4c0d467265a3385d6caf926d5515e58efd161a3",
- mem_to_hexstring(hash, AVB_AFTL_HASH_SIZE))
- << "Failed with seed: "
- << "\"1234567890abcdefghijklmnopqrstuv\", proof ["
- << "\"abcdefghijklmnopqrstuvwxyz123456\"], and leaf_index 0";
- memcpy(proof[1], "7890abcdefghijklmnopqrstuvwxyz12", AVB_AFTL_HASH_SIZE);
- avb_aftl_chain_inner(seed, AVB_AFTL_HASH_SIZE, (uint8_t*)proof, 2, 0, hash);
- EXPECT_EQ("368d8213cd7d62335a84b3a3d75c8a0302c0d63c93cbbd22c5396dc4c75ba019",
- mem_to_hexstring(hash, AVB_AFTL_HASH_SIZE))
- << "Failed with seed: "
- << "\"1234567890abcdefghijklmnopqrstuv\", proof ["
- << "\"abcdefghijklmnopqrstuvwxyz123456\", "
- "\"7890abcdefghijklmnopqrstuvwxyz12\"],"
- << " and leaf_index 0";
- avb_aftl_chain_inner(seed, AVB_AFTL_HASH_SIZE, (uint8_t*)proof, 2, 1, hash);
- EXPECT_EQ("78418158eb5943c50ec581b41f105ba9aecc1b9e7aba3ea2e93021cbd5bd166e",
- mem_to_hexstring(hash, AVB_AFTL_HASH_SIZE))
- << "Failed with seed: "
- << "\"1234567890abcdefghijklmnopqrstuv\", proof ["
- << "\"abcdefghijklmnopqrstuvwxyz123456\", "
- "\"7890abcdefghijklmnopqrstuvwxyz12\"],"
- << " and leaf_index 1";
- memcpy(proof[2], "abcdefghijklmn0pqrstuvwxyz123456", AVB_AFTL_HASH_SIZE);
- memcpy(proof[3], "7890abcdefgh1jklmnopqrstuvwxyz12", AVB_AFTL_HASH_SIZE);
- avb_aftl_chain_inner(seed, AVB_AFTL_HASH_SIZE, (uint8_t*)proof, 4, 1, hash);
- EXPECT_EQ("83309c48fb92707f5788b6dd4c9a89042dff20856ad9529b7fb8e5cdf47c04f8",
- mem_to_hexstring(hash, AVB_AFTL_HASH_SIZE))
- << "Failed with seed: "
- << "\"1234567890abcdefghijklmnopqrstuv\", proof ["
- << "\"abcdefghijklmnopqrstuvwxyz123456\", "
- "\"7890abcdefghijklmnopqrstuvwxyz12\","
- << "\"abcdefghijklmnopqrstuvwxyz123456\", "
- "\"7890abcdefghijklmnopqrstuvwxyz12\"]"
- << " and leaf_index 1";
- avb_aftl_chain_inner(seed, AVB_AFTL_HASH_SIZE, (uint8_t*)proof, 4, 3, hash);
- EXPECT_EQ("13e5f7e441dc4dbea659acbc989ac33222f4447546e3dac36b0e0c9977d52b97",
- mem_to_hexstring(hash, AVB_AFTL_HASH_SIZE))
- << "Failed with seed: "
- << "\"1234567890abcdefghijklmnopqrstuv\", proof ["
- << "\"abcdefghijklmnopqrstuvwxyz123456\", "
- "\"7890abcdefghijklmnopqrstuvwxyz12\","
- << "\"abcdefghijklmnopqrstuvwxyz123456\", "
- "\"7890abcdefghijklmnopqrstuvwxyz12\"]"
- << " and leaf_index 3";
-}
-
-TEST_F(AvbAftlValidateTest, ChainBorderRight) {
- uint8_t hash[AVB_AFTL_HASH_SIZE];
- uint8_t seed[AVB_AFTL_HASH_SIZE];
- uint8_t proof[2][AVB_AFTL_HASH_SIZE];
- uint64_t i;
-
- for (i = 0; i < AVB_AFTL_HASH_SIZE; i++) {
- hash[i] = 0;
- }
-
- memcpy(seed, "1234567890abcdefghijklmnopqrstuv", AVB_AFTL_HASH_SIZE);
- memcpy(proof[0], "abcdefghijklmnopqrstuvwxyz123456", AVB_AFTL_HASH_SIZE);
- avb_aftl_chain_border_right(
- seed, AVB_AFTL_HASH_SIZE, (uint8_t*)proof, 1, hash);
- EXPECT_EQ("363aa8a62b784be38392ab69ade1aac2562f8989ce8986bec685d2957d657310",
- mem_to_hexstring(hash, AVB_AFTL_HASH_SIZE))
- << "Failed with seed: "
- << "\"1234567890abcdefghijklmnopqrstuv\" and proof "
- "[\"abcdefghijklmnopqrstuvwxyz123456\"]";
- memcpy(proof[1], "7890abcdefghijklmnopqrstuvwxyz12", AVB_AFTL_HASH_SIZE);
- avb_aftl_chain_border_right(
- seed, AVB_AFTL_HASH_SIZE, (uint8_t*)proof, 2, hash);
- EXPECT_EQ("618fc58c45faea808e0bbe0f82afbe7687f4db2608824120e8ade507cbce221f",
- mem_to_hexstring(hash, AVB_AFTL_HASH_SIZE))
- << "Failed with seed: "
- << "\"1234567890abcdefghijklmnopqrstuv\" and proof ["
- << "\"abcdefghijklmnopqrstuvwxyz123456\", "
- "\"7890abcdefghijklmnopqrstuvwxyz12\"]";
-}
-
-TEST_F(AvbAftlValidateTest, RFC6962HashChildren) {
- uint8_t hash[AVB_AFTL_HASH_SIZE];
-
- avb_aftl_rfc6962_hash_children((uint8_t*)"", 0, (uint8_t*)"", 0, hash);
- EXPECT_EQ("4bf5122f344554c53bde2ebb8cd2b7e3d1600ad631c385a5d7cce23c7785459a",
- mem_to_hexstring(hash, AVB_AFTL_HASH_SIZE))
- << "Failed on inputs \"\" and \"\"";
-
- avb_aftl_rfc6962_hash_children((uint8_t*)"abcd", 4, (uint8_t*)"", 0, hash);
- EXPECT_EQ("b75eb7b06e69c1c49597fba37398e0f5ba319c7164ed67bb19b41e9d576313b9",
- mem_to_hexstring(hash, AVB_AFTL_HASH_SIZE))
- << "Failed on inputs \"abcd\" and \"\"";
-
- avb_aftl_rfc6962_hash_children((uint8_t*)"", 0, (uint8_t*)"efgh", 4, hash);
- EXPECT_EQ("8d65f3e92e3853cee633345caca3e035f01c2e44815371985baed2c45c10ca40",
- mem_to_hexstring(hash, AVB_AFTL_HASH_SIZE))
- << "Failed on inputs \"\" and \"efgh\"";
-
- avb_aftl_rfc6962_hash_children(
- (uint8_t*)"abcd", 4, (uint8_t*)"efgh", 4, hash);
- EXPECT_EQ("41561b1297f692dad705e28ece8bf47060fba1abeeebda0aa67c43570a36bf79",
- mem_to_hexstring(hash, AVB_AFTL_HASH_SIZE))
- << "Failed on inputs \"abcd\" and \"efgh\"";
-}
-
-TEST_F(AvbAftlValidateTest, RFC6962HashLeaf) {
- uint8_t hash[AVB_AFTL_HASH_SIZE];
- avb_aftl_rfc6962_hash_leaf((uint8_t*)"", 0, hash);
- EXPECT_EQ("6e340b9cffb37a989ca544e6bb780a2c78901d3fb33738768511a30617afa01d",
- mem_to_hexstring(hash, AVB_AFTL_HASH_SIZE))
- << "Failed on input \"\"";
- avb_aftl_rfc6962_hash_leaf((uint8_t*)"abcdefg", 7, hash);
- EXPECT_EQ("6b43f785b72386e132b275bc918c25dbc687ab8427836bef6ce4509b64f4f54d",
- mem_to_hexstring(hash, AVB_AFTL_HASH_SIZE))
- << "Failed on input \"abcdefg\"";
-}
-
-TEST_F(AvbAftlValidateTest, Sha256) {
- /* Computed with:
- *
- * $ echo -n foobar |sha256sum
- * c3ab8ff13720e8ad9047dd39466b3c8974e592c2fa383d4a3960714caef0c4f2
- */
- uint8_t hash[AVB_AFTL_HASH_SIZE];
- avb_aftl_sha256(NULL, 0, hash);
- EXPECT_EQ("e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855",
- mem_to_hexstring(hash, AVB_AFTL_HASH_SIZE));
- avb_aftl_sha256((uint8_t*)"foobar", 6, hash);
- EXPECT_EQ("c3ab8ff13720e8ad9047dd39466b3c8974e592c2fa383d4a3960714caef0c4f2",
- mem_to_hexstring(hash, AVB_AFTL_HASH_SIZE));
-}
-
-TEST_F(AvbAftlValidateTest, AvbAftlCountLeadingZeros) {
- /* Spot checks to ensure aftl_count_leading_zeros is correct. */
- EXPECT_EQ(52ull, avb_aftl_count_leading_zeros(4095))
- << "Failed on input 4095";
- EXPECT_EQ(12ull, avb_aftl_count_leading_zeros(0xfffffffffffff))
- << "Failed on input 0xfffffffffffff";
- EXPECT_EQ(64ull, avb_aftl_count_leading_zeros(0)) << "Failed on input 0";
- EXPECT_EQ(0ull, avb_aftl_count_leading_zeros(0xffffffffffffffff))
- << "Failed on input 0xffffffffffffffff";
-}
-
-} /* namespace avb */
diff --git a/test/avb_aftl_verify_unittest.cc b/test/avb_aftl_verify_unittest.cc
deleted file mode 100644
index 1e44a4a..0000000
--- a/test/avb_aftl_verify_unittest.cc
+++ /dev/null
@@ -1,140 +0,0 @@
-/*
- * Copyright (C) 2020 The Android Open Source Project
- *
- * Permission is hereby granted, free of charge, to any person
- * obtaining a copy of this software and associated documentation
- * files (the "Software"), to deal in the Software without
- * restriction, including without limitation the rights to use, copy,
- * modify, merge, publish, distribute, sublicense, and/or sell copies
- * of the Software, and to permit persons to whom the Software is
- * furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be
- * included in all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
- * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
- * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
- * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
- * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
- * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
- * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
- * SOFTWARE.
- */
-
-#include <gtest/gtest.h>
-
-#include <libavb_aftl/libavb_aftl.h>
-
-#include "avb_unittest_util.h"
-#include "fake_avb_ops.h"
-#include "libavb_aftl/avb_aftl_types.h"
-#include "libavb_aftl/avb_aftl_util.h"
-#include "libavb_aftl/avb_aftl_validate.h"
-#include "libavb_aftl/avb_aftl_verify.h"
-
-namespace {
-
-/* Log transparency key */
-const char kAftlTestKey[] = "test/data/aftl_pubkey_1.bin";
-/* Full VBMeta partition which contains an AftlImage */
-/* TODO(b/154115873): These VBMetas are manually generated. We need to implement
- * a mock in aftltool that generates an inclusion proof and call that mock from
- * the unit tests, similarly to what is done with GenerateVBMetaImage. */
-const char kVbmetaWithAftlDescBin[] =
- "test/data/aftl_output_vbmeta_with_1_icp.img";
-/* Size of the VBMetaImage in the partition */
-const uint64_t kVbmetaSize = 0x1100;
-
-} /* namespace */
-
-namespace avb {
-
-/* Extend BaseAvbToolTest to take advantage of common checks and tooling. */
-class AvbAftlVerifyTest : public BaseAvbToolTest,
- public FakeAvbOpsDelegateWithDefaults {
- public:
- AvbAftlVerifyTest() {}
- ~AvbAftlVerifyTest() {}
- void SetUp() override {
- BaseAvbToolTest::SetUp();
- ops_.set_delegate(this);
- ops_.set_partition_dir(base::FilePath("test/data"));
- asv_test_data_ = NULL;
-
- /* Read in the test data. */
- ASSERT_TRUE(base::ReadFileToString(base::FilePath(kAftlTestKey), &key_));
- ASSERT_TRUE(base::ReadFileToString(base::FilePath(kVbmetaWithAftlDescBin),
- &vbmeta_icp_));
- /* Keep a truncated version of the image without the ICP */
- vbmeta_ = vbmeta_icp_.substr(0, kVbmetaSize);
-
- /* Set up required parts of asv_test_data */
- asv_test_data_ = (AvbSlotVerifyData*)avb_calloc(sizeof(AvbSlotVerifyData));
- ASSERT_TRUE(asv_test_data_ != NULL);
- asv_test_data_->ab_suffix = (char*)"";
- asv_test_data_->num_vbmeta_images = 1;
- asv_test_data_->vbmeta_images =
- (AvbVBMetaData*)avb_calloc(sizeof(AvbVBMetaData));
- ASSERT_TRUE(asv_test_data_->vbmeta_images != NULL);
- asv_test_data_->vbmeta_images[0].vbmeta_size = vbmeta_.size();
- asv_test_data_->vbmeta_images[0].vbmeta_data =
- (uint8_t*)avb_calloc(vbmeta_.size());
- ASSERT_TRUE(asv_test_data_->vbmeta_images[0].vbmeta_data != NULL);
- memcpy(asv_test_data_->vbmeta_images[0].vbmeta_data,
- vbmeta_.data(),
- vbmeta_.size());
- asv_test_data_->vbmeta_images[0].partition_name =
- (char*)"aftl_output_vbmeta_with_1_icp";
- }
-
- void TearDown() override {
- if (asv_test_data_ != NULL) {
- if (asv_test_data_->vbmeta_images != NULL) {
- if (asv_test_data_->vbmeta_images[0].vbmeta_data != NULL) {
- avb_free(asv_test_data_->vbmeta_images[0].vbmeta_data);
- }
- avb_free(asv_test_data_->vbmeta_images);
- }
- avb_free(asv_test_data_);
- }
- BaseAvbToolTest::TearDown();
- }
-
- protected:
- AvbSlotVerifyData* asv_test_data_;
- std::string key_;
- std::string vbmeta_;
- std::string vbmeta_icp_;
-};
-
-TEST_F(AvbAftlVerifyTest, Basic) {
- AftlSlotVerifyResult result = aftl_slot_verify(
- ops_.avb_ops(), asv_test_data_, (uint8_t*)key_.data(), key_.size());
- EXPECT_EQ(result, AFTL_SLOT_VERIFY_RESULT_OK);
-}
-
-TEST_F(AvbAftlVerifyTest, PartitionError) {
- asv_test_data_->vbmeta_images[0].partition_name = (char*)"do-no-exist";
- AftlSlotVerifyResult result = aftl_slot_verify(
- ops_.avb_ops(), asv_test_data_, (uint8_t*)key_.data(), key_.size());
- EXPECT_EQ(result, AFTL_SLOT_VERIFY_RESULT_ERROR_IMAGE_NOT_FOUND);
-}
-
-TEST_F(AvbAftlVerifyTest, MismatchingVBMeta) {
- asv_test_data_->vbmeta_images[0].vbmeta_data[0] = 'X';
- AftlSlotVerifyResult result = aftl_slot_verify(
- ops_.avb_ops(), asv_test_data_, (uint8_t*)key_.data(), key_.size());
- EXPECT_EQ(result, AFTL_SLOT_VERIFY_RESULT_ERROR_VBMETA_HASH_MISMATCH);
-}
-
-TEST_F(AvbAftlVerifyTest, InvalidKey) {
- // Corrupt the key in order to fail the verification: complement the last
- // byte, we keep the key header valid.
- key_[key_.size() - 1] = ~key_[key_.size() - 1];
- AftlSlotVerifyResult result = aftl_slot_verify(
- ops_.avb_ops(), asv_test_data_, (uint8_t*)key_.data(), key_.size());
- EXPECT_EQ(result, AFTL_SLOT_VERIFY_RESULT_ERROR_INVALID_PROOF_SIGNATURE);
-}
-
-} /* namespace avb */
diff --git a/test/avbtool_unittest.cc b/test/avbtool_unittest.cc
index 7fb89c4..908aa71 100644
--- a/test/avbtool_unittest.cc
+++ b/test/avbtool_unittest.cc
@@ -1950,6 +1950,59 @@
path.value().c_str());
}
+TEST_F(AvbToolTest, AddHashtreeFooterWithCheckAtMostOnce) {
+ size_t partition_size = 10 * 1024 * 1024;
+ base::FilePath path = GenerateImage("digest_location", partition_size / 2);
+ EXPECT_COMMAND(0,
+ "./avbtool add_hashtree_footer --salt d00df00d "
+ "--hash_algorithm sha256 --image %s "
+ "--partition_size %d --partition_name foobar "
+ "--algorithm SHA256_RSA2048 "
+ "--key test/data/testkey_rsa2048.pem "
+ "--internal_release_string \"\" "
+ "--check_at_most_once",
+ path.value().c_str(),
+ (int)partition_size);
+ // There are two important bits here we're expecting with --check_at_most_once:
+ // Minimum libavb version = 1.1
+ // Hashtree descriptor -> Flags = 2
+ ASSERT_EQ(
+ "Footer version: 1.0\n"
+ "Image size: 10485760 bytes\n"
+ "Original image size: 5242880 bytes\n"
+ "VBMeta offset: 5337088\n"
+ "VBMeta size: 1344 bytes\n"
+ "--\n"
+ "Minimum libavb version: 1.1\n"
+ "Header Block: 256 bytes\n"
+ "Authentication Block: 320 bytes\n"
+ "Auxiliary Block: 768 bytes\n"
+ "Public key (sha1): cdbb77177f731920bbe0a0f94f84d9038ae0617d\n"
+ "Algorithm: SHA256_RSA2048\n"
+ "Rollback Index: 0\n"
+ "Flags: 0\n"
+ "Rollback Index Location: 0\n"
+ "Release String: ''\n"
+ "Descriptors:\n"
+ " Hashtree descriptor:\n"
+ " Version of dm-verity: 1\n"
+ " Image Size: 5242880 bytes\n"
+ " Tree Offset: 5242880\n"
+ " Tree Size: 45056 bytes\n"
+ " Data Block Size: 4096 bytes\n"
+ " Hash Block Size: 4096 bytes\n"
+ " FEC num roots: 2\n"
+ " FEC offset: 5287936\n"
+ " FEC size: 49152 bytes\n"
+ " Hash Algorithm: sha256\n"
+ " Partition Name: foobar\n"
+ " Salt: d00df00d\n"
+ " Root Digest: "
+ "d0e31526f5a3f8e3f59acf726bd31ae7861ee78f9baa9195356bf479c6f9119d\n"
+ " Flags: 2\n",
+ InfoImage(path));
+}
+
TEST_F(AvbToolTest, KernelCmdlineDescriptor) {
base::FilePath vbmeta_path =
testdir_.Append("vbmeta_kernel_cmdline_desc.bin");
@@ -3118,7 +3171,7 @@
std::string extra_args;
if (target_required_minor_version == 1) {
// The --do_not_use_ab option will require 1.1.
- extra_args = "--do_not_use_ab";
+ extra_args = "--do_not_use_ab --check_at_most_once";
} else if (target_required_minor_version == 2) {
extra_args = "--rollback_index_location 2";
}
diff --git a/test/corpus/icp.bin b/test/corpus/icp.bin
deleted file mode 100644
index 19125fe..0000000
--- a/test/corpus/icp.bin
+++ /dev/null
Binary files differ
diff --git a/test/data/aftl_input_vbmeta.img b/test/data/aftl_input_vbmeta.img
deleted file mode 100644
index 4660701..0000000
--- a/test/data/aftl_input_vbmeta.img
+++ /dev/null
Binary files differ
diff --git a/test/data/aftl_output_vbmeta_with_1_icp.img b/test/data/aftl_output_vbmeta_with_1_icp.img
deleted file mode 100644
index 74b67bb..0000000
--- a/test/data/aftl_output_vbmeta_with_1_icp.img
+++ /dev/null
Binary files differ
diff --git a/test/data/aftl_output_vbmeta_with_2_icp_same_log.img b/test/data/aftl_output_vbmeta_with_2_icp_same_log.img
deleted file mode 100644
index 2a6368e..0000000
--- a/test/data/aftl_output_vbmeta_with_2_icp_same_log.img
+++ /dev/null
Binary files differ
diff --git a/test/data/aftl_pubkey_1.bin b/test/data/aftl_pubkey_1.bin
deleted file mode 100644
index 5bad4be..0000000
--- a/test/data/aftl_pubkey_1.bin
+++ /dev/null
Binary files differ
diff --git a/test/data/aftl_pubkey_1.pem b/test/data/aftl_pubkey_1.pem
deleted file mode 100644
index 8bfd816..0000000
--- a/test/data/aftl_pubkey_1.pem
+++ /dev/null
@@ -1,15 +0,0 @@
------BEGIN PUBLIC KEY-----
-MIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEA4ilqCNsenNA013iCdwgD
-YPxZ853nbHG9lMBp9boXiwRcqT/8bUKHIL7YX5z7s+QoRYVY3rkMKppRabclXzyx
-H59YnPMaU4uv7NqwWzjgaZo7E+vo7IF+KBjV3cJulId5Av0yIYUCsrwd7MpGtWdC
-Q3S+7Vd4zwzCKEhcvliNIhnNlp1U3wNkPCxOyCAsMEn6k8O5ar12ke5TvxDv15db
-rPDeHh8G2OYWoCkWL+lSN35L2kOJqKqVbLKWrrOd96RCYrrtbPCi580OADJRcUlG
-lgcjwmNwmypBWvQMZ6ITj0P0ksHnl1zZz1DE2rXe1goLI1doghb5KxLaezlR8c2C
-E3w/uo9KJgNmNgUVzzqZZ6FE0moyIDNOpP7KtZAL0DvEZj6jqLbB0ccPQElrg52m
-Dv2/A3nYSr0mYBKeskT4+Bg7PGgoC8p7WyLSxMyzJEDYdtrj9OFx6eZaA23oqTQx
-k3Qq5H8RfNBeeSUEeKF7pKH/7gyqZ2bNzBFMA2EBZgBozwRfaeN/HCv3qbaCnwvu
-6caacmAsK+RxiYxSL1QsJqyhCWWGxVyenmxdc1KG/u5ypi7OIioztyzR3t2tAzD3
-Nb+2t8lgHBRxbV24yiPlnvPmB1ZYEctXnlRR9Evpl1o9xA9NnybPHKr9rozN39CZ
-V/USB8K6ao1y5xPZxa8CZksCAwEAAQ==
------END PUBLIC KEY-----
-
diff --git a/test/data/find_aftl_descriptor.bin b/test/data/find_aftl_descriptor.bin
deleted file mode 100644
index 5044ab3..0000000
--- a/test/data/find_aftl_descriptor.bin
+++ /dev/null
Binary files differ