blob: db7d59a2be7b0d0d2b77343bb501a0817b0d4990 [file] [log] [blame]
# Copyright 2021 The Pigweed Authors
#
# 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
#
# https://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.
"""Facilities for generating the 'root' metadata."""
import argparse
from pathlib import Path
from typing import Iterable, List, NewType
from pw_software_update import keys, metadata
from pw_software_update.tuf_pb2 import (RootMetadata, SignedRootMetadata,
SignatureRequirement)
RootKeys = NewType('RootKeys', List[bytes])
TargetsKeys = NewType('TargetsKeys', List[bytes])
def gen_root_metadata(root_key_pems: RootKeys,
targets_key_pems: TargetsKeys,
version: int = 1) -> RootMetadata:
"""Generates a RootMetadata.
Args:
root_key_pems: list of root public keys in PEM format.
targets_key_pems: list of targets keys in PEM format.
version: Version number for rollback checks.
"""
common = metadata.gen_common_metadata(metadata.RoleType.ROOT,
version=version)
root_keys = [keys.import_ecdsa_public_key(pem) for pem in root_key_pems]
targets_keys = [
keys.import_ecdsa_public_key(pem) for pem in targets_key_pems
]
return RootMetadata(common_metadata=common,
consistent_snapshot=False,
keys=root_keys + targets_keys,
root_signature_requirement=SignatureRequirement(
key_ids=[k.key_id for k in root_keys],
threshold=1),
targets_signature_requirement=SignatureRequirement(
key_ids=[k.key_id for k in targets_keys],
threshold=1))
def parse_args():
"""Parse CLI arguments."""
parser = argparse.ArgumentParser(description=__doc__)
parser.add_argument('-o',
'--out',
type=Path,
required=True,
help='Output path for the generated root metadata')
parser.add_argument('--version',
type=int,
default=1,
help='Canonical version number for rollback checks')
parser.add_argument('--root-key',
type=Path,
required=True,
nargs='+',
help='Public key filename for the "Root" role')
parser.add_argument('--targets-key',
type=Path,
required=True,
nargs='+',
help='Public key filename for the "Targets" role')
return parser.parse_args()
def main(out: Path, root_key: Iterable[Path], targets_key: Iterable[Path],
version: int) -> None:
"""Generates and writes to disk an unsigned SignedRootMetadata."""
root_metadata = gen_root_metadata(
RootKeys([k.read_bytes() for k in root_key]),
TargetsKeys([k.read_bytes() for k in targets_key]), version)
signed = SignedRootMetadata(
serialized_root_metadata=root_metadata.SerializeToString())
out.write_bytes(signed.SerializeToString())
if __name__ == '__main__':
main(**vars(parse_args()))