xref: /aosp_15_r20/external/autotest/server/site_tests/firmware_Cr50Keygen/firmware_Cr50Keygen.py (revision 9c5db1993ded3edbeafc8092d69fe5de2ee02df7)
1# Copyright 2021 The Chromium OS Authors. All rights reserved.
2# Use of this source code is governed by a BSD-style license that can be
3# found in the LICENSE file.
4
5import logging
6import re
7import time
8
9from autotest_lib.client.common_lib import error
10from autotest_lib.server.cros.faft.firmware_test import FirmwareTest
11
12
13class firmware_Cr50Keygen(FirmwareTest):
14    """Verify cr50 can tell the state of the dev mode switch."""
15    version = 1
16
17    RUNS = 20
18    TIME_RE = r'KeyPair took (\d+) '
19    TRUNKS_BASE = (
20            'trunks_client --key_create --key_blob=/tmp/key --print_time '
21            '--usage=decrypt ')
22    RSA_CMD_ARGS = '--rsa=2048'
23    # TODO(mruthven): look at results to see if 5000 is a reasonable average and
24    # 30s is a reasonable max across the test devices. Start a low threshold to
25    # get an idea for how the lab devices are operating.
26    # Raise an error if the average RSA key generation time takes longer than
27    # this threshold in ms.
28    RSA_AVG_THRESHOLD = 8000
29    # Raise an error if the max RSA key generation time takes longer than this
30    # threshold in ms.
31    RSA_MAX_THRESHOLD = 30000
32    ECC_CMD_ARGS = '--ecc'
33    # TODO(mruthven): look at results to see if 150 is a reasonable average and
34    # 500 is a reasonable max across the test devices. Start a low threshold to
35    # get an idea for how the lab devices are operating.
36    # Raise an error if the average ECC key generation time takes longer than
37    # this threshold.
38    ECC_AVG_THRESHOLD = 150
39    # Raise an error if the max ECC key generation time takes longer than this
40    # threshold in ms.
41    ECC_MAX_THRESHOLD = 500
42
43    def wait_for_client_after_changing_ccd(self, enable):
44        """Change CCD and wait for client.
45
46        @param enable: True to enable ccd. False to disable it.
47        @raises TestError if the DUT isn't pingable after changing ccd.
48        """
49        if not hasattr(self, 'cr50') or not self.cr50:
50            return
51
52        if enable:
53            self.cr50.ccd_enable()
54        else:
55            self.cr50.ccd_disable()
56
57        time.sleep(5)
58
59        if self.host.ping_wait_up(180):
60            return
61        msg = ('DUT is not pingable after %sabling ccd' %
62               'en' if enable else 'dis')
63        logging.info(msg)
64        logging.info('Resetting DUT')
65        self.host.reset_via_servo()
66        if not self.host.ping_wait_up(180):
67            raise error.TestError(msg)
68
69    def get_key_attr(self, attr):
70        """Get the attribute for the type of key the test is generating."""
71        return getattr(self, self.key_type + '_' + attr)
72
73    def get_keygen_cmd(self):
74        """Generate the trunks_client key_create command."""
75        return self.TRUNKS_BASE + self.get_key_attr('CMD_ARGS')
76
77    def run_once(self, host, key_type='RSA'):
78        """Check ECC and RSA Keygen times."""
79        self.host = host
80        self.key_type = key_type.upper()
81
82        # TODO(b/218492933) : find better way to disable rddkeepalive
83        # Disable rddkeepalive, so the test can disable ccd.
84        self.cr50.send_command('ccd testlab open')
85        self.cr50.send_command('rddkeepalive disable')
86        # Lock cr50 so the console will be restricted
87        self.cr50.set_ccd_level('lock')
88
89        self.wait_for_client_after_changing_ccd(False)
90
91        cmd = self.get_keygen_cmd()
92        logging.info(cmd)
93        full_cmd = ('for i in {1..%d} ; do echo $i ; %s || break; done' %
94                    (self.RUNS, cmd))
95        response = host.run(full_cmd)
96        logging.debug(response.stdout)
97        times = [int(t) for t in re.findall(self.TIME_RE, response.stdout)]
98        logging.info(times)
99        avg_time = sum(times) / len(times)
100        max_time = max(times)
101        logging.info('Average time: %s', avg_time)
102        logging.info('Max time: %s', max_time)
103        self.wait_for_client_after_changing_ccd(True)
104        if len(times) != self.RUNS:
105            raise error.TestFail('did not generate %d keys' % self.RUNS)
106        max_threshold = self.get_key_attr('MAX_THRESHOLD')
107        if max_time > max_threshold:
108            raise error.TestFail('MAX time %r is over the acceptable '
109                                 'threshold(%dms)' % (max_time, max_threshold))
110        avg_threshold = self.get_key_attr('AVG_THRESHOLD')
111        if avg_time > avg_threshold:
112            raise error.TestFail('Average time %r is over the acceptable '
113                                 'threshold(%dms)' % (avg_time, avg_threshold))
114