Back to home page

OSCL-LXR

 
 

    


0001 # SPDX-License-Identifier: (GPL-2.0 OR BSD-3-Clause)
0002 
0003 import hashlib
0004 import os
0005 import socket
0006 import struct
0007 import sys
0008 import unittest
0009 import fcntl
0010 import select
0011 
0012 TPM2_ST_NO_SESSIONS = 0x8001
0013 TPM2_ST_SESSIONS = 0x8002
0014 
0015 TPM2_CC_FIRST = 0x01FF
0016 
0017 TPM2_CC_CREATE_PRIMARY = 0x0131
0018 TPM2_CC_DICTIONARY_ATTACK_LOCK_RESET = 0x0139
0019 TPM2_CC_CREATE = 0x0153
0020 TPM2_CC_LOAD = 0x0157
0021 TPM2_CC_UNSEAL = 0x015E
0022 TPM2_CC_FLUSH_CONTEXT = 0x0165
0023 TPM2_CC_START_AUTH_SESSION = 0x0176
0024 TPM2_CC_GET_CAPABILITY  = 0x017A
0025 TPM2_CC_GET_RANDOM = 0x017B
0026 TPM2_CC_PCR_READ = 0x017E
0027 TPM2_CC_POLICY_PCR = 0x017F
0028 TPM2_CC_PCR_EXTEND = 0x0182
0029 TPM2_CC_POLICY_PASSWORD = 0x018C
0030 TPM2_CC_POLICY_GET_DIGEST = 0x0189
0031 
0032 TPM2_SE_POLICY = 0x01
0033 TPM2_SE_TRIAL = 0x03
0034 
0035 TPM2_ALG_RSA = 0x0001
0036 TPM2_ALG_SHA1 = 0x0004
0037 TPM2_ALG_AES = 0x0006
0038 TPM2_ALG_KEYEDHASH = 0x0008
0039 TPM2_ALG_SHA256 = 0x000B
0040 TPM2_ALG_NULL = 0x0010
0041 TPM2_ALG_CBC = 0x0042
0042 TPM2_ALG_CFB = 0x0043
0043 
0044 TPM2_RH_OWNER = 0x40000001
0045 TPM2_RH_NULL = 0x40000007
0046 TPM2_RH_LOCKOUT = 0x4000000A
0047 TPM2_RS_PW = 0x40000009
0048 
0049 TPM2_RC_SIZE            = 0x01D5
0050 TPM2_RC_AUTH_FAIL       = 0x098E
0051 TPM2_RC_POLICY_FAIL     = 0x099D
0052 TPM2_RC_COMMAND_CODE    = 0x0143
0053 
0054 TSS2_RC_LAYER_SHIFT = 16
0055 TSS2_RESMGR_TPM_RC_LAYER = (11 << TSS2_RC_LAYER_SHIFT)
0056 
0057 TPM2_CAP_HANDLES = 0x00000001
0058 TPM2_CAP_COMMANDS = 0x00000002
0059 TPM2_CAP_PCRS = 0x00000005
0060 TPM2_CAP_TPM_PROPERTIES = 0x00000006
0061 
0062 TPM2_PT_FIXED = 0x100
0063 TPM2_PT_TOTAL_COMMANDS = TPM2_PT_FIXED + 41
0064 
0065 HR_SHIFT = 24
0066 HR_LOADED_SESSION = 0x02000000
0067 HR_TRANSIENT = 0x80000000
0068 
0069 SHA1_DIGEST_SIZE = 20
0070 SHA256_DIGEST_SIZE = 32
0071 
0072 TPM2_VER0_ERRORS = {
0073     0x000: "TPM_RC_SUCCESS",
0074     0x030: "TPM_RC_BAD_TAG",
0075 }
0076 
0077 TPM2_VER1_ERRORS = {
0078     0x000: "TPM_RC_FAILURE",
0079     0x001: "TPM_RC_FAILURE",
0080     0x003: "TPM_RC_SEQUENCE",
0081     0x00B: "TPM_RC_PRIVATE",
0082     0x019: "TPM_RC_HMAC",
0083     0x020: "TPM_RC_DISABLED",
0084     0x021: "TPM_RC_EXCLUSIVE",
0085     0x024: "TPM_RC_AUTH_TYPE",
0086     0x025: "TPM_RC_AUTH_MISSING",
0087     0x026: "TPM_RC_POLICY",
0088     0x027: "TPM_RC_PCR",
0089     0x028: "TPM_RC_PCR_CHANGED",
0090     0x02D: "TPM_RC_UPGRADE",
0091     0x02E: "TPM_RC_TOO_MANY_CONTEXTS",
0092     0x02F: "TPM_RC_AUTH_UNAVAILABLE",
0093     0x030: "TPM_RC_REBOOT",
0094     0x031: "TPM_RC_UNBALANCED",
0095     0x042: "TPM_RC_COMMAND_SIZE",
0096     0x043: "TPM_RC_COMMAND_CODE",
0097     0x044: "TPM_RC_AUTHSIZE",
0098     0x045: "TPM_RC_AUTH_CONTEXT",
0099     0x046: "TPM_RC_NV_RANGE",
0100     0x047: "TPM_RC_NV_SIZE",
0101     0x048: "TPM_RC_NV_LOCKED",
0102     0x049: "TPM_RC_NV_AUTHORIZATION",
0103     0x04A: "TPM_RC_NV_UNINITIALIZED",
0104     0x04B: "TPM_RC_NV_SPACE",
0105     0x04C: "TPM_RC_NV_DEFINED",
0106     0x050: "TPM_RC_BAD_CONTEXT",
0107     0x051: "TPM_RC_CPHASH",
0108     0x052: "TPM_RC_PARENT",
0109     0x053: "TPM_RC_NEEDS_TEST",
0110     0x054: "TPM_RC_NO_RESULT",
0111     0x055: "TPM_RC_SENSITIVE",
0112     0x07F: "RC_MAX_FM0",
0113 }
0114 
0115 TPM2_FMT1_ERRORS = {
0116     0x001: "TPM_RC_ASYMMETRIC",
0117     0x002: "TPM_RC_ATTRIBUTES",
0118     0x003: "TPM_RC_HASH",
0119     0x004: "TPM_RC_VALUE",
0120     0x005: "TPM_RC_HIERARCHY",
0121     0x007: "TPM_RC_KEY_SIZE",
0122     0x008: "TPM_RC_MGF",
0123     0x009: "TPM_RC_MODE",
0124     0x00A: "TPM_RC_TYPE",
0125     0x00B: "TPM_RC_HANDLE",
0126     0x00C: "TPM_RC_KDF",
0127     0x00D: "TPM_RC_RANGE",
0128     0x00E: "TPM_RC_AUTH_FAIL",
0129     0x00F: "TPM_RC_NONCE",
0130     0x010: "TPM_RC_PP",
0131     0x012: "TPM_RC_SCHEME",
0132     0x015: "TPM_RC_SIZE",
0133     0x016: "TPM_RC_SYMMETRIC",
0134     0x017: "TPM_RC_TAG",
0135     0x018: "TPM_RC_SELECTOR",
0136     0x01A: "TPM_RC_INSUFFICIENT",
0137     0x01B: "TPM_RC_SIGNATURE",
0138     0x01C: "TPM_RC_KEY",
0139     0x01D: "TPM_RC_POLICY_FAIL",
0140     0x01F: "TPM_RC_INTEGRITY",
0141     0x020: "TPM_RC_TICKET",
0142     0x021: "TPM_RC_RESERVED_BITS",
0143     0x022: "TPM_RC_BAD_AUTH",
0144     0x023: "TPM_RC_EXPIRED",
0145     0x024: "TPM_RC_POLICY_CC",
0146     0x025: "TPM_RC_BINDING",
0147     0x026: "TPM_RC_CURVE",
0148     0x027: "TPM_RC_ECC_POINT",
0149 }
0150 
0151 TPM2_WARN_ERRORS = {
0152     0x001: "TPM_RC_CONTEXT_GAP",
0153     0x002: "TPM_RC_OBJECT_MEMORY",
0154     0x003: "TPM_RC_SESSION_MEMORY",
0155     0x004: "TPM_RC_MEMORY",
0156     0x005: "TPM_RC_SESSION_HANDLES",
0157     0x006: "TPM_RC_OBJECT_HANDLES",
0158     0x007: "TPM_RC_LOCALITY",
0159     0x008: "TPM_RC_YIELDED",
0160     0x009: "TPM_RC_CANCELED",
0161     0x00A: "TPM_RC_TESTING",
0162     0x010: "TPM_RC_REFERENCE_H0",
0163     0x011: "TPM_RC_REFERENCE_H1",
0164     0x012: "TPM_RC_REFERENCE_H2",
0165     0x013: "TPM_RC_REFERENCE_H3",
0166     0x014: "TPM_RC_REFERENCE_H4",
0167     0x015: "TPM_RC_REFERENCE_H5",
0168     0x016: "TPM_RC_REFERENCE_H6",
0169     0x018: "TPM_RC_REFERENCE_S0",
0170     0x019: "TPM_RC_REFERENCE_S1",
0171     0x01A: "TPM_RC_REFERENCE_S2",
0172     0x01B: "TPM_RC_REFERENCE_S3",
0173     0x01C: "TPM_RC_REFERENCE_S4",
0174     0x01D: "TPM_RC_REFERENCE_S5",
0175     0x01E: "TPM_RC_REFERENCE_S6",
0176     0x020: "TPM_RC_NV_RATE",
0177     0x021: "TPM_RC_LOCKOUT",
0178     0x022: "TPM_RC_RETRY",
0179     0x023: "TPM_RC_NV_UNAVAILABLE",
0180     0x7F: "TPM_RC_NOT_USED",
0181 }
0182 
0183 RC_VER1 = 0x100
0184 RC_FMT1 = 0x080
0185 RC_WARN = 0x900
0186 
0187 ALG_DIGEST_SIZE_MAP = {
0188     TPM2_ALG_SHA1: SHA1_DIGEST_SIZE,
0189     TPM2_ALG_SHA256: SHA256_DIGEST_SIZE,
0190 }
0191 
0192 ALG_HASH_FUNCTION_MAP = {
0193     TPM2_ALG_SHA1: hashlib.sha1,
0194     TPM2_ALG_SHA256: hashlib.sha256
0195 }
0196 
0197 NAME_ALG_MAP = {
0198     "sha1": TPM2_ALG_SHA1,
0199     "sha256": TPM2_ALG_SHA256,
0200 }
0201 
0202 
0203 class UnknownAlgorithmIdError(Exception):
0204     def __init__(self, alg):
0205         self.alg = alg
0206 
0207     def __str__(self):
0208         return '0x%0x' % (alg)
0209 
0210 
0211 class UnknownAlgorithmNameError(Exception):
0212     def __init__(self, name):
0213         self.name = name
0214 
0215     def __str__(self):
0216         return name
0217 
0218 
0219 class UnknownPCRBankError(Exception):
0220     def __init__(self, alg):
0221         self.alg = alg
0222 
0223     def __str__(self):
0224         return '0x%0x' % (alg)
0225 
0226 
0227 class ProtocolError(Exception):
0228     def __init__(self, cc, rc):
0229         self.cc = cc
0230         self.rc = rc
0231 
0232         if (rc & RC_FMT1) == RC_FMT1:
0233             self.name = TPM2_FMT1_ERRORS.get(rc & 0x3f, "TPM_RC_UNKNOWN")
0234         elif (rc & RC_WARN) == RC_WARN:
0235             self.name = TPM2_WARN_ERRORS.get(rc & 0x7f, "TPM_RC_UNKNOWN")
0236         elif (rc & RC_VER1) == RC_VER1:
0237             self.name = TPM2_VER1_ERRORS.get(rc & 0x7f, "TPM_RC_UNKNOWN")
0238         else:
0239             self.name = TPM2_VER0_ERRORS.get(rc & 0x7f, "TPM_RC_UNKNOWN")
0240 
0241     def __str__(self):
0242         if self.cc:
0243             return '%s: cc=0x%08x, rc=0x%08x' % (self.name, self.cc, self.rc)
0244         else:
0245             return '%s: rc=0x%08x' % (self.name, self.rc)
0246 
0247 
0248 class AuthCommand(object):
0249     """TPMS_AUTH_COMMAND"""
0250 
0251     def __init__(self, session_handle=TPM2_RS_PW, nonce=bytes(),
0252                  session_attributes=0, hmac=bytes()):
0253         self.session_handle = session_handle
0254         self.nonce = nonce
0255         self.session_attributes = session_attributes
0256         self.hmac = hmac
0257 
0258     def __bytes__(self):
0259         fmt = '>I H%us B H%us' % (len(self.nonce), len(self.hmac))
0260         return struct.pack(fmt, self.session_handle, len(self.nonce),
0261                            self.nonce, self.session_attributes, len(self.hmac),
0262                            self.hmac)
0263 
0264     def __len__(self):
0265         fmt = '>I H%us B H%us' % (len(self.nonce), len(self.hmac))
0266         return struct.calcsize(fmt)
0267 
0268 
0269 class SensitiveCreate(object):
0270     """TPMS_SENSITIVE_CREATE"""
0271 
0272     def __init__(self, user_auth=bytes(), data=bytes()):
0273         self.user_auth = user_auth
0274         self.data = data
0275 
0276     def __bytes__(self):
0277         fmt = '>H%us H%us' % (len(self.user_auth), len(self.data))
0278         return struct.pack(fmt, len(self.user_auth), self.user_auth,
0279                            len(self.data), self.data)
0280 
0281     def __len__(self):
0282         fmt = '>H%us H%us' % (len(self.user_auth), len(self.data))
0283         return struct.calcsize(fmt)
0284 
0285 
0286 class Public(object):
0287     """TPMT_PUBLIC"""
0288 
0289     FIXED_TPM = (1 << 1)
0290     FIXED_PARENT = (1 << 4)
0291     SENSITIVE_DATA_ORIGIN = (1 << 5)
0292     USER_WITH_AUTH = (1 << 6)
0293     RESTRICTED = (1 << 16)
0294     DECRYPT = (1 << 17)
0295 
0296     def __fmt(self):
0297         return '>HHIH%us%usH%us' % \
0298             (len(self.auth_policy), len(self.parameters), len(self.unique))
0299 
0300     def __init__(self, object_type, name_alg, object_attributes,
0301                  auth_policy=bytes(), parameters=bytes(),
0302                  unique=bytes()):
0303         self.object_type = object_type
0304         self.name_alg = name_alg
0305         self.object_attributes = object_attributes
0306         self.auth_policy = auth_policy
0307         self.parameters = parameters
0308         self.unique = unique
0309 
0310     def __bytes__(self):
0311         return struct.pack(self.__fmt(),
0312                            self.object_type,
0313                            self.name_alg,
0314                            self.object_attributes,
0315                            len(self.auth_policy),
0316                            self.auth_policy,
0317                            self.parameters,
0318                            len(self.unique),
0319                            self.unique)
0320 
0321     def __len__(self):
0322         return struct.calcsize(self.__fmt())
0323 
0324 
0325 def get_digest_size(alg):
0326     ds = ALG_DIGEST_SIZE_MAP.get(alg)
0327     if not ds:
0328         raise UnknownAlgorithmIdError(alg)
0329     return ds
0330 
0331 
0332 def get_hash_function(alg):
0333     f = ALG_HASH_FUNCTION_MAP.get(alg)
0334     if not f:
0335         raise UnknownAlgorithmIdError(alg)
0336     return f
0337 
0338 
0339 def get_algorithm(name):
0340     alg = NAME_ALG_MAP.get(name)
0341     if not alg:
0342         raise UnknownAlgorithmNameError(name)
0343     return alg
0344 
0345 
0346 def hex_dump(d):
0347     d = [format(ord(x), '02x') for x in d]
0348     d = [d[i: i + 16] for i in range(0, len(d), 16)]
0349     d = [' '.join(x) for x in d]
0350     d = os.linesep.join(d)
0351 
0352     return d
0353 
0354 class Client:
0355     FLAG_DEBUG = 0x01
0356     FLAG_SPACE = 0x02
0357     FLAG_NONBLOCK = 0x04
0358     TPM_IOC_NEW_SPACE = 0xa200
0359 
0360     def __init__(self, flags = 0):
0361         self.flags = flags
0362 
0363         if (self.flags & Client.FLAG_SPACE) == 0:
0364             self.tpm = open('/dev/tpm0', 'r+b', buffering=0)
0365         else:
0366             self.tpm = open('/dev/tpmrm0', 'r+b', buffering=0)
0367 
0368         if (self.flags & Client.FLAG_NONBLOCK):
0369             flags = fcntl.fcntl(self.tpm, fcntl.F_GETFL)
0370             flags |= os.O_NONBLOCK
0371             fcntl.fcntl(self.tpm, fcntl.F_SETFL, flags)
0372             self.tpm_poll = select.poll()
0373 
0374     def close(self):
0375         self.tpm.close()
0376 
0377     def send_cmd(self, cmd):
0378         self.tpm.write(cmd)
0379 
0380         if (self.flags & Client.FLAG_NONBLOCK):
0381             self.tpm_poll.register(self.tpm, select.POLLIN)
0382             self.tpm_poll.poll(10000)
0383 
0384         rsp = self.tpm.read()
0385 
0386         if (self.flags & Client.FLAG_NONBLOCK):
0387             self.tpm_poll.unregister(self.tpm)
0388 
0389         if (self.flags & Client.FLAG_DEBUG) != 0:
0390             sys.stderr.write('cmd' + os.linesep)
0391             sys.stderr.write(hex_dump(cmd) + os.linesep)
0392             sys.stderr.write('rsp' + os.linesep)
0393             sys.stderr.write(hex_dump(rsp) + os.linesep)
0394 
0395         rc = struct.unpack('>I', rsp[6:10])[0]
0396         if rc != 0:
0397             cc = struct.unpack('>I', cmd[6:10])[0]
0398             raise ProtocolError(cc, rc)
0399 
0400         return rsp
0401 
0402     def read_pcr(self, i, bank_alg = TPM2_ALG_SHA1):
0403         pcrsel_len = max((i >> 3) + 1, 3)
0404         pcrsel = [0] * pcrsel_len
0405         pcrsel[i >> 3] = 1 << (i & 7)
0406         pcrsel = ''.join(map(chr, pcrsel)).encode()
0407 
0408         fmt = '>HII IHB%us' % (pcrsel_len)
0409         cmd = struct.pack(fmt,
0410                           TPM2_ST_NO_SESSIONS,
0411                           struct.calcsize(fmt),
0412                           TPM2_CC_PCR_READ,
0413                           1,
0414                           bank_alg,
0415                           pcrsel_len, pcrsel)
0416 
0417         rsp = self.send_cmd(cmd)
0418 
0419         pcr_update_cnt, pcr_select_cnt = struct.unpack('>II', rsp[10:18])
0420         assert pcr_select_cnt == 1
0421         rsp = rsp[18:]
0422 
0423         alg2, pcrsel_len2 = struct.unpack('>HB', rsp[:3])
0424         assert bank_alg == alg2 and pcrsel_len == pcrsel_len2
0425         rsp = rsp[3 + pcrsel_len:]
0426 
0427         digest_cnt = struct.unpack('>I', rsp[:4])[0]
0428         if digest_cnt == 0:
0429             return None
0430         rsp = rsp[6:]
0431 
0432         return rsp
0433 
0434     def extend_pcr(self, i, dig, bank_alg = TPM2_ALG_SHA1):
0435         ds = get_digest_size(bank_alg)
0436         assert(ds == len(dig))
0437 
0438         auth_cmd = AuthCommand()
0439 
0440         fmt = '>HII I I%us IH%us' % (len(auth_cmd), ds)
0441         cmd = struct.pack(
0442             fmt,
0443             TPM2_ST_SESSIONS,
0444             struct.calcsize(fmt),
0445             TPM2_CC_PCR_EXTEND,
0446             i,
0447             len(auth_cmd),
0448             bytes(auth_cmd),
0449             1, bank_alg, dig)
0450 
0451         self.send_cmd(cmd)
0452 
0453     def start_auth_session(self, session_type, name_alg = TPM2_ALG_SHA1):
0454         fmt = '>HII IIH16sHBHH'
0455         cmd = struct.pack(fmt,
0456                           TPM2_ST_NO_SESSIONS,
0457                           struct.calcsize(fmt),
0458                           TPM2_CC_START_AUTH_SESSION,
0459                           TPM2_RH_NULL,
0460                           TPM2_RH_NULL,
0461                           16,
0462                           ('\0' * 16).encode(),
0463                           0,
0464                           session_type,
0465                           TPM2_ALG_NULL,
0466                           name_alg)
0467 
0468         return struct.unpack('>I', self.send_cmd(cmd)[10:14])[0]
0469 
0470     def __calc_pcr_digest(self, pcrs, bank_alg = TPM2_ALG_SHA1,
0471                           digest_alg = TPM2_ALG_SHA1):
0472         x = []
0473         f = get_hash_function(digest_alg)
0474 
0475         for i in pcrs:
0476             pcr = self.read_pcr(i, bank_alg)
0477             if pcr is None:
0478                 return None
0479             x += pcr
0480 
0481         return f(bytearray(x)).digest()
0482 
0483     def policy_pcr(self, handle, pcrs, bank_alg = TPM2_ALG_SHA1,
0484                    name_alg = TPM2_ALG_SHA1):
0485         ds = get_digest_size(name_alg)
0486         dig = self.__calc_pcr_digest(pcrs, bank_alg, name_alg)
0487         if not dig:
0488             raise UnknownPCRBankError(bank_alg)
0489 
0490         pcrsel_len = max((max(pcrs) >> 3) + 1, 3)
0491         pcrsel = [0] * pcrsel_len
0492         for i in pcrs:
0493             pcrsel[i >> 3] |= 1 << (i & 7)
0494         pcrsel = ''.join(map(chr, pcrsel)).encode()
0495 
0496         fmt = '>HII IH%usIHB3s' % ds
0497         cmd = struct.pack(fmt,
0498                           TPM2_ST_NO_SESSIONS,
0499                           struct.calcsize(fmt),
0500                           TPM2_CC_POLICY_PCR,
0501                           handle,
0502                           len(dig),
0503                           bytes(dig),
0504                           1,
0505                           bank_alg,
0506                           pcrsel_len, pcrsel)
0507 
0508         self.send_cmd(cmd)
0509 
0510     def policy_password(self, handle):
0511         fmt = '>HII I'
0512         cmd = struct.pack(fmt,
0513                           TPM2_ST_NO_SESSIONS,
0514                           struct.calcsize(fmt),
0515                           TPM2_CC_POLICY_PASSWORD,
0516                           handle)
0517 
0518         self.send_cmd(cmd)
0519 
0520     def get_policy_digest(self, handle):
0521         fmt = '>HII I'
0522         cmd = struct.pack(fmt,
0523                           TPM2_ST_NO_SESSIONS,
0524                           struct.calcsize(fmt),
0525                           TPM2_CC_POLICY_GET_DIGEST,
0526                           handle)
0527 
0528         return self.send_cmd(cmd)[12:]
0529 
0530     def flush_context(self, handle):
0531         fmt = '>HIII'
0532         cmd = struct.pack(fmt,
0533                           TPM2_ST_NO_SESSIONS,
0534                           struct.calcsize(fmt),
0535                           TPM2_CC_FLUSH_CONTEXT,
0536                           handle)
0537 
0538         self.send_cmd(cmd)
0539 
0540     def create_root_key(self, auth_value = bytes()):
0541         attributes = \
0542             Public.FIXED_TPM | \
0543             Public.FIXED_PARENT | \
0544             Public.SENSITIVE_DATA_ORIGIN | \
0545             Public.USER_WITH_AUTH | \
0546             Public.RESTRICTED | \
0547             Public.DECRYPT
0548 
0549         auth_cmd = AuthCommand()
0550         sensitive = SensitiveCreate(user_auth=auth_value)
0551 
0552         public_parms = struct.pack(
0553             '>HHHHHI',
0554             TPM2_ALG_AES,
0555             128,
0556             TPM2_ALG_CFB,
0557             TPM2_ALG_NULL,
0558             2048,
0559             0)
0560 
0561         public = Public(
0562             object_type=TPM2_ALG_RSA,
0563             name_alg=TPM2_ALG_SHA1,
0564             object_attributes=attributes,
0565             parameters=public_parms)
0566 
0567         fmt = '>HIII I%us H%us H%us HI' % \
0568             (len(auth_cmd), len(sensitive), len(public))
0569         cmd = struct.pack(
0570             fmt,
0571             TPM2_ST_SESSIONS,
0572             struct.calcsize(fmt),
0573             TPM2_CC_CREATE_PRIMARY,
0574             TPM2_RH_OWNER,
0575             len(auth_cmd),
0576             bytes(auth_cmd),
0577             len(sensitive),
0578             bytes(sensitive),
0579             len(public),
0580             bytes(public),
0581             0, 0)
0582 
0583         return struct.unpack('>I', self.send_cmd(cmd)[10:14])[0]
0584 
0585     def seal(self, parent_key, data, auth_value, policy_dig,
0586              name_alg = TPM2_ALG_SHA1):
0587         ds = get_digest_size(name_alg)
0588         assert(not policy_dig or ds == len(policy_dig))
0589 
0590         attributes = 0
0591         if not policy_dig:
0592             attributes |= Public.USER_WITH_AUTH
0593             policy_dig = bytes()
0594 
0595         auth_cmd =  AuthCommand()
0596         sensitive = SensitiveCreate(user_auth=auth_value, data=data)
0597 
0598         public = Public(
0599             object_type=TPM2_ALG_KEYEDHASH,
0600             name_alg=name_alg,
0601             object_attributes=attributes,
0602             auth_policy=policy_dig,
0603             parameters=struct.pack('>H', TPM2_ALG_NULL))
0604 
0605         fmt = '>HIII I%us H%us H%us HI' % \
0606             (len(auth_cmd), len(sensitive), len(public))
0607         cmd = struct.pack(
0608             fmt,
0609             TPM2_ST_SESSIONS,
0610             struct.calcsize(fmt),
0611             TPM2_CC_CREATE,
0612             parent_key,
0613             len(auth_cmd),
0614             bytes(auth_cmd),
0615             len(sensitive),
0616             bytes(sensitive),
0617             len(public),
0618             bytes(public),
0619             0, 0)
0620 
0621         rsp = self.send_cmd(cmd)
0622 
0623         return rsp[14:]
0624 
0625     def unseal(self, parent_key, blob, auth_value, policy_handle):
0626         private_len = struct.unpack('>H', blob[0:2])[0]
0627         public_start = private_len + 2
0628         public_len = struct.unpack('>H', blob[public_start:public_start + 2])[0]
0629         blob = blob[:private_len + public_len + 4]
0630 
0631         auth_cmd = AuthCommand()
0632 
0633         fmt = '>HII I I%us %us' % (len(auth_cmd), len(blob))
0634         cmd = struct.pack(
0635             fmt,
0636             TPM2_ST_SESSIONS,
0637             struct.calcsize(fmt),
0638             TPM2_CC_LOAD,
0639             parent_key,
0640             len(auth_cmd),
0641             bytes(auth_cmd),
0642             blob)
0643 
0644         data_handle = struct.unpack('>I', self.send_cmd(cmd)[10:14])[0]
0645 
0646         if policy_handle:
0647             auth_cmd = AuthCommand(session_handle=policy_handle, hmac=auth_value)
0648         else:
0649             auth_cmd = AuthCommand(hmac=auth_value)
0650 
0651         fmt = '>HII I I%us' % (len(auth_cmd))
0652         cmd = struct.pack(
0653             fmt,
0654             TPM2_ST_SESSIONS,
0655             struct.calcsize(fmt),
0656             TPM2_CC_UNSEAL,
0657             data_handle,
0658             len(auth_cmd),
0659             bytes(auth_cmd))
0660 
0661         try:
0662             rsp = self.send_cmd(cmd)
0663         finally:
0664             self.flush_context(data_handle)
0665 
0666         data_len = struct.unpack('>I', rsp[10:14])[0] - 2
0667 
0668         return rsp[16:16 + data_len]
0669 
0670     def reset_da_lock(self):
0671         auth_cmd = AuthCommand()
0672 
0673         fmt = '>HII I I%us' % (len(auth_cmd))
0674         cmd = struct.pack(
0675             fmt,
0676             TPM2_ST_SESSIONS,
0677             struct.calcsize(fmt),
0678             TPM2_CC_DICTIONARY_ATTACK_LOCK_RESET,
0679             TPM2_RH_LOCKOUT,
0680             len(auth_cmd),
0681             bytes(auth_cmd))
0682 
0683         self.send_cmd(cmd)
0684 
0685     def __get_cap_cnt(self, cap, pt, cnt):
0686         handles = []
0687         fmt = '>HII III'
0688 
0689         cmd = struct.pack(fmt,
0690                           TPM2_ST_NO_SESSIONS,
0691                           struct.calcsize(fmt),
0692                           TPM2_CC_GET_CAPABILITY,
0693                           cap, pt, cnt)
0694 
0695         rsp = self.send_cmd(cmd)[10:]
0696         more_data, cap, cnt = struct.unpack('>BII', rsp[:9])
0697         rsp = rsp[9:]
0698 
0699         for i in range(0, cnt):
0700             handle = struct.unpack('>I', rsp[:4])[0]
0701             handles.append(handle)
0702             rsp = rsp[4:]
0703 
0704         return handles, more_data
0705 
0706     def get_cap(self, cap, pt):
0707         handles = []
0708 
0709         more_data = True
0710         while more_data:
0711             next_handles, more_data = self.__get_cap_cnt(cap, pt, 1)
0712             handles += next_handles
0713             pt += 1
0714 
0715         return handles
0716 
0717     def get_cap_pcrs(self):
0718         pcr_banks = {}
0719 
0720         fmt = '>HII III'
0721 
0722         cmd = struct.pack(fmt,
0723                           TPM2_ST_NO_SESSIONS,
0724                           struct.calcsize(fmt),
0725                           TPM2_CC_GET_CAPABILITY,
0726                           TPM2_CAP_PCRS, 0, 1)
0727         rsp = self.send_cmd(cmd)[10:]
0728         _, _, cnt = struct.unpack('>BII', rsp[:9])
0729         rsp = rsp[9:]
0730 
0731         # items are TPMS_PCR_SELECTION's
0732         for i in range(0, cnt):
0733               hash, sizeOfSelect = struct.unpack('>HB', rsp[:3])
0734               rsp = rsp[3:]
0735 
0736               pcrSelect = 0
0737               if sizeOfSelect > 0:
0738                   pcrSelect, = struct.unpack('%ds' % sizeOfSelect,
0739                                              rsp[:sizeOfSelect])
0740                   rsp = rsp[sizeOfSelect:]
0741                   pcrSelect = int.from_bytes(pcrSelect, byteorder='big')
0742 
0743               pcr_banks[hash] = pcrSelect
0744 
0745         return pcr_banks