| 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 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 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): |
| lenauth = len(auth) |
| print "AUTh len is %d" %lenauth |
| 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 |