tpm2.py 21 KB

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