brintos

brintos / linux-shallow public Read only

0
0
Text · 20.7 KiB · bba8cb5 Raw
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