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

import hashlib

from autotest_lib.client.common_lib import error
from autotest_lib.client.common_lib.cros import g2f_utils
from autotest_lib.client.common_lib.cros import tpm_utils
from autotest_lib.server.cros.faft.firmware_test import FirmwareTest

U2F_AUTH_ENFORCE=3

class firmware_Cr50U2fPowerwash(FirmwareTest):
    """
    A test that runs confidence checks for U2F register and authenticate
    functions, and checks that key handles are invalidated after TPM clear.
    """
    version = 1

    TEST_CHALLENGE_DIGEST = hashlib.sha256(b'test_challenge').hexdigest()
    TEST_APPLICATION_DIGEST = hashlib.sha256(b'test_application').hexdigest()

    def _safe_power_short_press(self):
        """Stop powerd before pressing the power button."""
        # Validating U2F requires pressing the power button. If those power button
        # presses power off the AP, stop powerd before the test to ignore them.
        if self.faft_config.ec_forwards_short_pp_press:
            self.stop_powerd()
        self.servo.power_short_press()

    def parse_g2ftool_output(self, stdout):
        """Parses the key-value pairs returned by g2ftool

        @param stdout: g2ftool output.
        """
        return dict((k, v)
                    for k,v in (line.split('=')
                                for line in stdout.strip().split('\n')))

    def run_once(self, host=None):
        """Tests that U2F keys are invalidated by powerwash."""
        if not host.servo:
            raise error.TestNAError('Test requires servo.')
        # Test needs to control the GSC power button input.
        if not host.servo.main_device_is_flex():
            raise error.TestNAError('Run with c2d2 or servo micro.')

        self.client = host

        # Start by clearing TPM to make sure the device is in a known state.
        tpm_utils.ClearTPMOwnerRequest(self.client, wait_for_ready=True)

        # u2fd reads files from the user's home dir, so we need to log in.
        g2f_utils.ChromeOSLogin(self.client);

        # U2fd does will not start normally if the device has not gone
        # through OOBE. Force it to startup.
        cr50_dev = g2f_utils.StartU2fd(self.client)

        if cr50_dev is None:
            raise error.TestError('Could not find U2F device.')

        # Register requires physical presence.
        self._safe_power_short_press()

        # Register to create a new key handle.
        g2f_reg = g2f_utils.G2fRegister(self.client, cr50_dev,
                                        self.TEST_CHALLENGE_DIGEST,
                                        self.TEST_APPLICATION_DIGEST,
                                        U2F_AUTH_ENFORCE)

        # Check that we managed to register.
        if not g2f_reg.exit_status == 0:
            raise error.TestError('Register failed: %d' % g2f_reg.exit_status)

        # Extract newly created key handle.
        key_handle = self.parse_g2ftool_output(g2f_reg.stdout)['key_handle']

        # Auth requires physical presence.
        self._safe_power_short_press()

        # Check that we can authenticate with the new key handle.
        g2f_auth = g2f_utils.G2fAuth(self.client, cr50_dev,
                                     self.TEST_CHALLENGE_DIGEST,
                                     self.TEST_APPLICATION_DIGEST, key_handle,
                                     U2F_AUTH_ENFORCE)

        if not g2f_auth.exit_status == 0:
            raise error.TestError('Authenticate failed.')

        # Clear TPM. We should no longer be able to authenticate with the
        # key handle after this.
        tpm_utils.ClearTPMOwnerRequest(self.client, wait_for_ready=True)

        # u2fd reads files from the user's home dir, so we need to log in.
        g2f_utils.ChromeOSLogin(self.client)

        # U2fd does will not start normally if the device has not gone
        # through OOBE. Force it to startup.
        cr50_dev = g2f_utils.StartU2fd(self.client)

        if cr50_dev is None:
            raise error.TestError('Could not find U2F device.')

        # Check the key handle is no longer valid.
        self._safe_power_short_press()
        g2f_auth_clear = g2f_utils.G2fAuth(self.client, cr50_dev,
                                           self.TEST_CHALLENGE_DIGEST,
                                           self.TEST_APPLICATION_DIGEST,
                                           key_handle, U2F_AUTH_ENFORCE)

        if g2f_auth_clear.exit_status == 0:
            raise error.TestError('Authenticate succeeded; should have failed')


    def cleanup(self):
        """Leave the device in a predictable state"""
        g2f_utils.ChromeOSLogout(self.client)

        super(firmware_Cr50U2fPowerwash, self).cleanup()
