aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJames Bottomley <James.Bottomley@HansenPartnership.com>2017-01-15 10:16:22 -0800
committerJames Bottomley <James.Bottomley@HansenPartnership.com>2017-01-27 09:01:33 -0800
commitdb6586061dd0c8ffc8433c11c16d18752b722dc8 (patch)
tree15792ebf93d72611f450ec2d0f96389120adee35
parentf0d5c22b9a3c845dbccd3d6ca6116593c02f84e4 (diff)
downloadtpm2-scripts-db6586061dd0c8ffc8433c11c16d18752b722dc8.tar.gz
add session smoke tests using tss2
-rw-r--r--tpm2.py17
-rwxr-xr-xtpm2_sessions_smoke.py72
-rw-r--r--tss2.py233
3 files changed, 322 insertions, 0 deletions
diff --git a/tpm2.py b/tpm2.py
index 58a6a78..d32a86e 100644
--- a/tpm2.py
+++ b/tpm2.py
@@ -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()
diff --git a/tss2.py b/tss2.py
new file mode 100644
index 0000000..2ef0568
--- /dev/null
+++ b/tss2.py
@@ -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