diff options
Diffstat (limited to 'test/tpm_test/u2f_test.py')
-rw-r--r-- | test/tpm_test/u2f_test.py | 100 |
1 files changed, 100 insertions, 0 deletions
diff --git a/test/tpm_test/u2f_test.py b/test/tpm_test/u2f_test.py new file mode 100644 index 0000000000..9cb7d5e609 --- /dev/null +++ b/test/tpm_test/u2f_test.py @@ -0,0 +1,100 @@ +# -*- coding: utf-8 -*- +# Copyright 2021 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. + +"""Module for testing u2f functions using extended commands.""" +from binascii import a2b_hex as a2b +import hashlib +import os +import struct + +import subcmd +import utils + + +# U2F_GENERATE: +# origin [32] | user [32] | flag | [auth_secret[32]] +def u2f_generate(tpm, origin, user, flag, auth): + origin = origin[:32].ljust(32, b'\0') + user = user[:32].ljust(32, b'\0') + auth = auth[:32].ljust(32, b'\0') + cmd = origin + user + flag.to_bytes(1, 'big') + auth + wrapped_response = tpm.command(tpm.wrap_ext_command(subcmd.U2F_GENERATE, cmd)) + response = tpm.unwrap_ext_response(subcmd.U2F_GENERATE, wrapped_response) + public_key = response[:65] + kh = response[65:] + return public_key, kh + +def u2f_sign(tpm, origin, user, auth, kh, msg, flag, fail=False): + origin = origin[:32].ljust(32, b'\0') + user = user[:32].ljust(32, b'\0') + auth = auth[:32].ljust(32, b'\0') + msg = msg[:32].ljust(32, b'\0') + + # determine version by size of key handle + if (len(kh) == 64): + cmd = origin + user + kh + msg + flag.to_bytes(1, 'big') + else: + cmd = origin + user + auth + msg + flag.to_bytes(1, 'big') + kh + + if fail==False: + wrapped_response = tpm.command(tpm.wrap_ext_command( + subcmd.U2F_SIGN, cmd)) + response = tpm.unwrap_ext_response(subcmd.U2F_SIGN, wrapped_response) + sig = response[:64] + else: + response, size, response_code = tpm.command_unchecked( + tpm.wrap_ext_command(subcmd.U2F_SIGN, cmd)) + if size != 12: + raise subcmd.TpmTestError('Unexpected response: ' + + utils.hex_dump(response)) + print('response: ', hex(response_code)) + return b'' + return sig + +def u2f_attest(tpm, origin, user, challenge, kh, public_key, fail=False): + origin = origin[:32].ljust(32, b'\0') + user = user[:32].ljust(32, b'\0') + challenge = challenge[:32].ljust(32, b'\0') + g2f_cmd = b'\0' + origin + challenge + kh + public_key + cmd = user + b'\0' + len(g2f_cmd).to_bytes(1, 'big') + g2f_cmd + if fail==False: + wrapped_response = tpm.command(tpm.wrap_ext_command( + subcmd.U2F_ATTEST, cmd)) + response = tpm.unwrap_ext_response(subcmd.U2F_ATTEST, wrapped_response) + sig = response[:64] + else: + response, size, response_code = tpm.command_unchecked( + tpm.wrap_ext_command(subcmd.U2F_ATTEST, cmd)) + if size != 12: + raise subcmd.TpmTestError('Unexpected response: ' + + utils.hex_dump(response)) + print('response: ', hex(response_code)) + return b'' + return sig + +def u2f_test(tpm): + """Run U2F tests""" + origin = b'1' + user = b'2' + auth = b'3' + msg = b'12345' + public_key1, khv1 = u2f_generate(tpm, origin, user, 0, auth) + print('key_handle v1 = ',utils.hex_dump(khv1), len(khv1)) + print('public_key v1 = ',utils.hex_dump(public_key1), len(public_key1)) + + public_key2, khv2 = u2f_generate(tpm, origin, user, 8, auth) + print('key_handle v2 = ',utils.hex_dump(khv2), len(khv2)) + + sig1 = u2f_sign(tpm, origin, user, auth, khv1, msg, 2) + print('sig v1 = ',utils.hex_dump(sig1), len(sig1)) + + sig1 = u2f_sign(tpm, origin, user, auth, khv2, msg, 2) + print('sig v2 = ',utils.hex_dump(sig1), len(sig1)) + + sig1 = u2f_sign(tpm, user, origin, auth, khv2, msg, 2, fail=True) + print('sig v2 = ',utils.hex_dump(sig1), len(sig1)) + + sig_attest = u2f_attest(tpm, origin, user, auth, khv1, public_key1) + print('sig attest = ',utils.hex_dump(sig_attest), len(sig_attest)) |