blob: 10a32894c4fa86fb2f50262b8e75dbea745b47dc [file] [log] [blame]
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 TPM2B_CONTEXT_DATA(ctypes.Structure):
_fields_ = [("size", ctypes.c_uint16),
("buffer", ctypes.c_uint8 * 2048)]
class TPMS_CONTEXT(ctypes.Structure):
_fields_ = [("sequence", ctypes.c_uint64),
("savedHandle", ctypes.c_uint32),
("hierarchy", ctypes.c_uint32),
("contextBlob", TPM2B_CONTEXT_DATA)]
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 ObjectChangeAuth_In(ctypes.Structure):
_fields_ = [("objectHandle", ctypes.c_uint32),
("parentHandle", ctypes.c_uint32),
("newAuth", TPM2B_NONCE)]
class ObjectChangeAuth_Out(ctypes.Structure):
_fields_ = [("outPrivate", TPM2B_PRIVATE)]
class ContextSave_In(ctypes.Structure):
_fields_ = [("saveHandle", ctypes.c_uint32)]
class tpm_error(Exception):
def __init__(self, rc):
self.raw_rc = rc
if ((rc & 0x80) == 0x80): # RC_FMT1
rc = rc & 0xbf
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.raw_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)
def close(self):
lib.TSS_Delete(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):
lenauth = len(auth)
inp.inSensitive.sensitive.userAuth.b[0:lenauth] = bytearray(auth)
inp.inSensitive.sensitive.userAuth.s = lenauth
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
def change_auth(self, parent, handle, oldauth, newauth, hmacSession = tpm2.TPM2_RS_PW, hmacCont = 0, encSession = tpm2.TPM2_RH_NULL, encCont = 0):
inp = ObjectChangeAuth_In()
out = ObjectChangeAuth_Out()
inp.parentHandle = parent
inp.objectHandle = handle
inp.newAuth.b[0:len(newauth)] = bytearray(newauth)
inp.newAuth.s = len(newauth)
self.TSS_Execute(ctypes.byref(out), ctypes.byref(inp), None,
tpm2.TPM2_CC_OBJECT_CHANGE_AUTH,
hmacSession, oldauth, hmacCont,
encSession, None, encCont | 0x20,
tpm2.TPM2_RH_NULL, None, 0)
return out.outPrivate
def context_save(self, handle):
inp = ContextSave_In()
out = TPMS_CONTEXT()
inp.saveHandle = handle
self.TSS_Execute(ctypes.byref(out), ctypes.byref(inp), None,
tpm2.TPM2_CC_CONTEXT_SAVE,
tpm2.TPM2_RH_NULL, None, 0)
return out
def context_load(self, inp):
out = ContextSave_In()
self.TSS_Execute(ctypes.byref(out), ctypes.byref(inp), None,
tpm2.TPM2_CC_CONTEXT_LOAD,
tpm2.TPM2_RH_NULL, None, 0)
return out.saveHandle