| # Copyright 2019 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. |
| |
| import time |
| |
| from autotest_lib.client.common_lib import error |
| from autotest_lib.client.common_lib.cros import tpm_utils |
| from autotest_lib.server.cros.faft.firmware_test import FirmwareTest |
| |
| # TPM vendor commands have the following header structure: |
| |
| # 8001 TPM_ST_NO_SESSIONS |
| # 00000000 Command/response size |
| # 20000000 Cr50 Vendor Command (Constant, TPM Command Code) |
| # 0000 Vendor Command Code (VENDOR_CC_ enum) |
| |
| TPM_TAG_SIZE_BYTES = 2 |
| VENDOR_CC_SIZE_BYTES = 2 |
| VENDOR_CMD_HEADER_SIZE_BYTES = 12 |
| |
| # Responses to TPM vendor commands have the following header structure: |
| |
| # 8001 TPM_ST_NO_SESSIONS |
| # 00000000 Response size |
| # 00000000 Response code |
| # 0000 Vendor Command Code |
| |
| VENDOR_CMD_RESPONSE_SIZE_OFFSET = TPM_TAG_SIZE_BYTES |
| VENDOR_CMD_RESPONSE_SIZE_BYTES = 4 |
| VENDOR_CMD_RESPONSE_CODE_OFFSET = ( |
| VENDOR_CMD_RESPONSE_SIZE_OFFSET + VENDOR_CMD_RESPONSE_SIZE_BYTES) |
| VENDOR_CMD_RESPONSE_CODE_SIZE_BYTES = 4 |
| VENDOR_CMD_RESPONSE_CC_OFFSET = ( |
| VENDOR_CMD_RESPONSE_CODE_OFFSET + VENDOR_CMD_RESPONSE_CODE_SIZE_BYTES) |
| |
| # Vendor command codes being tested |
| |
| VENDOR_CC_U2F_GENERATE = '002C' |
| VENDOR_CC_U2F_SIGN = '002D' |
| VENDOR_CC_U2F_ATTEST = '002E' |
| |
| # Expected response sizes (body only) |
| |
| VENDOR_CC_U2F_SIGN_RESPONSE_SIZE_BYTES = 64 |
| VENDOR_CC_U2F_GENERATE_RESPONSE_SIZE_BYTES = 129 |
| VENDOR_CC_U2F_ATTEST_RESPONSE_SIZE_BYTES = 64 |
| |
| # Response Codes |
| |
| VENDOR_CMD_RESPONSE_SUCCESS = '00000000' |
| VENDOR_CMD_RESPONSE_BOGUS_ARGS = '00000501' |
| VENDOR_CMD_RESPONSE_NOT_ALLOWED = '00000507' |
| VENDOR_CMD_RESPONSE_PASSWORD_REQUIRED = '0000050A' |
| |
| # U2F Attest constants |
| |
| U2F_ATTEST_FORMAT_REG_RESP = '00' |
| U2F_ATTEST_REG_RESP_SIZE_BYTES = 194 |
| |
| # Some 'random' input to simulate actual inputs. |
| APP_ID = '699abb209a23ec31dcef298064a92ed9829e70a1bc873b272db321fe1644feae' |
| APP_ID_2 = '3c67e46408ec57dc6e4fb46fd0aecddadcf10c7b856446986ef67544a00530fa' |
| USER_SECRET_1 = ('1b6e854dcc052dfff2b5ece48c60a9db' |
| 'c69d27315c5f3ef8031abab60aa24d61') |
| USER_SECRET_2 = ('26398186431b14de9a6b99f849d71d342' |
| 'a1ec246d413aed42b7f2ac98846f24d') |
| HASH_TO_SIGN = ('91f93c8d88ed6168d07a36de53bd62b6' |
| '649e84d343dd417ed6062775739b6e65') |
| RANDOM_32 = '0fd2bf886fa8c036d069adf321bf1390859da4d615034c3a81ca3812a210ce0d' |
| |
| # For complying with struct u2f_generate_req only. |
| # Auth-time secret hash is used only in versioned KHs. |
| UNUSED_AUTH_TIME_SECRET_HASH = '00' * 32 |
| |
| def get_bytes(tpm_str, start, length): |
| return tpm_str[(start * 2):(start * 2 + length * 2)] |
| |
| |
| def assert_byte_length(str, len_bytes): |
| """Assert str represents a byte sequence len_bytes long""" |
| assert (len(str) / 2) == len_bytes |
| |
| |
| def get_str_length_as_hex(str, additional_len=0): |
| """Get the length of str plus any additional_len as a hex string.""" |
| assert (len(str) % 2) == 0 |
| length_bytes = len(str) / 2 |
| # hex() returns strings with a '0x' prefix, which we remove. |
| return hex(length_bytes + additional_len)[2:] |
| |
| |
| def check_response_size(response, expected_response, success_size): |
| """If the response is expected to be success, check it's size is as expected, |
| |
| otherwise, check it is 0. |
| """ |
| response_size = response['length'] |
| if expected_response == VENDOR_CMD_RESPONSE_SUCCESS: |
| if response_size != success_size: |
| raise error.TestFail( |
| 'Invalid successful response size: {}'.format(response_size)) |
| elif response_size != 0: |
| raise error.TestFail( |
| 'Non-zero response size on failure: {}'.format(response_size)) |
| |
| |
| class firmware_Cr50U2fCommands(FirmwareTest): |
| """Tests the custom U2F commands in cr50""" |
| |
| version = 1 |
| |
| def __send_vendor_cmd(self, |
| vendor_cc, |
| cmd_body, |
| expected_response_code=VENDOR_CMD_RESPONSE_SUCCESS): |
| assert_byte_length(vendor_cc, VENDOR_CC_SIZE_BYTES) |
| |
| cmd_size_str = get_str_length_as_hex(cmd_body, VENDOR_CMD_HEADER_SIZE_BYTES) |
| |
| cmd = ( |
| '8001' # TPM_ST_NO_SESSIONS |
| '{:0>8}' # Command Size (UINT32) |
| '20000000' # CR50 Vendor Command (TPM CC) |
| '{}' # Vendor Command Code (Subcommand Code, UINT16) |
| '{}' # Command Body |
| ).format(cmd_size_str, vendor_cc, cmd_body) |
| |
| result = self.client.run('trunks_send --raw {}'.format(cmd)).stdout.strip() |
| |
| if get_bytes(result, 0, TPM_TAG_SIZE_BYTES) != '8001': |
| raise error.TestFail( |
| 'Unexpected response tag from vendor command: {}'.format(result)) |
| |
| response_size_bytes = int( |
| get_bytes(result, VENDOR_CMD_RESPONSE_SIZE_OFFSET, |
| VENDOR_CMD_RESPONSE_SIZE_BYTES), 16) |
| |
| if response_size_bytes < VENDOR_CMD_HEADER_SIZE_BYTES: |
| raise error.TestFail( |
| 'Unexpected response length from vendor command: {}'.format(result)) |
| |
| response_code = get_bytes(result, VENDOR_CMD_RESPONSE_CODE_OFFSET, |
| VENDOR_CMD_RESPONSE_CODE_SIZE_BYTES) |
| |
| if response_code != expected_response_code: |
| raise error.TestFail( |
| 'Unexpected response received from vendor command: {}'.format( |
| response_code)) |
| |
| response_vendor_cc = get_bytes(result, VENDOR_CMD_RESPONSE_CC_OFFSET, |
| VENDOR_CC_SIZE_BYTES) |
| |
| if response_vendor_cc != vendor_cc: |
| raise error.TestFail( |
| 'Received response for unexpected vendor command code: {}'.format( |
| response_vendor_cc)) |
| |
| response_body_size_bytes = ( |
| response_size_bytes - VENDOR_CMD_HEADER_SIZE_BYTES) |
| |
| return { |
| 'length': |
| response_body_size_bytes, |
| 'value': |
| get_bytes(result, VENDOR_CMD_HEADER_SIZE_BYTES, |
| response_body_size_bytes) |
| } |
| |
| def __u2f_sign(self, app_id, user_secret, key_handle, hash, flags, |
| expected_response): |
| assert_byte_length(app_id, 32) |
| assert_byte_length(user_secret, 32) |
| assert_byte_length(key_handle, 64) |
| assert_byte_length(flags, 1) |
| |
| response = self.__send_vendor_cmd( |
| VENDOR_CC_U2F_SIGN, '{}{}{}{}{}'.format(app_id, user_secret, key_handle, |
| hash, flags), expected_response) |
| |
| expected_response_size = VENDOR_CC_U2F_SIGN_RESPONSE_SIZE_BYTES |
| # 'check-only' requests don't have a response body. |
| if flags == '07': |
| expected_response_size = 0 |
| |
| check_response_size(response, expected_response, expected_response_size) |
| |
| def __u2f_generate(self, |
| app_id, |
| user_secret, |
| flags, |
| expected_response=VENDOR_CMD_RESPONSE_SUCCESS): |
| assert_byte_length(app_id, 32) |
| assert_byte_length(user_secret, 32) |
| assert_byte_length(flags, 1) |
| |
| response = self.__send_vendor_cmd( |
| VENDOR_CC_U2F_GENERATE, '{}{}{}{}'.format(app_id, user_secret, flags, |
| UNUSED_AUTH_TIME_SECRET_HASH), |
| expected_response) |
| |
| check_response_size(response, expected_response, |
| VENDOR_CC_U2F_GENERATE_RESPONSE_SIZE_BYTES) |
| |
| return { |
| 'pubKey': response['value'][0:130], |
| 'keyHandle': response['value'][130:258] |
| } |
| |
| def __u2f_attest(self, |
| user_secret, |
| format, |
| data, |
| expected_response=VENDOR_CMD_RESPONSE_SUCCESS, |
| pad=False, |
| truncated=False): |
| assert_byte_length(user_secret, 32) |
| assert_byte_length(format, 1) |
| |
| data_len_str = get_str_length_as_hex(data) |
| |
| if truncated: |
| # Send 1 less byte of data than will be advertised in data_len field |
| assert pad == False |
| assert len(data) >= 2 |
| data = data[:len(data) - 2] |
| |
| if pad: |
| # Max data size is 256 bytes |
| data = data + '0' * (512 - len(data)) |
| |
| response = self.__send_vendor_cmd( |
| VENDOR_CC_U2F_ATTEST, '{}{}{}{}'.format( |
| user_secret, format, data_len_str, data), expected_response) |
| |
| check_response_size(response, expected_response, |
| VENDOR_CC_U2F_ATTEST_RESPONSE_SIZE_BYTES) |
| |
| def __test_generate_unique(self): |
| registration = self.__u2f_generate(APP_ID, USER_SECRET_1, '00') |
| registration_2 = self.__u2f_generate(APP_ID, USER_SECRET_1, '00') |
| |
| if registration['pubKey'] == registration_2['pubKey']: |
| raise error.TestFail('Public keys not unique') |
| |
| if registration['keyHandle'] == registration_2['keyHandle']: |
| raise error.TestFail('Key handles not unique') |
| |
| 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 __test_generate_sign_simple(self): |
| registration = self.__u2f_generate(APP_ID, USER_SECRET_1, '00') |
| |
| self._safe_power_short_press() |
| |
| self.__u2f_sign(APP_ID, USER_SECRET_1, registration['keyHandle'], |
| HASH_TO_SIGN, '00', VENDOR_CMD_RESPONSE_SUCCESS) |
| |
| def __test_generate_with_presence(self): |
| # Wait 11 seconds to ensure no presence. |
| |
| time.sleep(11) |
| |
| self.__u2f_generate( |
| APP_ID, |
| USER_SECRET_1, |
| '01', # U2F_AUTH_FLAG_TUP |
| VENDOR_CMD_RESPONSE_NOT_ALLOWED) |
| |
| self._safe_power_short_press() |
| |
| self.__u2f_generate( |
| APP_ID, |
| USER_SECRET_1, |
| '01', # U2F_AUTH_FLAG_TUP |
| VENDOR_CMD_RESPONSE_SUCCESS) |
| |
| def __test_generate_consume_presence(self): |
| self._safe_power_short_press() |
| |
| self.__u2f_generate( |
| APP_ID, |
| USER_SECRET_1, |
| '03', # U2F_AUTH_FLAG_TUP | G2F_CONSUME |
| VENDOR_CMD_RESPONSE_SUCCESS) |
| |
| self.__u2f_generate( |
| APP_ID, |
| USER_SECRET_1, |
| '01', # U2F_AUTH_FLAG_TUP |
| VENDOR_CMD_RESPONSE_NOT_ALLOWED) |
| |
| def __test_sign_requires_presence(self): |
| registration = self.__u2f_generate(APP_ID, USER_SECRET_1, '00') |
| |
| # U2F asserts presence by checking for a power button press within the |
| # last 10 seconds, sleep so that we are sure there was not one. |
| |
| time.sleep(11) |
| |
| self.__u2f_sign(APP_ID, USER_SECRET_1, registration['keyHandle'], |
| HASH_TO_SIGN, '00', VENDOR_CMD_RESPONSE_NOT_ALLOWED) |
| |
| def __test_sign_multiple_no_consume(self): |
| registration = self.__u2f_generate(APP_ID, USER_SECRET_1, '00') |
| |
| self._safe_power_short_press() |
| |
| self.__u2f_sign(APP_ID, USER_SECRET_1, registration['keyHandle'], |
| HASH_TO_SIGN, '00', VENDOR_CMD_RESPONSE_SUCCESS) |
| |
| # We should be able to sign again, as this will happen within 10 |
| # seconds of the power button press, and we did not consume. |
| |
| self.__u2f_sign(APP_ID, USER_SECRET_1, registration['keyHandle'], |
| HASH_TO_SIGN, '00', VENDOR_CMD_RESPONSE_SUCCESS) |
| |
| def __test_sign_consume(self): |
| registration = self.__u2f_generate(APP_ID, USER_SECRET_1, '00') |
| |
| self._safe_power_short_press() |
| |
| self.__u2f_sign( |
| APP_ID, |
| USER_SECRET_1, |
| registration['keyHandle'], |
| HASH_TO_SIGN, |
| '02', # G2F_CONSUME |
| VENDOR_CMD_RESPONSE_SUCCESS) |
| |
| # We should have consumed the power button press, so we should not be |
| # able to sign again. |
| |
| self.__u2f_sign(APP_ID, USER_SECRET_1, registration['keyHandle'], |
| HASH_TO_SIGN, '00', VENDOR_CMD_RESPONSE_NOT_ALLOWED) |
| |
| def __test_sign_wrong_user_secret(self): |
| registration = self.__u2f_generate(APP_ID, USER_SECRET_1, '00') |
| |
| self._safe_power_short_press() |
| |
| # Sanity check. |
| self.__u2f_sign(APP_ID, USER_SECRET_1, registration['keyHandle'], |
| HASH_TO_SIGN, '00', VENDOR_CMD_RESPONSE_SUCCESS) |
| |
| self.__u2f_sign(APP_ID, USER_SECRET_2, registration['keyHandle'], |
| HASH_TO_SIGN, '00', VENDOR_CMD_RESPONSE_PASSWORD_REQUIRED) |
| |
| def __test_sign_wrong_app_id(self): |
| registration = self.__u2f_generate(APP_ID, USER_SECRET_1, '00') |
| |
| self._safe_power_short_press() |
| |
| # Sanity check. |
| self.__u2f_sign(APP_ID, USER_SECRET_1, registration['keyHandle'], |
| HASH_TO_SIGN, '00', VENDOR_CMD_RESPONSE_SUCCESS) |
| |
| self.__u2f_sign(APP_ID_2, USER_SECRET_1, registration['keyHandle'], |
| HASH_TO_SIGN, '00', VENDOR_CMD_RESPONSE_PASSWORD_REQUIRED) |
| |
| def __test_sign_invalid_kh(self): |
| # U2F asserts presence by checking for a power button press within the |
| # last 10 seconds, sleep so that we are sure there was not one. |
| |
| time.sleep(11) |
| |
| self.__u2f_sign( |
| APP_ID, |
| USER_SECRET_1, |
| RANDOM_32 + RANDOM_32, # KH is 64 bytes long |
| HASH_TO_SIGN, |
| '00', |
| VENDOR_CMD_RESPONSE_PASSWORD_REQUIRED) |
| |
| self.__u2f_sign( |
| APP_ID, |
| USER_SECRET_1, |
| RANDOM_32 + RANDOM_32, # KH is 64 bytes long |
| HASH_TO_SIGN, |
| '02', # G2F_CONSUME |
| VENDOR_CMD_RESPONSE_PASSWORD_REQUIRED) |
| |
| def __test_sign_invalid_kh_with_presence(self): |
| registration = self.__u2f_generate(APP_ID, USER_SECRET_1, '00') |
| |
| self._safe_power_short_press() |
| |
| # Should return invalid KH error, without consuming presence. |
| self.__u2f_sign( |
| APP_ID, |
| USER_SECRET_1, |
| RANDOM_32 + RANDOM_32, # KH is 64 bytes long |
| HASH_TO_SIGN, |
| '02', # G2F_CONSUME |
| VENDOR_CMD_RESPONSE_PASSWORD_REQUIRED) |
| |
| # Check presence was not consumed. |
| self.__u2f_sign(APP_ID, USER_SECRET_1, registration['keyHandle'], |
| HASH_TO_SIGN, '00', VENDOR_CMD_RESPONSE_SUCCESS) |
| |
| def __test_sign_check_only(self): |
| registration = self.__u2f_generate(APP_ID, USER_SECRET_1, '00') |
| |
| # U2F asserts presence by checking for a power button press within the |
| # last 10 seconds, sleep so that we are sure there was not one. |
| |
| time.sleep(11) |
| |
| self.__u2f_sign(APP_ID, USER_SECRET_1, registration['keyHandle'], |
| HASH_TO_SIGN, '07', VENDOR_CMD_RESPONSE_SUCCESS) |
| |
| def __test_sign_check_only_with_presence(self): |
| registration = self.__u2f_generate(APP_ID, USER_SECRET_1, '00') |
| |
| self._safe_power_short_press() |
| |
| self.__u2f_sign(APP_ID, USER_SECRET_1, registration['keyHandle'], |
| HASH_TO_SIGN, '07', VENDOR_CMD_RESPONSE_SUCCESS) |
| |
| def __test_sign_check_only_invalid_kh(self): |
| # U2F asserts presence by checking for a power button press within the |
| # last 10 seconds, sleep so that we are sure there was not one. |
| |
| time.sleep(11) |
| |
| self.__u2f_sign(APP_ID, |
| USER_SECRET_1, |
| RANDOM_32 + RANDOM_32, # KH is 64 bytes long |
| HASH_TO_SIGN, |
| '07', |
| VENDOR_CMD_RESPONSE_PASSWORD_REQUIRED) |
| |
| def __test_sign_check_only_invalid_kh_with_presence(self): |
| registration = self.__u2f_generate(APP_ID, USER_SECRET_1, '00') |
| |
| self._safe_power_short_press() |
| |
| self.__u2f_sign(APP_ID, |
| USER_SECRET_1, |
| RANDOM_32 + RANDOM_32, # KH is 64 bytes long |
| HASH_TO_SIGN, |
| '07', |
| VENDOR_CMD_RESPONSE_PASSWORD_REQUIRED) |
| |
| def __check_attest_reg_resp(self, |
| app_id, |
| key_handle, |
| pub_key, |
| user_secret, |
| expected_response, |
| pad=False): |
| register_resp = '00{}{}{}{}'.format( |
| app_id, |
| RANDOM_32, # challenge |
| key_handle, |
| pub_key) |
| |
| self.__u2f_attest(user_secret, U2F_ATTEST_FORMAT_REG_RESP, register_resp, |
| expected_response, pad) |
| |
| def __test_attest_simple(self): |
| # Attest does not require user presence |
| time.sleep(11) |
| |
| registration = self.__u2f_generate(APP_ID, USER_SECRET_1, '00') |
| |
| self.__check_attest_reg_resp(APP_ID, registration['keyHandle'], |
| registration['pubKey'], USER_SECRET_1, |
| VENDOR_CMD_RESPONSE_SUCCESS) |
| |
| def __test_attest_simple_padded(self): |
| registration = self.__u2f_generate(APP_ID, USER_SECRET_1, '00') |
| |
| self.__check_attest_reg_resp( |
| APP_ID, |
| registration['keyHandle'], |
| registration['pubKey'], |
| USER_SECRET_1, |
| VENDOR_CMD_RESPONSE_SUCCESS, |
| pad=True) |
| |
| def __test_attest_wrong_user(self): |
| registration = self.__u2f_generate(APP_ID, USER_SECRET_1, '00') |
| |
| self.__check_attest_reg_resp(APP_ID, registration['keyHandle'], |
| registration['pubKey'], USER_SECRET_2, |
| VENDOR_CMD_RESPONSE_NOT_ALLOWED) |
| |
| def __test_attest_wrong_app_id(self): |
| registration = self.__u2f_generate(APP_ID, USER_SECRET_1, '00') |
| |
| self.__check_attest_reg_resp(APP_ID_2, registration['keyHandle'], |
| registration['pubKey'], USER_SECRET_1, |
| VENDOR_CMD_RESPONSE_NOT_ALLOWED) |
| |
| def __test_attest_wrong_pub_key(self): |
| registration = self.__u2f_generate(APP_ID, USER_SECRET_1, '00') |
| |
| self.__check_attest_reg_resp(APP_ID, registration['keyHandle'], |
| 'FF' * 65, USER_SECRET_1, |
| VENDOR_CMD_RESPONSE_NOT_ALLOWED) |
| |
| def __test_attest_garbage_data(self): |
| self.__u2f_attest(USER_SECRET_1, U2F_ATTEST_FORMAT_REG_RESP, |
| 'ff' * U2F_ATTEST_REG_RESP_SIZE_BYTES, |
| VENDOR_CMD_RESPONSE_NOT_ALLOWED) |
| |
| def __test_attest_truncated_data(self): |
| registration = self.__u2f_generate(APP_ID, USER_SECRET_1, '00') |
| |
| register_resp = '00{}{}{}{}'.format( |
| APP_ID, |
| RANDOM_32, # challenge |
| registration['keyHandle'], |
| registration['pubKey']) |
| |
| # Attempt to attest to valid data with invalid format. |
| self.__u2f_attest(USER_SECRET_1, U2F_ATTEST_FORMAT_REG_RESP, register_resp, |
| VENDOR_CMD_RESPONSE_BOGUS_ARGS, truncated=True) |
| |
| def __test_attest_invalid_format(self): |
| registration = self.__u2f_generate(APP_ID, USER_SECRET_1, '00') |
| |
| register_resp = '00{}{}{}{}'.format( |
| APP_ID, |
| RANDOM_32, # challenge |
| registration['keyHandle'], |
| registration['pubKey']) |
| |
| # Attempt to attest to valid data with invalid format. |
| self.__u2f_attest(USER_SECRET_1, 'ff', register_resp, |
| VENDOR_CMD_RESPONSE_NOT_ALLOWED) |
| |
| def __test_attest_invalid_reserved_byte(self): |
| registration = self.__u2f_generate(APP_ID, USER_SECRET_1, '00') |
| |
| register_resp = '{}{}{}{}{}'.format( |
| '01', # unexpected reserved byte |
| APP_ID, |
| RANDOM_32, # challenge |
| registration['keyHandle'], |
| registration['pubKey']) |
| |
| # Attempt to attest to valid data with invalid format. |
| self.__u2f_attest(USER_SECRET_1, U2F_ATTEST_FORMAT_REG_RESP, register_resp, |
| VENDOR_CMD_RESPONSE_NOT_ALLOWED) |
| |
| def __test_kh_invalidated_by_powerwash(self): |
| registration = self.__u2f_generate(APP_ID, USER_SECRET_1, '00') |
| |
| self._safe_power_short_press() |
| |
| # Sanity check |
| self.__u2f_sign(APP_ID, USER_SECRET_1, registration['keyHandle'], |
| HASH_TO_SIGN, '00', VENDOR_CMD_RESPONSE_SUCCESS) |
| |
| # 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) |
| |
| self._safe_power_short_press() |
| |
| self.__u2f_sign(APP_ID, USER_SECRET_1, registration['keyHandle'], |
| HASH_TO_SIGN, '00', VENDOR_CMD_RESPONSE_PASSWORD_REQUIRED) |
| |
| def run_once(self, host=None): |
| """Run the tests.""" |
| |
| self.client = host |
| |
| # Basic functionality |
| self.__test_generate_unique() |
| self.__test_generate_sign_simple() |
| |
| # Generate - presence |
| self.__test_generate_with_presence() |
| self.__test_generate_consume_presence() |
| |
| # Sign - presence |
| self.__test_sign_requires_presence() |
| self.__test_sign_multiple_no_consume() |
| self.__test_sign_consume() |
| |
| # Sign - key handle |
| self.__test_sign_wrong_user_secret() |
| self.__test_sign_wrong_app_id() |
| self.__test_sign_invalid_kh() |
| |
| # Sign - check only |
| self.__test_sign_check_only() |
| self.__test_sign_check_only_with_presence() |
| self.__test_sign_check_only_invalid_kh() |
| self.__test_sign_check_only_invalid_kh_with_presence() |
| |
| # Attest |
| self.__test_attest_simple() |
| self.__test_attest_simple_padded() |
| self.__test_attest_wrong_user() |
| self.__test_attest_wrong_app_id() |
| self.__test_attest_wrong_pub_key() |
| self.__test_attest_garbage_data() |
| self.__test_attest_truncated_data() |
| self.__test_attest_invalid_format() |
| self.__test_attest_invalid_reserved_byte() |
| |
| # Powerwash |
| self.__test_kh_invalidated_by_powerwash() |