#!/usr/bin/env python3
#
# Copyright 2022, The Android Open Source Project
#
# 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.
#

"""Certify a GKI boot image by generating and appending its boot_signature."""

from argparse import ArgumentParser
import glob
import os
import shlex
import shutil
import subprocess
import tempfile

from gki.generate_gki_certificate import generate_gki_certificate
from unpack_bootimg import unpack_bootimg

BOOT_SIGNATURE_SIZE = 16 * 1024


def get_kernel(boot_img):
    """Extracts the kernel from |boot_img| and returns it."""
    with tempfile.TemporaryDirectory() as unpack_dir:
        unpack_bootimg(boot_img, unpack_dir)
        with open(os.path.join(unpack_dir, 'kernel'), 'rb') as kernel:
            kernel_bytes = kernel.read()
            assert len(kernel_bytes) > 0
            return kernel_bytes


def add_certificate(boot_img, algorithm, key, extra_args):
    """Appends certificates to the end of the boot image.

    This functions appends two certificates to the end of the |boot_img|:
    the 'boot' certificate and the 'generic_kernel' certificate. The former
    is to certify the entire |boot_img|, while the latter is to certify
    the kernel inside the |boot_img|.
    """

    def generate_certificate(image, certificate_name):
        """Generates the certificate and returns the certificate content."""
        with tempfile.NamedTemporaryFile() as output_certificate:
            generate_gki_certificate(
                image=image, avbtool='avbtool', name=certificate_name,
                algorithm=algorithm, key=key, salt='d00df00d',
                additional_avb_args=extra_args, output=output_certificate.name)
            output_certificate.seek(os.SEEK_SET, 0)
            return output_certificate.read()

    boot_signature_bytes = b''
    boot_signature_bytes += generate_certificate(boot_img, 'boot')

    with tempfile.NamedTemporaryFile() as kernel_img:
        kernel_img.write(get_kernel(boot_img))
        kernel_img.flush()
        boot_signature_bytes += generate_certificate(kernel_img.name,
                                                     'generic_kernel')

    if len(boot_signature_bytes) > BOOT_SIGNATURE_SIZE:
        raise ValueError(
            f'boot_signature size must be <= {BOOT_SIGNATURE_SIZE}')
    boot_signature_bytes += (
        b'\0' * (BOOT_SIGNATURE_SIZE - len(boot_signature_bytes)))
    assert len(boot_signature_bytes) == BOOT_SIGNATURE_SIZE

    with open(boot_img, 'ab') as f:
        f.write(boot_signature_bytes)


def erase_certificate_and_avb_footer(boot_img):
    """Erases the boot certificate and avb footer.

    A boot image might already contain a certificate and/or a AVB footer.
    This function erases these additional metadata from the |boot_img|.
    """
    # Tries to erase the AVB footer first, which may or may not exist.
    avbtool_cmd = ['avbtool', 'erase_footer', '--image', boot_img]
    subprocess.run(avbtool_cmd, check=False, stderr=subprocess.DEVNULL)
    assert os.path.getsize(boot_img) > 0

    # No boot signature to erase, just return.
    if os.path.getsize(boot_img) <= BOOT_SIGNATURE_SIZE:
        return

    # Checks if the last 16K is a boot signature, then erases it.
    with open(boot_img, 'rb') as image:
        image.seek(-BOOT_SIGNATURE_SIZE, os.SEEK_END)
        boot_signature = image.read(BOOT_SIGNATURE_SIZE)
        assert len(boot_signature) == BOOT_SIGNATURE_SIZE

    with tempfile.NamedTemporaryFile() as signature_tmpfile:
        signature_tmpfile.write(boot_signature)
        signature_tmpfile.flush()
        avbtool_info_cmd = [
            'avbtool', 'info_image', '--image', signature_tmpfile.name]
        result = subprocess.run(avbtool_info_cmd, check=False,
                                stdout=subprocess.DEVNULL,
                                stderr=subprocess.DEVNULL)
        has_boot_signature = (result.returncode == 0)

    if has_boot_signature:
        new_file_size = os.path.getsize(boot_img) - BOOT_SIGNATURE_SIZE
        os.truncate(boot_img, new_file_size)

    assert os.path.getsize(boot_img) > 0


def get_avb_image_size(image):
    """Returns the image size if there is a AVB footer, else return zero."""

    avbtool_info_cmd = ['avbtool', 'info_image', '--image', image]
    result = subprocess.run(avbtool_info_cmd, check=False,
                            stdout=subprocess.DEVNULL,
                            stderr=subprocess.DEVNULL)

    if result.returncode == 0:
        return os.path.getsize(image)

    return 0


def add_avb_footer(image, partition_size, extra_footer_args):
    """Appends a AVB hash footer to the image."""

    avbtool_cmd = ['avbtool', 'add_hash_footer', '--image', image,
                   '--partition_name', 'boot']

    if partition_size:
        avbtool_cmd.extend(['--partition_size', str(partition_size)])
    else:
        avbtool_cmd.extend(['--dynamic_partition_size'])

    avbtool_cmd.extend(extra_footer_args)
    subprocess.check_call(avbtool_cmd)


def load_dict_from_file(path):
    """Loads key=value pairs from |path| and returns a dict."""
    d = {}
    with open(path, 'r', encoding='utf-8') as f:
        for line in f:
            line = line.strip()
            if not line or line.startswith('#'):
                continue
            if '=' in line:
                name, value = line.split('=', 1)
                d[name] = value
    return d


def load_gki_info_file(gki_info_file, extra_args, extra_footer_args):
    """Loads extra arguments from the gki info file.

    Args:
        gki_info_file: path to a gki-info.txt.
        extra_args: the extra arguments forwarded to avbtool when creating
          the gki certificate.
        extra_footer_args: the extra arguments forwarded to avbtool when
          creating the avb footer.

    """
    info_dict = load_dict_from_file(gki_info_file)
    if 'certify_bootimg_extra_args' in info_dict:
        extra_args.extend(
            shlex.split(info_dict['certify_bootimg_extra_args']))
    if 'certify_bootimg_extra_footer_args' in info_dict:
        extra_footer_args.extend(
            shlex.split(info_dict['certify_bootimg_extra_footer_args']))


def get_archive_name_and_format_for_shutil(path):
    """Returns archive name and format to shutil.make_archive() for the |path|.

    e.g., returns ('/path/to/boot-img', 'gztar') if |path| is
    '/path/to/boot-img.tar.gz'.
    """
    for format_name, format_extensions, _ in shutil.get_unpack_formats():
        for extension in format_extensions:
            if path.endswith(extension):
                return path[:-len(extension)], format_name

    raise ValueError(f"Unsupported archive format: '{path}'")


def parse_cmdline():
    """Parse command-line options."""
    parser = ArgumentParser(add_help=True)

    # Required args.
    input_group = parser.add_mutually_exclusive_group(required=True)
    input_group.add_argument(
        '--boot_img', help='path to the boot image to certify')
    input_group.add_argument(
        '--boot_img_archive', help='path to the boot images archive to certify')

    parser.add_argument('--algorithm', required=True,
                        help='signing algorithm for the certificate')
    parser.add_argument('--key', required=True,
                        help='path to the RSA private key')
    parser.add_argument('--gki_info',
                        help='path to a gki-info.txt to append additional'
                             'properties into the boot signature')
    parser.add_argument('-o', '--output', required=True,
                        help='output file name')

    # Optional args.
    parser.add_argument('--extra_args', default=[], action='append',
                        help='extra arguments to be forwarded to avbtool')
    parser.add_argument('--extra_footer_args', default=[], action='append',
                        help='extra arguments for adding the avb footer')

    args = parser.parse_args()

    if args.gki_info and args.boot_img_archive:
        parser.error('--gki_info cannot be used with --boot_image_archive. '
                     'The gki_info file should be included in the archive.')

    extra_args = []
    for a in args.extra_args:
        extra_args.extend(shlex.split(a))
    args.extra_args = extra_args

    extra_footer_args = []
    for a in args.extra_footer_args:
        extra_footer_args.extend(shlex.split(a))
    args.extra_footer_args = extra_footer_args

    if args.gki_info:
        load_gki_info_file(args.gki_info,
                           args.extra_args,
                           args.extra_footer_args)

    return args


def certify_bootimg(boot_img, output_img, algorithm, key, extra_args,
                    extra_footer_args):
    """Certify a GKI boot image by generating and appending a boot_signature."""
    with tempfile.TemporaryDirectory() as temp_dir:
        boot_tmp = os.path.join(temp_dir, 'boot.tmp')
        shutil.copy2(boot_img, boot_tmp)

        erase_certificate_and_avb_footer(boot_tmp)
        add_certificate(boot_tmp, algorithm, key, extra_args)

        avb_partition_size = get_avb_image_size(boot_img)
        add_avb_footer(boot_tmp, avb_partition_size, extra_footer_args)

        # We're done, copy the temp image to the final output.
        shutil.copy2(boot_tmp, output_img)


def certify_bootimg_archive(boot_img_archive, output_archive,
                            algorithm, key, extra_args, extra_footer_args):
    """Similar to certify_bootimg(), but for an archive of boot images."""
    with tempfile.TemporaryDirectory() as unpack_dir:
        shutil.unpack_archive(boot_img_archive, unpack_dir)

        gki_info_file = os.path.join(unpack_dir, 'gki-info.txt')
        if os.path.exists(gki_info_file):
            load_gki_info_file(gki_info_file, extra_args, extra_footer_args)

        for boot_img in glob.glob(os.path.join(unpack_dir, 'boot-*.img')):
            print(f'Certifying {os.path.basename(boot_img)} ...')
            certify_bootimg(boot_img=boot_img, output_img=boot_img,
                            algorithm=algorithm, key=key, extra_args=extra_args,
                            extra_footer_args=extra_footer_args)

        print(f'Making certified archive: {output_archive}')
        archive_file_name, archive_format = (
            get_archive_name_and_format_for_shutil(output_archive))
        built_archive = shutil.make_archive(archive_file_name,
                                            archive_format,
                                            unpack_dir)
        # shutil.make_archive() builds *.tar.gz when then |archive_format| is
        # 'gztar'. However, the end user might specify |output_archive| with
        # *.tgz. Renaming *.tar.gz to *.tgz for this case.
        if built_archive != os.path.realpath(output_archive):
            print(f'Renaming {built_archive} -> {output_archive} ...')
            os.rename(built_archive, output_archive)


def main():
    """Parse arguments and certify the boot image."""
    args = parse_cmdline()

    if args.boot_img_archive:
        certify_bootimg_archive(args.boot_img_archive, args.output,
                                args.algorithm, args.key, args.extra_args,
                                args.extra_footer_args)
    else:
        certify_bootimg(args.boot_img, args.output, args.algorithm,
                        args.key, args.extra_args, args.extra_footer_args)


if __name__ == '__main__':
    main()
