16ea3dfe1SJarkko Sakkinen# SPDX-License-Identifier: (GPL-2.0 OR BSD-3-Clause) 26ea3dfe1SJarkko Sakkinen 36ea3dfe1SJarkko Sakkinenfrom argparse import ArgumentParser 46ea3dfe1SJarkko Sakkinenfrom argparse import FileType 56ea3dfe1SJarkko Sakkinenimport os 66ea3dfe1SJarkko Sakkinenimport sys 76ea3dfe1SJarkko Sakkinenimport tpm2 86ea3dfe1SJarkko Sakkinenfrom tpm2 import ProtocolError 96ea3dfe1SJarkko Sakkinenimport unittest 106ea3dfe1SJarkko Sakkinenimport logging 116ea3dfe1SJarkko Sakkinenimport struct 126ea3dfe1SJarkko Sakkinen 136ea3dfe1SJarkko Sakkinenclass SmokeTest(unittest.TestCase): 146ea3dfe1SJarkko Sakkinen def setUp(self): 156ea3dfe1SJarkko Sakkinen self.client = tpm2.Client() 166ea3dfe1SJarkko Sakkinen self.root_key = self.client.create_root_key() 176ea3dfe1SJarkko Sakkinen 186ea3dfe1SJarkko Sakkinen def tearDown(self): 196ea3dfe1SJarkko Sakkinen self.client.flush_context(self.root_key) 206ea3dfe1SJarkko Sakkinen self.client.close() 216ea3dfe1SJarkko Sakkinen 226ea3dfe1SJarkko Sakkinen def test_seal_with_auth(self): 236ea3dfe1SJarkko Sakkinen data = 'X' * 64 246ea3dfe1SJarkko Sakkinen auth = 'A' * 15 256ea3dfe1SJarkko Sakkinen 266ea3dfe1SJarkko Sakkinen blob = self.client.seal(self.root_key, data, auth, None) 276ea3dfe1SJarkko Sakkinen result = self.client.unseal(self.root_key, blob, auth, None) 286ea3dfe1SJarkko Sakkinen self.assertEqual(data, result) 296ea3dfe1SJarkko Sakkinen 306ea3dfe1SJarkko Sakkinen def test_seal_with_policy(self): 316ea3dfe1SJarkko Sakkinen handle = self.client.start_auth_session(tpm2.TPM2_SE_TRIAL) 326ea3dfe1SJarkko Sakkinen 336ea3dfe1SJarkko Sakkinen data = 'X' * 64 346ea3dfe1SJarkko Sakkinen auth = 'A' * 15 356ea3dfe1SJarkko Sakkinen pcrs = [16] 366ea3dfe1SJarkko Sakkinen 376ea3dfe1SJarkko Sakkinen try: 386ea3dfe1SJarkko Sakkinen self.client.policy_pcr(handle, pcrs) 396ea3dfe1SJarkko Sakkinen self.client.policy_password(handle) 406ea3dfe1SJarkko Sakkinen 416ea3dfe1SJarkko Sakkinen policy_dig = self.client.get_policy_digest(handle) 426ea3dfe1SJarkko Sakkinen finally: 436ea3dfe1SJarkko Sakkinen self.client.flush_context(handle) 446ea3dfe1SJarkko Sakkinen 456ea3dfe1SJarkko Sakkinen blob = self.client.seal(self.root_key, data, auth, policy_dig) 466ea3dfe1SJarkko Sakkinen 476ea3dfe1SJarkko Sakkinen handle = self.client.start_auth_session(tpm2.TPM2_SE_POLICY) 486ea3dfe1SJarkko Sakkinen 496ea3dfe1SJarkko Sakkinen try: 506ea3dfe1SJarkko Sakkinen self.client.policy_pcr(handle, pcrs) 516ea3dfe1SJarkko Sakkinen self.client.policy_password(handle) 526ea3dfe1SJarkko Sakkinen 536ea3dfe1SJarkko Sakkinen result = self.client.unseal(self.root_key, blob, auth, handle) 546ea3dfe1SJarkko Sakkinen except: 556ea3dfe1SJarkko Sakkinen self.client.flush_context(handle) 566ea3dfe1SJarkko Sakkinen raise 576ea3dfe1SJarkko Sakkinen 586ea3dfe1SJarkko Sakkinen self.assertEqual(data, result) 596ea3dfe1SJarkko Sakkinen 606ea3dfe1SJarkko Sakkinen def test_unseal_with_wrong_auth(self): 616ea3dfe1SJarkko Sakkinen data = 'X' * 64 626ea3dfe1SJarkko Sakkinen auth = 'A' * 20 636ea3dfe1SJarkko Sakkinen rc = 0 646ea3dfe1SJarkko Sakkinen 656ea3dfe1SJarkko Sakkinen blob = self.client.seal(self.root_key, data, auth, None) 666ea3dfe1SJarkko Sakkinen try: 676ea3dfe1SJarkko Sakkinen result = self.client.unseal(self.root_key, blob, auth[:-1] + 'B', None) 686ea3dfe1SJarkko Sakkinen except ProtocolError, e: 696ea3dfe1SJarkko Sakkinen rc = e.rc 706ea3dfe1SJarkko Sakkinen 716ea3dfe1SJarkko Sakkinen self.assertEqual(rc, tpm2.TPM2_RC_AUTH_FAIL) 726ea3dfe1SJarkko Sakkinen 736ea3dfe1SJarkko Sakkinen def test_unseal_with_wrong_policy(self): 746ea3dfe1SJarkko Sakkinen handle = self.client.start_auth_session(tpm2.TPM2_SE_TRIAL) 756ea3dfe1SJarkko Sakkinen 766ea3dfe1SJarkko Sakkinen data = 'X' * 64 776ea3dfe1SJarkko Sakkinen auth = 'A' * 17 786ea3dfe1SJarkko Sakkinen pcrs = [16] 796ea3dfe1SJarkko Sakkinen 806ea3dfe1SJarkko Sakkinen try: 816ea3dfe1SJarkko Sakkinen self.client.policy_pcr(handle, pcrs) 826ea3dfe1SJarkko Sakkinen self.client.policy_password(handle) 836ea3dfe1SJarkko Sakkinen 846ea3dfe1SJarkko Sakkinen policy_dig = self.client.get_policy_digest(handle) 856ea3dfe1SJarkko Sakkinen finally: 866ea3dfe1SJarkko Sakkinen self.client.flush_context(handle) 876ea3dfe1SJarkko Sakkinen 886ea3dfe1SJarkko Sakkinen blob = self.client.seal(self.root_key, data, auth, policy_dig) 896ea3dfe1SJarkko Sakkinen 906ea3dfe1SJarkko Sakkinen # Extend first a PCR that is not part of the policy and try to unseal. 916ea3dfe1SJarkko Sakkinen # This should succeed. 926ea3dfe1SJarkko Sakkinen 936ea3dfe1SJarkko Sakkinen ds = tpm2.get_digest_size(tpm2.TPM2_ALG_SHA1) 946ea3dfe1SJarkko Sakkinen self.client.extend_pcr(1, 'X' * ds) 956ea3dfe1SJarkko Sakkinen 966ea3dfe1SJarkko Sakkinen handle = self.client.start_auth_session(tpm2.TPM2_SE_POLICY) 976ea3dfe1SJarkko Sakkinen 986ea3dfe1SJarkko Sakkinen try: 996ea3dfe1SJarkko Sakkinen self.client.policy_pcr(handle, pcrs) 1006ea3dfe1SJarkko Sakkinen self.client.policy_password(handle) 1016ea3dfe1SJarkko Sakkinen 1026ea3dfe1SJarkko Sakkinen result = self.client.unseal(self.root_key, blob, auth, handle) 1036ea3dfe1SJarkko Sakkinen except: 1046ea3dfe1SJarkko Sakkinen self.client.flush_context(handle) 1056ea3dfe1SJarkko Sakkinen raise 1066ea3dfe1SJarkko Sakkinen 1076ea3dfe1SJarkko Sakkinen self.assertEqual(data, result) 1086ea3dfe1SJarkko Sakkinen 1096ea3dfe1SJarkko Sakkinen # Then, extend a PCR that is part of the policy and try to unseal. 1106ea3dfe1SJarkko Sakkinen # This should fail. 1116ea3dfe1SJarkko Sakkinen self.client.extend_pcr(16, 'X' * ds) 1126ea3dfe1SJarkko Sakkinen 1136ea3dfe1SJarkko Sakkinen handle = self.client.start_auth_session(tpm2.TPM2_SE_POLICY) 1146ea3dfe1SJarkko Sakkinen 1156ea3dfe1SJarkko Sakkinen rc = 0 1166ea3dfe1SJarkko Sakkinen 1176ea3dfe1SJarkko Sakkinen try: 1186ea3dfe1SJarkko Sakkinen self.client.policy_pcr(handle, pcrs) 1196ea3dfe1SJarkko Sakkinen self.client.policy_password(handle) 1206ea3dfe1SJarkko Sakkinen 1216ea3dfe1SJarkko Sakkinen result = self.client.unseal(self.root_key, blob, auth, handle) 1226ea3dfe1SJarkko Sakkinen except ProtocolError, e: 1236ea3dfe1SJarkko Sakkinen rc = e.rc 1246ea3dfe1SJarkko Sakkinen self.client.flush_context(handle) 1256ea3dfe1SJarkko Sakkinen except: 1266ea3dfe1SJarkko Sakkinen self.client.flush_context(handle) 1276ea3dfe1SJarkko Sakkinen raise 1286ea3dfe1SJarkko Sakkinen 1296ea3dfe1SJarkko Sakkinen self.assertEqual(rc, tpm2.TPM2_RC_POLICY_FAIL) 1306ea3dfe1SJarkko Sakkinen 1316ea3dfe1SJarkko Sakkinen def test_seal_with_too_long_auth(self): 1326ea3dfe1SJarkko Sakkinen ds = tpm2.get_digest_size(tpm2.TPM2_ALG_SHA1) 1336ea3dfe1SJarkko Sakkinen data = 'X' * 64 1346ea3dfe1SJarkko Sakkinen auth = 'A' * (ds + 1) 1356ea3dfe1SJarkko Sakkinen 1366ea3dfe1SJarkko Sakkinen rc = 0 1376ea3dfe1SJarkko Sakkinen try: 1386ea3dfe1SJarkko Sakkinen blob = self.client.seal(self.root_key, data, auth, None) 1396ea3dfe1SJarkko Sakkinen except ProtocolError, e: 1406ea3dfe1SJarkko Sakkinen rc = e.rc 1416ea3dfe1SJarkko Sakkinen 1426ea3dfe1SJarkko Sakkinen self.assertEqual(rc, tpm2.TPM2_RC_SIZE) 1436ea3dfe1SJarkko Sakkinen 1446ea3dfe1SJarkko Sakkinen def test_too_short_cmd(self): 1456ea3dfe1SJarkko Sakkinen rejected = False 1466ea3dfe1SJarkko Sakkinen try: 1476ea3dfe1SJarkko Sakkinen fmt = '>HIII' 1486ea3dfe1SJarkko Sakkinen cmd = struct.pack(fmt, 1496ea3dfe1SJarkko Sakkinen tpm2.TPM2_ST_NO_SESSIONS, 1506ea3dfe1SJarkko Sakkinen struct.calcsize(fmt) + 1, 1516ea3dfe1SJarkko Sakkinen tpm2.TPM2_CC_FLUSH_CONTEXT, 1526ea3dfe1SJarkko Sakkinen 0xDEADBEEF) 1536ea3dfe1SJarkko Sakkinen 1546ea3dfe1SJarkko Sakkinen self.client.send_cmd(cmd) 1556ea3dfe1SJarkko Sakkinen except IOError, e: 1566ea3dfe1SJarkko Sakkinen rejected = True 1576ea3dfe1SJarkko Sakkinen except: 1586ea3dfe1SJarkko Sakkinen pass 1596ea3dfe1SJarkko Sakkinen self.assertEqual(rejected, True) 1606ea3dfe1SJarkko Sakkinen 161f1a0ba6cSTadeusz Struk def test_read_partial_resp(self): 162f1a0ba6cSTadeusz Struk try: 163f1a0ba6cSTadeusz Struk fmt = '>HIIH' 164f1a0ba6cSTadeusz Struk cmd = struct.pack(fmt, 165f1a0ba6cSTadeusz Struk tpm2.TPM2_ST_NO_SESSIONS, 166f1a0ba6cSTadeusz Struk struct.calcsize(fmt), 167f1a0ba6cSTadeusz Struk tpm2.TPM2_CC_GET_RANDOM, 168f1a0ba6cSTadeusz Struk 0x20) 169f1a0ba6cSTadeusz Struk self.client.tpm.write(cmd) 170f1a0ba6cSTadeusz Struk hdr = self.client.tpm.read(10) 171f1a0ba6cSTadeusz Struk sz = struct.unpack('>I', hdr[2:6])[0] 172f1a0ba6cSTadeusz Struk rsp = self.client.tpm.read() 173f1a0ba6cSTadeusz Struk except: 174f1a0ba6cSTadeusz Struk pass 175f1a0ba6cSTadeusz Struk self.assertEqual(sz, 10 + 2 + 32) 176f1a0ba6cSTadeusz Struk self.assertEqual(len(rsp), 2 + 32) 177f1a0ba6cSTadeusz Struk 178f1a0ba6cSTadeusz Struk def test_read_partial_overwrite(self): 179f1a0ba6cSTadeusz Struk try: 180f1a0ba6cSTadeusz Struk fmt = '>HIIH' 181f1a0ba6cSTadeusz Struk cmd = struct.pack(fmt, 182f1a0ba6cSTadeusz Struk tpm2.TPM2_ST_NO_SESSIONS, 183f1a0ba6cSTadeusz Struk struct.calcsize(fmt), 184f1a0ba6cSTadeusz Struk tpm2.TPM2_CC_GET_RANDOM, 185f1a0ba6cSTadeusz Struk 0x20) 186f1a0ba6cSTadeusz Struk self.client.tpm.write(cmd) 187f1a0ba6cSTadeusz Struk # Read part of the respone 188f1a0ba6cSTadeusz Struk rsp1 = self.client.tpm.read(15) 189f1a0ba6cSTadeusz Struk 190f1a0ba6cSTadeusz Struk # Send a new cmd 191f1a0ba6cSTadeusz Struk self.client.tpm.write(cmd) 192f1a0ba6cSTadeusz Struk 193f1a0ba6cSTadeusz Struk # Read the whole respone 194f1a0ba6cSTadeusz Struk rsp2 = self.client.tpm.read() 195f1a0ba6cSTadeusz Struk except: 196f1a0ba6cSTadeusz Struk pass 197f1a0ba6cSTadeusz Struk self.assertEqual(len(rsp1), 15) 198f1a0ba6cSTadeusz Struk self.assertEqual(len(rsp2), 10 + 2 + 32) 199f1a0ba6cSTadeusz Struk 200f1a0ba6cSTadeusz Struk def test_send_two_cmds(self): 201f1a0ba6cSTadeusz Struk rejected = False 202f1a0ba6cSTadeusz Struk try: 203f1a0ba6cSTadeusz Struk fmt = '>HIIH' 204f1a0ba6cSTadeusz Struk cmd = struct.pack(fmt, 205f1a0ba6cSTadeusz Struk tpm2.TPM2_ST_NO_SESSIONS, 206f1a0ba6cSTadeusz Struk struct.calcsize(fmt), 207f1a0ba6cSTadeusz Struk tpm2.TPM2_CC_GET_RANDOM, 208f1a0ba6cSTadeusz Struk 0x20) 209f1a0ba6cSTadeusz Struk self.client.tpm.write(cmd) 210f1a0ba6cSTadeusz Struk 211f1a0ba6cSTadeusz Struk # expect the second one to raise -EBUSY error 212f1a0ba6cSTadeusz Struk self.client.tpm.write(cmd) 213f1a0ba6cSTadeusz Struk rsp = self.client.tpm.read() 214f1a0ba6cSTadeusz Struk 215f1a0ba6cSTadeusz Struk except IOError, e: 216f1a0ba6cSTadeusz Struk # read the response 217f1a0ba6cSTadeusz Struk rsp = self.client.tpm.read() 218f1a0ba6cSTadeusz Struk rejected = True 219f1a0ba6cSTadeusz Struk pass 220f1a0ba6cSTadeusz Struk except: 221f1a0ba6cSTadeusz Struk pass 222f1a0ba6cSTadeusz Struk self.assertEqual(rejected, True) 223f1a0ba6cSTadeusz Struk 2246ea3dfe1SJarkko Sakkinenclass SpaceTest(unittest.TestCase): 2256ea3dfe1SJarkko Sakkinen def setUp(self): 2266ea3dfe1SJarkko Sakkinen logging.basicConfig(filename='SpaceTest.log', level=logging.DEBUG) 2276ea3dfe1SJarkko Sakkinen 2286ea3dfe1SJarkko Sakkinen def test_make_two_spaces(self): 2296ea3dfe1SJarkko Sakkinen log = logging.getLogger(__name__) 2306ea3dfe1SJarkko Sakkinen log.debug("test_make_two_spaces") 2316ea3dfe1SJarkko Sakkinen 2326ea3dfe1SJarkko Sakkinen space1 = tpm2.Client(tpm2.Client.FLAG_SPACE) 2336ea3dfe1SJarkko Sakkinen root1 = space1.create_root_key() 2346ea3dfe1SJarkko Sakkinen space2 = tpm2.Client(tpm2.Client.FLAG_SPACE) 2356ea3dfe1SJarkko Sakkinen root2 = space2.create_root_key() 2366ea3dfe1SJarkko Sakkinen root3 = space2.create_root_key() 2376ea3dfe1SJarkko Sakkinen 2386ea3dfe1SJarkko Sakkinen log.debug("%08x" % (root1)) 2396ea3dfe1SJarkko Sakkinen log.debug("%08x" % (root2)) 2406ea3dfe1SJarkko Sakkinen log.debug("%08x" % (root3)) 2416ea3dfe1SJarkko Sakkinen 2426ea3dfe1SJarkko Sakkinen def test_flush_context(self): 2436ea3dfe1SJarkko Sakkinen log = logging.getLogger(__name__) 2446ea3dfe1SJarkko Sakkinen log.debug("test_flush_context") 2456ea3dfe1SJarkko Sakkinen 2466ea3dfe1SJarkko Sakkinen space1 = tpm2.Client(tpm2.Client.FLAG_SPACE) 2476ea3dfe1SJarkko Sakkinen root1 = space1.create_root_key() 2486ea3dfe1SJarkko Sakkinen log.debug("%08x" % (root1)) 2496ea3dfe1SJarkko Sakkinen 2506ea3dfe1SJarkko Sakkinen space1.flush_context(root1) 2516ea3dfe1SJarkko Sakkinen 2526ea3dfe1SJarkko Sakkinen def test_get_handles(self): 2536ea3dfe1SJarkko Sakkinen log = logging.getLogger(__name__) 2546ea3dfe1SJarkko Sakkinen log.debug("test_get_handles") 2556ea3dfe1SJarkko Sakkinen 2566ea3dfe1SJarkko Sakkinen space1 = tpm2.Client(tpm2.Client.FLAG_SPACE) 2576ea3dfe1SJarkko Sakkinen space1.create_root_key() 2586ea3dfe1SJarkko Sakkinen space2 = tpm2.Client(tpm2.Client.FLAG_SPACE) 2596ea3dfe1SJarkko Sakkinen space2.create_root_key() 2606ea3dfe1SJarkko Sakkinen space2.create_root_key() 2616ea3dfe1SJarkko Sakkinen 2626ea3dfe1SJarkko Sakkinen handles = space2.get_cap(tpm2.TPM2_CAP_HANDLES, tpm2.HR_TRANSIENT) 2636ea3dfe1SJarkko Sakkinen 2646ea3dfe1SJarkko Sakkinen self.assertEqual(len(handles), 2) 2656ea3dfe1SJarkko Sakkinen 2666ea3dfe1SJarkko Sakkinen log.debug("%08x" % (handles[0])) 2676ea3dfe1SJarkko Sakkinen log.debug("%08x" % (handles[1])) 2686ea3dfe1SJarkko Sakkinen 2696ea3dfe1SJarkko Sakkinen def test_invalid_cc(self): 2706ea3dfe1SJarkko Sakkinen log = logging.getLogger(__name__) 2716ea3dfe1SJarkko Sakkinen log.debug(sys._getframe().f_code.co_name) 2726ea3dfe1SJarkko Sakkinen 2736ea3dfe1SJarkko Sakkinen TPM2_CC_INVALID = tpm2.TPM2_CC_FIRST - 1 2746ea3dfe1SJarkko Sakkinen 2756ea3dfe1SJarkko Sakkinen space1 = tpm2.Client(tpm2.Client.FLAG_SPACE) 2766ea3dfe1SJarkko Sakkinen root1 = space1.create_root_key() 2776ea3dfe1SJarkko Sakkinen log.debug("%08x" % (root1)) 2786ea3dfe1SJarkko Sakkinen 2796ea3dfe1SJarkko Sakkinen fmt = '>HII' 2806ea3dfe1SJarkko Sakkinen cmd = struct.pack(fmt, tpm2.TPM2_ST_NO_SESSIONS, struct.calcsize(fmt), 2816ea3dfe1SJarkko Sakkinen TPM2_CC_INVALID) 2826ea3dfe1SJarkko Sakkinen 2836ea3dfe1SJarkko Sakkinen rc = 0 2846ea3dfe1SJarkko Sakkinen try: 2856ea3dfe1SJarkko Sakkinen space1.send_cmd(cmd) 2866ea3dfe1SJarkko Sakkinen except ProtocolError, e: 2876ea3dfe1SJarkko Sakkinen rc = e.rc 2886ea3dfe1SJarkko Sakkinen 2896ea3dfe1SJarkko Sakkinen self.assertEqual(rc, tpm2.TPM2_RC_COMMAND_CODE | 2906ea3dfe1SJarkko Sakkinen tpm2.TSS2_RESMGR_TPM_RC_LAYER) 2918f84bddcSTadeusz Struk 2928f84bddcSTadeusz Strukclass AsyncTest(unittest.TestCase): 2938f84bddcSTadeusz Struk def setUp(self): 2948f84bddcSTadeusz Struk logging.basicConfig(filename='AsyncTest.log', level=logging.DEBUG) 2958f84bddcSTadeusz Struk 2968f84bddcSTadeusz Struk def test_async(self): 2978f84bddcSTadeusz Struk log = logging.getLogger(__name__) 2988f84bddcSTadeusz Struk log.debug(sys._getframe().f_code.co_name) 2998f84bddcSTadeusz Struk 3008f84bddcSTadeusz Struk async_client = tpm2.Client(tpm2.Client.FLAG_NONBLOCK) 3018f84bddcSTadeusz Struk log.debug("Calling get_cap in a NON_BLOCKING mode") 3028f84bddcSTadeusz Struk async_client.get_cap(tpm2.TPM2_CAP_HANDLES, tpm2.HR_LOADED_SESSION) 3038f84bddcSTadeusz Struk async_client.close() 304