diff options
author | James Bottomley <James.Bottomley@HansenPartnership.com> | 2017-01-15 10:16:22 -0800 |
---|---|---|
committer | James Bottomley <James.Bottomley@HansenPartnership.com> | 2017-01-27 09:01:33 -0800 |
commit | db6586061dd0c8ffc8433c11c16d18752b722dc8 (patch) | |
tree | 15792ebf93d72611f450ec2d0f96389120adee35 | |
parent | f0d5c22b9a3c845dbccd3d6ca6116593c02f84e4 (diff) | |
download | tpm2-scripts-db6586061dd0c8ffc8433c11c16d18752b722dc8.tar.gz |
add session smoke tests using tss2
-rw-r--r-- | tpm2.py | 17 | ||||
-rwxr-xr-x | tpm2_sessions_smoke.py | 72 | ||||
-rw-r--r-- | tss2.py | 233 |
3 files changed, 322 insertions, 0 deletions
@@ -16,6 +16,7 @@ TPM2_CC_CREATE = 0x0153 TPM2_CC_LOAD = 0x0157 TPM2_CC_UNSEAL = 0x015E TPM2_CC_FLUSH_CONTEXT = 0x0165 +TPM2_CC_READ_PUBLIC = 0x0173 TPM2_CC_START_AUTH_SESSION = 0x0176 TPM2_CC_GET_CAPABILITY = 0x017A TPM2_CC_PCR_READ = 0x017E @@ -24,13 +25,27 @@ TPM2_CC_PCR_EXTEND = 0x0182 TPM2_CC_POLICY_PASSWORD = 0x018C TPM2_CC_POLICY_GET_DIGEST = 0x0189 +TPM2_SE_HMAC = 0x00 TPM2_SE_POLICY = 0x01 TPM2_SE_TRIAL = 0x03 +TPMA_OBJECT_FIXEDTPM = 0x00000002 +TPMA_OBJECT_STCLEAR = 0x00000004 +TPMA_OBJECT_FIXEDPARENT = 0x00000010 +TPMA_OBJECT_SENSITIVEDATAORIGIN = 0x00000020 +TPMA_OBJECT_USERWITHAUTH = 0x00000040 +TPMA_OBJECT_ADMINWITHPOLICY = 0x00000080 +TPMA_OBJECT_NODA = 0x00000400 +TPMA_OBJECT_ENCRYPTEDDUPLICATION = 0x00000800 +TPMA_OBJECT_RESTRICTED = 0x00010000 +TPMA_OBJECT_DECRYPT = 0x00020000 +TPMA_OBJECT_SIGN = 0x00040000 + TPM2_ALG_RSA = 0x0001 TPM2_ALG_SHA1 = 0x0004 TPM2_ALG_AES = 0x0006 TPM2_ALG_KEYEDHASH = 0x0008 +TPM2_ALG_XOR = 0x000A TPM2_ALG_SHA256 = 0x000B TPM2_ALG_NULL = 0x0010 TPM2_ALG_CBC = 0x0042 @@ -42,6 +57,7 @@ TPM2_RH_LOCKOUT = 0x4000000A TPM2_RS_PW = 0x40000009 TPM2_RC_SIZE = 0x000001D5 +TPM2_RC_SESSION_MEMORY = 0x00000903 TPM2_RC_AUTH_FAIL = 0x0000098E TPM2_RC_POLICY_FAIL = 0x0000099D @@ -50,6 +66,7 @@ TPM2_CAP_COMMANDS = 0x00000002 TPM2_CAP_TPM_PROPERTIES = 0x00000006 TPM2_PT_FIXED = 0x100 +TPM2_PT_ACTIVE_SESSIONS_MAX = TPM2_PT_FIXED + 17 TPM2_PT_TOTAL_COMMANDS = TPM2_PT_FIXED + 41 HR_SHIFT = 24 diff --git a/tpm2_sessions_smoke.py b/tpm2_sessions_smoke.py new file mode 100755 index 0000000..f9ce342 --- /dev/null +++ b/tpm2_sessions_smoke.py @@ -0,0 +1,72 @@ +from argparse import ArgumentParser +from argparse import FileType +import os +import sys +import tpm2 +from tpm2 import ProtocolError +import unittest +import logging +import tss2 + +pwd1 = "wibble" + + +class SessionTest(unittest.TestCase): + def setUp(self): + self.c = tss2.Client() + + def tearDown(self): + self.c.close() + + # open handles until failure. Return the ones we got + def open_handles(self): + ha = [] + try: + for i in range(0, 10): + h = self.c.start_session(tpm2.TPM2_SE_HMAC) + print "Handle is %08x" % h + ha.append(h) + except tss2.tpm_error, e: + if (e.rc != tpm2.TPM2_RC_SESSION_MEMORY): + raise e + return ha + + def test_handle_clearing(self): + i = self.open_handles() + print "Ran out of handles at %d" %len(i) + self.c.close() + self.c = tss2.Client() + # closing and reopening a space session should clear out our handles + j = self.open_handles() + print "Ran out of handles at %d" %len(j) + self.assertNotEqual(len(i), 0) + self.assertEqual(len(i), len(j)) + + def test_flush(self): + i = self.open_handles() + print "opened %d handles" % len(i) + self.c.flush_context(i[0]) + self.c.flush_context(i[1]) + i = self.open_handles() + self.assertEqual(len(i), 2); + + def test_session_consumption(self): + self.c.read_public(self.c.SRK) + hmac = self.c.start_session(tpm2.TPM2_SE_HMAC) + enc = self.c.start_session(tpm2.TPM2_SE_HMAC, self.c.SRK) + i = self.open_handles() + # create rsa key continuing both hmac and encryption sessions + k = self.c.create_rsa(self.c.SRK, pwd1, hmac, 1, enc, 1) + # should be no handles left + i = self.open_handles() + self.assertEqual(len(i),0) + k = self.c.create_rsa(self.c.SRK, pwd1, hmac, 0, enc, 0) + # now should be two handles left + i = self.open_handles() + self.assertEqual(len(i),2) + k = self.c.load(self.c.SRK, k.outPrivate, k.outPublic, None) + + + +if __name__ == '__main__': + unittest.main() @@ -0,0 +1,233 @@ +from ctypes import cdll +import ctypes +import os +import tpm2 +lib = cdll.LoadLibrary('libtss.so.0') + +class TPM2B_NONCE(ctypes.Structure): + _fields_ = [("s", ctypes.c_uint16), + ("b", ctypes.c_uint8 * 128)] + +class TPM2B_ENCRYPTED_SECRET(ctypes.Structure): + _fields_ = [("s", ctypes.c_uint16), + ("b", ctypes.c_uint8 * 256)] + +class TPMT_SYM_DEF(ctypes.Structure): + _fields_ = [("algorithm", ctypes.c_uint16), + ("keyBits", ctypes.c_uint16), + ("mode", ctypes.c_uint16)] + +class TPMT_RSA_SCHEME(ctypes.Structure): + _fields_ = [("scheme", ctypes.c_uint16), + ("details", ctypes.c_uint8 * 4)] + +class TPMS_RSA_PARMS(ctypes.Structure): + _fields_ = [("symmetric", TPMT_SYM_DEF), + ("scheme", TPMT_RSA_SCHEME), + ("keyBits", ctypes.c_uint16), + ("exponent", ctypes.c_uint32)] + +class TPMU_PUBLIC_PARMS(ctypes.Union): + _fields_ = [("buffer", ctypes.c_uint8 *20), + ("rsaDetail", TPMS_RSA_PARMS)] + + +class TPMT_PUBLIC(ctypes.Structure): + _fields_ = [("Type", ctypes.c_uint16), + ("nameAlg", ctypes.c_uint16), + ("objectAttributes", ctypes.c_uint32), + ("authPolicy", TPM2B_NONCE), + ("parameters", TPMU_PUBLIC_PARMS), + ("unique", ctypes.c_uint8 * 258)] + +class TPM2B_PUBLIC(ctypes.Structure): + _fields_ = [("size", ctypes.c_uint16), + ("publicArea", TPMT_PUBLIC)] + +class TPMT_TK_CREATION(ctypes.Structure): + _fields_ = [("tag", ctypes.c_uint16), + ("hierarchy", ctypes.c_uint32), + ("digest", TPM2B_NONCE)] + +class TPM2B_SENSITIVE_DATA(ctypes.Structure): + _fields_ = [("size", ctypes.c_uint16), + ("buffer", ctypes.c_uint8 * 130)] + +class TPMS_SENSITIVE_CREATE(ctypes.Structure): + _fields_ = [("userAuth", TPM2B_NONCE), + ("data", TPM2B_SENSITIVE_DATA)] + +class TPM2B_SENSITIVE_CREATE(ctypes.Structure): + _fields_ = [("size", ctypes.c_uint16), + ("sensitive", TPMS_SENSITIVE_CREATE)] + +class TPM2B_PRIVATE(ctypes.Structure): + _fields_ = [("size", ctypes.c_uint16), + ("buffer", ctypes.c_uint8 * 1166)] + + +class StartAuthSession_In(ctypes.Structure): + _fields_ = [("tpmKey", ctypes.c_uint32), + ("bind", ctypes.c_uint32), + ("nonce", TPM2B_NONCE), + ("encryptedSalt", TPM2B_ENCRYPTED_SECRET), + ("sessionType", ctypes.c_uint8), + ("symmetric", TPMT_SYM_DEF), + ("authHash", ctypes.c_uint16)] + +class StartAuthSession_Out(ctypes.Structure): + _fields_ = [("sessionHandle", ctypes.c_uint32), + ("nonceTPM", TPM2B_NONCE)] + +class StartAuthSession_Extra(ctypes.Structure): + _fields_ = [("bindPassword", ctypes.c_char_p), + ("salt", TPM2B_NONCE)] + +class ReadPublic_In(ctypes.Structure): + _fields_ = [("objectHandle", ctypes.c_uint32)] + +class ReadPublic_Out(ctypes.Structure): + _fields_ = [("outPublic", TPM2B_PUBLIC), + ("name", TPM2B_NONCE), + ("qualifiedName", TPM2B_NONCE)] + +class Create_In(ctypes.Structure): + _fields_ = [("parentHandle", ctypes.c_uint32), + ("inSensitive", TPM2B_SENSITIVE_CREATE), + ("inPublic", TPM2B_PUBLIC), + ("outsideInfo", TPM2B_NONCE), + ("creationPCR", ctypes.c_uint8 * 24)] + +class Create_Out(ctypes.Structure): + _fields_ = [("outPrivate", TPM2B_PRIVATE), + ("outPublic", TPM2B_PUBLIC), + ("creationData", ctypes.c_uint8 * 564), + ("creationHash", TPM2B_NONCE), + ("creationTicket", TPMT_TK_CREATION)] + +class FlushContext_In(ctypes.Structure): + _fields_ = [("flushHandle", ctypes.c_uint32)] + +class Load_In(ctypes.Structure): + _fields_ = [("parentHandle", ctypes.c_uint32), + ("inPrivate", TPM2B_PRIVATE), + ("inPublic", TPM2B_PUBLIC)] + +class Load_Out(ctypes.Structure): + _fields_ = [("objectHandle", ctypes.c_uint32), + ("name", TPM2B_NONCE)] + +class tpm_error(Exception): + + def __init__(self, rc): + self.rc = rc + + def __str__(self): + msg = ctypes.c_char_p() + submsg = ctypes.c_char_p() + num = ctypes.c_char_p() + lib.TSS_ResponseCode_toString(ctypes.byref(msg), + ctypes.byref(submsg), + ctypes.byref(num), self.rc); + return "%s%s%s" % (msg.value, submsg.value, num.value) + +class Client: + + def __init__(self): + self.ctx = ctypes.c_void_p(None) + os.environ["TPM_DEVICE"] = '/dev/tpms1' + rc = lib.TSS_Create(ctypes.byref(self.ctx)) + # verify SRK is at 81000001 + self.SRK = 0x81000001 + # we need the public area in the context for salted parameter encryption + self.read_public(self.SRK) + + print self.ctx + + def close(self): + lib.TSS_Delete(self.ctx) + print "closed" + print self.ctx + + def TSS_Execute(self, out, inp, extra, ordinal, *sessions): + rc = lib.TSS_Execute(self.ctx, out, inp, + extra, ordinal, *sessions) + if (rc != 0): + raise tpm_error(rc) + + def start_session(self, Type, salt_key = tpm2.TPM2_RH_NULL): + inp = StartAuthSession_In() + out = StartAuthSession_Out() + extra = StartAuthSession_Extra() + + inp.sessionType = Type + inp.authHash = tpm2.TPM2_ALG_SHA256 + inp.tpmKey = salt_key + inp.symmetric.algorithm = tpm2.TPM2_ALG_AES + inp.symmetric.keyBits = 128 + inp.symmetric.mode = tpm2.TPM2_ALG_CFB + + self.TSS_Execute(ctypes.byref(out), ctypes.byref(inp), + ctypes.byref(extra), + tpm2.TPM2_CC_START_AUTH_SESSION, + tpm2.TPM2_RH_NULL, None, 0) + return out.sessionHandle + + def read_public(self, handle): + inp = ReadPublic_In() + out = ReadPublic_Out() + inp.objectHandle = handle + + self.TSS_Execute(ctypes.byref(out), ctypes.byref(inp), + None, tpm2.TPM2_CC_READ_PUBLIC, + tpm2.TPM2_RH_NULL, None, 0) + return out + + def flush_context(self, handle): + inp = FlushContext_In() + inp.flushHandle = handle + + self.TSS_Execute(None, ctypes.byref(inp), None, + tpm2.TPM2_CC_FLUSH_CONTEXT, + tpm2.TPM2_RH_NULL, None, 0) + + def create_rsa(self, parent, auth, hmacSession = tpm2.TPM2_RS_PW, hmacCont = 0, encSession = tpm2.TPM2_RH_NULL, encCont = 0): + inp = Create_In() + out = Create_Out() + + inp.parentHandle = parent + if (auth != None): + inp.inSensitive.sensitive.userAuth.b = ctypes.c_ubyte_Array_128(auth) + inp.inSensitive.sensitive.userAuth.s = strlen(auth) + inp.inPublic.publicArea.Type = tpm2.TPM2_ALG_RSA + inp.inPublic.publicArea.nameAlg = tpm2.TPM2_ALG_SHA256 + inp.inPublic.publicArea.objectAttributes = tpm2.TPMA_OBJECT_NODA | tpm2.TPMA_OBJECT_DECRYPT | tpm2.TPMA_OBJECT_USERWITHAUTH | tpm2.TPMA_OBJECT_SENSITIVEDATAORIGIN + inp.inPublic.publicArea.parameters.rsaDetail.symmetric.algorithm = tpm2.TPM2_ALG_NULL + inp.inPublic.publicArea.parameters.rsaDetail.scheme.scheme = tpm2.TPM2_ALG_NULL + inp.inPublic.publicArea.parameters.rsaDetail.keyBits = 2048 + inp.inPublic.publicArea.parameters.rsaDetail.exponent = 0 + if (hmacSession == 0): + hmacSession = tpm2.TPM2_RS_PW + + self.TSS_Execute(ctypes.byref(out), ctypes.byref(inp), None, + tpm2.TPM2_CC_CREATE, + hmacSession, None, hmacCont, + # 0x20 is TPMA_OBJECT_DECRYPT + encSession, None, encCont | 0x20, + tpm2.TPM2_RH_NULL, None, 0); + return out + + def load(self, parent, private, public, auth, hmacSession = tpm2.TPM2_RS_PW, hmacCont = 0): + inp = Load_In() + out = Load_Out() + + inp.parentHandle = parent + inp.inPrivate = private + inp.inPublic = public + + self.TSS_Execute(ctypes.byref(out), ctypes.byref(inp), None, + tpm2.TPM2_CC_LOAD, + hmacSession, auth, hmacCont, + tpm2.TPM2_RH_NULL, None, 0); + + return out.objectHandle |