xref: /OK3568_Linux_fs/kernel/tools/testing/selftests/tpm2/tpm2.py (revision 4882a59341e53eb6f0b4789bf948001014eff981)
1*4882a593Smuzhiyun# SPDX-License-Identifier: (GPL-2.0 OR BSD-3-Clause)
2*4882a593Smuzhiyun
3*4882a593Smuzhiyunimport hashlib
4*4882a593Smuzhiyunimport os
5*4882a593Smuzhiyunimport socket
6*4882a593Smuzhiyunimport struct
7*4882a593Smuzhiyunimport sys
8*4882a593Smuzhiyunimport unittest
9*4882a593Smuzhiyunimport fcntl
10*4882a593Smuzhiyunimport select
11*4882a593Smuzhiyun
12*4882a593SmuzhiyunTPM2_ST_NO_SESSIONS = 0x8001
13*4882a593SmuzhiyunTPM2_ST_SESSIONS = 0x8002
14*4882a593Smuzhiyun
15*4882a593SmuzhiyunTPM2_CC_FIRST = 0x01FF
16*4882a593Smuzhiyun
17*4882a593SmuzhiyunTPM2_CC_CREATE_PRIMARY = 0x0131
18*4882a593SmuzhiyunTPM2_CC_DICTIONARY_ATTACK_LOCK_RESET = 0x0139
19*4882a593SmuzhiyunTPM2_CC_CREATE = 0x0153
20*4882a593SmuzhiyunTPM2_CC_LOAD = 0x0157
21*4882a593SmuzhiyunTPM2_CC_UNSEAL = 0x015E
22*4882a593SmuzhiyunTPM2_CC_FLUSH_CONTEXT = 0x0165
23*4882a593SmuzhiyunTPM2_CC_START_AUTH_SESSION = 0x0176
24*4882a593SmuzhiyunTPM2_CC_GET_CAPABILITY	= 0x017A
25*4882a593SmuzhiyunTPM2_CC_GET_RANDOM = 0x017B
26*4882a593SmuzhiyunTPM2_CC_PCR_READ = 0x017E
27*4882a593SmuzhiyunTPM2_CC_POLICY_PCR = 0x017F
28*4882a593SmuzhiyunTPM2_CC_PCR_EXTEND = 0x0182
29*4882a593SmuzhiyunTPM2_CC_POLICY_PASSWORD = 0x018C
30*4882a593SmuzhiyunTPM2_CC_POLICY_GET_DIGEST = 0x0189
31*4882a593Smuzhiyun
32*4882a593SmuzhiyunTPM2_SE_POLICY = 0x01
33*4882a593SmuzhiyunTPM2_SE_TRIAL = 0x03
34*4882a593Smuzhiyun
35*4882a593SmuzhiyunTPM2_ALG_RSA = 0x0001
36*4882a593SmuzhiyunTPM2_ALG_SHA1 = 0x0004
37*4882a593SmuzhiyunTPM2_ALG_AES = 0x0006
38*4882a593SmuzhiyunTPM2_ALG_KEYEDHASH = 0x0008
39*4882a593SmuzhiyunTPM2_ALG_SHA256 = 0x000B
40*4882a593SmuzhiyunTPM2_ALG_NULL = 0x0010
41*4882a593SmuzhiyunTPM2_ALG_CBC = 0x0042
42*4882a593SmuzhiyunTPM2_ALG_CFB = 0x0043
43*4882a593Smuzhiyun
44*4882a593SmuzhiyunTPM2_RH_OWNER = 0x40000001
45*4882a593SmuzhiyunTPM2_RH_NULL = 0x40000007
46*4882a593SmuzhiyunTPM2_RH_LOCKOUT = 0x4000000A
47*4882a593SmuzhiyunTPM2_RS_PW = 0x40000009
48*4882a593Smuzhiyun
49*4882a593SmuzhiyunTPM2_RC_SIZE            = 0x01D5
50*4882a593SmuzhiyunTPM2_RC_AUTH_FAIL       = 0x098E
51*4882a593SmuzhiyunTPM2_RC_POLICY_FAIL     = 0x099D
52*4882a593SmuzhiyunTPM2_RC_COMMAND_CODE    = 0x0143
53*4882a593Smuzhiyun
54*4882a593SmuzhiyunTSS2_RC_LAYER_SHIFT = 16
55*4882a593SmuzhiyunTSS2_RESMGR_TPM_RC_LAYER = (11 << TSS2_RC_LAYER_SHIFT)
56*4882a593Smuzhiyun
57*4882a593SmuzhiyunTPM2_CAP_HANDLES = 0x00000001
58*4882a593SmuzhiyunTPM2_CAP_COMMANDS = 0x00000002
59*4882a593SmuzhiyunTPM2_CAP_TPM_PROPERTIES = 0x00000006
60*4882a593Smuzhiyun
61*4882a593SmuzhiyunTPM2_PT_FIXED = 0x100
62*4882a593SmuzhiyunTPM2_PT_TOTAL_COMMANDS = TPM2_PT_FIXED + 41
63*4882a593Smuzhiyun
64*4882a593SmuzhiyunHR_SHIFT = 24
65*4882a593SmuzhiyunHR_LOADED_SESSION = 0x02000000
66*4882a593SmuzhiyunHR_TRANSIENT = 0x80000000
67*4882a593Smuzhiyun
68*4882a593SmuzhiyunSHA1_DIGEST_SIZE = 20
69*4882a593SmuzhiyunSHA256_DIGEST_SIZE = 32
70*4882a593Smuzhiyun
71*4882a593SmuzhiyunTPM2_VER0_ERRORS = {
72*4882a593Smuzhiyun    0x000: "TPM_RC_SUCCESS",
73*4882a593Smuzhiyun    0x030: "TPM_RC_BAD_TAG",
74*4882a593Smuzhiyun}
75*4882a593Smuzhiyun
76*4882a593SmuzhiyunTPM2_VER1_ERRORS = {
77*4882a593Smuzhiyun    0x000: "TPM_RC_FAILURE",
78*4882a593Smuzhiyun    0x001: "TPM_RC_FAILURE",
79*4882a593Smuzhiyun    0x003: "TPM_RC_SEQUENCE",
80*4882a593Smuzhiyun    0x00B: "TPM_RC_PRIVATE",
81*4882a593Smuzhiyun    0x019: "TPM_RC_HMAC",
82*4882a593Smuzhiyun    0x020: "TPM_RC_DISABLED",
83*4882a593Smuzhiyun    0x021: "TPM_RC_EXCLUSIVE",
84*4882a593Smuzhiyun    0x024: "TPM_RC_AUTH_TYPE",
85*4882a593Smuzhiyun    0x025: "TPM_RC_AUTH_MISSING",
86*4882a593Smuzhiyun    0x026: "TPM_RC_POLICY",
87*4882a593Smuzhiyun    0x027: "TPM_RC_PCR",
88*4882a593Smuzhiyun    0x028: "TPM_RC_PCR_CHANGED",
89*4882a593Smuzhiyun    0x02D: "TPM_RC_UPGRADE",
90*4882a593Smuzhiyun    0x02E: "TPM_RC_TOO_MANY_CONTEXTS",
91*4882a593Smuzhiyun    0x02F: "TPM_RC_AUTH_UNAVAILABLE",
92*4882a593Smuzhiyun    0x030: "TPM_RC_REBOOT",
93*4882a593Smuzhiyun    0x031: "TPM_RC_UNBALANCED",
94*4882a593Smuzhiyun    0x042: "TPM_RC_COMMAND_SIZE",
95*4882a593Smuzhiyun    0x043: "TPM_RC_COMMAND_CODE",
96*4882a593Smuzhiyun    0x044: "TPM_RC_AUTHSIZE",
97*4882a593Smuzhiyun    0x045: "TPM_RC_AUTH_CONTEXT",
98*4882a593Smuzhiyun    0x046: "TPM_RC_NV_RANGE",
99*4882a593Smuzhiyun    0x047: "TPM_RC_NV_SIZE",
100*4882a593Smuzhiyun    0x048: "TPM_RC_NV_LOCKED",
101*4882a593Smuzhiyun    0x049: "TPM_RC_NV_AUTHORIZATION",
102*4882a593Smuzhiyun    0x04A: "TPM_RC_NV_UNINITIALIZED",
103*4882a593Smuzhiyun    0x04B: "TPM_RC_NV_SPACE",
104*4882a593Smuzhiyun    0x04C: "TPM_RC_NV_DEFINED",
105*4882a593Smuzhiyun    0x050: "TPM_RC_BAD_CONTEXT",
106*4882a593Smuzhiyun    0x051: "TPM_RC_CPHASH",
107*4882a593Smuzhiyun    0x052: "TPM_RC_PARENT",
108*4882a593Smuzhiyun    0x053: "TPM_RC_NEEDS_TEST",
109*4882a593Smuzhiyun    0x054: "TPM_RC_NO_RESULT",
110*4882a593Smuzhiyun    0x055: "TPM_RC_SENSITIVE",
111*4882a593Smuzhiyun    0x07F: "RC_MAX_FM0",
112*4882a593Smuzhiyun}
113*4882a593Smuzhiyun
114*4882a593SmuzhiyunTPM2_FMT1_ERRORS = {
115*4882a593Smuzhiyun    0x001: "TPM_RC_ASYMMETRIC",
116*4882a593Smuzhiyun    0x002: "TPM_RC_ATTRIBUTES",
117*4882a593Smuzhiyun    0x003: "TPM_RC_HASH",
118*4882a593Smuzhiyun    0x004: "TPM_RC_VALUE",
119*4882a593Smuzhiyun    0x005: "TPM_RC_HIERARCHY",
120*4882a593Smuzhiyun    0x007: "TPM_RC_KEY_SIZE",
121*4882a593Smuzhiyun    0x008: "TPM_RC_MGF",
122*4882a593Smuzhiyun    0x009: "TPM_RC_MODE",
123*4882a593Smuzhiyun    0x00A: "TPM_RC_TYPE",
124*4882a593Smuzhiyun    0x00B: "TPM_RC_HANDLE",
125*4882a593Smuzhiyun    0x00C: "TPM_RC_KDF",
126*4882a593Smuzhiyun    0x00D: "TPM_RC_RANGE",
127*4882a593Smuzhiyun    0x00E: "TPM_RC_AUTH_FAIL",
128*4882a593Smuzhiyun    0x00F: "TPM_RC_NONCE",
129*4882a593Smuzhiyun    0x010: "TPM_RC_PP",
130*4882a593Smuzhiyun    0x012: "TPM_RC_SCHEME",
131*4882a593Smuzhiyun    0x015: "TPM_RC_SIZE",
132*4882a593Smuzhiyun    0x016: "TPM_RC_SYMMETRIC",
133*4882a593Smuzhiyun    0x017: "TPM_RC_TAG",
134*4882a593Smuzhiyun    0x018: "TPM_RC_SELECTOR",
135*4882a593Smuzhiyun    0x01A: "TPM_RC_INSUFFICIENT",
136*4882a593Smuzhiyun    0x01B: "TPM_RC_SIGNATURE",
137*4882a593Smuzhiyun    0x01C: "TPM_RC_KEY",
138*4882a593Smuzhiyun    0x01D: "TPM_RC_POLICY_FAIL",
139*4882a593Smuzhiyun    0x01F: "TPM_RC_INTEGRITY",
140*4882a593Smuzhiyun    0x020: "TPM_RC_TICKET",
141*4882a593Smuzhiyun    0x021: "TPM_RC_RESERVED_BITS",
142*4882a593Smuzhiyun    0x022: "TPM_RC_BAD_AUTH",
143*4882a593Smuzhiyun    0x023: "TPM_RC_EXPIRED",
144*4882a593Smuzhiyun    0x024: "TPM_RC_POLICY_CC",
145*4882a593Smuzhiyun    0x025: "TPM_RC_BINDING",
146*4882a593Smuzhiyun    0x026: "TPM_RC_CURVE",
147*4882a593Smuzhiyun    0x027: "TPM_RC_ECC_POINT",
148*4882a593Smuzhiyun}
149*4882a593Smuzhiyun
150*4882a593SmuzhiyunTPM2_WARN_ERRORS = {
151*4882a593Smuzhiyun    0x001: "TPM_RC_CONTEXT_GAP",
152*4882a593Smuzhiyun    0x002: "TPM_RC_OBJECT_MEMORY",
153*4882a593Smuzhiyun    0x003: "TPM_RC_SESSION_MEMORY",
154*4882a593Smuzhiyun    0x004: "TPM_RC_MEMORY",
155*4882a593Smuzhiyun    0x005: "TPM_RC_SESSION_HANDLES",
156*4882a593Smuzhiyun    0x006: "TPM_RC_OBJECT_HANDLES",
157*4882a593Smuzhiyun    0x007: "TPM_RC_LOCALITY",
158*4882a593Smuzhiyun    0x008: "TPM_RC_YIELDED",
159*4882a593Smuzhiyun    0x009: "TPM_RC_CANCELED",
160*4882a593Smuzhiyun    0x00A: "TPM_RC_TESTING",
161*4882a593Smuzhiyun    0x010: "TPM_RC_REFERENCE_H0",
162*4882a593Smuzhiyun    0x011: "TPM_RC_REFERENCE_H1",
163*4882a593Smuzhiyun    0x012: "TPM_RC_REFERENCE_H2",
164*4882a593Smuzhiyun    0x013: "TPM_RC_REFERENCE_H3",
165*4882a593Smuzhiyun    0x014: "TPM_RC_REFERENCE_H4",
166*4882a593Smuzhiyun    0x015: "TPM_RC_REFERENCE_H5",
167*4882a593Smuzhiyun    0x016: "TPM_RC_REFERENCE_H6",
168*4882a593Smuzhiyun    0x018: "TPM_RC_REFERENCE_S0",
169*4882a593Smuzhiyun    0x019: "TPM_RC_REFERENCE_S1",
170*4882a593Smuzhiyun    0x01A: "TPM_RC_REFERENCE_S2",
171*4882a593Smuzhiyun    0x01B: "TPM_RC_REFERENCE_S3",
172*4882a593Smuzhiyun    0x01C: "TPM_RC_REFERENCE_S4",
173*4882a593Smuzhiyun    0x01D: "TPM_RC_REFERENCE_S5",
174*4882a593Smuzhiyun    0x01E: "TPM_RC_REFERENCE_S6",
175*4882a593Smuzhiyun    0x020: "TPM_RC_NV_RATE",
176*4882a593Smuzhiyun    0x021: "TPM_RC_LOCKOUT",
177*4882a593Smuzhiyun    0x022: "TPM_RC_RETRY",
178*4882a593Smuzhiyun    0x023: "TPM_RC_NV_UNAVAILABLE",
179*4882a593Smuzhiyun    0x7F: "TPM_RC_NOT_USED",
180*4882a593Smuzhiyun}
181*4882a593Smuzhiyun
182*4882a593SmuzhiyunRC_VER1 = 0x100
183*4882a593SmuzhiyunRC_FMT1 = 0x080
184*4882a593SmuzhiyunRC_WARN = 0x900
185*4882a593Smuzhiyun
186*4882a593SmuzhiyunALG_DIGEST_SIZE_MAP = {
187*4882a593Smuzhiyun    TPM2_ALG_SHA1: SHA1_DIGEST_SIZE,
188*4882a593Smuzhiyun    TPM2_ALG_SHA256: SHA256_DIGEST_SIZE,
189*4882a593Smuzhiyun}
190*4882a593Smuzhiyun
191*4882a593SmuzhiyunALG_HASH_FUNCTION_MAP = {
192*4882a593Smuzhiyun    TPM2_ALG_SHA1: hashlib.sha1,
193*4882a593Smuzhiyun    TPM2_ALG_SHA256: hashlib.sha256
194*4882a593Smuzhiyun}
195*4882a593Smuzhiyun
196*4882a593SmuzhiyunNAME_ALG_MAP = {
197*4882a593Smuzhiyun    "sha1": TPM2_ALG_SHA1,
198*4882a593Smuzhiyun    "sha256": TPM2_ALG_SHA256,
199*4882a593Smuzhiyun}
200*4882a593Smuzhiyun
201*4882a593Smuzhiyun
202*4882a593Smuzhiyunclass UnknownAlgorithmIdError(Exception):
203*4882a593Smuzhiyun    def __init__(self, alg):
204*4882a593Smuzhiyun        self.alg = alg
205*4882a593Smuzhiyun
206*4882a593Smuzhiyun    def __str__(self):
207*4882a593Smuzhiyun        return '0x%0x' % (alg)
208*4882a593Smuzhiyun
209*4882a593Smuzhiyun
210*4882a593Smuzhiyunclass UnknownAlgorithmNameError(Exception):
211*4882a593Smuzhiyun    def __init__(self, name):
212*4882a593Smuzhiyun        self.name = name
213*4882a593Smuzhiyun
214*4882a593Smuzhiyun    def __str__(self):
215*4882a593Smuzhiyun        return name
216*4882a593Smuzhiyun
217*4882a593Smuzhiyun
218*4882a593Smuzhiyunclass UnknownPCRBankError(Exception):
219*4882a593Smuzhiyun    def __init__(self, alg):
220*4882a593Smuzhiyun        self.alg = alg
221*4882a593Smuzhiyun
222*4882a593Smuzhiyun    def __str__(self):
223*4882a593Smuzhiyun        return '0x%0x' % (alg)
224*4882a593Smuzhiyun
225*4882a593Smuzhiyun
226*4882a593Smuzhiyunclass ProtocolError(Exception):
227*4882a593Smuzhiyun    def __init__(self, cc, rc):
228*4882a593Smuzhiyun        self.cc = cc
229*4882a593Smuzhiyun        self.rc = rc
230*4882a593Smuzhiyun
231*4882a593Smuzhiyun        if (rc & RC_FMT1) == RC_FMT1:
232*4882a593Smuzhiyun            self.name = TPM2_FMT1_ERRORS.get(rc & 0x3f, "TPM_RC_UNKNOWN")
233*4882a593Smuzhiyun        elif (rc & RC_WARN) == RC_WARN:
234*4882a593Smuzhiyun            self.name = TPM2_WARN_ERRORS.get(rc & 0x7f, "TPM_RC_UNKNOWN")
235*4882a593Smuzhiyun        elif (rc & RC_VER1) == RC_VER1:
236*4882a593Smuzhiyun            self.name = TPM2_VER1_ERRORS.get(rc & 0x7f, "TPM_RC_UNKNOWN")
237*4882a593Smuzhiyun        else:
238*4882a593Smuzhiyun            self.name = TPM2_VER0_ERRORS.get(rc & 0x7f, "TPM_RC_UNKNOWN")
239*4882a593Smuzhiyun
240*4882a593Smuzhiyun    def __str__(self):
241*4882a593Smuzhiyun        if self.cc:
242*4882a593Smuzhiyun            return '%s: cc=0x%08x, rc=0x%08x' % (self.name, self.cc, self.rc)
243*4882a593Smuzhiyun        else:
244*4882a593Smuzhiyun            return '%s: rc=0x%08x' % (self.name, self.rc)
245*4882a593Smuzhiyun
246*4882a593Smuzhiyun
247*4882a593Smuzhiyunclass AuthCommand(object):
248*4882a593Smuzhiyun    """TPMS_AUTH_COMMAND"""
249*4882a593Smuzhiyun
250*4882a593Smuzhiyun    def __init__(self, session_handle=TPM2_RS_PW, nonce=bytes(),
251*4882a593Smuzhiyun                 session_attributes=0, hmac=bytes()):
252*4882a593Smuzhiyun        self.session_handle = session_handle
253*4882a593Smuzhiyun        self.nonce = nonce
254*4882a593Smuzhiyun        self.session_attributes = session_attributes
255*4882a593Smuzhiyun        self.hmac = hmac
256*4882a593Smuzhiyun
257*4882a593Smuzhiyun    def __bytes__(self):
258*4882a593Smuzhiyun        fmt = '>I H%us B H%us' % (len(self.nonce), len(self.hmac))
259*4882a593Smuzhiyun        return struct.pack(fmt, self.session_handle, len(self.nonce),
260*4882a593Smuzhiyun                           self.nonce, self.session_attributes, len(self.hmac),
261*4882a593Smuzhiyun                           self.hmac)
262*4882a593Smuzhiyun
263*4882a593Smuzhiyun    def __len__(self):
264*4882a593Smuzhiyun        fmt = '>I H%us B H%us' % (len(self.nonce), len(self.hmac))
265*4882a593Smuzhiyun        return struct.calcsize(fmt)
266*4882a593Smuzhiyun
267*4882a593Smuzhiyun
268*4882a593Smuzhiyunclass SensitiveCreate(object):
269*4882a593Smuzhiyun    """TPMS_SENSITIVE_CREATE"""
270*4882a593Smuzhiyun
271*4882a593Smuzhiyun    def __init__(self, user_auth=bytes(), data=bytes()):
272*4882a593Smuzhiyun        self.user_auth = user_auth
273*4882a593Smuzhiyun        self.data = data
274*4882a593Smuzhiyun
275*4882a593Smuzhiyun    def __bytes__(self):
276*4882a593Smuzhiyun        fmt = '>H%us H%us' % (len(self.user_auth), len(self.data))
277*4882a593Smuzhiyun        return struct.pack(fmt, len(self.user_auth), self.user_auth,
278*4882a593Smuzhiyun                           len(self.data), self.data)
279*4882a593Smuzhiyun
280*4882a593Smuzhiyun    def __len__(self):
281*4882a593Smuzhiyun        fmt = '>H%us H%us' % (len(self.user_auth), len(self.data))
282*4882a593Smuzhiyun        return struct.calcsize(fmt)
283*4882a593Smuzhiyun
284*4882a593Smuzhiyun
285*4882a593Smuzhiyunclass Public(object):
286*4882a593Smuzhiyun    """TPMT_PUBLIC"""
287*4882a593Smuzhiyun
288*4882a593Smuzhiyun    FIXED_TPM = (1 << 1)
289*4882a593Smuzhiyun    FIXED_PARENT = (1 << 4)
290*4882a593Smuzhiyun    SENSITIVE_DATA_ORIGIN = (1 << 5)
291*4882a593Smuzhiyun    USER_WITH_AUTH = (1 << 6)
292*4882a593Smuzhiyun    RESTRICTED = (1 << 16)
293*4882a593Smuzhiyun    DECRYPT = (1 << 17)
294*4882a593Smuzhiyun
295*4882a593Smuzhiyun    def __fmt(self):
296*4882a593Smuzhiyun        return '>HHIH%us%usH%us' % \
297*4882a593Smuzhiyun            (len(self.auth_policy), len(self.parameters), len(self.unique))
298*4882a593Smuzhiyun
299*4882a593Smuzhiyun    def __init__(self, object_type, name_alg, object_attributes,
300*4882a593Smuzhiyun                 auth_policy=bytes(), parameters=bytes(),
301*4882a593Smuzhiyun                 unique=bytes()):
302*4882a593Smuzhiyun        self.object_type = object_type
303*4882a593Smuzhiyun        self.name_alg = name_alg
304*4882a593Smuzhiyun        self.object_attributes = object_attributes
305*4882a593Smuzhiyun        self.auth_policy = auth_policy
306*4882a593Smuzhiyun        self.parameters = parameters
307*4882a593Smuzhiyun        self.unique = unique
308*4882a593Smuzhiyun
309*4882a593Smuzhiyun    def __bytes__(self):
310*4882a593Smuzhiyun        return struct.pack(self.__fmt(),
311*4882a593Smuzhiyun                           self.object_type,
312*4882a593Smuzhiyun                           self.name_alg,
313*4882a593Smuzhiyun                           self.object_attributes,
314*4882a593Smuzhiyun                           len(self.auth_policy),
315*4882a593Smuzhiyun                           self.auth_policy,
316*4882a593Smuzhiyun                           self.parameters,
317*4882a593Smuzhiyun                           len(self.unique),
318*4882a593Smuzhiyun                           self.unique)
319*4882a593Smuzhiyun
320*4882a593Smuzhiyun    def __len__(self):
321*4882a593Smuzhiyun        return struct.calcsize(self.__fmt())
322*4882a593Smuzhiyun
323*4882a593Smuzhiyun
324*4882a593Smuzhiyundef get_digest_size(alg):
325*4882a593Smuzhiyun    ds = ALG_DIGEST_SIZE_MAP.get(alg)
326*4882a593Smuzhiyun    if not ds:
327*4882a593Smuzhiyun        raise UnknownAlgorithmIdError(alg)
328*4882a593Smuzhiyun    return ds
329*4882a593Smuzhiyun
330*4882a593Smuzhiyun
331*4882a593Smuzhiyundef get_hash_function(alg):
332*4882a593Smuzhiyun    f = ALG_HASH_FUNCTION_MAP.get(alg)
333*4882a593Smuzhiyun    if not f:
334*4882a593Smuzhiyun        raise UnknownAlgorithmIdError(alg)
335*4882a593Smuzhiyun    return f
336*4882a593Smuzhiyun
337*4882a593Smuzhiyun
338*4882a593Smuzhiyundef get_algorithm(name):
339*4882a593Smuzhiyun    alg = NAME_ALG_MAP.get(name)
340*4882a593Smuzhiyun    if not alg:
341*4882a593Smuzhiyun        raise UnknownAlgorithmNameError(name)
342*4882a593Smuzhiyun    return alg
343*4882a593Smuzhiyun
344*4882a593Smuzhiyun
345*4882a593Smuzhiyundef hex_dump(d):
346*4882a593Smuzhiyun    d = [format(ord(x), '02x') for x in d]
347*4882a593Smuzhiyun    d = [d[i: i + 16] for i in range(0, len(d), 16)]
348*4882a593Smuzhiyun    d = [' '.join(x) for x in d]
349*4882a593Smuzhiyun    d = os.linesep.join(d)
350*4882a593Smuzhiyun
351*4882a593Smuzhiyun    return d
352*4882a593Smuzhiyun
353*4882a593Smuzhiyunclass Client:
354*4882a593Smuzhiyun    FLAG_DEBUG = 0x01
355*4882a593Smuzhiyun    FLAG_SPACE = 0x02
356*4882a593Smuzhiyun    FLAG_NONBLOCK = 0x04
357*4882a593Smuzhiyun    TPM_IOC_NEW_SPACE = 0xa200
358*4882a593Smuzhiyun
359*4882a593Smuzhiyun    def __init__(self, flags = 0):
360*4882a593Smuzhiyun        self.flags = flags
361*4882a593Smuzhiyun
362*4882a593Smuzhiyun        if (self.flags & Client.FLAG_SPACE) == 0:
363*4882a593Smuzhiyun            self.tpm = open('/dev/tpm0', 'r+b', buffering=0)
364*4882a593Smuzhiyun        else:
365*4882a593Smuzhiyun            self.tpm = open('/dev/tpmrm0', 'r+b', buffering=0)
366*4882a593Smuzhiyun
367*4882a593Smuzhiyun        if (self.flags & Client.FLAG_NONBLOCK):
368*4882a593Smuzhiyun            flags = fcntl.fcntl(self.tpm, fcntl.F_GETFL)
369*4882a593Smuzhiyun            flags |= os.O_NONBLOCK
370*4882a593Smuzhiyun            fcntl.fcntl(self.tpm, fcntl.F_SETFL, flags)
371*4882a593Smuzhiyun            self.tpm_poll = select.poll()
372*4882a593Smuzhiyun
373*4882a593Smuzhiyun    def __del__(self):
374*4882a593Smuzhiyun        if self.tpm:
375*4882a593Smuzhiyun            self.tpm.close()
376*4882a593Smuzhiyun
377*4882a593Smuzhiyun    def close(self):
378*4882a593Smuzhiyun        self.tpm.close()
379*4882a593Smuzhiyun
380*4882a593Smuzhiyun    def send_cmd(self, cmd):
381*4882a593Smuzhiyun        self.tpm.write(cmd)
382*4882a593Smuzhiyun
383*4882a593Smuzhiyun        if (self.flags & Client.FLAG_NONBLOCK):
384*4882a593Smuzhiyun            self.tpm_poll.register(self.tpm, select.POLLIN)
385*4882a593Smuzhiyun            self.tpm_poll.poll(10000)
386*4882a593Smuzhiyun
387*4882a593Smuzhiyun        rsp = self.tpm.read()
388*4882a593Smuzhiyun
389*4882a593Smuzhiyun        if (self.flags & Client.FLAG_NONBLOCK):
390*4882a593Smuzhiyun            self.tpm_poll.unregister(self.tpm)
391*4882a593Smuzhiyun
392*4882a593Smuzhiyun        if (self.flags & Client.FLAG_DEBUG) != 0:
393*4882a593Smuzhiyun            sys.stderr.write('cmd' + os.linesep)
394*4882a593Smuzhiyun            sys.stderr.write(hex_dump(cmd) + os.linesep)
395*4882a593Smuzhiyun            sys.stderr.write('rsp' + os.linesep)
396*4882a593Smuzhiyun            sys.stderr.write(hex_dump(rsp) + os.linesep)
397*4882a593Smuzhiyun
398*4882a593Smuzhiyun        rc = struct.unpack('>I', rsp[6:10])[0]
399*4882a593Smuzhiyun        if rc != 0:
400*4882a593Smuzhiyun            cc = struct.unpack('>I', cmd[6:10])[0]
401*4882a593Smuzhiyun            raise ProtocolError(cc, rc)
402*4882a593Smuzhiyun
403*4882a593Smuzhiyun        return rsp
404*4882a593Smuzhiyun
405*4882a593Smuzhiyun    def read_pcr(self, i, bank_alg = TPM2_ALG_SHA1):
406*4882a593Smuzhiyun        pcrsel_len = max((i >> 3) + 1, 3)
407*4882a593Smuzhiyun        pcrsel = [0] * pcrsel_len
408*4882a593Smuzhiyun        pcrsel[i >> 3] = 1 << (i & 7)
409*4882a593Smuzhiyun        pcrsel = ''.join(map(chr, pcrsel)).encode()
410*4882a593Smuzhiyun
411*4882a593Smuzhiyun        fmt = '>HII IHB%us' % (pcrsel_len)
412*4882a593Smuzhiyun        cmd = struct.pack(fmt,
413*4882a593Smuzhiyun                          TPM2_ST_NO_SESSIONS,
414*4882a593Smuzhiyun                          struct.calcsize(fmt),
415*4882a593Smuzhiyun                          TPM2_CC_PCR_READ,
416*4882a593Smuzhiyun                          1,
417*4882a593Smuzhiyun                          bank_alg,
418*4882a593Smuzhiyun                          pcrsel_len, pcrsel)
419*4882a593Smuzhiyun
420*4882a593Smuzhiyun        rsp = self.send_cmd(cmd)
421*4882a593Smuzhiyun
422*4882a593Smuzhiyun        pcr_update_cnt, pcr_select_cnt = struct.unpack('>II', rsp[10:18])
423*4882a593Smuzhiyun        assert pcr_select_cnt == 1
424*4882a593Smuzhiyun        rsp = rsp[18:]
425*4882a593Smuzhiyun
426*4882a593Smuzhiyun        alg2, pcrsel_len2 = struct.unpack('>HB', rsp[:3])
427*4882a593Smuzhiyun        assert bank_alg == alg2 and pcrsel_len == pcrsel_len2
428*4882a593Smuzhiyun        rsp = rsp[3 + pcrsel_len:]
429*4882a593Smuzhiyun
430*4882a593Smuzhiyun        digest_cnt = struct.unpack('>I', rsp[:4])[0]
431*4882a593Smuzhiyun        if digest_cnt == 0:
432*4882a593Smuzhiyun            return None
433*4882a593Smuzhiyun        rsp = rsp[6:]
434*4882a593Smuzhiyun
435*4882a593Smuzhiyun        return rsp
436*4882a593Smuzhiyun
437*4882a593Smuzhiyun    def extend_pcr(self, i, dig, bank_alg = TPM2_ALG_SHA1):
438*4882a593Smuzhiyun        ds = get_digest_size(bank_alg)
439*4882a593Smuzhiyun        assert(ds == len(dig))
440*4882a593Smuzhiyun
441*4882a593Smuzhiyun        auth_cmd = AuthCommand()
442*4882a593Smuzhiyun
443*4882a593Smuzhiyun        fmt = '>HII I I%us IH%us' % (len(auth_cmd), ds)
444*4882a593Smuzhiyun        cmd = struct.pack(
445*4882a593Smuzhiyun            fmt,
446*4882a593Smuzhiyun            TPM2_ST_SESSIONS,
447*4882a593Smuzhiyun            struct.calcsize(fmt),
448*4882a593Smuzhiyun            TPM2_CC_PCR_EXTEND,
449*4882a593Smuzhiyun            i,
450*4882a593Smuzhiyun            len(auth_cmd),
451*4882a593Smuzhiyun            bytes(auth_cmd),
452*4882a593Smuzhiyun            1, bank_alg, dig)
453*4882a593Smuzhiyun
454*4882a593Smuzhiyun        self.send_cmd(cmd)
455*4882a593Smuzhiyun
456*4882a593Smuzhiyun    def start_auth_session(self, session_type, name_alg = TPM2_ALG_SHA1):
457*4882a593Smuzhiyun        fmt = '>HII IIH16sHBHH'
458*4882a593Smuzhiyun        cmd = struct.pack(fmt,
459*4882a593Smuzhiyun                          TPM2_ST_NO_SESSIONS,
460*4882a593Smuzhiyun                          struct.calcsize(fmt),
461*4882a593Smuzhiyun                          TPM2_CC_START_AUTH_SESSION,
462*4882a593Smuzhiyun                          TPM2_RH_NULL,
463*4882a593Smuzhiyun                          TPM2_RH_NULL,
464*4882a593Smuzhiyun                          16,
465*4882a593Smuzhiyun                          ('\0' * 16).encode(),
466*4882a593Smuzhiyun                          0,
467*4882a593Smuzhiyun                          session_type,
468*4882a593Smuzhiyun                          TPM2_ALG_NULL,
469*4882a593Smuzhiyun                          name_alg)
470*4882a593Smuzhiyun
471*4882a593Smuzhiyun        return struct.unpack('>I', self.send_cmd(cmd)[10:14])[0]
472*4882a593Smuzhiyun
473*4882a593Smuzhiyun    def __calc_pcr_digest(self, pcrs, bank_alg = TPM2_ALG_SHA1,
474*4882a593Smuzhiyun                          digest_alg = TPM2_ALG_SHA1):
475*4882a593Smuzhiyun        x = []
476*4882a593Smuzhiyun        f = get_hash_function(digest_alg)
477*4882a593Smuzhiyun
478*4882a593Smuzhiyun        for i in pcrs:
479*4882a593Smuzhiyun            pcr = self.read_pcr(i, bank_alg)
480*4882a593Smuzhiyun            if pcr is None:
481*4882a593Smuzhiyun                return None
482*4882a593Smuzhiyun            x += pcr
483*4882a593Smuzhiyun
484*4882a593Smuzhiyun        return f(bytearray(x)).digest()
485*4882a593Smuzhiyun
486*4882a593Smuzhiyun    def policy_pcr(self, handle, pcrs, bank_alg = TPM2_ALG_SHA1,
487*4882a593Smuzhiyun                   name_alg = TPM2_ALG_SHA1):
488*4882a593Smuzhiyun        ds = get_digest_size(name_alg)
489*4882a593Smuzhiyun        dig = self.__calc_pcr_digest(pcrs, bank_alg, name_alg)
490*4882a593Smuzhiyun        if not dig:
491*4882a593Smuzhiyun            raise UnknownPCRBankError(bank_alg)
492*4882a593Smuzhiyun
493*4882a593Smuzhiyun        pcrsel_len = max((max(pcrs) >> 3) + 1, 3)
494*4882a593Smuzhiyun        pcrsel = [0] * pcrsel_len
495*4882a593Smuzhiyun        for i in pcrs:
496*4882a593Smuzhiyun            pcrsel[i >> 3] |= 1 << (i & 7)
497*4882a593Smuzhiyun        pcrsel = ''.join(map(chr, pcrsel)).encode()
498*4882a593Smuzhiyun
499*4882a593Smuzhiyun        fmt = '>HII IH%usIHB3s' % ds
500*4882a593Smuzhiyun        cmd = struct.pack(fmt,
501*4882a593Smuzhiyun                          TPM2_ST_NO_SESSIONS,
502*4882a593Smuzhiyun                          struct.calcsize(fmt),
503*4882a593Smuzhiyun                          TPM2_CC_POLICY_PCR,
504*4882a593Smuzhiyun                          handle,
505*4882a593Smuzhiyun                          len(dig),
506*4882a593Smuzhiyun                          bytes(dig),
507*4882a593Smuzhiyun                          1,
508*4882a593Smuzhiyun                          bank_alg,
509*4882a593Smuzhiyun                          pcrsel_len, pcrsel)
510*4882a593Smuzhiyun
511*4882a593Smuzhiyun        self.send_cmd(cmd)
512*4882a593Smuzhiyun
513*4882a593Smuzhiyun    def policy_password(self, handle):
514*4882a593Smuzhiyun        fmt = '>HII I'
515*4882a593Smuzhiyun        cmd = struct.pack(fmt,
516*4882a593Smuzhiyun                          TPM2_ST_NO_SESSIONS,
517*4882a593Smuzhiyun                          struct.calcsize(fmt),
518*4882a593Smuzhiyun                          TPM2_CC_POLICY_PASSWORD,
519*4882a593Smuzhiyun                          handle)
520*4882a593Smuzhiyun
521*4882a593Smuzhiyun        self.send_cmd(cmd)
522*4882a593Smuzhiyun
523*4882a593Smuzhiyun    def get_policy_digest(self, handle):
524*4882a593Smuzhiyun        fmt = '>HII I'
525*4882a593Smuzhiyun        cmd = struct.pack(fmt,
526*4882a593Smuzhiyun                          TPM2_ST_NO_SESSIONS,
527*4882a593Smuzhiyun                          struct.calcsize(fmt),
528*4882a593Smuzhiyun                          TPM2_CC_POLICY_GET_DIGEST,
529*4882a593Smuzhiyun                          handle)
530*4882a593Smuzhiyun
531*4882a593Smuzhiyun        return self.send_cmd(cmd)[12:]
532*4882a593Smuzhiyun
533*4882a593Smuzhiyun    def flush_context(self, handle):
534*4882a593Smuzhiyun        fmt = '>HIII'
535*4882a593Smuzhiyun        cmd = struct.pack(fmt,
536*4882a593Smuzhiyun                          TPM2_ST_NO_SESSIONS,
537*4882a593Smuzhiyun                          struct.calcsize(fmt),
538*4882a593Smuzhiyun                          TPM2_CC_FLUSH_CONTEXT,
539*4882a593Smuzhiyun                          handle)
540*4882a593Smuzhiyun
541*4882a593Smuzhiyun        self.send_cmd(cmd)
542*4882a593Smuzhiyun
543*4882a593Smuzhiyun    def create_root_key(self, auth_value = bytes()):
544*4882a593Smuzhiyun        attributes = \
545*4882a593Smuzhiyun            Public.FIXED_TPM | \
546*4882a593Smuzhiyun            Public.FIXED_PARENT | \
547*4882a593Smuzhiyun            Public.SENSITIVE_DATA_ORIGIN | \
548*4882a593Smuzhiyun            Public.USER_WITH_AUTH | \
549*4882a593Smuzhiyun            Public.RESTRICTED | \
550*4882a593Smuzhiyun            Public.DECRYPT
551*4882a593Smuzhiyun
552*4882a593Smuzhiyun        auth_cmd = AuthCommand()
553*4882a593Smuzhiyun        sensitive = SensitiveCreate(user_auth=auth_value)
554*4882a593Smuzhiyun
555*4882a593Smuzhiyun        public_parms = struct.pack(
556*4882a593Smuzhiyun            '>HHHHHI',
557*4882a593Smuzhiyun            TPM2_ALG_AES,
558*4882a593Smuzhiyun            128,
559*4882a593Smuzhiyun            TPM2_ALG_CFB,
560*4882a593Smuzhiyun            TPM2_ALG_NULL,
561*4882a593Smuzhiyun            2048,
562*4882a593Smuzhiyun            0)
563*4882a593Smuzhiyun
564*4882a593Smuzhiyun        public = Public(
565*4882a593Smuzhiyun            object_type=TPM2_ALG_RSA,
566*4882a593Smuzhiyun            name_alg=TPM2_ALG_SHA1,
567*4882a593Smuzhiyun            object_attributes=attributes,
568*4882a593Smuzhiyun            parameters=public_parms)
569*4882a593Smuzhiyun
570*4882a593Smuzhiyun        fmt = '>HIII I%us H%us H%us HI' % \
571*4882a593Smuzhiyun            (len(auth_cmd), len(sensitive), len(public))
572*4882a593Smuzhiyun        cmd = struct.pack(
573*4882a593Smuzhiyun            fmt,
574*4882a593Smuzhiyun            TPM2_ST_SESSIONS,
575*4882a593Smuzhiyun            struct.calcsize(fmt),
576*4882a593Smuzhiyun            TPM2_CC_CREATE_PRIMARY,
577*4882a593Smuzhiyun            TPM2_RH_OWNER,
578*4882a593Smuzhiyun            len(auth_cmd),
579*4882a593Smuzhiyun            bytes(auth_cmd),
580*4882a593Smuzhiyun            len(sensitive),
581*4882a593Smuzhiyun            bytes(sensitive),
582*4882a593Smuzhiyun            len(public),
583*4882a593Smuzhiyun            bytes(public),
584*4882a593Smuzhiyun            0, 0)
585*4882a593Smuzhiyun
586*4882a593Smuzhiyun        return struct.unpack('>I', self.send_cmd(cmd)[10:14])[0]
587*4882a593Smuzhiyun
588*4882a593Smuzhiyun    def seal(self, parent_key, data, auth_value, policy_dig,
589*4882a593Smuzhiyun             name_alg = TPM2_ALG_SHA1):
590*4882a593Smuzhiyun        ds = get_digest_size(name_alg)
591*4882a593Smuzhiyun        assert(not policy_dig or ds == len(policy_dig))
592*4882a593Smuzhiyun
593*4882a593Smuzhiyun        attributes = 0
594*4882a593Smuzhiyun        if not policy_dig:
595*4882a593Smuzhiyun            attributes |= Public.USER_WITH_AUTH
596*4882a593Smuzhiyun            policy_dig = bytes()
597*4882a593Smuzhiyun
598*4882a593Smuzhiyun        auth_cmd =  AuthCommand()
599*4882a593Smuzhiyun        sensitive = SensitiveCreate(user_auth=auth_value, data=data)
600*4882a593Smuzhiyun
601*4882a593Smuzhiyun        public = Public(
602*4882a593Smuzhiyun            object_type=TPM2_ALG_KEYEDHASH,
603*4882a593Smuzhiyun            name_alg=name_alg,
604*4882a593Smuzhiyun            object_attributes=attributes,
605*4882a593Smuzhiyun            auth_policy=policy_dig,
606*4882a593Smuzhiyun            parameters=struct.pack('>H', TPM2_ALG_NULL))
607*4882a593Smuzhiyun
608*4882a593Smuzhiyun        fmt = '>HIII I%us H%us H%us HI' % \
609*4882a593Smuzhiyun            (len(auth_cmd), len(sensitive), len(public))
610*4882a593Smuzhiyun        cmd = struct.pack(
611*4882a593Smuzhiyun            fmt,
612*4882a593Smuzhiyun            TPM2_ST_SESSIONS,
613*4882a593Smuzhiyun            struct.calcsize(fmt),
614*4882a593Smuzhiyun            TPM2_CC_CREATE,
615*4882a593Smuzhiyun            parent_key,
616*4882a593Smuzhiyun            len(auth_cmd),
617*4882a593Smuzhiyun            bytes(auth_cmd),
618*4882a593Smuzhiyun            len(sensitive),
619*4882a593Smuzhiyun            bytes(sensitive),
620*4882a593Smuzhiyun            len(public),
621*4882a593Smuzhiyun            bytes(public),
622*4882a593Smuzhiyun            0, 0)
623*4882a593Smuzhiyun
624*4882a593Smuzhiyun        rsp = self.send_cmd(cmd)
625*4882a593Smuzhiyun
626*4882a593Smuzhiyun        return rsp[14:]
627*4882a593Smuzhiyun
628*4882a593Smuzhiyun    def unseal(self, parent_key, blob, auth_value, policy_handle):
629*4882a593Smuzhiyun        private_len = struct.unpack('>H', blob[0:2])[0]
630*4882a593Smuzhiyun        public_start = private_len + 2
631*4882a593Smuzhiyun        public_len = struct.unpack('>H', blob[public_start:public_start + 2])[0]
632*4882a593Smuzhiyun        blob = blob[:private_len + public_len + 4]
633*4882a593Smuzhiyun
634*4882a593Smuzhiyun        auth_cmd = AuthCommand()
635*4882a593Smuzhiyun
636*4882a593Smuzhiyun        fmt = '>HII I I%us %us' % (len(auth_cmd), len(blob))
637*4882a593Smuzhiyun        cmd = struct.pack(
638*4882a593Smuzhiyun            fmt,
639*4882a593Smuzhiyun            TPM2_ST_SESSIONS,
640*4882a593Smuzhiyun            struct.calcsize(fmt),
641*4882a593Smuzhiyun            TPM2_CC_LOAD,
642*4882a593Smuzhiyun            parent_key,
643*4882a593Smuzhiyun            len(auth_cmd),
644*4882a593Smuzhiyun            bytes(auth_cmd),
645*4882a593Smuzhiyun            blob)
646*4882a593Smuzhiyun
647*4882a593Smuzhiyun        data_handle = struct.unpack('>I', self.send_cmd(cmd)[10:14])[0]
648*4882a593Smuzhiyun
649*4882a593Smuzhiyun        if policy_handle:
650*4882a593Smuzhiyun            auth_cmd = AuthCommand(session_handle=policy_handle, hmac=auth_value)
651*4882a593Smuzhiyun        else:
652*4882a593Smuzhiyun            auth_cmd = AuthCommand(hmac=auth_value)
653*4882a593Smuzhiyun
654*4882a593Smuzhiyun        fmt = '>HII I I%us' % (len(auth_cmd))
655*4882a593Smuzhiyun        cmd = struct.pack(
656*4882a593Smuzhiyun            fmt,
657*4882a593Smuzhiyun            TPM2_ST_SESSIONS,
658*4882a593Smuzhiyun            struct.calcsize(fmt),
659*4882a593Smuzhiyun            TPM2_CC_UNSEAL,
660*4882a593Smuzhiyun            data_handle,
661*4882a593Smuzhiyun            len(auth_cmd),
662*4882a593Smuzhiyun            bytes(auth_cmd))
663*4882a593Smuzhiyun
664*4882a593Smuzhiyun        try:
665*4882a593Smuzhiyun            rsp = self.send_cmd(cmd)
666*4882a593Smuzhiyun        finally:
667*4882a593Smuzhiyun            self.flush_context(data_handle)
668*4882a593Smuzhiyun
669*4882a593Smuzhiyun        data_len = struct.unpack('>I', rsp[10:14])[0] - 2
670*4882a593Smuzhiyun
671*4882a593Smuzhiyun        return rsp[16:16 + data_len]
672*4882a593Smuzhiyun
673*4882a593Smuzhiyun    def reset_da_lock(self):
674*4882a593Smuzhiyun        auth_cmd = AuthCommand()
675*4882a593Smuzhiyun
676*4882a593Smuzhiyun        fmt = '>HII I I%us' % (len(auth_cmd))
677*4882a593Smuzhiyun        cmd = struct.pack(
678*4882a593Smuzhiyun            fmt,
679*4882a593Smuzhiyun            TPM2_ST_SESSIONS,
680*4882a593Smuzhiyun            struct.calcsize(fmt),
681*4882a593Smuzhiyun            TPM2_CC_DICTIONARY_ATTACK_LOCK_RESET,
682*4882a593Smuzhiyun            TPM2_RH_LOCKOUT,
683*4882a593Smuzhiyun            len(auth_cmd),
684*4882a593Smuzhiyun            bytes(auth_cmd))
685*4882a593Smuzhiyun
686*4882a593Smuzhiyun        self.send_cmd(cmd)
687*4882a593Smuzhiyun
688*4882a593Smuzhiyun    def __get_cap_cnt(self, cap, pt, cnt):
689*4882a593Smuzhiyun        handles = []
690*4882a593Smuzhiyun        fmt = '>HII III'
691*4882a593Smuzhiyun
692*4882a593Smuzhiyun        cmd = struct.pack(fmt,
693*4882a593Smuzhiyun                          TPM2_ST_NO_SESSIONS,
694*4882a593Smuzhiyun                          struct.calcsize(fmt),
695*4882a593Smuzhiyun                          TPM2_CC_GET_CAPABILITY,
696*4882a593Smuzhiyun                          cap, pt, cnt)
697*4882a593Smuzhiyun
698*4882a593Smuzhiyun        rsp = self.send_cmd(cmd)[10:]
699*4882a593Smuzhiyun        more_data, cap, cnt = struct.unpack('>BII', rsp[:9])
700*4882a593Smuzhiyun        rsp = rsp[9:]
701*4882a593Smuzhiyun
702*4882a593Smuzhiyun        for i in range(0, cnt):
703*4882a593Smuzhiyun            handle = struct.unpack('>I', rsp[:4])[0]
704*4882a593Smuzhiyun            handles.append(handle)
705*4882a593Smuzhiyun            rsp = rsp[4:]
706*4882a593Smuzhiyun
707*4882a593Smuzhiyun        return handles, more_data
708*4882a593Smuzhiyun
709*4882a593Smuzhiyun    def get_cap(self, cap, pt):
710*4882a593Smuzhiyun        handles = []
711*4882a593Smuzhiyun
712*4882a593Smuzhiyun        more_data = True
713*4882a593Smuzhiyun        while more_data:
714*4882a593Smuzhiyun            next_handles, more_data = self.__get_cap_cnt(cap, pt, 1)
715*4882a593Smuzhiyun            handles += next_handles
716*4882a593Smuzhiyun            pt += 1
717*4882a593Smuzhiyun
718*4882a593Smuzhiyun        return handles
719