750 lines · python
1# SPDX-License-Identifier: (GPL-2.0 OR BSD-3-Clause)2 3import hashlib4import os5import socket6import struct7import sys8import unittest9import fcntl10import select11 12TPM2_ST_NO_SESSIONS = 0x800113TPM2_ST_SESSIONS = 0x800214 15TPM2_CC_FIRST = 0x01FF16 17TPM2_CC_CREATE_PRIMARY = 0x013118TPM2_CC_DICTIONARY_ATTACK_LOCK_RESET = 0x013919TPM2_CC_CREATE = 0x015320TPM2_CC_LOAD = 0x015721TPM2_CC_UNSEAL = 0x015E22TPM2_CC_FLUSH_CONTEXT = 0x016523TPM2_CC_START_AUTH_SESSION = 0x017624TPM2_CC_GET_CAPABILITY = 0x017A25TPM2_CC_GET_RANDOM = 0x017B26TPM2_CC_PCR_READ = 0x017E27TPM2_CC_POLICY_PCR = 0x017F28TPM2_CC_PCR_EXTEND = 0x018229TPM2_CC_POLICY_PASSWORD = 0x018C30TPM2_CC_POLICY_GET_DIGEST = 0x018931 32TPM2_SE_POLICY = 0x0133TPM2_SE_TRIAL = 0x0334 35TPM2_ALG_RSA = 0x000136TPM2_ALG_SHA1 = 0x000437TPM2_ALG_AES = 0x000638TPM2_ALG_KEYEDHASH = 0x000839TPM2_ALG_SHA256 = 0x000B40TPM2_ALG_NULL = 0x001041TPM2_ALG_CBC = 0x004242TPM2_ALG_CFB = 0x004343 44TPM2_RH_OWNER = 0x4000000145TPM2_RH_NULL = 0x4000000746TPM2_RH_LOCKOUT = 0x4000000A47TPM2_RS_PW = 0x4000000948 49TPM2_RC_SIZE = 0x01D550TPM2_RC_AUTH_FAIL = 0x098E51TPM2_RC_POLICY_FAIL = 0x099D52TPM2_RC_COMMAND_CODE = 0x014353 54TSS2_RC_LAYER_SHIFT = 1655TSS2_RESMGR_TPM_RC_LAYER = (11 << TSS2_RC_LAYER_SHIFT)56 57TPM2_CAP_HANDLES = 0x0000000158TPM2_CAP_COMMANDS = 0x0000000259TPM2_CAP_PCRS = 0x0000000560TPM2_CAP_TPM_PROPERTIES = 0x0000000661 62TPM2_PT_FIXED = 0x10063TPM2_PT_TOTAL_COMMANDS = TPM2_PT_FIXED + 4164 65HR_SHIFT = 2466HR_LOADED_SESSION = 0x0200000067HR_TRANSIENT = 0x8000000068 69SHA1_DIGEST_SIZE = 2070SHA256_DIGEST_SIZE = 3271 72TPM2_VER0_ERRORS = {73 0x000: "TPM_RC_SUCCESS",74 0x030: "TPM_RC_BAD_TAG",75}76 77TPM2_VER1_ERRORS = {78 0x000: "TPM_RC_FAILURE",79 0x001: "TPM_RC_FAILURE",80 0x003: "TPM_RC_SEQUENCE",81 0x00B: "TPM_RC_PRIVATE",82 0x019: "TPM_RC_HMAC",83 0x020: "TPM_RC_DISABLED",84 0x021: "TPM_RC_EXCLUSIVE",85 0x024: "TPM_RC_AUTH_TYPE",86 0x025: "TPM_RC_AUTH_MISSING",87 0x026: "TPM_RC_POLICY",88 0x027: "TPM_RC_PCR",89 0x028: "TPM_RC_PCR_CHANGED",90 0x02D: "TPM_RC_UPGRADE",91 0x02E: "TPM_RC_TOO_MANY_CONTEXTS",92 0x02F: "TPM_RC_AUTH_UNAVAILABLE",93 0x030: "TPM_RC_REBOOT",94 0x031: "TPM_RC_UNBALANCED",95 0x042: "TPM_RC_COMMAND_SIZE",96 0x043: "TPM_RC_COMMAND_CODE",97 0x044: "TPM_RC_AUTHSIZE",98 0x045: "TPM_RC_AUTH_CONTEXT",99 0x046: "TPM_RC_NV_RANGE",100 0x047: "TPM_RC_NV_SIZE",101 0x048: "TPM_RC_NV_LOCKED",102 0x049: "TPM_RC_NV_AUTHORIZATION",103 0x04A: "TPM_RC_NV_UNINITIALIZED",104 0x04B: "TPM_RC_NV_SPACE",105 0x04C: "TPM_RC_NV_DEFINED",106 0x050: "TPM_RC_BAD_CONTEXT",107 0x051: "TPM_RC_CPHASH",108 0x052: "TPM_RC_PARENT",109 0x053: "TPM_RC_NEEDS_TEST",110 0x054: "TPM_RC_NO_RESULT",111 0x055: "TPM_RC_SENSITIVE",112 0x07F: "RC_MAX_FM0",113}114 115TPM2_FMT1_ERRORS = {116 0x001: "TPM_RC_ASYMMETRIC",117 0x002: "TPM_RC_ATTRIBUTES",118 0x003: "TPM_RC_HASH",119 0x004: "TPM_RC_VALUE",120 0x005: "TPM_RC_HIERARCHY",121 0x007: "TPM_RC_KEY_SIZE",122 0x008: "TPM_RC_MGF",123 0x009: "TPM_RC_MODE",124 0x00A: "TPM_RC_TYPE",125 0x00B: "TPM_RC_HANDLE",126 0x00C: "TPM_RC_KDF",127 0x00D: "TPM_RC_RANGE",128 0x00E: "TPM_RC_AUTH_FAIL",129 0x00F: "TPM_RC_NONCE",130 0x010: "TPM_RC_PP",131 0x012: "TPM_RC_SCHEME",132 0x015: "TPM_RC_SIZE",133 0x016: "TPM_RC_SYMMETRIC",134 0x017: "TPM_RC_TAG",135 0x018: "TPM_RC_SELECTOR",136 0x01A: "TPM_RC_INSUFFICIENT",137 0x01B: "TPM_RC_SIGNATURE",138 0x01C: "TPM_RC_KEY",139 0x01D: "TPM_RC_POLICY_FAIL",140 0x01F: "TPM_RC_INTEGRITY",141 0x020: "TPM_RC_TICKET",142 0x021: "TPM_RC_RESERVED_BITS",143 0x022: "TPM_RC_BAD_AUTH",144 0x023: "TPM_RC_EXPIRED",145 0x024: "TPM_RC_POLICY_CC",146 0x025: "TPM_RC_BINDING",147 0x026: "TPM_RC_CURVE",148 0x027: "TPM_RC_ECC_POINT",149}150 151TPM2_WARN_ERRORS = {152 0x001: "TPM_RC_CONTEXT_GAP",153 0x002: "TPM_RC_OBJECT_MEMORY",154 0x003: "TPM_RC_SESSION_MEMORY",155 0x004: "TPM_RC_MEMORY",156 0x005: "TPM_RC_SESSION_HANDLES",157 0x006: "TPM_RC_OBJECT_HANDLES",158 0x007: "TPM_RC_LOCALITY",159 0x008: "TPM_RC_YIELDED",160 0x009: "TPM_RC_CANCELED",161 0x00A: "TPM_RC_TESTING",162 0x010: "TPM_RC_REFERENCE_H0",163 0x011: "TPM_RC_REFERENCE_H1",164 0x012: "TPM_RC_REFERENCE_H2",165 0x013: "TPM_RC_REFERENCE_H3",166 0x014: "TPM_RC_REFERENCE_H4",167 0x015: "TPM_RC_REFERENCE_H5",168 0x016: "TPM_RC_REFERENCE_H6",169 0x018: "TPM_RC_REFERENCE_S0",170 0x019: "TPM_RC_REFERENCE_S1",171 0x01A: "TPM_RC_REFERENCE_S2",172 0x01B: "TPM_RC_REFERENCE_S3",173 0x01C: "TPM_RC_REFERENCE_S4",174 0x01D: "TPM_RC_REFERENCE_S5",175 0x01E: "TPM_RC_REFERENCE_S6",176 0x020: "TPM_RC_NV_RATE",177 0x021: "TPM_RC_LOCKOUT",178 0x022: "TPM_RC_RETRY",179 0x023: "TPM_RC_NV_UNAVAILABLE",180 0x7F: "TPM_RC_NOT_USED",181}182 183RC_VER1 = 0x100184RC_FMT1 = 0x080185RC_WARN = 0x900186 187ALG_DIGEST_SIZE_MAP = {188 TPM2_ALG_SHA1: SHA1_DIGEST_SIZE,189 TPM2_ALG_SHA256: SHA256_DIGEST_SIZE,190}191 192ALG_HASH_FUNCTION_MAP = {193 TPM2_ALG_SHA1: hashlib.sha1,194 TPM2_ALG_SHA256: hashlib.sha256195}196 197NAME_ALG_MAP = {198 "sha1": TPM2_ALG_SHA1,199 "sha256": TPM2_ALG_SHA256,200}201 202 203class UnknownAlgorithmIdError(Exception):204 def __init__(self, alg):205 self.alg = alg206 207 def __str__(self):208 return '0x%0x' % (alg)209 210 211class UnknownAlgorithmNameError(Exception):212 def __init__(self, name):213 self.name = name214 215 def __str__(self):216 return name217 218 219class UnknownPCRBankError(Exception):220 def __init__(self, alg):221 self.alg = alg222 223 def __str__(self):224 return '0x%0x' % (alg)225 226 227class ProtocolError(Exception):228 def __init__(self, cc, rc):229 self.cc = cc230 self.rc = rc231 232 if (rc & RC_FMT1) == RC_FMT1:233 self.name = TPM2_FMT1_ERRORS.get(rc & 0x3f, "TPM_RC_UNKNOWN")234 elif (rc & RC_WARN) == RC_WARN:235 self.name = TPM2_WARN_ERRORS.get(rc & 0x7f, "TPM_RC_UNKNOWN")236 elif (rc & RC_VER1) == RC_VER1:237 self.name = TPM2_VER1_ERRORS.get(rc & 0x7f, "TPM_RC_UNKNOWN")238 else:239 self.name = TPM2_VER0_ERRORS.get(rc & 0x7f, "TPM_RC_UNKNOWN")240 241 def __str__(self):242 if self.cc:243 return '%s: cc=0x%08x, rc=0x%08x' % (self.name, self.cc, self.rc)244 else:245 return '%s: rc=0x%08x' % (self.name, self.rc)246 247 248class AuthCommand(object):249 """TPMS_AUTH_COMMAND"""250 251 def __init__(self, session_handle=TPM2_RS_PW, nonce=bytes(),252 session_attributes=0, hmac=bytes()):253 self.session_handle = session_handle254 self.nonce = nonce255 self.session_attributes = session_attributes256 self.hmac = hmac257 258 def __bytes__(self):259 fmt = '>I H%us B H%us' % (len(self.nonce), len(self.hmac))260 return struct.pack(fmt, self.session_handle, len(self.nonce),261 self.nonce, self.session_attributes, len(self.hmac),262 self.hmac)263 264 def __len__(self):265 fmt = '>I H%us B H%us' % (len(self.nonce), len(self.hmac))266 return struct.calcsize(fmt)267 268 269class SensitiveCreate(object):270 """TPMS_SENSITIVE_CREATE"""271 272 def __init__(self, user_auth=bytes(), data=bytes()):273 self.user_auth = user_auth274 self.data = data275 276 def __bytes__(self):277 fmt = '>H%us H%us' % (len(self.user_auth), len(self.data))278 return struct.pack(fmt, len(self.user_auth), self.user_auth,279 len(self.data), self.data)280 281 def __len__(self):282 fmt = '>H%us H%us' % (len(self.user_auth), len(self.data))283 return struct.calcsize(fmt)284 285 286class Public(object):287 """TPMT_PUBLIC"""288 289 FIXED_TPM = (1 << 1)290 FIXED_PARENT = (1 << 4)291 SENSITIVE_DATA_ORIGIN = (1 << 5)292 USER_WITH_AUTH = (1 << 6)293 RESTRICTED = (1 << 16)294 DECRYPT = (1 << 17)295 296 def __fmt(self):297 return '>HHIH%us%usH%us' % \298 (len(self.auth_policy), len(self.parameters), len(self.unique))299 300 def __init__(self, object_type, name_alg, object_attributes,301 auth_policy=bytes(), parameters=bytes(),302 unique=bytes()):303 self.object_type = object_type304 self.name_alg = name_alg305 self.object_attributes = object_attributes306 self.auth_policy = auth_policy307 self.parameters = parameters308 self.unique = unique309 310 def __bytes__(self):311 return struct.pack(self.__fmt(),312 self.object_type,313 self.name_alg,314 self.object_attributes,315 len(self.auth_policy),316 self.auth_policy,317 self.parameters,318 len(self.unique),319 self.unique)320 321 def __len__(self):322 return struct.calcsize(self.__fmt())323 324 325def get_digest_size(alg):326 ds = ALG_DIGEST_SIZE_MAP.get(alg)327 if not ds:328 raise UnknownAlgorithmIdError(alg)329 return ds330 331 332def get_hash_function(alg):333 f = ALG_HASH_FUNCTION_MAP.get(alg)334 if not f:335 raise UnknownAlgorithmIdError(alg)336 return f337 338 339def get_algorithm(name):340 alg = NAME_ALG_MAP.get(name)341 if not alg:342 raise UnknownAlgorithmNameError(name)343 return alg344 345 346def hex_dump(d):347 d = [format(x, '02x') for x in d]348 d = [d[i: i + 16] for i in range(0, len(d), 16)]349 d = [' '.join(x) for x in d]350 d = os.linesep.join(d)351 352 return d353 354class Client:355 FLAG_DEBUG = 0x01356 FLAG_SPACE = 0x02357 FLAG_NONBLOCK = 0x04358 TPM_IOC_NEW_SPACE = 0xa200359 360 def __init__(self, flags = 0):361 self.flags = flags362 363 if (self.flags & Client.FLAG_SPACE) == 0:364 self.tpm = open('/dev/tpm0', 'r+b', buffering=0)365 else:366 self.tpm = open('/dev/tpmrm0', 'r+b', buffering=0)367 368 if (self.flags & Client.FLAG_NONBLOCK):369 flags = fcntl.fcntl(self.tpm, fcntl.F_GETFL)370 flags |= os.O_NONBLOCK371 fcntl.fcntl(self.tpm, fcntl.F_SETFL, flags)372 self.tpm_poll = select.poll()373 374 def __del__(self):375 if self.tpm:376 self.tpm.close()377 378 def close(self):379 self.tpm.close()380 381 def send_cmd(self, cmd):382 self.tpm.write(cmd)383 384 if (self.flags & Client.FLAG_NONBLOCK):385 self.tpm_poll.register(self.tpm, select.POLLIN)386 self.tpm_poll.poll(10000)387 388 rsp = self.tpm.read()389 390 if (self.flags & Client.FLAG_NONBLOCK):391 self.tpm_poll.unregister(self.tpm)392 393 if (self.flags & Client.FLAG_DEBUG) != 0:394 sys.stderr.write('cmd' + os.linesep)395 sys.stderr.write(hex_dump(cmd) + os.linesep)396 sys.stderr.write('rsp' + os.linesep)397 sys.stderr.write(hex_dump(rsp) + os.linesep)398 399 rc = struct.unpack('>I', rsp[6:10])[0]400 if rc != 0:401 cc = struct.unpack('>I', cmd[6:10])[0]402 raise ProtocolError(cc, rc)403 404 return rsp405 406 def read_pcr(self, i, bank_alg = TPM2_ALG_SHA1):407 pcrsel_len = max((i >> 3) + 1, 3)408 pcrsel = [0] * pcrsel_len409 pcrsel[i >> 3] = 1 << (i & 7)410 pcrsel = ''.join(map(chr, pcrsel)).encode()411 412 fmt = '>HII IHB%us' % (pcrsel_len)413 cmd = struct.pack(fmt,414 TPM2_ST_NO_SESSIONS,415 struct.calcsize(fmt),416 TPM2_CC_PCR_READ,417 1,418 bank_alg,419 pcrsel_len, pcrsel)420 421 rsp = self.send_cmd(cmd)422 423 pcr_update_cnt, pcr_select_cnt = struct.unpack('>II', rsp[10:18])424 assert pcr_select_cnt == 1425 rsp = rsp[18:]426 427 alg2, pcrsel_len2 = struct.unpack('>HB', rsp[:3])428 assert bank_alg == alg2 and pcrsel_len == pcrsel_len2429 rsp = rsp[3 + pcrsel_len:]430 431 digest_cnt = struct.unpack('>I', rsp[:4])[0]432 if digest_cnt == 0:433 return None434 rsp = rsp[6:]435 436 return rsp437 438 def extend_pcr(self, i, dig, bank_alg = TPM2_ALG_SHA1):439 ds = get_digest_size(bank_alg)440 assert(ds == len(dig))441 442 auth_cmd = AuthCommand()443 444 fmt = '>HII I I%us IH%us' % (len(auth_cmd), ds)445 cmd = struct.pack(446 fmt,447 TPM2_ST_SESSIONS,448 struct.calcsize(fmt),449 TPM2_CC_PCR_EXTEND,450 i,451 len(auth_cmd),452 bytes(auth_cmd),453 1, bank_alg, dig)454 455 self.send_cmd(cmd)456 457 def start_auth_session(self, session_type, name_alg = TPM2_ALG_SHA1):458 fmt = '>HII IIH16sHBHH'459 cmd = struct.pack(fmt,460 TPM2_ST_NO_SESSIONS,461 struct.calcsize(fmt),462 TPM2_CC_START_AUTH_SESSION,463 TPM2_RH_NULL,464 TPM2_RH_NULL,465 16,466 ('\0' * 16).encode(),467 0,468 session_type,469 TPM2_ALG_NULL,470 name_alg)471 472 return struct.unpack('>I', self.send_cmd(cmd)[10:14])[0]473 474 def __calc_pcr_digest(self, pcrs, bank_alg = TPM2_ALG_SHA1,475 digest_alg = TPM2_ALG_SHA1):476 x = []477 f = get_hash_function(digest_alg)478 479 for i in pcrs:480 pcr = self.read_pcr(i, bank_alg)481 if pcr is None:482 return None483 x += pcr484 485 return f(bytearray(x)).digest()486 487 def policy_pcr(self, handle, pcrs, bank_alg = TPM2_ALG_SHA1,488 name_alg = TPM2_ALG_SHA1):489 ds = get_digest_size(name_alg)490 dig = self.__calc_pcr_digest(pcrs, bank_alg, name_alg)491 if not dig:492 raise UnknownPCRBankError(bank_alg)493 494 pcrsel_len = max((max(pcrs) >> 3) + 1, 3)495 pcrsel = [0] * pcrsel_len496 for i in pcrs:497 pcrsel[i >> 3] |= 1 << (i & 7)498 pcrsel = ''.join(map(chr, pcrsel)).encode()499 500 fmt = '>HII IH%usIHB3s' % ds501 cmd = struct.pack(fmt,502 TPM2_ST_NO_SESSIONS,503 struct.calcsize(fmt),504 TPM2_CC_POLICY_PCR,505 handle,506 len(dig),507 bytes(dig),508 1,509 bank_alg,510 pcrsel_len, pcrsel)511 512 self.send_cmd(cmd)513 514 def policy_password(self, handle):515 fmt = '>HII I'516 cmd = struct.pack(fmt,517 TPM2_ST_NO_SESSIONS,518 struct.calcsize(fmt),519 TPM2_CC_POLICY_PASSWORD,520 handle)521 522 self.send_cmd(cmd)523 524 def get_policy_digest(self, handle):525 fmt = '>HII I'526 cmd = struct.pack(fmt,527 TPM2_ST_NO_SESSIONS,528 struct.calcsize(fmt),529 TPM2_CC_POLICY_GET_DIGEST,530 handle)531 532 return self.send_cmd(cmd)[12:]533 534 def flush_context(self, handle):535 fmt = '>HIII'536 cmd = struct.pack(fmt,537 TPM2_ST_NO_SESSIONS,538 struct.calcsize(fmt),539 TPM2_CC_FLUSH_CONTEXT,540 handle)541 542 self.send_cmd(cmd)543 544 def create_root_key(self, auth_value = bytes()):545 attributes = \546 Public.FIXED_TPM | \547 Public.FIXED_PARENT | \548 Public.SENSITIVE_DATA_ORIGIN | \549 Public.USER_WITH_AUTH | \550 Public.RESTRICTED | \551 Public.DECRYPT552 553 auth_cmd = AuthCommand()554 sensitive = SensitiveCreate(user_auth=auth_value)555 556 public_parms = struct.pack(557 '>HHHHHI',558 TPM2_ALG_AES,559 128,560 TPM2_ALG_CFB,561 TPM2_ALG_NULL,562 2048,563 0)564 565 public = Public(566 object_type=TPM2_ALG_RSA,567 name_alg=TPM2_ALG_SHA1,568 object_attributes=attributes,569 parameters=public_parms)570 571 fmt = '>HIII I%us H%us H%us HI' % \572 (len(auth_cmd), len(sensitive), len(public))573 cmd = struct.pack(574 fmt,575 TPM2_ST_SESSIONS,576 struct.calcsize(fmt),577 TPM2_CC_CREATE_PRIMARY,578 TPM2_RH_OWNER,579 len(auth_cmd),580 bytes(auth_cmd),581 len(sensitive),582 bytes(sensitive),583 len(public),584 bytes(public),585 0, 0)586 587 return struct.unpack('>I', self.send_cmd(cmd)[10:14])[0]588 589 def seal(self, parent_key, data, auth_value, policy_dig,590 name_alg = TPM2_ALG_SHA1):591 ds = get_digest_size(name_alg)592 assert(not policy_dig or ds == len(policy_dig))593 594 attributes = 0595 if not policy_dig:596 attributes |= Public.USER_WITH_AUTH597 policy_dig = bytes()598 599 auth_cmd = AuthCommand()600 sensitive = SensitiveCreate(user_auth=auth_value, data=data)601 602 public = Public(603 object_type=TPM2_ALG_KEYEDHASH,604 name_alg=name_alg,605 object_attributes=attributes,606 auth_policy=policy_dig,607 parameters=struct.pack('>H', TPM2_ALG_NULL))608 609 fmt = '>HIII I%us H%us H%us HI' % \610 (len(auth_cmd), len(sensitive), len(public))611 cmd = struct.pack(612 fmt,613 TPM2_ST_SESSIONS,614 struct.calcsize(fmt),615 TPM2_CC_CREATE,616 parent_key,617 len(auth_cmd),618 bytes(auth_cmd),619 len(sensitive),620 bytes(sensitive),621 len(public),622 bytes(public),623 0, 0)624 625 rsp = self.send_cmd(cmd)626 627 return rsp[14:]628 629 def unseal(self, parent_key, blob, auth_value, policy_handle):630 private_len = struct.unpack('>H', blob[0:2])[0]631 public_start = private_len + 2632 public_len = struct.unpack('>H', blob[public_start:public_start + 2])[0]633 blob = blob[:private_len + public_len + 4]634 635 auth_cmd = AuthCommand()636 637 fmt = '>HII I I%us %us' % (len(auth_cmd), len(blob))638 cmd = struct.pack(639 fmt,640 TPM2_ST_SESSIONS,641 struct.calcsize(fmt),642 TPM2_CC_LOAD,643 parent_key,644 len(auth_cmd),645 bytes(auth_cmd),646 blob)647 648 data_handle = struct.unpack('>I', self.send_cmd(cmd)[10:14])[0]649 650 if policy_handle:651 auth_cmd = AuthCommand(session_handle=policy_handle, hmac=auth_value)652 else:653 auth_cmd = AuthCommand(hmac=auth_value)654 655 fmt = '>HII I I%us' % (len(auth_cmd))656 cmd = struct.pack(657 fmt,658 TPM2_ST_SESSIONS,659 struct.calcsize(fmt),660 TPM2_CC_UNSEAL,661 data_handle,662 len(auth_cmd),663 bytes(auth_cmd))664 665 try:666 rsp = self.send_cmd(cmd)667 finally:668 self.flush_context(data_handle)669 670 data_len = struct.unpack('>I', rsp[10:14])[0] - 2671 672 return rsp[16:16 + data_len]673 674 def reset_da_lock(self):675 auth_cmd = AuthCommand()676 677 fmt = '>HII I I%us' % (len(auth_cmd))678 cmd = struct.pack(679 fmt,680 TPM2_ST_SESSIONS,681 struct.calcsize(fmt),682 TPM2_CC_DICTIONARY_ATTACK_LOCK_RESET,683 TPM2_RH_LOCKOUT,684 len(auth_cmd),685 bytes(auth_cmd))686 687 self.send_cmd(cmd)688 689 def __get_cap_cnt(self, cap, pt, cnt):690 handles = []691 fmt = '>HII III'692 693 cmd = struct.pack(fmt,694 TPM2_ST_NO_SESSIONS,695 struct.calcsize(fmt),696 TPM2_CC_GET_CAPABILITY,697 cap, pt, cnt)698 699 rsp = self.send_cmd(cmd)[10:]700 more_data, cap, cnt = struct.unpack('>BII', rsp[:9])701 rsp = rsp[9:]702 703 for i in range(0, cnt):704 handle = struct.unpack('>I', rsp[:4])[0]705 handles.append(handle)706 rsp = rsp[4:]707 708 return handles, more_data709 710 def get_cap(self, cap, pt):711 handles = []712 713 more_data = True714 while more_data:715 next_handles, more_data = self.__get_cap_cnt(cap, pt, 1)716 handles += next_handles717 pt += 1718 719 return handles720 721 def get_cap_pcrs(self):722 pcr_banks = {}723 724 fmt = '>HII III'725 726 cmd = struct.pack(fmt,727 TPM2_ST_NO_SESSIONS,728 struct.calcsize(fmt),729 TPM2_CC_GET_CAPABILITY,730 TPM2_CAP_PCRS, 0, 1)731 rsp = self.send_cmd(cmd)[10:]732 _, _, cnt = struct.unpack('>BII', rsp[:9])733 rsp = rsp[9:]734 735 # items are TPMS_PCR_SELECTION's736 for i in range(0, cnt):737 hash, sizeOfSelect = struct.unpack('>HB', rsp[:3])738 rsp = rsp[3:]739 740 pcrSelect = 0741 if sizeOfSelect > 0:742 pcrSelect, = struct.unpack('%ds' % sizeOfSelect,743 rsp[:sizeOfSelect])744 rsp = rsp[sizeOfSelect:]745 pcrSelect = int.from_bytes(pcrSelect, byteorder='big')746 747 pcr_banks[hash] = pcrSelect748 749 return pcr_banks750