# Copyright 2018 The ChromiumOS Authors
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.

import logging
import time

from autotest_lib.client.common_lib import error
from autotest_lib.client.common_lib.cros import cr50_utils
from autotest_lib.server.cros.faft.cr50_test import Cr50Test


class firmware_Cr50Password(Cr50Test):
    """Verify cr50 set password."""
    version = 1
    NEW_PASSWORD = 'robot'

    def usb_set_password(self, password):
        """Try sending the password command from the console and ccd usb.

        Verify the console command and usb vendor command fail to set the
        password.
        """
        start_pw_state = self.gsc.password_is_reset()
        start_level = self.gsc.get_ccd_level()
        logging.info('Password is %s', 'cleared' if start_pw_state else 'set')
        time.sleep(self.gsc.CCD_PASSWORD_RATE_LIMIT)
        # CCD password from the console should always be inaccessible.
        self.gsc.set_password(password)
        time.sleep(self.gsc.CCD_PASSWORD_RATE_LIMIT)
        if start_pw_state != self.gsc.password_is_reset():
            raise error.TestFail('changed password from console')
        if start_level != self.gsc.get_ccd_level():
            raise error.TestFail(
                    'changed ccd level with set password console command')
        if self.ccd_programmer_connected_to_servo_host():
            time.sleep(self.gsc.CCD_PASSWORD_RATE_LIMIT)
            cmd = self._ccd_programmer.get_ccd_gsctool_cmd('-P')
            full_cmd = "echo -e '%s\n%s\n' | %s" % (password, password, cmd)
            logging.info('ccd password command: %r', full_cmd)
            result = self._ccd_programmer.run(full_cmd, ignore_status=True)
            logging.info('CCD password result: %r', result)
            time.sleep(self.gsc.CCD_PASSWORD_RATE_LIMIT)
            if start_pw_state != self.gsc.password_is_reset():
                raise error.TestFail('changed password with ccd')
            if start_level != self.gsc.get_ccd_level():
                raise error.TestFail('changed ccd level with ccd')

        logging.info('After ccd commands, password is %s',
                     'cleared' if self.gsc.password_is_reset() else 'set')

    def try_wrong_password(self, wrong_password):
        """Try to open ccd with the wrong password.

        Raise an error if it works.
        """
        time.sleep(self.gsc.CCD_PASSWORD_RATE_LIMIT)
        try:
            self.gsc.set_ccd_level('open', wrong_password)
            raise error.TestFail(
                    'Opened ccd with incorrect password: used %r actual %r',
                    wrong_password, self.test_password)
        except error.TestFail as e:
            logging.info('successfully rejected ccd open using %r',
                         wrong_password)

    def run_once(self):
        """Check we can set the cr50 password."""
        self.test_password = self.CCD_PASSWORD
        # Make sure the case is enforced. If the password is lower case, try
        # upper. If it's uppercase, try lower.
        wrong_case = (self.test_password.upper()
                      if self.test_password.islower() else
                      self.test_password.lower())

        # Make sure to enable testlab mode, so we can guarantee the password
        # can be cleared.
        self.fast_ccd_open(enable_testlab=True)
        self.gsc.ccd_reset()

        # CCD password from the console should always be inaccessible.
        self.usb_set_password(self.test_password)
        # Set the password.
        self.set_ccd_password(self.test_password)
        if self.gsc.password_is_reset():
            raise error.TestFail('Failed to set password')

        # Test 'ccd reset' clears the password.
        self.gsc.ccd_reset()
        if not self.gsc.password_is_reset():
            raise error.TestFail('ccd reset did not clear the password')
        # Set OpenFromUSB to IfOpened, so the test will only be able to open
        # ccd with a console command if the password is set. This is cleared
        # in Cr50Test cleanup.
        self.gsc.set_cap('OpenFromUSB', 'IfOpened')

        # Set the password again while cr50 is open.
        self.set_ccd_password(self.test_password)
        if self.gsc.password_is_reset():
            raise error.TestFail('Failed to set password')

        # The password can't be changed once it's set.
        # It needs to be cleared first.
        self.set_ccd_password(self.NEW_PASSWORD, expect_error=True)

        self.gsc.reboot()
        if self.gsc.password_is_reset():
            raise error.TestFail('Password cleared after reboot')

        # Verify ccd can't be opened with the wrong password. Verify case is
        # enforced
        self.try_wrong_password(wrong_case)
        self.try_wrong_password(self.NEW_PASSWORD)

        # Verify ccd can be opened with the correct password.
        self.gsc.set_ccd_level('open', self.test_password)

        self.gsc.set_ccd_level('lock')
        # The password can't be cleared while the console is locked from the
        # AP or ccd.
        self.usb_set_password('clear:' + self.test_password)
        self.set_ccd_password('clear:' + self.test_password, expect_error=True)
        if self.gsc.password_is_reset():
            raise error.TestFail('Cleared password while locked')

        if self.gsc.unlock_is_supported():
            self.gsc.send_command('ccd unlock ' + self.test_password)
            # The password can be cleared while the console is unlocked.
            self.set_ccd_password('clear:' + self.test_password)

            # Open the console, set the password again.
            self.gsc.send_command('ccd testlab open')
            self.set_ccd_password(self.test_password)
        else:
            # Open the console.
            self.gsc.send_command('ccd testlab open')

        # The password can't be cleared using the wrong password.
        self.set_ccd_password('clear:' + wrong_case, expect_error=True)
        self.set_ccd_password('clear:' + self.NEW_PASSWORD, expect_error=True)
        # The right password can't be used to clear the password from
        # the console.
        self.usb_set_password('clear:' + self.test_password)
        # The password can be cleared using the correct password.
        self.set_ccd_password('clear:' + self.test_password)
        if not self.gsc.password_is_reset():
            raise error.TestFail('Failed to clear password')

        # The password can be set to anything when there isn't one set.
        self.set_ccd_password(self.NEW_PASSWORD)
        if self.gsc.password_is_reset():
            raise error.TestFail('Failed to set password')

        self.gsc.send_command('ccd testlab open')
        self.gsc.ccd_reset()

        if not self.gsc.unlock_is_supported():
            return

        # Run through the same steps when the password was set with the console
        # unlocked.

        self.host.run('gsctool -a -U')

        # Set the password when the console is unlocked.
        self.set_ccd_password(self.test_password)

        self.gsc.set_ccd_level('lock')
        # The password can't be cleared while the console is locked.
        self.set_ccd_password('clear:' + self.test_password, expect_error=True)

        # Unlock the console.
        self.ccd_unlock_from_ap(self.test_password)
        # The password can be cleared while the console is unlocked.
        self.set_ccd_password('clear:' + self.test_password)
        # Set the password again when the console is unlocked.
        self.set_ccd_password(self.test_password)

        self.gsc.send_command('ccd testlab open')
        # The password can be cleared when the console is open.
        self.set_ccd_password('clear:' + self.test_password)
