# -*- coding: utf-8 -*-
# Copyright 2018 The Chromium OS Authors. All rights reserved.
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.

"""ChromeOS image signer logic

Terminology:
  Keyset:     Set of keys used for signing, similar to a keyring
  Signer:     Object able to sign a type of image: bios, ec, kernel, etc...
  Image:      Fle that can be signed by a Signer

Signing requires an image to sign and its required keys.

A Signer is expected to understand how to take an input and output signed
artifacts using the stored Keychain.

A Keyset consists of keys and signed objects called keyblocks.

Signing Flow:

 Key+------+->Keyset+---+->Signer+->Image Out
           |            |
 Keyblock+-+  Image In+-+
"""

from __future__ import print_function


import ConfigParser
import os
import re

from chromite.lib import cros_build_lib


class SigningFailedError(Exception):
  """Raise when a signing failed"""

class SignerOutputTemplateError(Exception):
  """Raise when there is an issue with filling a signer output template"""


class SignerInstructionConfig(object):
  """Signer Configuration based on ini file.

  See Signer Documentation - Instruction File Format:
  https://goto.google.com/cros-signer-instruction-file
  """
  DEFAULT_TEMPLATE = ('chromeos_@VERSION@_@BOARD@_@TYPE@_@CHANNEL@-channel_'
                      '@KEYSET@.bin')

  def __init__(self, archive='', board='', artifact_type='', version='',
               versionrev='', keyset='', channel='', input_files=(),
               output_files=()):
    """Initialize Configuration."""
    # [general] section
    self.archive = archive
    self.board = board
    self.artifact_type = artifact_type
    self.version = version
    self.versionrev = versionrev

    # [insns] section
    self.keyset = keyset
    self.channel = channel

    # Wrap files in tuple if given as a string
    self.input_files = ((input_files,) if isinstance(input_files, basestring)
                        else input_files)

    self.output_files = ((output_files,) if isinstance(output_files, basestring)
                         else output_files)

  def __eq__(self, other):
    return self.ToIniDict() == other.ToIniDict()

  def ToIniDict(self):
    """Return ini layout."""

    # [general] section
    general_dict = {}
    if self.archive:
      general_dict['archive'] = self.archive
    if self.board:
      general_dict['board'] = self.board
    if self.artifact_type:
      general_dict['type'] = self.artifact_type
    if self.version:
      general_dict['version'] = self.version
    if self.versionrev:
      general_dict['versionrev'] = self.versionrev

    # [insns] section
    insns_dict = {}
    if self.keyset:
      insns_dict['keyset'] = self.keyset
    if self.channel:
      insns_dict['channel'] = self.channel
    if self.input_files:
      insns_dict['input_files'] = ' '.join(self.input_files)
    if self.output_files:
      insns_dict['output_names'] = ' '.join(self.output_files)

    return {'general': general_dict,
            'insns': insns_dict}

  def ReadIniFile(self, fd):
    """Reads given file descriptor into configuration"""
    config = ConfigParser.ConfigParser(self.ToIniDict())
    config.readfp(fd)

    self.archive = config.get('general', 'archive')
    self.board = config.get('general', 'board')
    self.artifact_type = config.get('general', 'type')
    self.version = config.get('general', 'version')
    self.versionrev = config.get('general', 'versionrev')

    self.keyset = config.get('insns', 'keyset')
    self.channel = config.get('insns', 'channel')

    # Optional options
    if config.has_option('insns', 'input_files'):
      self.input_files = config.get('insns', 'input_files').split(' ')

    if config.has_option('insns', 'output_names'):
      self.output_files = config.get('insns', 'output_names').split(' ')

  def GetFilePairs(self):
    """Returns list of (input_file,output_file) tuples"""
    files = []

    if self.output_files:
      out_files = self.output_files
    else:
      out_files = [SignerInstructionConfig.DEFAULT_TEMPLATE]

    if len(out_files) == 1:
      out_file = out_files[0]

      # Check template generate unique output files
      if (len(self.input_files) > 1 and
          not re.search('(@BASENAME@)|(@ROOTNAME@)', out_file)):
        raise SignerOutputTemplateError('@BASENAME@ or @ROOTNAME@ required for'
                                        'templates with multiple input files')

      for in_file in self.input_files:
        files.append((in_file, self.FillTemplate(out_file, filename=in_file)))

    elif len(self.input_files) == len(out_files):
      for in_file, out_file in zip(self.input_files, out_files):
        files.append((in_file, self.FillTemplate(out_file, filename=in_file)))

    else:
      raise IndexError('Equal number of input_files and output_names required')


    return files

  def FillTemplate(self, template_str, filename=''):
    """Return string based on given template."""

    rep_dict = {'@BOARD@': self.board,
                '@CHANNEL@': self.channel,
                '@KEYSET@': self.keyset,
                '@TYPE@': self.artifact_type,
                '@VERSION@': self.version,
               }

    if filename:
      basename = os.path.basename(filename)
      rep_dict['@BASENAME@'] = basename
      rep_dict['@ROOTNAME@'] = os.path.splitext(basename)[0]

    return re.sub('@[A-Z]+@',
                  lambda x: rep_dict.get(x.group(0), x.group(0)),
                  template_str)


class BaseSigner(object):
  """Base Signer object."""

  # Override the following lists to enforce key requirements
  required_keys = ()
  required_keys_public = ()
  required_keys_private = ()
  required_keyblocks = ()

  def CheckKeyset(self, keyset):
    """Returns true if all required keys and keyblocks are in keyset."""
    for k in self.required_keys:
      if k not in keyset.keys:
        return False

    for k in self.required_keys_public:
      if not keyset.KeyExists(k, require_public=True):
        return False

    for k in self.required_keys_private:
      if not keyset.KeyExists(k, require_private=True):
        return False

    for kb in self.required_keyblocks:
      if not keyset.KeyblockExists(kb):
        return False

    return True

  def Sign(self, keyset, input_name, output_name):
    """Sign given input to output. Raises SigningFailedError on error"""
    raise NotImplementedError


class FutilitySigner(BaseSigner):
  """Base class for signers that use futility command."""

  def GetFutilityArgs(self, keyset, input_name, output_name):
    """Return list of arguments to use with futility."""
    raise NotImplementedError

  def Sign(self, keyset, input_name, output_name):
    if self.CheckKeyset(keyset):
      if not RunFutility(self.GetFutilityArgs(keyset, input_name, output_name)):
        raise SigningFailedError('Signing Command Failed for ' + input_name)


def RunFutility(args):
  """Runs futility with the given args, returns True if success"""
  cmd = ['futility']
  cmd += args
  return cros_build_lib.RunCommand(cmd, error_code_ok=True).returncode == 0
