diff -Nru tboot-1.9.4/CHANGELOG tboot-1.9.5/CHANGELOG --- tboot-1.9.4/CHANGELOG 2016-08-06 12:51:16.000000000 +0000 +++ tboot-1.9.5/CHANGELOG 2016-12-17 03:19:38.000000000 +0000 @@ -1,3 +1,15 @@ +20161216: v1.9.5 + Add 2nd generation of LCP creation tool source codes for TPM 2.0 platforms. + Add user guide for 2nd generation LCP creation tool + Provide workaround for Intel PTT(Platform Trust Technology) & Linux PTT driver. + Add new fields in Linux kernel header struct to accommodate Linux kernel new capabilities. + Fix a pointer dereference regression in the tboot native Linux loader which manifests itself as a system reset. + Fix the issue of overwriting tboot when the loaded elf kernel is located below tboot. + Add support to release TPM localities when tboot exits to linux kernel. + Fix the evtlog dump function for tpm2 case. + Initiaize kernel header comdline buffer before copying kernel cmdline arguments to the buffer to avoid random + data at end of the original cmdline contents. + Move tpm_detect() to an earlier stage so as to get tpm interface initialized before checking TXT platform capabilities. 20160518: v1.9.4 Added TPM 2.0 CRB support Increased BSP and AP stacks to avoid stack overflow diff -Nru tboot-1.9.4/debian/changelog tboot-1.9.5/debian/changelog --- tboot-1.9.4/debian/changelog 2016-09-08 19:11:23.000000000 +0000 +++ tboot-1.9.5/debian/changelog 2017-02-16 15:19:14.000000000 +0000 @@ -1,3 +1,11 @@ +tboot (1.9.5-0ubuntu1) zesty; urgency=medium + + * Update to 1.9.5 (LP:#1645532) + - Adds support for 4.8 and newer kernels + - Fixes TPM2 support added in 1.9.4 + + -- Robert Hooker Thu, 16 Feb 2017 09:50:36 -0500 + tboot (1.9.4-0ubuntu1) yakkety; urgency=medium * Update to 1.9.4 diff -Nru tboot-1.9.4/debian/docs tboot-1.9.5/debian/docs --- tboot-1.9.4/debian/docs 2014-02-07 14:14:05.000000000 +0000 +++ tboot-1.9.5/debian/docs 2017-02-16 14:51:44.000000000 +0000 @@ -3,3 +3,4 @@ docs/* lcptools/lcptools2.txt lcptools/Linux_LCP_Tools_User_Manual.pdf +lcp-gen2/UserGuide.txt diff -Nru tboot-1.9.4/.hgtags tboot-1.9.5/.hgtags --- tboot-1.9.4/.hgtags 2016-08-06 12:51:16.000000000 +0000 +++ tboot-1.9.5/.hgtags 2016-12-17 03:19:38.000000000 +0000 @@ -14,3 +14,4 @@ fa1a2d6f4812f2bec1272d5b037d92c0fe5a9228 v1.8.3 6a1500686f57d92ff6de0391624587ee805e7497 v1.8.3 9d8ee7ff40107fde7512b0a9196c568152ce1c72 v1.9.4 +698548a9b9fe6201361d19099100f8eb59fad4f6 v1.9.5 diff -Nru tboot-1.9.4/lcp-gen2/asn1spec.py tboot-1.9.5/lcp-gen2/asn1spec.py --- tboot-1.9.4/lcp-gen2/asn1spec.py 1970-01-01 00:00:00.000000000 +0000 +++ tboot-1.9.5/lcp-gen2/asn1spec.py 2016-12-17 03:19:38.000000000 +0000 @@ -0,0 +1,128 @@ + +from pyasn1.type import univ, namedtype, tag +from pyasn1.codec.der import decoder as der_decoder + + +#RFC2313 +#RSAPrivateKey ::= SEQUENCE { +# version Version, +# modulus INTEGER, -- n +# publicExponent INTEGER, -- e +# privateExponent INTEGER, -- d +# prime1 INTEGER, -- p +# prime2 INTEGER, -- q +# exponent1 INTEGER, -- d mod (p-1) +# exponent2 INTEGER, -- d mod (q-1) +# coefficient INTEGER -- (inverse of q) mod p +#} +class RSAPrivateKey(univ.Sequence): + componentType = namedtype.NamedTypes( + namedtype.NamedType('Version', univ.Integer()), + namedtype.NamedType('modulus', univ.Integer()), + namedtype.NamedType('publicExponent', univ.Integer()), + namedtype.NamedType('privateExponent', univ.Integer()), + namedtype.NamedType('prime1', univ.Integer()), + namedtype.NamedType('prime2', univ.Integer()), + namedtype.NamedType('exponent1', univ.Integer()), + namedtype.NamedType('exponent2', univ.Integer()), + namedtype.NamedType('coefficient', univ.Integer()) + ) + + +#RFC3447 +#RSAPublicKey ::= SEQUENCE { +# modulus INTEGER, -- n +# publicExponent INTEGER -- e +#} +class RSAPublicKey(univ.Sequence): + componentType = namedtype.NamedTypes( + namedtype.NamedType('modulus', univ.Integer()), + namedtype.NamedType('publicExponent', univ.Integer()) + ) + + +#RFC 5480 +#AlgorithmIdentifier ::= SEQUENCE { +# algorithm OBJECT IDENTIFIER, +# parameters ANY DEFINED BY algorithm OPTIONAL +#} +class AlgorithmIdentifier(univ.Sequence): + componentType = namedtype.NamedTypes( + namedtype.NamedType('algorithm', univ.ObjectIdentifier()), + namedtype.OptionalNamedType('parameters', univ.Any()) + ) + + +#RFC 5480 +#SubjectPublicKeyInfo ::= SEQUENCE { +# algorithm AlgorithmIdentifier, +# subjectPublicKey BIT STRING +#} +class SubjectPublicKeyInfo(univ.Sequence): + componentType = namedtype.NamedTypes( + namedtype.NamedType('algorithm', AlgorithmIdentifier()), + namedtype.NamedType('subjectPublicKey', univ.BitString()) + ) + + +#RFC 5912 +#ECParameters ::= CHOICE { +# namedCurve CURVE.&id({NamedCurve}) +# -- implicitCurve NULL +# -- implicitCurve MUST NOT be used in PKIX +# -- specifiedCurve SpecifiedCurve +# -- specifiedCurve MUST NOT be used in PKIX +# -- Details for specifiedCurve can be found in [X9.62] +# -- Any future additions to this CHOICE should be coordinated +# -- with ANSI X.9. +# } +# +class ECParameters(univ.Choice): + componentType = namedtype.NamedTypes( + namedtype.NamedType('namedCurve', univ.ObjectIdentifier()), + namedtype.NamedType('implicitCurve', univ.Null()), + namedtype.NamedType('specifiedCurve', univ.ObjectIdentifier()) + ) + + +#RFC 5915 +#ECPrivateKey ::= SEQUENCE { +# version INTEGER { ecPrivkeyVer1(1) } (ecPrivkeyVer1), +# privateKey OCTET STRING, +# parameters [0] EXPLICIT ECParameters {{ NamedCurve }} OPTIONAL, +# publicKey [1] EXPLICIT BIT STRING OPTIONAL +#} +# +# PKIX compliant +class ECPrivateKey(univ.Sequence): + componentType = namedtype.NamedTypes( + namedtype.NamedType('version', univ.Integer()), + namedtype.NamedType('privateKey', univ.OctetString()), + #namedtype.NamedType('ECParameters', ECParameters().subtype( + # explicitTag=tag.Tag(tag.tagClassContext, tag.tagFormatSimple, 0))), + namedtype.OptionalNamedType('ECParameters', univ.ObjectIdentifier().subtype( + explicitTag=tag.Tag(tag.tagClassContext, tag.tagFormatSimple, 0))), + namedtype.OptionalNamedType('publicKey', univ.BitString().subtype( + explicitTag=tag.Tag(tag.tagClassContext, tag.tagFormatSimple, 1))) + ) + + +#DigestInfo ::= SEQUENCE { +# digestAlgorithm AlgorithmIdentifier, +# digest OCTET STRING +#} + + + +#ECDSASignature ::= SEQUENCE { +# r INTEGER, +# s INTEGER +#} +# +class ECDSASignature(univ.Sequence): + componentType = namedtype.NamedTypes( + namedtype.NamedType('r', univ.Integer()), + namedtype.NamedType('s', univ.Integer()) + ) + + diff -Nru tboot-1.9.4/lcp-gen2/build.py tboot-1.9.5/lcp-gen2/build.py --- tboot-1.9.4/lcp-gen2/build.py 1970-01-01 00:00:00.000000000 +0000 +++ tboot-1.9.5/lcp-gen2/build.py 2016-12-17 03:19:38.000000000 +0000 @@ -0,0 +1,813 @@ +#!/usr/bin/python +# Copyright (c) 2013, Intel Corporation. All rights reserved. + +# TXT Policy Generator Tool +# support for Building LCP_POLICY and LCP_POLICY_DATA Files + +# using print() built in function, disable print statement +from __future__ import print_function + +from struct import * +#import hashlib +import binascii + +from defines import DEFINES +from pdef import PDEF + +from util import UTILS +utilities = UTILS() + +from LcpPolicy import * +LcpPolicy = LCP_POLICY2() +LcpPolicyData = LCP_POLICY_DATA2() + +ListMeasurements = ListMeasurements() # DIGEST ListMeasurements[PDEF.NumLists] + +try: + import os + import sys +except ImportError: + raise ImportError, "import OS failed" + +import array +import M2Crypto + +from asn1spec import * + + +class Build( object ): + """build LCP_POLICY2 and LCP_POLICY_DATA2 Files""" + + filename = "MyPlatformXXXXXXXXXXXXX" + dirname = os.getcwd() + + def __init__( self ): + """Build - constructor""" + pass + + # Build the .pol file + # returns True if all went ok + # returns False on error + def buildRawLcpPolicyFile(self, pdef, statusBar): + """buildRawLcpPolicyFile - build the raw format LCP_POLICY2 file (.pol)""" + + self.StatusBar = statusBar + + # if policy version is 3.0, clear bit positions for ignore PS elements + policyversion = str(pdef.PolVersionMajor)+'.'+str(pdef.PolVersionMinor) + if policyversion == '3.0': + mask = DEFINES.PolicyControlIgnorePsMleBitMask | DEFINES.PolicyControlIgnorePsPconfBitMask | DEFINES.PolicyControlIgnorePsStmBitMask + pdef.PolicyControl &= ~mask + + # pack the LCP_POLICY2 struct [without the hash] into a binary string ready for the LCP_POLICY2 file + packedLcpPolicy = pack(LcpPolicy.LcpPolicyFormatStringNoHash, + pdef.PolVersionMinor, pdef.PolVersionMajor, + pdef.HashAlg, pdef.PolicyType, pdef.SinitMinVersion, + pdef.DataRevocationCounters[0], pdef.DataRevocationCounters[1], + pdef.DataRevocationCounters[2], pdef.DataRevocationCounters[3], + pdef.DataRevocationCounters[4], pdef.DataRevocationCounters[5], + pdef.DataRevocationCounters[6], pdef.DataRevocationCounters[7], + pdef.PolicyControl, + pdef.MaxSinitMinVersion, pdef.MaxBiosMinVersion, + pdef.LcpHashAlgMask, pdef.LcpSignAlgMask, pdef.AuxHashAlgMask, 0) + + # reuse the base name [with .pol extension] and don't prompt for a file name again + basefilename, ext = self.filename.rsplit('.', 1) + #polfilename = utilities.formFileName(basefilename, "pol") + polfilename = ".".join([basefilename, 'pol']) + print("buildRawLcpPolicyFile: creating Text LCP_POLICY file %s" % (polfilename)) # DBGDBG + + # write the raw LCP_POLICY file + # 1st write the struct, then write the hash from pdef.PolicyHash + try: + f = open(os.path.join(self.dirname, polfilename), 'wb') + print(packedLcpPolicy, end='', file=f ) # suppress EOL (0x0a) + + try: + # reverse lookup of the hash algorithm name(key) for the given HashAlg value + hashAlgName = (key for key,val in DEFINES.TPM_ALG_HASH.items() if (val == pdef.HashAlg)).next() + + # If PolicyType==ANY, haven't updated pdef.PolicyHash (since there were no lists to process) + # In that case, write a hash of all 0's + if(pdef.PolicyType == DEFINES.ANY): + # Pack hash value which is 0 for PolicyType of ANY + b = bytes() + pdef.PolicyHash = b.join(pack('B', 0) for i in range(DEFINES.DIGEST_SIZE[hashAlgName])) + else: + # Write packed hash value to .pol file. + print(pdef.PolicyHash, end='', file=f ) + + except StopIteration: + # pdef.HashAlg value is not found in DEFINES.TPM_ALG_HASH list + self.StatusBar.SetStatusText("Aborting build, Hash Algorithm %d is not supported." % (pdef.HashAlg)) + print("buildRawLcpPolicyFile: ANY - aborting - Hash Algorithm %d is not supported." % (pdef.HashAlg)) # DBGDBG + f.close() + return False + + # If PolicyType==ANY, haven't updated pdef.PolicyHash (since there were no lists to process) + # In that case, write a hash of all 0's + #if(pdef.PolicyType == DEFINES.ANY): + # # Pack hash value which is 0 for PolicyType of ANY + # if (hashAlgName != None): + # b = bytes() + # pdef.PolicyHash = b.join(pack('B', 0) for i in range(DEFINES.DIGEST_SIZE[hashAlgName])) + # else: + # self.StatusBar.SetStatusText("Aborting build, Hash Algorithm %d is not supported." % (pdef.HashAlg)) + # print("buildRawLcpPolicyFile: ANY - aborting - Hash Algorithm %d is not supported." % (pdef.HashAlg)) # DBGDBG + # f.close() + # return False + + #if(pdef.HashAlg == DEFINES.TPM_ALG_HASH['SHA1']): + # pdef.PolicyHashSha1 = pack("20B", 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0) + #elif(pdef.HashAlg == DEFINES.TPM_ALG_HASH['SHA256']): + # pdef.PolicyHashSha256 = pack("32B", 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0) + #elif(pdef.HashAlg == DEFINES.TPM_ALG_HASH['SHA384']): + # pdef.PolicyHashSha384 = pack("40B", 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0) + #elif(pdef.HashAlg == DEFINES.TPM_ALG_HASH['SM3']): + # pdef.PolicyHashSm3 = pack("32B", 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0) + #else: + # self.StatusBar.SetStatusText("Aborting build, Hash Algorithm %d is not supported." % (pdef.HashAlg)) + # print("buildRawLcpPolicyFile: ANY - aborting - Hash Algorithm %d is not supported." % (pdef.HashAlg)) # DBGDBG + # f.close() + # return False + + + # Pack hash value which is 0 for PolicyType of ANY + #if (hashAlgName != None): + # # Write packed hash value to .pol file. + # print(pdef.PolicyHash, end='', file=f ) + #else: # don't hit the above else case if policyType=LIST + # self.StatusBar.SetStatusText("Aborting build, Hash Algorithm %d is not supported." % (pdef.HashAlg)) + # print("buildRawLcpPolicyFile: LIST - aborting - Hash Algorithm %d is not supported." % (pdef.HashAlg)) # DBGDBG + # f.close() + # return False + #if(pdef.HashAlg == DEFINES.TPM_ALG_HASH['SHA1']): + # print(pdef.PolicyHashSha1, end='', file=f ) + #elif(pdef.HashAlg == DEFINES.TPM_ALG_HASH['SHA256']): + # print(pdef.PolicyHashSha256, end='', file=f ) + #else: # don't hit the above else case if policyType=LIST + # self.StatusBar.SetStatusText("Aborting build, Hash Algorithm %d is not supported." % (pdef.HashAlg)) + # print("buildRawLcpPolicyFile: LIST - aborting - Hash Algorithm %d is not supported." % (pdef.HashAlg)) # DBGDBG + # f.close() + # return False + + except IOError: + print ("IOError writing raw LCP_POLICY file %s" % (polfilename)) + finally: + f.close() + + print("buildRawLcpPolicyFile: Raw LCP_POLICY file %s built" % (polfilename)) # DBGDBG + + # originally, filename had no extention so strip it off + #self.filename, ext = self.filename.rsplit('.', 1) + return True + + def buildTxtLcpPolicyFile(self, pdef): + """buildTxtLcpPolicyFile - build the text format LCP_POLICY2 file""" + + # reuse the base name [with .txt extention] and don't prompt for a file name again + basefilename, ext = self.filename.rsplit('.', 1) + txtfilename = utilities.formFileName(basefilename, "txt") + #self.filename = utilities.formFileName(self.filename, "txt") + print("buildTxtLcpPolicyFile: creating Text LCP_POLICY2 file %s" % (txtfilename)) # DBGDBG + + try: + f = open(os.path.join(self.dirname, txtfilename), 'w') + + # suppress separator with sep='' + # use 'fmt' % (value) to prepend 0's to value + + print("#Policy Data", file=f) + + version = '%02d%02d' % (pdef.PolVersionMajor, pdef.PolVersionMinor) + print("word=", version, "\t\t# Version", sep='', file=f) + + hashAlg = '%04d' % (pdef.HashAlg) + print("word=", hashAlg, "\t\t# Hash Alg (4=Sha1[20], 11=Sha256[32]", sep='', file=f) + + policyType = '%02d' % (pdef.PolicyType) + print("byte=", policyType, "\t\t\t# PolicyType (0 = LIST, 1 = ANY)", sep='', file=f) + + sinitMinVersion = '%02d' % (pdef.SinitMinVersion) + print("byte=", sinitMinVersion, "\t\t\t# SinitMinVersion", sep='', file=f) + + i = 0 + while(i < pdef.MaxLists): + dataRevCnt = '%04d' % (pdef.DataRevocationCounters[i]) + print("word=", dataRevCnt, "\t\t# DataRevocationCounters[", i, "]", sep='', file=f) + i += 1 + + policyControl = '0x%08x' % (pdef.PolicyControl) + print("dword=", policyControl, "\t# PolicyControl (Bit 1=Allow NPW, 2=PCR17, 3=Force Owner 15=Aux Delete)", sep='', file=f) + + maxSinitMinVersion = '%02d' % (pdef.MaxSinitMinVersion) + print("byte=", maxSinitMinVersion, "\t\t\t# MaxSinitMinVersion", sep='', file=f) + maxBiosMinVersion = '%02d' % (pdef.MaxBiosMinVersion) + print("byte=", maxBiosMinVersion, "\t\t\t# MaxBiosMinVersion", sep='', file=f) + + lcpHashAlgMask = '%04d' % (pdef.LcpHashAlgMask) + print("word=", lcpHashAlgMask, "\t\t# LcpHashAlgMask", sep='', file=f) + lcpSignAlgMask = '%04d' % (pdef.LcpSignAlgMask) + print("dword=", lcpSignAlgMask, "\t\t# LcpSignAlgMask", sep='', file=f) + auxHashAlgMask = '%04d' % (pdef.AuxHashAlgMask) + print("word=", auxHashAlgMask, "\t\t# AuxHashAlgMask", sep='', file=f) + + reserved = '%02d' % (0) + print("byte=", reserved, "\t\t\t# Reserved", sep='', file=f) + + #if(pdef.HashAlg == DEFINES.TPM_ALG_HASH['SHA256']): + # print("byte=", pdef.PolicyHashSha256Hex, " # Hash", sep='', file=f) # need to print the hex hash + #elif(pdef.HashAlg == DEFINES.TPM_ALG_HASH['SHA1']): + # print("byte=", pdef.PolicyHashSha1Hex, " # Hash", sep='', file=f) # need to print the hex hash + print("byte=", binascii.b2a_hex(pdef.PolicyHash), " # Hash", sep='', file=f) # need to print the hex hash + + except IOError: + print ("IOError writing file %s" % (txtfilename)) + finally: + f.close() + + print("buildTxtLcpPolicyFile: Text LCP_POLICY file %s built" % (txtfilename)) # DBGDBG + + # originally, filename had no extention so strip it off + #self.filename, ext = self.filename.rsplit('.', 1) + + # LCP2 does not generate an XML output file - so no buildXmlLcpPolicyFile() + + # If no error, return True, else False + # Build can fail reading hash or pcr files, or if no public or private key file was selected + # + def buildLcpPolicyDataStruct(self, pdef, statusBar): + """buildLcpPolicyDataStruct - create a LCP_POLICY_DATA struct including calculating the PolicyHash""" + + global LcpPolicyData + + self.StatusBar = statusBar + #LcpPolicy = LCP_POLICY2() + LcpPolicyData = LCP_POLICY_DATA2() + # ListMeasurements - object to hold ListMeasurements[pdef.NumLists] + # LcpPolicyData - object for LCP_POLICY_DATA + # build file header: FileSignature,0,0,0,NumLists + LcpPolicyData.NumLists = pdef.NumLists + + print("buildLcpPolicyDataStruct: LCP_POLICY_DATA: FileSignature=%s, NumLists=%d" % + (LcpPolicyData.FileSignature, LcpPolicyData.NumLists)) # DBGDBG + + # For each list + # If 1st list, build the list header: ListVersion, 0, SigAlgorithm, PolicyElementsSize=0 + # build the elements + # if List is unsigned, hash the list + # else list is signed so build the signature block ie: + # Done with this list + # Done with all the lists + policyElementsSize = 0 # cumulative size of all the elements in this list + listCnt = 0 + listCntStr = str(listCnt) + while(listCnt < pdef.NumLists): + thisPdefList = pdef.PolListInfo[listCntStr] + thisPolicyList = LcpPolicyData.PolicyLists[listCntStr] + + # build the LCP_POLICY_LIST.PolicyList[N] header from pdef.PolListInfo[N] + thisPolicyList.VersionMajor = thisPdefList.ListVersionMajor + thisPolicyList.VersionMinor = thisPdefList.ListVersionMinor + thisPolicyList.SigAlgorithm = thisPdefList.SigAlgorithm + thisPolicyList.PolicyElementsSize = 0 # TBD + + # if the list is signed, make sure that a public and private key file was specified + # otherwise abort the build + #if(thisPdefList.SigAlgorithm == DEFINES.LCP_POLSALG_RSA_PKCS_15): # TODO: add external signature support + #if(thisPdefList.SigAlgorithm == DEFINES.TPM_ALG_SIGN['RSASSA']): + if thisPdefList.SigAlgorithm == DEFINES.TPM_ALG_SIGN['NULL']: + # Not Signing.. + pass + elif thisPdefList.SigAlgorithm in DEFINES.TPM_ALG_SIGN.values(): + if((thisPdefList.PubKeyFile == "") or (thisPdefList.PvtKeyFile == "") and not thisPdefList.PvtKeyFileIsSignature): + self.StatusBar.SetStatusText("Build failed: does not have both a public and private key file selected") + print("buildLcpPolicyDataStruct failed - see status bar") # DBGDBG + return False + else: + # What about invalid signature algorithms. + print("ERROR: undefined signature algorithm") + pass + + #IncludeElement = utilities.getIncludeElement(thisPdefList) + #i=0 + #flag = False + #while(i < len(IncludeElement)): + # if(IncludeElement[i] == True): + # flag = True + # i += 1 + + # if there are elements to build, then build them and update PolicyElementsSize + #if(flag == True): + if len(thisPdefList.ElementDefData): + thisPolicyList.PolicyElementsSize = self.buildListElements(pdef, thisPdefList, thisPolicyList, listCnt) + # check for errors building the elements, i.e. reading the hash or pcr files + if(thisPolicyList.PolicyElementsSize == 0): + print("buildLcpPolicyDataStruct failed: PolicyElementsSize=0") # DBGDBG + return False + + if not self.hashListOrBuildSignatureBlock(pdef, thisPdefList, thisPolicyList, listCnt): + return False + print("buildLcpPolicyDataStruct: LCP_POLICY_LIST: Version=%x.%x, SigAlgorithm=%d, PolicyElementsSize=%d" % + (thisPolicyList.VersionMajor, thisPolicyList.VersionMinor, + thisPolicyList.SigAlgorithm, thisPolicyList.PolicyElementsSize)) # DBGDBG + + thisPdefList.ListModified = False + listCnt += 1 + listCntStr = str(listCnt) + + try: + # reverse lookup of the hash algorithm name(key) for the given HashAlg value + hashAlgName = (key for key,val in DEFINES.TPM_ALG_HASH.items() if (val == pdef.HashAlg)).next() + except StopIteration: + print("Aborting build, Hash Algorithm %d is not supported" % (pdef.HashAlg)) + return False + + # Calculate list measurements - hash ListMeasurements[] using pdef.HashAlg + + hash = M2Crypto.EVP.MessageDigest(hashAlgName.lower()) + + listCnt = 0 + while(listCnt < pdef.NumLists): + #if(pdef.HashAlg == DEFINES.TPM_ALG_HASH['SHA1']): + # thisHash = ListMeasurements.hashes[str(listCnt)] + #elif(pdef.HashAlg == DEFINES.TPM_ALG_HASH['SHA256']): + # thisHash = ListMeasurements.hashes32[str(listCnt)] + thisHash = ListMeasurements.hashes[str(listCnt)] + + hash.update(bytes(thisHash)) + #print("buildLcpPolicyDataStruct: ListMeasurement[%d] hash=%s" % (listCnt, thisHash)) # DBGDBG + print("buildLcpPolicyDataStruct: ListMeasurement[%d] hashed" % (listCnt)) # DBGDBG + listCnt += 1 + + # save to pdef.PolicyHash + pdef.PolicyHash = hash.digest() + + #print("buildLcpPolicyDataStruct - hash size=%d hexdigest=%s" % (hash.digest_size, hash.hexdigest())) # DBGDBG + pdef.Modified = False + return True + + # Build the elements and return their size + # If an error occurred, size = 0 + # Build can fail reading hash or pcr files + # + def buildListElements(self, pdef, thisPdefList, thisPolicyList, listCnt): + """buildElements - build this lists elements""" + func = 'buildListElements' + + print("%s: list %d - MLE, PCONF then SBIOS" % (func, listCnt)) # DBGDBG + policyElementsSize = 0 + thisElementSize = 0 + + # Sort element in this order [MLE, STM, SBIOS, PCONF] from [SHA512... SHA1, SHA1-LEGACY] + sortedPdefList = [] + mlelist = [element for element in thisPdefList.ElementDefData if 'MLE' in element.Name] + sortedPdefList += sorted(mlelist, key=lambda x: x.HashAlg, reverse=True) + stmlist = [element for element in thisPdefList.ElementDefData if 'STM' in element.Name] + sortedPdefList += sorted(stmlist, key=lambda x: x.HashAlg, reverse=True) + sbioslist = [element for element in thisPdefList.ElementDefData if 'SBIOS' in element.Name] + sortedPdefList += sorted(sbioslist, key=lambda x: x.HashAlg, reverse=True) + pconflist = [element for element in thisPdefList.ElementDefData if 'PCONF' in element.Name] + sortedPdefList += sorted(pconflist, key=lambda x: x.HashAlg, reverse=True) + + elementCnt = 0 + for element in sortedPdefList: + print("building Element %s" %(element.Name)) + # call the element's build function to build the elements of this policy + thisElementSize = element.build(thisPdefList, thisPolicyList.PolicyElements, pdef.WorkingDirectory) + policyElementsSize += thisElementSize + elementCnt += 1 + + print("%s: list %d - elementCnt=%d, policyElementsSize=0x%x" % (func, listCnt, elementCnt, policyElementsSize)) # DBGDBG + return(policyElementsSize) + + + # Build the .dat file + def buildLcpPolicyDataFile(self, pdef): + """buildLcpPolicyDataFile - build the LCP_POLICY_DATA2 file (.dat)""" + func = 'buildLcpPolicyDataFile' + + # reuse the base name [with .dat extention] and don't prompt for a file name again + basefilename, ext = self.filename.rsplit('.', 1) + datfilename = utilities.formFileName(basefilename, "dat") + #self.filename = utilities.formFileName(self.filename, "dat") + #lcpPolicyDataHeader = self.packLcpPolicyDataHeader() + lcpPolicyDataHeader = LcpPolicyData.pack() + + # write the LCP_POLICY_DATA header to the .dat file: f + # write the data to be signed to tmpFile: tmp + # + tmpFile = "tmpLcpPolicyList.tmp" + try: + f = open(os.path.join(self.dirname, datfilename), 'wb') + print(lcpPolicyDataHeader, end='', file=f ) # suppress EOL (0x0a) + except IOError: + self.StatusBar.SetStatusText("IOError writing raw LCP_POLICY_DATA file %s" % (datfilename)) + return + + # For each List in LcpPolicyData.PolicyLists[] + print("buildLcpPolicyDataFile: creating LCP_POLICY_DATA file %s" % (datfilename)) # DBGDBG + listCnt = 0 + listCntStr = str(listCnt) + while(listCnt < pdef.NumLists): + try: + tmp = open(os.path.join(self.dirname, tmpFile), 'wb') + except IOError: + self.StatusBar.SetStatusText("IOError opening tempFile %s" % (tmpFile)) + return + print("buildLcpPolicyDataFile: processing list %d of %d" % (listCnt, pdef.NumLists)) # DBGDBG + thisPolicyList = LcpPolicyData.PolicyLists[listCntStr] + #lcpPolicyListHeader = self.packLcpPolicyListHeader(thisPolicyList) + lcpPolicyListHeader = thisPolicyList.pack() + + # There can be 1 element of each type of each hash algorithm, See LCP_POLICY_LIST2::PolicyElements[] + lcpPolicyListElement = [None, None, None, None, None, None, None, None] + + # pack this list's elements, if they exist + i=0 + numElements = len(thisPolicyList.PolicyElements) + while(i < numElements): + #print("%s - checking if PolicyElement %d of %d exists" % (func, i, numElements)) # DBGDBG + if(thisPolicyList.PolicyElements[i] != None): + print("%s - packing PolicyElement %d of %d" % (func, i, numElements)) # DBGDBG + #lcpPolicyListElement[i] = self.packLcpPolicyElement(pdef, str(listCnt), i, thisPolicyList.PolicyElements[i]) + lcpPolicyListElement[i] = thisPolicyList.PolicyElements[i].pack() + else: + break # done after all existing elements are packed + i += 1 + + # write this LCP_POLICY_LIST to the .dat file + # 1st write the LcpPolicyListHeader, + # then write the elements and optionally the signature (if list is signed) + # + try: + print(lcpPolicyListHeader, end='', file=f ) + print(lcpPolicyListHeader, end='', file=tmp ) + # print the this list's elements, if they exist + i=0 + while(i < numElements): + #print("%s - checking if PolicyElement %d of %d was packed" % (func, i, numElements)) # DBGDBG + if(lcpPolicyListElement[i] != None): + print("%s - writing PolicyElement %d of %d to the file" % (func, i, numElements)) # DBGDBG + print(lcpPolicyListElement[i], end='', file=f ) + print(lcpPolicyListElement[i], end='', file=tmp ) + i += 1 + + except IOError: + print ("IOError writing raw LCP_POLICY_DATA file %s" % (datfilename)) + f.close() + return + + # if list is signed, now that we have formed all the binary data, it can be signed + # and the LCP_SIGNATURE object can be written to the file + # + # The RSA signature is calculated over the entire LCP_POLICY_LIST struct, + # including the Signature member, EXCEPT for the SigBlock + # + #if(thisPolicyList.SigAlgorithm == DEFINES.LCP_POLSALG_RSA_PKCS_15): + if(thisPolicyList.SigAlgorithm != DEFINES.TPM_ALG_SIGN['NULL']): + print("buildLcpPolicyDataFile: sign list %d" % (listCnt)) # DBGDBG + self.signThisList(pdef, listCntStr, thisPolicyList, f, tmp, tmpFile) + + listCnt += 1 + listCntStr = str(listCnt) + + f.close() + print("buildLcpPolicyDataFile: LCP_POLICY_DATA file %s built" % (datfilename)) # DBGDBG + + + def signThisList(self, pdef, listCntStr, thisPolicyList, f, tmp, tmpFile): + """signThisList - form the signature of the specified list and write it to the specified files""" + + # get the private key from its file + thisPdefList = pdef.PolListInfo[listCntStr] + + signAlgStr = "" + try: + signAlgStr = (key for key,val in DEFINES.TPM_ALG_SIGN.items() if val == thisPdefList.SigAlgorithm).next() + except StopIteration: + print ("Unsupported signature algorithm (%d)" %(thisPdefList.SigAlgorithm)) + return + + # pack the LCP_SIGNATURE2 object except for the PublicKeyValue and SigBlock and write it to the file + # those 2 member's size depends on keySize so they are written separately + lcpSignature = thisPolicyList.Signature.pack() + print(lcpSignature, end='', file=f ) + print(lcpSignature, end='', file=tmp ) + + # Append Public key to signature block. + if 'RSA' in signAlgStr: + print(thisPolicyList.Signature.PubkeyValue, end='', file=f) + print(thisPolicyList.Signature.PubkeyValue, end='', file=tmp) + else: + # ECC + print(thisPolicyList.Signature.Qx, end='', file=f) + print(thisPolicyList.Signature.Qx, end='', file=tmp) + print(thisPolicyList.Signature.Qy, end='', file=f) + print(thisPolicyList.Signature.Qy, end='', file=tmp) + tmp.close() # done writing to tmp + + # read back the list data from the tmp file so it can be hashed and signed + tmp = open(os.path.join(self.dirname, tmpFile), 'rb') + tmp.seek (0, os.SEEK_END) + listFileSize = tmp.tell () + tmp.seek (0, os.SEEK_SET) # back to the beginning + tmpListData = array.array ("B") # Load file into data array + try: + tmpListData.fromfile (tmp, listFileSize) + except: + self.StatusBar.SetStatusText("Error reading list data from tmp file") + print("signThisList: ******Error reading list data from tmp file!!!!!!" ) # DBGDBG ****** + tmp.close() + return + + tmp.close() + + print("signThisList: hashing %d bytes from %s" % (listFileSize, tmpFile)) # DBGDBG + # hash the list and sign the hash + signatureBE = None + hashAlgName = "" + try: + # reverse lookup of the hash algorithm name(key) for the given HashAlg value + hashAlgName = (key for key,val in DEFINES.TPM_ALG_HASH.items() if (val == thisPdefList.sigAlgorithmHash)).next() + except StopIteration: + self.StatusBar.SetStatusText("Aborting build, Hash Algorithm %d is not supported." % (thisPdefList.sigAlgorithmHash)) + print("signThisList: aborting - Hash Algorithm %d is not supported." % (thisPdefList.sigAlgorithmHash)) # DBGDBG + return + + h = None # set hash value to null first + MsgDigest = M2Crypto.EVP.MessageDigest(hashAlgName.lower()) + MsgDigest.update(tmpListData) + h = MsgDigest.digest() + + # Output hash for each list to a file for CA signing + basefilename, ext = self.filename.rsplit('.', 1) + hashfilename = basefilename + '_list' + listCntStr + '.hash' + hashout = open(os.path.join(self.dirname, hashfilename), 'wb') + hashout.write(h) + hashout.close() + # Output list raw binary output to a file for CA hashing and signing + listbinfilename = basefilename + '_list' + listCntStr + '.bin' + listbinout = open(os.path.join(self.dirname, listbinfilename), 'wb') + listbinout.write(tmpListData) + listbinout.close() + + + # Write signature data. + if thisPdefList.PvtKeyFileIsSignature: + sig_str = "" + if thisPdefList.PvtKeyFile != "": + # Load signature using the file in private key + fsig = open(os.path.join(self.dirname, thisPdefList.PvtKeyFile), 'rb') + fsig.seek(0, 2) + size = fsig.tell() + fsig.seek(0, 0) + sig_array = array.array('B') + sig_array.fromfile(fsig, size) + sig_str = sig_array.tostring() + fsig.close() + else: + # if no file defined, then it's the first pass, before the list is signed by certificate authority(CA) + pass + + if 'RSA' in signAlgStr: + + signatureBE = sig_str + # byte reverse the signature, i.e. convert from big to little-endian + signatureLE = signatureBE[::-1] + thisPolicyList.Signature.SigBlock = signatureLE + #print("signThisList: LCP_POLICY_LIST %d sigLen=0x%x sig=\n%s" % (listCnt, len(signature), signature)) # DBGDBG + + # write the LCP_SIGNATURE.SigBlock object to the file + print(signatureLE, end='', file=f ) + print("signThisList: Finished writing signature for list %d" % (int(listCntStr))) # DBGDBG + else: + # ECC signatures + signature, substrate = der_decoder.decode(sig_str, asn1Spec=ECDSASignature()) + + ri = signature.getComponentByName('r') + si = signature.getComponentByName('s') + + roctet = univ.OctetString(hexValue=format(int(ri), '0x')) + soctet = univ.OctetString(hexValue=format(int(si), '0x')) + + rBE = roctet.asNumbers() + sBE = soctet.asNumbers() + + rLE = rBE[::-1] + sLE = sBE[::-1] + thisPolicyList.Signature.r = rLE + thisPolicyList.Signature.s = sLE + # write the LCP_SIGNATURE.SigBlock object to the file + print(rLE, end='', file=f ) + print(sLE, end='', file=f ) + + else: + # Read Private Key from file + # then sign the list + #key = RSA.importKey(open(os.path.join(self.dirname, thisPdefList.PvtKeyFile)).read()) + key = None + mb = None + with open(os.path.join(self.dirname, thisPdefList.PvtKeyFile), 'rb') as kf: + mb = M2Crypto.BIO.MemoryBuffer(kf.read()) + if mb: + if 'RSA' in signAlgStr: + key = M2Crypto.RSA.load_key_bio(mb) + elif 'EC' in signAlgStr: + # if ECC algorithm + key = M2Crypto.EC.load_key_bio(mb) + else: + print("DEBUG: error load key") + kf.close() + + #print("signThisList: LCP_POLICY_LIST %s pvt key=\n%s" % (listCntStr, key)) # DBGDBG + + if 'RSA' in signAlgStr: + #signer = PKCS1_v1_5.new(key) + #signatureBE = signer.sign(h) + signatureBE = key.sign(h, hashAlgName.lower()) + # byte reverse the signature, i.e. convert from big to little-endian + signatureLE = signatureBE[::-1] + thisPolicyList.Signature.SigBlock = signatureLE + #print("signThisList: LCP_POLICY_LIST %d sigLen=0x%x sig=\n%s" % (listCnt, len(signature), signature)) # DBGDBG + + # write the LCP_SIGNATURE.SigBlock object to the file + print(signatureLE, end='', file=f ) + else: + # ECC signatures + r, s = key.sign_dsa(h) + #print("DEBUG: ECC signature size r(%d) s(%d)" %(len(rBE), len(sBE))) + + length = int(thisPdefList.KeySize)/8 + rBE = r[-length:] + sBE = s[-length:] + rLE = rBE[::-1] + sLE = sBE[::-1] + thisPolicyList.Signature.r = rLE + thisPolicyList.Signature.s = sLE + # write the LCP_SIGNATURE.SigBlock object to the file + print(rLE, end='', file=f ) + print(sLE, end='', file=f ) + + print("signThisList: Finished writing signature for list %d" % (int(listCntStr))) # DBGDBG + + + def packLcpSignatureHdr(self, lcpSignature): + """packLcpSignature - pack this LCP_SIGNATURE object except its SigBlock member ad return the packed data""" + + # Note - The public key size in the pdef is the number of bits (1024, 2048, 3072) + # while LCP_SIGNATURE.PublicKeySize is the number if bytes, hence the /8 below + return(pack(lcpSignature.LcpSignatureHdrFormatString, + lcpSignature.RevocationCounter, lcpSignature.PubkeySize/8)) + + def hashListOrBuildSignatureBlock(self, pdef, thisPdefList, thisPolicyList, listCnt) : + """hashListOrBuildSignatureBlock - if list unsigned then hash it, if signed build the signature block""" + + #print("hashListOrBuildSignatureBlock") # DBGDBG + + if(thisPdefList.SigAlgorithm in DEFINES.TPM_ALG_SIGN.values()): + #if(thisPdefList.SigAlgorithm == DEFINES.LCP_POLSALG_NONE): + if(thisPdefList.SigAlgorithm == DEFINES.TPM_ALG_SIGN['NULL']): + if(not self.hashThisList(pdef, thisPdefList, thisPolicyList, listCnt)): + return False + #elif(thisPdefList.SigAlgorithm == DEFINES.LCP_POLSALG_RSA_PKCS_15): + #elif(thisPdefList.SigAlgorithm == DEFINES.TPM_ALG_SIGN['RSASSA']): + else: + # Get the key from the file again in case it was replaced + type = DEFINES.KEY_FILE_TYPE['PUBLIC_RSASSA'] + # once the entire file name is entered, verify it, else clear it + if(thisPdefList.PubKeyFile.endswith(".pem")): + if thisPdefList.SigAlgorithm == DEFINES.TPM_ALG_SIGN['RSASSA']: + type = DEFINES.KEY_FILE_TYPE['PUBLIC_RSASSA'] + elif thisPdefList.SigAlgorithm == DEFINES.TPM_ALG_SIGN['ECDSA']: + type = DEFINES.KEY_FILE_TYPE['PUBLIC_ECDSA'] + pubkeyfile = os.path.join(self.dirname, thisPdefList.PubKeyFile) + if not utilities.verifyKeyFile(pubkeyfile, type, thisPdefList): + print("Invalid Public Key file %s" %(thisPdefList.PubKeyFile)) + return False + self.createSignatureBlock(pdef, thisPdefList, thisPolicyList, listCnt) + else: + self.StatusBar.SetStatusText("hashListOrBuildSignatureBlock: aborting unknown pdef.SigAlgorithm=%x" % (thisPdefList.SigAlgorithm)) + return False + + return True + + def hashThisList(self, pdef, thisPdefList, thisPolicyList, listCnt): + """hashThisList - when building an unsigned list, calcuate its hash""" + func = 'hashThisList' + + print("%s: list %d of %d" % (func, listCnt+1, pdef.NumLists)) + + # for each list in PolicyLists[] + # hash the list header + # hash the list's PolicyElements[] + # copy the hash to ListMeasurements[i] + # Note: hash of the 1st list does NOT include the hash of the LCP_POLICY_DATA header + + try: + hashAlgString = (key for key,val in DEFINES.TPM_ALG_HASH.items() if val == pdef.HashAlg).next() + except StopIteration: + self.StatusBar.SetStatusText("Hash Algorithm %d is not supported." % (pdef.HashAlg)) + print("%s: HashAlg %d is not supported" % (func, pdef.HashAlg)) + return False + + if hashAlgString == 'NULL': + # Nothing to do + return True + else: + hash = M2Crypto.EVP.MessageDigest(hashAlgString.lower()) + + #lcpPolicyListHeader = self.packLcpPolicyListHeader(thisPolicyList) + lcpPolicyListHeader = thisPolicyList.pack() + hash.update(lcpPolicyListHeader) + + # hash this list's PolicyElements[], if they exist + # Note: if list has no elements just hash the PolicyList header + i=0 + numElements = len(thisPolicyList.PolicyElements) + while(i < numElements): + print("%s - checking if PolicyElement %d of %d exists" % (func, i, numElements)) # DBGDBG + if(thisPolicyList.PolicyElements[i] != None): + print("%s - packing PolicyElement %d of %d" % (func, i, numElements)) # DBGDBG + #lcpPolicyListElement = self.packLcpPolicyElement(pdef, str(listCnt), i, thisPolicyList.PolicyElements[i]) + lcpPolicyListElement = thisPolicyList.PolicyElements[i].pack() + hash.update(lcpPolicyListElement) + else: + break # done after all existing elements are packed + i += 1 + + ListMeasurements.hashes[str(listCnt)] = hash.digest() + #print("hashThisList - ListMeasurements[%d] hash size=%d hexdigest=%s" % + # (listCnt, hash.digest_size, hash.hexdigest())) # DBGDBG + return True + + def createSignatureBlock(self, pdef, thisPdefList, thisPolicyList, listCnt): + """createSignatureBlock - when building a signed list, form its signature block""" + + try: + signAlgStr = (key for key,val in DEFINES.TPM_ALG_SIGN.items() if val == thisPolicyList.SigAlgorithm).next() + except StopIteration: + print ("ERROR, Signing algorithm not supported (%d)" %(thisPolicyList.SigAlgorithm)) + return + + if 'RSA' in signAlgStr: + # Create signature block for RSA signature structure + thisPolicyList.Signature = LCP_RSA_SIGNATURE() + # Copy public key to Policy data structure + thisPolicyList.Signature.PubkeyValue = thisPdefList.PubKeyData + else: + # Create signature block for ECC signature structure + thisPolicyList.Signature = LCP_ECC_SIGNATURE() + # Copy public key to Policy data structure + thisPolicyList.Signature.Qx = thisPdefList.PubKeyQx + thisPolicyList.Signature.Qy = thisPdefList.PubKeyQy + + # Copy other common parameters + + # RevocationCounter = PDEF.PolListInfo[i].RevocationCounter + # Note: Code differs from the tool spec algorithm in section 5.3.1 p19 as follows: + # - List Revocation Counters are incremented on the 1st change after a build, not here + # - RevokeCounter is sync'd to Revocation counter in list.onBuildButtonClick() not here + thisPolicyList.Signature.RevocationCounter = thisPdefList.RevocationCounter + + # PubkeySize = PDEF.PolListInfo[i].PubkeySize + thisPolicyList.Signature.PubkeySize = int(thisPdefList.KeySize) + print("createSignatureBlock - RevocationCounter=%d, keySize=%d per PDEF KeySize=%s" % + (thisPolicyList.Signature.RevocationCounter, thisPolicyList.Signature.PubkeySize, thisPdefList.KeySize)) # DBGDBG + + # Calculate Hash of public key using PDEF,HashAlg + # Copy to ListMeasurements[i] + + try: + # reverse lookup of the hash algorithm name(key) for the given HashAlg value + hashAlgStr = (key for key,val in DEFINES.TPM_ALG_HASH.items() if (val == pdef.HashAlg)).next() + except StopIteration: + self.StatusBar.SetStatusText("Hash Algorithm is not supported, (pdef.HashAlg=%d)" % (pdef.HashAlg)) + return + + hash = M2Crypto.EVP.MessageDigest(hashAlgStr.lower()) + if 'RSA' in signAlgStr: + hash.update(thisPolicyList.Signature.PubkeyValue) + else: + hash.update(thisPolicyList.Signature.Qx) + hash.update(thisPolicyList.Signature.Qy) + digest = hash.digest() + ListMeasurements.hashes[str(listCnt)] = digest + + # Build SigBlock[PubkeySize] + # Calculate hash of LIST using PDEF,HashAlg + # Encrypt hash using private key [ie Sign it] + # A.2.1 - For a signed list, the RSA signature is calculated over the entire LCP_POLICY_LIST struct, + # including the Signature member, EXCEPT for the SigBlock + # Copy encrypted hash to policy data structure LCP_SIGNATURE.SigBlock + # Done with signature + + # NOTE: The list is signed later, and the signature copied to LCP_SIGNATURE.SigBlock + # when the list is written to its .dat file in buildLcpPolicyDataFile() + # since that is when the 'signable' binary data is packed + # [vs. the Python object form of the data available here] + + + # the last function in the file doesn't show up in the scope list in Understand for some reason! + def stub(self): + pass diff -Nru tboot-1.9.4/lcp-gen2/defines.py tboot-1.9.5/lcp-gen2/defines.py --- tboot-1.9.4/lcp-gen2/defines.py 1970-01-01 00:00:00.000000000 +0000 +++ tboot-1.9.5/lcp-gen2/defines.py 2016-12-17 03:19:38.000000000 +0000 @@ -0,0 +1,275 @@ +#!/usr/bin/python +# Copyright (c) 2013, Intel Corporation. All rights reserved. + +class DEFINES( object ): + """ Defines Class""" + + def __init__( self ): + pass + + LCP_VERSION = 2 + TOOL_VERSION = '0.5' + BUILD_DATE = '2013-09-06' + + SUPPORTED_LCP_VERSION = { + # Policy Version : List Verson + '3.1' : '2.1', + '3.0' : '2.0' + } + + # Policy Type global values: + LIST = 0 + ANY = 1 + + # Policy Rules global values + PsRules = 0 + PoRules = 1 + + # max value for Min SINIT Version and BIOS & SINIT Revocation Limit fields + maxVersion = 255 + + # The PolicyControlField provides a number of control bits which are defined as: + # Bit31 AUXDeletionControl + # Bits30:4 Reserved and should set to zero + # Bit20 Ignore PS STM + # Bit17 Ignore PS PCONF + # Bit16 Ignore PS MLE + # Bit 3 Indicates Force Owner Policy + # Bit 2 Allow NPW. + # Bit 1 PCR 17 + # Bit 0 Reserved and should set to zero + # + PolicyControlAUXDeletionControl = 0x80000000 # bit 31 + PolicyControlIgnorePsStmBitMask = 0x00100000 # bit 20 + PolicyControlIgnorePsPconfBitMask = 0x00020000 # bit 17 + PolicyControlIgnorePsMleBitMask = 0x00010000 # bit 16 + PolicyControlForceOwnerBitMask = 0x00000008 # bit 3 + PolicyControlPcr17BitMask = 0x00000004 # bit 2 + PolicyControlAllowNpwBitMask = 0x00000002 # bit 1 + + # List Policy Signing Algorithm + LCP_POLSALG_NONE = 0 # list not signed + LCP_POLSALG_RSA_PKCS_15 = 1 # list signed + LCP_POLSALG_ECDSA = 2 + LCP_POLSALG_SM2 = 3 + + # Element types: MLE, PCONF, SBIOS and STM + LCP_POLELT_TYPE_MLE = 0x00 + LCP_POLELT_TYPE_PCONF = 0x01 + LCP_POLELT_TYPE_SBIOS = 0x02 + LCP_POLELT_TYPE_MLE2 = 0x10 + LCP_POLELT_TYPE_PCONF2 = 0x11 + LCP_POLELT_TYPE_SBIOS2 = 0x12 + LCP_POLELT_TYPE_STM2 = 0x14 + + # Each list can have each element with each possible hash algorithm + # So Pdef_list.[Mle,Pconf,Sbios,Stm]DefData[x] is now an array + # where x is one of the indexes below which must be < MAX_ELEMENTS + DEFDATA_INDEX = { + 'SHA1' : 0, + 'SHA256' : 1, + 'SHA384' : 2, + 'SHA512' : 3, + #'SM3' : 4 + } + + + # Other than ELEMENT_NAME_NONE with no '-' character, + # all other names must be - + # This is used in list.py to create new element of the hash type. + # So the following element names are possible: + ELEMENT_NAME_NONE = "None" + ELEMENT_NAME_MLE_SHA1 = "MLE-SHA1" + ELEMENT_NAME_MLE_SHA256 = "MLE-SHA256" + ELEMENT_NAME_MLE_SHA384 = "MLE-SHA384" + ELEMENT_NAME_MLE_SHA512 = "MLE-SHA512" + ELEMENT_NAME_MLE_SM3 = "MLE-SM3" + + ELEMENT_NAME_PCONF_SHA1 = "PCONF-SHA1" + ELEMENT_NAME_PCONF_SHA256 = "PCONF-SHA256" + ELEMENT_NAME_PCONF_SHA384 = "PCONF-SHA384" + ELEMENT_NAME_PCONF_SHA512 = "PCONF-SHA512" + ELEMENT_NAME_PCONF_SM3 = "PCONF-SM3" + + ELEMENT_NAME_SBIOS_SHA1 = "SBIOS-SHA1" + ELEMENT_NAME_SBIOS_SHA256 = "SBIOS-SHA256" + ELEMENT_NAME_SBIOS_SHA384 = "SBIOS-SHA384" + ELEMENT_NAME_SBIOS_SHA512 = "SBIOS-SHA512" + ELEMENT_NAME_SBIOS_SM3 = "SBIOS-SM3" + + ELEMENT_NAME_STM_SHA1 = "STM-SHA1" + ELEMENT_NAME_STM_SHA256 = "STM-SHA256" + ELEMENT_NAME_STM_SHA384 = "STM-SHA384" + ELEMENT_NAME_STM_SHA512 = "STM-SHA512" + ELEMENT_NAME_STM_SM3 = "STM-SM3" + + ELEMENT_NAME_MLE_LEGACY = "MLE-LEGACY" + ELEMENT_NAME_PCONF_LEGACY = "PCONF-LEGACY" + ELEMENT_NAME_SBIOS_LEGACY = "SBIOS-LEGACY" + + # element name strings for PO rules + ELEMENT_PO_RULES = [ + ELEMENT_NAME_STM_SHA512, ELEMENT_NAME_STM_SHA384, + ELEMENT_NAME_STM_SHA256, ELEMENT_NAME_STM_SHA1, #ELEMENT_NAME_STM_SM3, + ELEMENT_NAME_PCONF_SHA512, ELEMENT_NAME_PCONF_SHA384, + ELEMENT_NAME_PCONF_SHA256, ELEMENT_NAME_PCONF_SHA1, #ELEMENT_NAME_PCONF_SM3, + ELEMENT_NAME_PCONF_LEGACY, + ELEMENT_NAME_MLE_SHA512, ELEMENT_NAME_MLE_SHA384, + ELEMENT_NAME_MLE_SHA256, ELEMENT_NAME_MLE_SHA1, #ELEMENT_NAME_MLE_SM3, + ELEMENT_NAME_MLE_LEGACY + ] + + """getElement - return array of element names strings""" + ELEMENT = [ + ELEMENT_NAME_SBIOS_SHA512, ELEMENT_NAME_SBIOS_SHA384, + ELEMENT_NAME_SBIOS_SHA256, ELEMENT_NAME_SBIOS_SHA1, #ELEMENT_NAME_SBIOS_SM3, + ELEMENT_NAME_SBIOS_LEGACY, + ELEMENT_NAME_STM_SHA512, ELEMENT_NAME_STM_SHA384, + ELEMENT_NAME_STM_SHA256, ELEMENT_NAME_STM_SHA1, #ELEMENT_NAME_STM_SM3, + ELEMENT_NAME_PCONF_SHA512, ELEMENT_NAME_PCONF_SHA384, + ELEMENT_NAME_PCONF_SHA256, ELEMENT_NAME_PCONF_SHA1, #ELEMENT_NAME_PCONF_SM3, + ELEMENT_NAME_PCONF_LEGACY, + ELEMENT_NAME_MLE_SHA512, ELEMENT_NAME_MLE_SHA384, + ELEMENT_NAME_MLE_SHA256, ELEMENT_NAME_MLE_SHA1, #ELEMENT_NAME_MLE_SM3, + ELEMENT_NAME_MLE_LEGACY + ] + + # This replaces util.getHashes() + # supported hash algorithm names + SUPPORTED_HASHES = [ + 'SHA1', 'SHA256', 'SHA384', 'SHA512', + #'SM3' + ] + + # allowed hash algorithm names + ALLOWED_HASHES = [ + 'SHA1', + #'SHA224', # not supported + 'SHA256', 'SHA384', 'SHA512', + 'SM3' + ] + + # ALLOWED_SIGNATURE_SCHEMES is ordered list that references TPM_ALG_SIGN_MASK + # allowed signing algorithm names + ALLOWED_SIGNATURE_SCHEMES = [ + #'RSA-1024-SHA1', 'RSA-1024-SHA256', 'RSA-2048-SHA1', # not supported + 'RSA-2048-SHA256', + #'RSA-2048-SHA384', 'RSA-2048-SHA512', # not supported + #'RSA-3072-SHA256', 'RSA-3072-SHA384', 'RSA-3072-SHA512', # not supported + #'RSA-4096-SHA256', 'RSA-4096-SHA384', 'RSA-4096-SHA512', # not supported + 'ECDSA P-256', 'ECDSA P-384', + 'SM2' + ] + + SIGNATURE_ALGORITHMS = [ + 'None', + #'RSA PKCS1.5/SHA1', + 'RSA PKCS1.5/SHA256', + #'RSA PKCS1.5/SHA384', + #'RSA PKCS1.5/SHA512', + 'ECDSA P-256/SHA256', + 'ECDSA P-384/SHA384', + #'SM2/SM3' + ] + + SIGNATURE_KEY_SIZE = { + 'None' : [], + 'RSA PKCS1.5/SHA256' : ['2048'], + 'ECDSA P-256/SHA256' : ['256'], + 'ECDSA P-384/SHA384' : ['384'], + 'SM2/SM3' : ['256'] + } + + # Hash Algorithm defines for pdef.hashAlg + TPM_ALG_HASH = { + 'SHA1_LEGACY' : 0x0000, + 'SHA1' : 0x0004, + 'SHA256' : 0x000B, + 'SHA384' : 0x000C, + 'SHA512' : 0x000D, + 'NULL' : 0x0010, + 'SM3' : 0x0012 + } + + # Signature Algorithm defined for LCP_POLICY_LIST2.SigAlgorithm + TPM_ALG_SIGN = { + 'NULL' : 0x0010, # same as in Hash Algorithm + 'RSASSA' : 0x0014, + 'ECDSA' : 0x0018, + 'SM2' : 0x001B + } + + # SHAXXXXX_DIGEST_SIZE + DIGEST_SIZE = { + 'SHA1' : 20, + 'SHA256' : 32, + 'SHA384' : 48, + 'SHA512' : 64, + 'SM3' : 32 + } + + # TPM_ALG_HASH_MASK_XXXX + TPM_ALG_HASH_MASK = { + 'SHA1' : 0x0001, + 'SHA224' : 0x0002, + 'SHA512_224' : 0x0004, + 'SHA256' : 0x0008, + 'SHA512_256' : 0x0010, + 'SM3' : 0x0020, + 'SHA384' : 0x0040, + 'SHA512' : 0x0080, + 'WHIRLPOOL' : 0x0100 + } + + # TPM_ALG_SIGN_MASK_XXXX + TPM_ALG_SIGN_MASK = { + 'RSA-1024-SHA1' : 0x00000001, + 'RSA-1024-SHA256' : 0x00000002, + 'RSA-2048-SHA1' : 0x00000004, + 'RSA-2048-SHA256' : 0x00000008, + 'RSA-2048-SHA384' : 0x00000010, + 'RSA-2048-SHA512' : 0x00000020, + 'RSA-3072-SHA256' : 0x00000040, + 'RSA-3072-SHA384' : 0x00000080, + 'RSA-3072-SHA512' : 0x00000100, + 'RSA-4096-SHA256' : 0x00000200, + 'RSA-4096-SHA384' : 0x00000400, + 'RSA-4096-SHA512' : 0x00000800, + 'ECDSA P-256' : 0x00001000, + 'ECDSA P-384' : 0x00002000, + 'SM2' : 0x00010000 + } + + # Types of hash files - see util.verifyHashFile() + + HashFileMode = { + 'HdrNull' : 0, + 'HdrSHA1' : 1, + 'RawSHA1' : 2, + 'RawSHA256' : 3, + 'RawSHA384' : 4, + 'RawSHA512' : 5, + 'RawSM3' : 6 #TODO: check the value + } + + # Types of PCR dump Files - see util.verifyPcrFile() + PcrFileMode = { + 'Null' : 0, + 'Pcrd' : 7, + 'Pcr2' : 8 + } + + # key files are private or public keys for RSA or ECC + KEY_FILE_TYPE = { + 'PRIVATE_RSASSA': 1, + 'PUBLIC_RSASSA' : 2, + 'PRIVATE_ECDSA' : 3, + 'PUBLIC_ECDSA' : 4 + } + + PCRDFileHdrSize = 16 + PCR2FileHdrSize = 8 + PCRFileMinHdrSize = 7 # 1st 6 bytes of PCRD or PCR2 file are enough to determine the type and check the HashAlg + + + diff -Nru tboot-1.9.4/lcp-gen2/ElementBase.py tboot-1.9.5/lcp-gen2/ElementBase.py --- tboot-1.9.4/lcp-gen2/ElementBase.py 1970-01-01 00:00:00.000000000 +0000 +++ tboot-1.9.5/lcp-gen2/ElementBase.py 2016-12-17 03:19:38.000000000 +0000 @@ -0,0 +1,62 @@ + +from struct import * +from array import * +from defines import DEFINES + + +class ElementBase(object): + + #MleDataSha1HashFormatString = "<20B" + #MleDataSha256HashFormatString = "<32B" + #MleDataSha384HashFormatString = "<48B" + #MleDataSha512HashFormatString = "<64B" + + def __init__(self): + pass + + + # alg is a string that specifies hash algorithm + # hash is the array of bytes of the hash value + # + def packHash(self, alg, hash): + #hashFormatString = "<" + str(DEFINES.DIGEST_SIZE[alg]) + "B" # Build the pack format string for different hash algorithms + #hashData = pack(hashFormatString, array('B', hash)) + #print "DEBUG: hash format string = "+ HashFormatString + + # Check hash size vs. expected size for specified algorithm + hashData = None + if (DEFINES.DIGEST_SIZE[alg] == len(hash)): + b = bytes() + hashData = b.join(pack('B', val) for val in hash) + else: + print ("ERROR: Hash buffer size %d does not match required size for %s" %(len(hash), alg)) + + return hashData + + + +if __name__ == "__main__": + sha1data = [val for val in range(DEFINES.DIGEST_SIZE['SHA1'])] + sha256data = [val for val in range(DEFINES.DIGEST_SIZE['SHA256'])] + e = ElementBase(); + packedHash = pack("<20B", sha1data[0], sha1data[1], sha1data[2], sha1data[3], sha1data[4], sha1data[5], + sha1data[6], sha1data[7], sha1data[8], sha1data[9], sha1data[10], sha1data[11], sha1data[12], + sha1data[13], sha1data[14], sha1data[15], sha1data[16], sha1data[17], sha1data[18], sha1data[19]) + joinedHash = e.packHash('SHA256', sha1data) + + if (packedHash == joinedHash): + print "SUCCESS" + else: + print "FAILED" + + print packedHash + print joinedHash + + + #packed = e.packHash('SHA256', sha256data) + #print packed + #e.packHash('SHA384') + #e.packHash('SHA512') + + + \ No newline at end of file diff -Nru tboot-1.9.4/lcp-gen2/ElementGui.py tboot-1.9.5/lcp-gen2/ElementGui.py --- tboot-1.9.4/lcp-gen2/ElementGui.py 1970-01-01 00:00:00.000000000 +0000 +++ tboot-1.9.5/lcp-gen2/ElementGui.py 2016-12-17 03:19:38.000000000 +0000 @@ -0,0 +1,140 @@ +#!/usr/bin/python +# Copyright (c) 2013, Intel Corporation. All rights reserved. + +# using print() built infunction, disable print statement +from __future__ import print_function + +# +# wxPython is not part of the standard Python distribution and has to be downloaded and installed separately. +# Tell the user that wxPython is required but has not been found +# +try: + import wx +except ImportError: + raise ImportError, "Please download the appropriate version of wxPython from www.wxpython.org" + + +import os +import shutil + +from defines import DEFINES + +# +# TXT Policy Generator Tool +# +class ElementGui( object ): + + CONST_TITLE = "Choose file" + CONST_WILDCARD = "All Files (*.*) | *.*" + + def __init__( self ): + pass + + + # isElementType() compares the name argument to the class name and stored hash algorithm name + # to find a matching element. + # The name argument should have a format of - + def isElementType(self, name): + result = False + type = name.split('-') + if len(type) != 2: + result = False + else: + elementType, hashAlg = type + if hashAlg == 'LEGACY': + if elementType in self.__class__.__name__: + result = True + else: + if elementType in self.__class__.__name__ and self.myHashAlg == DEFINES.TPM_ALG_HASH[hashAlg]: + result = True + return result + + + def getHashAlgName(self): + if 'Legacy' in self.__class__.__name__: + name = 'SHA1-LEGACY' + else: + try: + name = (key for key,val in DEFINES.TPM_ALG_HASH.items() if (val == self.myHashAlg)).next() + except StopIteration: + name = None + return name + + + # getName() is intended to get the class name from the classes defined in pdef.py + # + #def getName(self): + # if 'Legacy' in self.__class__.__name__: + # hashname = 'LEGACY' + # name = self.__class__.__name__.split('Legacy')[0] + '-' + hashname + # else: + # try: + # hashname = (key for key,val in DEFINES.TPM_ALG_HASH.items() if (val == self.myHashAlg)).next() + # name = self.__class__.__name__.split('_DEF')[0] + '-' + hashname + # except StopIteration: + # name = None + # return name + + def selectFile(self): + """onAddButtonClick - This code is common to all elements to select a file + and copy file into current working directory if the file doesn't exist """ + + filepath = '' + filename = '' + workdir = self.pdef.WorkingDirectory + + dlg = wx.FileDialog(self.parent, self.CONST_TITLE, workdir, "", self.CONST_WILDCARD, wx.FD_OPEN) + + if dlg.ShowModal() == wx.ID_CANCEL : + self.StatusBar.SetStatusText( "Add cancelled" ) + else: + filename = dlg.GetFilename() + filepath = dlg.GetDirectory() + + dlg.Destroy() + # return null string indicate file select cancelled. + return filepath, filename + + + def copyFile(self, filepath, filename): + workdir = self.pdef.WorkingDirectory + + if (filepath != workdir): + if (os.path.exists(os.path.join(workdir, filename))) : + dlg = wx.MessageDialog(self.parent, filename+" already exists in working directory\nOverwrite file in working directory?", "Confirm Copy", wx.OK|wx.CANCEL|wx.ICON_QUESTION) + + if (dlg.ShowModal() == wx.ID_OK): + shutil.copyfile(os.path.join(filepath, filename), os.path.join(workdir, filename)) + self.StatusBar.SetStatusText( "File copied" ) + else: + self.StatusBar.SetStatusText( "File copy aborted" ) + + dlg.Destroy() + else: + shutil.copyfile(os.path.join(filepath, filename), os.path.join(workdir, filename)) + + + def setListModified(self): + """setListModified - if list not modified yet, increment its rev cnt and set it to modified""" + + currentList = self.pdef.getCurrentListObject() + + #print("PCONF setListModified - ListModified was %s" % (currentList.ListModified)) # DBGDBG + if(currentList.ListModified == False): + currentList.RevocationCounter += 1 + self.listPanel.revocationCountEdit.ChangeValue(str(currentList.RevocationCounter)) # update the GUI + currentList.ListModified = True + self.pdef.Modified = True + + + def showV20Gui(self, enable): + if enable: + self.overridePsPolicy.Show() + else: + self.overridePsPolicy.Hide() + + + def enableDisableOverridePsPolicy(self, value): + """enableDisableOverridePsPolicy widget""" + + self.overridePsPolicy.Enable(value) \ No newline at end of file diff -Nru tboot-1.9.4/lcp-gen2/LcpPolicy.py tboot-1.9.5/lcp-gen2/LcpPolicy.py --- tboot-1.9.4/lcp-gen2/LcpPolicy.py 1970-01-01 00:00:00.000000000 +0000 +++ tboot-1.9.5/lcp-gen2/LcpPolicy.py 2016-12-17 03:19:38.000000000 +0000 @@ -0,0 +1,835 @@ +#!/usr/bin/python +# Copyright (c) 2013, Intel Corporation. All rights reserved. + +# TXT Policy Generator Tool +# LcpPolicy and LcpPolicyData Classes - LCP_POLICY and LCP_POLICY_DATA File Structure +# + +from defines import DEFINES +from ElementBase import * + + +class LCP_POLICY2( object ): + """ LCP_POLICY2 Class""" + + # + # LCP_POLICY2 struct + # + def __init__( self ): + """__init__() - LCP_POLICY2 class constructor""" + #self.Version # UINT16 - from pdef.PolVersion = 0x0300 + self.VersionMajor = 03 # UINT8 + self.VersionMinor = 00 # UINT8 + self.HashAlg = 00 # UINT16 - TPM_ALG_* from pdef.HashAlg + self.PolicyType = 00 # UINT8 - 0=LIST, 1=ANY - from pdef.PolicyType + self.SINITMinVersion = 00 # UINT8 - from pdef.SinitMinVersion + self.DataRevocationCounters = [0,0,0,0,0,0,0,0] # UINT16 DataRevocationCounters[MAX_LISTS] Default is 0's + # from pdef.DataRevocationCounters[] + self.PolicyControl = 0 # UINT32 Encoding of (NPW, PCR17, Force PO), from pdef.PolicyControl + self.MaxSinitMinVer = 0 # UINT8 PO only, reserved for PS + self.MaxBiosAcMinVer = 0 # UINT8 PO only, reserved for PS + self.LcpHashAlgMask = 0 # UINT16 HashMask for LCP eval. + self.LcpSignAlgMask = 0 + self.AuxHashAlgMask = 0 # UINT16 Hash Mask for Auto-Promotion + # Reserved # UINT16 + self.PolicyHash = [] + + # Doesn't really need to use 2 variable for each hash size for python + #self.PolicyHashSha1 = [0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0] # LCP_HASH + #self.PolicyHashSha256 = [0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0] + + # + # The raw [ie binary] format LCP_POLICY.pol file is generated using struct.pack + # based on the format string below. + # + # 'struct' module format string for a LCP_POLICY Structure + # where: B = UINT8, H = UINT16, L = UINT32 + # '<' means Little Endian, std size, no alignment between fields + #self.LcpPolicyFormatString = "pcr_selection.size_of_select = 3; + # // TPM structures are big-endian, so byte-swap + # bswap16(&pcr_info->pcr_selection.size_of_select); + # + # So do likewise + + elementData += pack( self.PconfDataSha1PcrInfoFormatString, + thisPcrInfo.pcrSelection.sizeOfSelect, + thisPcrInfo.pcrSelection.pcrSelect[0], + thisPcrInfo.pcrSelection.pcrSelect[1], + thisPcrInfo.pcrSelection.pcrSelect[2], + thisPcrInfo.localityAtRelease) + + # thisPcrInfo.digestAtRelease is the binary string produced by hash.digest() + # struct.pack() requires ints, not strings. + # But don't need to pack it, just output it directly + elementData += thisPcrInfo.digestAtRelease + i += 1 + + return( elementData ) + + +# #define TPM_LOCALITY_SELECTION BYTE +# +# typedef struct tdTPM_PCR_INFO_SHORT{ +# TPM_PCR_SELECTION pcrSelection; +# UINT8 localityAtRelease; //0x1F +# TPM_COMPOSITE_HASH digestAtRelease; +# } TPM_PCR_INFO_SHORT; +class TPM_PCR_INFO_SHORT( object ): + """TPM_PCR_INFO_SHORT class""" + + def __init__(self): + """__init__() - TPM_PCR_INFO_SHORT class constructor""" + + self.pcrSelection = TPM_PCR_SELECTION() # TPM_PCR_SELECTION + self.localityAtRelease = 0x1f # UINT8 + self.digestAtRelease = [] + + +# +# typedef struct tdTPM_PCR_SELECTION { +# UINT16 sizeOfSelect; // shall be 0x0003 +# [size_is(sizeOfSelect)] BYTE pcrSelect[]; +# } TPM_PCR_SELECTION; +# +class TPM_PCR_SELECTION( object ): + """TPM_PCR_SELECTION class""" + + def __init__(self): + """__init__() - TPM_PCR_SELECTION class constructor""" + + self.sizeOfSelect = 0x0003 # UINT16 + self.pcrSelect = [0, 0, 0] # [size_is(sizeOfSelect)] BYTE pcrSelect[] + + +# typedef struct tdTPM_DIGEST{ +# BYTE digest[digestSize]; // digestSize = 20 bytes for SHA1 +# } TPM_DIGEST; +# +# typedef TPM_DIGEST TPM_COMPOSITE_HASH; // hash of multiple measurements +# +class TPM_DIGEST( object ): + """TPM_DIGEST class""" + + def __init__(self): + """__init__() - TPM_DIGEST class constructor""" + + self.digest = [0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0] # BYTE digest[digestSize] MAX_HASH = 20 for SHA1 + + +# typedef struct { +# UINT32 ElementSize; +# UINT32 ElementType; // Type = 2 = LCP_POLELT_TYPE_SBIOS +# UINT32 PolEltControl; +# UINT8 HashAlg; // one of LCP_POLHALG_* +# UINT8 Reserved1[3]; // 0, 0, 0 +# LCP_HASH FallbackHash; +# UINT16 Reserved2; // 0x0000 +# UINT16 NumHashes; +# LCP_HASH Hashes[NumHashes]; +# } LCP_SBIOS_ELEMENT +# +class LCP_SBIOS_ELEMENT( ElementBase ): + """LCP_SBIOS_ELEMENT class""" + + def __init__(self): + """__init__() - LCP_SBIOS_ELEMENT class constructor""" + + self.ElementSize = 0 # UINT32 - header + self.ElementType = DEFINES.LCP_POLELT_TYPE_SBIOS # UINT32 - header + self.PolEltControl = 0 # UINT32 - header + self.HashAlg = 0 # UINT8 + #self.Reserved1[3] # UINT8 0, 0, 0 + self.FallbackHash = [0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0] + # LCP_HASH + #self.Reserved2 # UINT16 0x0000 + self.NumHashes = 0 # UINT16 + self.Hashes = [] # LCP_HASH Hashes[NumHashes] + + # 'struct' module format string for a LCP_SBIOS_ELEMENT Structure + # where: B = UINT8, H = UINT16, L = UINT32 c = char + # '<' means Little Endian, std size, no alignment between fields + #self.SbiosDataFormatString = " 0): + flag = True + self.selectElementEdit.SetValue(currentList.CurrentElementView) + #self.selectElementEdit.SetSelection(cnt) + else: + flag = False + currentList.CurrentElementView = DEFINES.ELEMENT_NAME_NONE + #self.visibleElement = DEFINES.ELEMENT_NAME_NONE + self.selectElementEdit.SetValue(DEFINES.ELEMENT_NAME_NONE) + self.selectElementEdit.SetSelection(0) + + # show element panel for selected element + selection = self.selectElementEdit.GetSelection() + if selection > 0: + self.includedElements[selection-1].showPanel() + self.selectElementEdit.Enable(flag) + self.deleteElementButton.Enable(flag) + + #print("restoreListPanel - Sync=%s SigAlgorithm=%x" % (currentList.SyncRevCount, currentList.SigAlgorithm)) # DBGDBG + self.Sync.SetValue(currentList.SyncRevCount) + self.allowedEdit.ChangeValue(str(currentList.RevokeCounter)) + self.revocationCountEdit.ChangeValue(str(currentList.RevocationCounter)) + self.keySizeEdit.SetValue(str(currentList.KeySize)) + #if (currentList.SigAlgorithm == 1): # For TPM 1.2 + + signAlgName = "" + try: + signAlgName = (key for key,val in DEFINES.TPM_ALG_SIGN.items() if currentList.SigAlgorithm == val).next() + except StopIteration: + print("WARNING - Invalid signature algorithm (%d)" %(currentList.SigAlgorithm)) + + hashAlgName = "" + try: + hashAlgName = (key for key,val in DEFINES.TPM_ALG_HASH.items() if currentList.sigAlgorithmHash == val).next() + except StopIteration: + print("WARNING - Invalid hash algorithm (%d)" %(currentList.sigAlgorithmHash)) + + selectionString = "None" + if 'RSA' in signAlgName: + selectionString = (name for name in DEFINES.SIGNATURE_ALGORITHMS if 'RSA' in name and hashAlgName in name).next() + enable = True + elif 'ECDSA' in signAlgName: + selectionString = (name for name in DEFINES.SIGNATURE_ALGORITHMS if signAlgName in name and currentList.KeySize in name).next() + enable = True + #elif 'SM2' in signAlgName: + # selectionString = (name for name in DEFINES.SIGNATURE_ALGORITHMS if signAlgName in name).next() + # enable = True + else: + enable = False + + self.enableDisableSigned(enable, selectionString) + self.algorithmEdit.SetValue(selectionString) + self.pvtKeyFileSel.SetSelection(currentList.PvtKeyFileIsSignature) + self.pubKeyFileEdit.ChangeValue(currentList.PubKeyFile) + self.pvtKeyFileEdit.ChangeValue(currentList.PvtKeyFile) + #currentList.ListModified = False # don't want to change the state of this variable + + def setListPanelToCurrentListView(self): + """setListPanelToCurrentListView - update the list panel to the specified list""" + + currentList = self.pdef.getCurrentListObject() + print("setListPanelToCurrentListView %i AllowedCounter=%i" % (self.pdef.CurrentListView, currentList.RevokeCounter)) # DBGDBG + + # Hide all panels before rebuilding the list for the new panel + self.hideAllPanels() + # Clear GUI panels for each element + self.includedElements = [] + + # Re-build the GUI panel for each element from the PDEF persistent object in pdef.py file + index = 0 + for defdata in currentList.ElementDefData: + # Get Name and Hash type of each and recreate GUI element with it. + + # Create a new element of selected spec and populate into currentListObject.MleDefData + elementType, hashAlg = defdata.Name.split('-') + + if hashAlg == 'LEGACY': + if elementType == 'SBIOS': + element = SBIOSLegacy() + elif elementType == 'MLE': + element = MLELegacy() + elif elementType == 'PCONF': + element = PCONFLegacy() + else: + print ("ERROR: invalid element") + else: + if elementType == 'SBIOS': + element = SBIOS(DEFINES.TPM_ALG_HASH[hashAlg]) # GUI panel + elif elementType == 'STM': + element = STM(DEFINES.TPM_ALG_HASH[hashAlg]) + elif elementType == 'MLE': + element = MLE(DEFINES.TPM_ALG_HASH[hashAlg]) + elif elementType == 'PCONF': + element = PCONF(DEFINES.TPM_ALG_HASH[hashAlg]) + else: + print ("ERROR: invalid element") + + element.createOrShowPanel(wx, self, self.parent, self.pdef, self.StatusBar) + element.myIndex = index + self.includedElements.append(element) + element.restorePanel(currentList, self.pdef.MaxHashes) + element.hidePanel() + index += 1 + + # restore any element panels that exist in the current PLIST_DEF + + # Also update this list's element panel, if one exists + # 1st hide all the elements and enable if they don't exist and rules allow that + #self.hideAllPanels() # Hide all the element panels + + # then disable add buttons for elements that exist + # and count the number of elements in this list + numberOfElements = len(currentList.ElementDefData) + + # rebuild selectElementEdit's choices list for the elements existing in this view + self.rebuildSelectElementChoices() + + # then show a panel + + # update the NumberOfElements and enable selectElementsEdit if > 0 + self.numberElementsEdit.ChangeValue(str(numberOfElements)) + if(numberOfElements > 0): + self.selectElementEdit.Enable( True ) + self.deleteElementButton.Enable( True ) + + self.restoreListPanel(currentList) + + + # only called if PolicyType = LIST if pdef.NumLists > 0 + # for each signed list, + # If Sync is checked, + # then update the current list's AllowedCounter from its RevocationCounter + # update pdef.DataRevocationCounters[list#] from the current list's Allowedounter + # if the current List is displayed in the list panel, update the list panel widgets + # + # NOTE: the current list's RevocationCounter is incr on its 1st modification + # + def onBuildButtonClick(self, pdef): + """ onBuildButtonClick - perform a build""" + #print("list::onBuildButtonClick") # DBGDBG + + listNum = 0 + while( listNum < pdef.NumLists): + thisList = pdef.PolListInfo[str(listNum)] + #if(thisList.SigAlgorithm == DEFINES.LCP_POLSALG_RSA_PKCS_15): # For TPM1.2 + if(thisList.SigAlgorithm == DEFINES.TPM_ALG_SIGN['RSASSA']): + if(thisList.SyncRevCount == True): + thisList.RevokeCounter = thisList.RevocationCounter + + pdef.DataRevocationCounters[listNum] = thisList.RevokeCounter + + # is this list being shown in the list panel? + if(pdef.CurrentListView == listNum + 1): + self.allowedEdit.ChangeValue(str(thisList.RevokeCounter)) + self.revocationCountEdit.ChangeValue(str(thisList.RevocationCounter)) + + if(thisList.RevocationCounter > 0): # can't reset til cnt > 0 + self.resetButton.Enable(True) + + print("list.onBuild - list %d, RevCnt=%d, RevokeCnt=%d, pdef.DataRevocationCounters[%d]=%d" % + (listNum+1, thisList.RevocationCounter, thisList.RevokeCounter, listNum+1, pdef.DataRevocationCounters[listNum])) # DBGDBG + + listNum += 1 + + #print("list.onBuild - pdef.DataRevocationCounters=%s" % (pdef.DataRevocationCounters)) # DBGDBG + + def onAllowedEdit(self, event): + """ onAllowedEdit - handle Allowed value change""" + + string = event.GetString() + self.StatusBar.SetStatusText("in onAllowedEdit, value=%s" % (string)) + + currentList = self.pdef.getCurrentListObject() + maxValue = currentList.RevocationCounter + #print("onAllowedEdit - MaxValue=%i" % (maxValue)) # DBGDBG + + try: + value = int(string) + except: + self.StatusBar.SetStatusText( "%s is invalid, Please enter only digits between 0 and %i" % (string, maxValue)) + else: + #print("onAllowedEdit - Value=%i" % (value)) # DBGDBG + if(value > maxValue): + self.allowedEdit.ChangeValue(str(currentList.RevokeCounter)) + self.StatusBar.SetStatusText( "%i is too large, the max value for Allowed is %i" % ( value, maxValue )) + else: + currentList.RevokeCounter = value + print("onAllowedEdit - setting RevokeCounter=%i MaxValue=%i" % (value, maxValue)) + self.setListModified() + + def onSelectElementEdit(self, event): + """onSelectElementEdit - view the selected element""" + func = 'onSelectElementEdit' + + #selection = self.selectElementEdit.GetSelection() + selection = event.GetEventObject().GetSelection() + selectionString = event.GetString() + #self.setListModified() # just looking at different element shouldn't be considered modifying it. + #Element = DEFINES.ELEMENT + #Object = self.getObject() + currentList = self.pdef.getCurrentListObject() + #IncludeElement = utilities.getIncludeElement(currentList) + + # Using exhaustive find method to match selected element by it's element name and hash alg + #for element in self.includedElements: + # found = element.isElementType(selectionString) + # if found: + # self.StatusBar.SetStatusText( "Displaying the %s element" % (selectionString)) + # self.hideAllPanels() + # element.showPanel() + # self.visibleElement = selectionString + # currentList.CurrentElementView = selectionString + # break + + if(selectionString == DEFINES.ELEMENT_NAME_NONE): + self.StatusBar.SetStatusText( "No element selected") + self.visibleElement = selectionString + currentList.CurrentElementView = selectionString + self.hideAllPanels() + else: + self.StatusBar.SetStatusText( "Displaying the %s element" % (selectionString)) + self.hideAllPanels() + self.includedElements[selection-1].showPanel() + self.visibleElement = selectionString + currentList.CurrentElementView = selectionString + + + #TODO: wxPython: onSelectElementEdit - how to resize panel here? Or set min size after each panel is created? + print("%s: selection=%d, visibleElement=%s" % (func, self.selectElementEdit.GetSelection(), self.visibleElement)) # DBGDBG) + + def onDeleteElementButtonClick(self, event): + """ onDeleteElementButtonClick - delete the current element""" + func = 'onDeleteElementButtonClick' + self.StatusBar.SetStatusText( "Deleted the current element") + + #exit if None is selected, else confirm the deletion and continue + if(self.visibleElement == DEFINES.ELEMENT_NAME_NONE): + self.StatusBar.SetStatusText( "No element selected, Please select the element to be deleted") + return + + # confirm delete + dlg = wx.MessageDialog(None, "Deleted Elements cannot be recovered. Continue?", 'Confirm Element Deletion', wx.YES_NO | wx.ICON_QUESTION) + response = dlg.ShowModal() + dlg.Destroy() + + if(response == wx.ID_NO): + self.StatusBar.SetStatusText( "Element Deletion cancelled" ) + return + else: + self.StatusBar.SetStatusText( "Element deleted") + + # ComboBox selection value is one index higher than self.includedElement[] index and PLIST_DEF.ElementDefData[] index + # because of the None element to select no view. + selection = self.selectElementEdit.GetSelection() # get the index + selectionString = self.selectElementEdit.GetValue() # get selected element and populate into Add Element menu + self.selectElementEdit.Delete(selection) + print("%s - Selection=%d VisibleElement=%s - Removed" % (func, selection, self.visibleElement)) # DBGDBG + + currentElementsCnt = int(self.numberElementsEdit.GetValue()) + if(selection > 0): + nextselection = selection - 1 + # fixup selection for out of order case where selection 1 was deleted, but are > 1 elements left + # ie should only select 0 if 0 elements left ie None is the only choice left + # Scenario: create > 1 elements, select 1, delete 1. 1 still selected + if((nextselection == 0) and (currentElementsCnt > 1)): + nextselection = 1 + self.selectElementEdit.SetSelection(nextselection) + else: + print("%s: selectElementEdit.GetSelection() is invalid, Aborting!! % (func)") + return + + # set IncludeXXX to False + # hide the current element, show another element if one exists + self.setListModified() + #self.dumpIncludeXXX( currentListObject, 'before delete' ) # show current value of all the XXXDefData[i].IncludeXXXX # DBGDBG + + # Add deleted element back to Add Element menu. + self.updateAddElementChoicesAfterDelete(selectionString) + + # update myIndex of the elements behind this element + for count in range(selection, len(self.includedElements)): + self.includedElements[count].myIndex -= 1 + + # remove item from pdef list + currentListObject = self.pdef.getCurrentListObject() + currentListObject.ElementDefData.pop(selection-1) + + # update GUI to show other element + if selection > 0: + self.includedElements[selection-1].hidePanel() + # remove this element's GUI + self.includedElements.pop(selection-1) + + # nextselection is indexing into the updated self.includedElements[] + if nextselection != 0: + self.includedElements[nextselection-1].showPanel() + + # Set other GUI fields + currentElementsCnt -= 1 + self.numberElementsEdit.ChangeValue(str(currentElementsCnt)) + if(currentElementsCnt > 0): + self.selectElementEdit.Enable( True ) + self.addElementButton.Enable(True) + self.visibleElement = self.selectElementEdit.GetValue() + currentListObject.CurrentElementView = self.selectElementEdit.GetValue() + print("%s - Selection=%d VisibleElement=%s" % (func, selection, self.visibleElement)) # DBGDBG + elif(currentElementsCnt == 0): + self.selectElementEdit.Enable( False ) + self.deleteElementButton.Enable( False ) + self.visibleElement = DEFINES.ELEMENT_NAME_NONE + currentListObject.CurrentElementView = DEFINES.ELEMENT_NAME_NONE + + #self.dumpIncludeXXX( currentListObject, 'after delete' ) # show current value of all the XXXDefData[i].IncludeXXXX # DBGDBG + + # Object - array of all the mle, sbios, pconf & stm 1 and 256 objects + # Element - array of all the ELEMENT_NAME_XXXX_SHAYYY strings + # IncludeElement - array of all the XXXXDefData[DEFINES.DEFDATA_INDEX_SHANNN.IncludeXXXX + # updated to indicate the just deleted element's value is now False + # + def showNextElement(self, Object, Element, IncludeElement, currentListObject): + """showNextElement - if another element's panel exists, show it""" + func = 'showNextElement' + + i=0 + while(i < len(Element)): + #print("%s - checking %s" % (func, Element[i])) # DBGDBG + if(IncludeElement[i] == True): + print("%s - showing %s" % (func, Element[i])) # DBGDBG + Object[i].showPanel() + self.visibleElement = Element[i] + currentListObject.CurrentElementView = Element[i] + self.selectElementEdit.SetValue(Element[i]) + break + + i += 1 # next element + + + def onResetButtonClick(self, event): + """ onResetButtonClick - reset the revocation count""" + self.StatusBar.SetStatusText( "You clicked the Reset Button!") + + if(self.revocationCountEdit.GetValue() != "0"): + dlg = wx.MessageDialog(None, "Revocation Count reset cannot be undone. Continue?", 'Confirm Revocation Count reset', wx.YES_NO | wx.ICON_QUESTION) + response = dlg.ShowModal() + dlg.Destroy() + + if(response == wx.ID_NO): + self.StatusBar.SetStatusText( "Revocation Count reset cancelled" ) + else: + self.StatusBar.SetStatusText( "Reset the Revocation Count " ) + self.revocationCountEdit.ChangeValue("0") + currentList = self.pdef.getCurrentListObject() + currentList.RevocationCounter = 0 + #self.setListModified() # don't set list modified here as that re-increments the revocation ctr + self.resetButton.Enable(False) + + def onSync(self, event): + """ onSync - force Allowed to equal Revocation Count and disable Allowed""" + + self.StatusBar.SetStatusText("You checked Sync") + currentList = self.pdef.getCurrentListObject() + if(event.IsChecked()): + self.allowedEdit.ChangeValue(self.revocationCountEdit.GetValue()) + currentList.SyncRevCount = True + currentList.RevokeCounter = currentList.RevocationCounter + self.setListModified() + print("onSync - PolList[%i].RevCnt=%i, Allowed=%i" % + (self.pdef.CurrentListView, currentList.RevokeCounter, currentList.RevocationCounter)) # DBGDBG + else: + currentList.SyncRevCount = False + + # when checked disable editing the allowed box + self.allowedEdit.Enable(not event.IsChecked()) + + def enableDisableSigned(self, value, signAlgName='None'): + """enableDiableSigned - perform common actions when Signed or Algorithm changed""" + + # Note: Sync checkbox and Algorithm pulldown are redundant + # Sync unchecked == LCP_POLSALG_NONE + # Sync checked == LCP_POLSALG_RSA_PKCS_15 + + #If Unsigned [ie algorithm=None], then revocation count, allowed, RESET, Sync, Key File & Key Size are all disabled, + # else enabled + + currentList = self.pdef.getCurrentListObject() + keysizeList = DEFINES.SIGNATURE_KEY_SIZE[signAlgName] + + if(value == False): + #value = False + self.allowedEdit.Enable(value) + #currentList.SigAlgorithm = DEFINES.TPM_ALG_SIGN['NULL'] # 0=Not signed + #self.algorithmEdit.SetValue(DEFINES.ELEMENT_NAME_NONE) + else: + #value = True + self.allowedEdit.Enable(not value) + + self.setListModified() + self.resetButton.Enable(value) + self.Sync.Enable(value) + self.pubKeyFileEdit.Enable(value) + self.pvtKeyFileEdit.Enable(value) + self.pubBrowseButton.Enable(value) + self.pvtBrowseButton.Enable(value) + self.keySizeEdit.SetItems(keysizeList) + self.keySizeEdit.SetValue(str(currentList.KeySize)) + self.keySizeEdit.Enable(value) + self.revocationCountLabel.Enable(value) + self.allowedLabel.Enable(value) + self.pvtKeyFileSel.Enable(value) + self.pubKeyFileLabel.Enable(value) + self.keySizeLabel.Enable(value) + + def onPubKeyFileEdit(self, event): + """ onpubKeyFileEdit - update the key file""" + + currentList = self.pdef.getCurrentListObject() + currentList.PubKeyFile = event.GetString() + self.setListModified() + + # once the entire file name is entered, verify it, else clear it + if(currentList.PubKeyFile.endswith(".pem")): + if currentList.SigAlgorithm == DEFINES.TPM_ALG_SIGN['RSASSA']: + type = DEFINES.KEY_FILE_TYPE['PUBLIC_RSASSA'] + elif currentList.SigAlgorithm == DEFINES.TPM_ALG_SIGN['ECDSA']: + type = DEFINES.KEY_FILE_TYPE['PUBLIC_ECDSA'] + + if(utilities.verifyKeyFile(currentList.PubKeyFile, type, currentList) == False): + self.pubKeyFileEdit.ChangeValue("") + + def onPvtKeyFileSel(self, event): + """ onPvtKeyFileEdit - update the key file""" + currentList = self.pdef.getCurrentListObject() + selectionString = event.GetString() + if selectionString == "Private Key": + currentList.PvtKeyFileIsSignature = False + else: + currentList.PvtKeyFileIsSignature = True + + + def onPvtKeyFileEdit(self, event): + """ onPvtKeyFileEdit - update the key file""" + + currentList = self.pdef.getCurrentListObject() + currentList.PvtKeyFile = event.GetString() + self.setListModified() + + # once the entire file name is entered, verify it, else clear it + if((currentList.PvtKeyFile.endswith(".pem")) or (currentList.PvtKeyFile.endswith(".key"))): + if(utilities.verifyKeyFile(currentList.PvtKeyFile, KEY_FILE_TYPE_PRIVATE, currentList) == False): + self.pvtKeyFileEdit.ChangeValue("") + + def onKeySizeEdit(self, event): + """ onKeySizeEdit - update the key size""" + + currentList = self.pdef.getCurrentListObject() + currentList.KeySize = event.GetString() + self.setListModified() + self.StatusBar.SetStatusText("") # clear any previous error messages + + #if key file was all rdy specified, verify its size is correct + file = self.pubKeyFileEdit.GetValue() + if(file != ""): + if(utilities.verifyKeyFile(file, KEY_FILE_TYPE_PUBLIC, currentList) == False): + self.pubKeyFileEdit.ChangeValue("") + currentList.PubKeyFile = "" + + file = self.pvtKeyFileEdit.GetValue() + if(file != ""): + if(utilities.verifyKeyFile(file, KEY_FILE_TYPE_PRIVATE, currentList) == False): + self.pvtKeyFileEdit.ChangeValue("") + currentList.PvtKeyFile = "" + + def onPvtBrowseButtonClick(self, event): + """ onPvtBrowseButtonClick - browse to an existing PDEF file""" + + #self.StatusBar.SetStatusText("You clicked the Browse button") + #TODO: Bill: handle .pems that have both the public and private keys? + #TODO: Bill: handle .pems with password protected private keys? + + currentList = self.pdef.getCurrentListObject() + #accept .key as well as pem files for private keys? + dirname = '' # current working directory + workdir = self.pdef.WorkingDirectory + + if currentList.PvtKeyFileIsSignature: + title = "Choose the Signature file" + wildcard = "All Files (*.*) | *.*" \ + "Key file (*.sig) | *.sig|" + else: + title = "Choose the Private Key file" + wildcard = "Key file (*.pem) | *.pem|" \ + "Key file (*.key) | *.key|" \ + "All Files (*.*) | *.*" + dlg = wx.FileDialog(self.parent, title, workdir, "", wildcard, wx.FD_OPEN) + + if dlg.ShowModal() == wx.ID_OK: + filename = dlg.GetFilename() + dirname = dlg.GetDirectory() + + self.pvtKeyFileEdit.ChangeValue(filename) + currentList.PvtKeyFile = filename + self.setListModified() + + if currentList.SigAlgorithm == DEFINES.TPM_ALG_SIGN['RSASSA']: + filetype = DEFINES.KEY_FILE_TYPE['PRIVATE_RSASSA'] + else: + filetype = DEFINES.KEY_FILE_TYPE['PRIVATE_ECDSA'] + + if currentList.PvtKeyFileIsSignature: + #copy signature file to the current working directory + pass + else: + # Verify Private Key file + if(utilities.verifyKeyFile(os.path.join(dirname, currentList.PvtKeyFile), filetype, currentList) == False): + self.pvtKeyFileEdit.ChangeValue("") + currentList.PvtKeyFile = "" + elif (dirname != workdir): + if (os.path.exists(os.path.join(workdir, filename))) : + confdlg = wx.MessageDialog(self.parent, filename+" already exists in working directory\nOverwrite file in working directory?", "Confirm Copy", wx.OK|wx.CANCEL|wx.ICON_QUESTION) + abortFlag = False + if (confdlg.ShowModal() == wx.ID_OK): + shutil.copyfile(os.path.join(dirname, filename), os.path.join(workdir, filename)) + else: + abortFlag = True + + confdlg.Destroy() + if(abortFlag == True): + if(utilities.verifyKeyFile(os.path.join(workdir, currentList.PvtKeyFile), filetype, currentList) == False): + # don't change + self.pvtKeyFileEdit.ChangeValue("") + currentList.PvtKeyFile = "" + self.StatusBar.SetStatusText( "Copy cancelled, using exiting key" ) + else: + shutil.copyfile(os.path.join(dirname, filename), os.path.join(workdir, filename)) + + dlg.Destroy() + #print("onPvtBrowseButtonClick: %s" % (currentList.PvtKeyFile)) # DBGDBG + + def onPubBrowseButtonClick(self, event): + """ onPubBrowseButtonClick - browse to an existing PDEF file""" + + #self.StatusBar.SetStatusText("You clicked the Browse button") + dirname = '' # current working directory + workdir = self.pdef.WorkingDirectory + wildcard = "Key file (*.pem) | *.pem|" \ + "All Files (*.*) | *.*" + dlg = wx.FileDialog(self.parent, "Choose the Public Key file", workdir, "", wildcard, wx.FD_OPEN) + + currentList = self.pdef.getCurrentListObject() + if currentList.SigAlgorithm == DEFINES.TPM_ALG_SIGN['RSASSA']: + filetype = DEFINES.KEY_FILE_TYPE['PUBLIC_RSASSA'] + else: + # treat SM2 as ECDSA key + filetype = DEFINES.KEY_FILE_TYPE['PUBLIC_ECDSA'] + + if dlg.ShowModal() == wx.ID_OK: + filename = dlg.GetFilename() + dirname = dlg.GetDirectory() + + self.pubKeyFileEdit.ChangeValue(filename) + currentList.PubKeyFile = filename + self.setListModified() + if(utilities.verifyKeyFile(os.path.join(dirname, currentList.PubKeyFile), filetype, currentList) == False): + self.pubKeyFileEdit.ChangeValue("") + currentList.PubKeyFile = "" + elif (dirname != workdir): + if (os.path.exists(os.path.join(workdir, filename))) : + confdlg = wx.MessageDialog(self.parent, filename+" already exists in working directory\nOverwrite file in working directory?", "Confirm Copy", wx.OK|wx.CANCEL|wx.ICON_QUESTION) + abortFlag = False + if (confdlg.ShowModal() == wx.ID_OK): + shutil.copyfile(os.path.join(dirname, filename), os.path.join(workdir, filename)) + else: + abortFlag = True + + confdlg.Destroy() + if(abortFlag == True): + # verify the existing file + if(utilities.verifyKeyFile(os.path.join(workdir, currentList.PubKeyFile), filetype, currentList) == False): + self.pubKeyFileEdit.ChangeValue("") + currentList.PubKeyFile = "" + self.StatusBar.SetStatusText( "Copy cancelled, using exiting key" ) + else: + shutil.copyfile(os.path.join(dirname, filename), os.path.join(workdir, filename)) + + dlg.Destroy() + #print("onPubBrowseButtonClick: %s" % (currentList.PubKeyFile)) # DBGDBG + + def onAlgorithmEdit(self, event): + """ onAlgorithmEdit - select the algorithm""" + + func = "onAlgorithmEdit" + currentList = self.pdef.getCurrentListObject() + selectionString = event.GetString() + algName = selectionString.split('/') + if len(algName) == 2: + sigAlg = algName[0].split(' ')[0] + hashAlg = algName[1] + + # Check for valid signature algorithm name + try: + sigAlgName = (key for key in DEFINES.TPM_ALG_SIGN.keys() if (sigAlg in key)).next() + except StopIteration: + self.StatusBar.SetStatusText("Signature algorithm name mismatch") + print("%s - Signature algorithm name mismatch" % (func)) # DBGDBG + return + + # Check for valid algorithm name + try: + hashAlgName = (key for key in DEFINES.TPM_ALG_HASH.keys() if (hashAlg in key)).next() + except StopIteration: + self.StatusBar.SetStatusText("Hash algotithm name mismatch") + print("%s - Hash algorithm name mismatch" % (func)) # DBGDBG + return + + currentList.SigAlgorithm = DEFINES.TPM_ALG_SIGN[sigAlgName] + currentList.sigAlgorithmHash = DEFINES.TPM_ALG_HASH[hashAlgName] + if currentList.KeySize not in DEFINES.SIGNATURE_KEY_SIZE[selectionString]: + currentList.KeySize = DEFINES.SIGNATURE_KEY_SIZE[selectionString][0] + self.enableDisableSigned(True, selectionString) + else: + currentList.SigAlgorithm = DEFINES.TPM_ALG_SIGN['NULL'] + self.enableDisableSigned(False) + + + def onAddElementClick(self, event): + """onAddElementClick""" + func = "onAddElementClick" + + # ask user to select the type of element and its hash algorithm + if(self.pdef.Rules == DEFINES.PsRules): + addElementChoices = self.addElementChoicesPs + elif(self.pdef.Rules == DEFINES.PoRules): + addElementChoices = self.addElementChoicesPo + else: + print("%s - invalid pdef.Rules=%d" % (func, self.pdef.Rules)) + return + + message = "Select the type of element and its hash algorithm" + title = "Add Element Selections" + dialog = wx.SingleChoiceDialog(None, message, title, addElementChoices) + if dialog.ShowModal() == wx.ID_OK: + requestedElement = dialog.GetStringSelection() + else: + dialog.Destroy() + return # cancel out + + dialog.Destroy() + self.StatusBar.SetStatusText("Adding a %s element to this LIST" % (requestedElement)) + + print("%s: adding %s" % (func, requestedElement)) # DBGDBG + self.deleteElementButton.Enable( True ) + currentListObject = self.pdef.getCurrentListObject() + self.selectElementEdit.Enable( True ) + currentElementsCnt = int(self.numberElementsEdit.GetValue()) + currentElementsCnt += 1 + self.numberElementsEdit.ChangeValue(str(currentElementsCnt)) + + # if an element is being shown, hide it. Then show the new one + if(currentListObject.CurrentElementView != DEFINES.ELEMENT_NAME_NONE): + self.hideThisPanel(currentListObject.CurrentElementView) + + currentListObject.CurrentElementView = requestedElement + self.selectElementEdit.Append(requestedElement) + currentSelection = self.selectElementEdit.GetSelection() + #print("%s: currentSelection=%d newSelection=%d" % (func, currentSelection, currentSelection+1)) # DBGDBG + self.selectElementEdit.SetSelection(currentSelection + 1) + self.selectElementEdit.SetValue(requestedElement) + self.updateAddElementChoicesAfterAdd(requestedElement) + self.visibleElement = requestedElement + + # Create a new element of selected spec and populate into currentListObject.MleDefData + elementType, hashAlg = requestedElement.split('-') + + if hashAlg == 'LEGACY': + if elementType == 'SBIOS': + element = SBIOSLegacy() + defdata = SBIOSLEGACY_DEF() + elif elementType == 'MLE': + element = MLELegacy() + defdata = MLELEGACY_DEF() + elif elementType == 'PCONF': + element = PCONFLegacy() + defdata = PCONFLEGACY_DEF() + else: + print ("ERROR: invalid element") + else: + if elementType == 'SBIOS': + element = SBIOS(DEFINES.TPM_ALG_HASH[hashAlg]) # GUI panel + defdata = SBIOS_DEF(DEFINES.TPM_ALG_HASH[hashAlg]) # Element defined in pdef.py + elif elementType == 'STM': + element = STM(DEFINES.TPM_ALG_HASH[hashAlg]) + defdata = STM_DEF(DEFINES.TPM_ALG_HASH[hashAlg]) + elif elementType == 'MLE': + element = MLE(DEFINES.TPM_ALG_HASH[hashAlg]) + defdata = MLE_DEF(DEFINES.TPM_ALG_HASH[hashAlg]) + elif elementType == 'PCONF': + element = PCONF(DEFINES.TPM_ALG_HASH[hashAlg]) + defdata = PCONF_DEF(DEFINES.TPM_ALG_HASH[hashAlg]) + else: + print ("ERROR: invalid element") + + currentListObject.ElementDefData.append(defdata) + element.createOrShowPanel(wx, self, self.parent, self.pdef, self.StatusBar) + self.includedElements.append(element) + + # Note - panels were constructed with the correct hashAlg, so no need to pass that thru here + # Note - iterators not used here since need to update the pdef's xxxDefData.IncludeXXX not the array's + + self.selectElementEdit.Enable(True) + self.parent.Layout() + + + def syncVersion(self, rule): + currentList = self.pdef.getCurrentListObject() + listversion = str(currentList.ListVersionMajor)+'.'+str(currentList.ListVersionMinor) + self.versionEdit.ChangeValue(listversion) + if rule == DEFINES.PoRules: + enable = True + else: + enable = False + for element in self.includedElements: + element.restorePanel(currentList, self.pdef.MaxHashes) + element.enableDisableOverridePsPolicy(enable) + + + def checkListModified(self, pdef): + """checkListModified - return True if any list has been modified, else False""" + + # pdef.PolListInfo is a dictionary of 8 PLIST_DEF's from '0' to '7' + # or None if that list was not added + # i.e. {'0':PLIST_DEF or None, ... '7':PLIST_DEF or None} + # + i = '0' + while(i<'8'): + #print("checkListModified list %s" % (i)) # DBGDBG + if(pdef.PolListInfo[i] != None): # if list exists + if(pdef.PolListInfo[i].ListModified == True): + print("checkListModified Return - list %s was modified" % (i)) # DBGDBG + return True + + i = str(int(i) + 1) + + return False + + + def setListModified(self): + """setListModified - if list not modified yet, increment its rev cnt and set it to modified""" + + currentList = self.pdef.getCurrentListObject() + #also set pdef.Modified for saving file\ + self.pdef.Modified = True + #print("setListModified - ListModified=%s" % (currentList.ListModified)) # DBGDBG + if(currentList.ListModified == False): + currentList.RevocationCounter += 1 + self.resetButton.Enable(True) + + self.revocationCountEdit.ChangeValue(str(currentList.RevocationCounter)) # update the GUI + currentList.ListModified = True + + def rebuildSelectElementChoices(self): + """rebuildSelectElementChoices - rebuild selectElementEdit's choices list for the elements existing in this view""" + func = 'rebuildSelectElementChoices' + + self.selectElementEdit.Clear() + self.selectElementEdit.Append('None') + # For each existing element in this list (ie IncludeXXXX==True) + currentList = self.pdef.getCurrentListObject() + for element in currentList.ElementDefData: + self.selectElementEdit.Append(element.Name) + + + # remove the added element from the add element selection list + def updateAddElementChoicesAfterAdd(self, requestedElement): + """updateAddElementChoicesAfterAdd""" + func = 'updateAddElementChoicesAfterAdd' + + if(self.pdef.Rules == DEFINES.PoRules): + self.addElementChoicesPo.remove(requestedElement) + if(len(self.addElementChoicesPo) == 0): + self.addElementButton.Enable(False) + if(self.pdef.Rules == DEFINES.PsRules): + self.addElementChoicesPs.remove(requestedElement) + if(len(self.addElementChoicesPs) == 0): + self.addElementButton.Enable(False) + + # append the deleted element to the add element selection list + def updateAddElementChoicesAfterDelete(self, deletedElement): + """updateAddElementChoicesAfterDelete""" + func='updateAddElementChoicesAfterDelete' + + # append the deleted element to the add element selection list + self.addElementChoicesPs.append(deletedElement) + self.addElementChoicesPo.append(deletedElement) + + + # rebuild the add element selection list to include all the elements that don't exist + def rebuildAddElementChoices(self): + """rebuildAddElementChoices""" + self.rebuildAddElementChoicesForPoRules() + self.rebuildAddElementChoicesForPsRules() + + # if a PO rules element doesn't exist, add it to the selections list + def rebuildAddElementChoicesForPoRules(self): + """rebuildAddElementChoicesForPoRules""" + func='rebuildAddElementChoicesForPoRules' + + #Element = DEFINES.ELEMENT_PO_RULES + self.addElementChoicesPo = [] + self.addElementChoicesPo += DEFINES.ELEMENT_PO_RULES + currentList = self.pdef.getCurrentListObject() + + for element in currentList.ElementDefData: + if element.Name in self.addElementChoicesPo: + self.addElementChoicesPo.remove(element.Name) + else: + print ("Element Name %s not found in Elements for PO rule" %(element.Name)) + + if len(currentList.ElementDefData) >= 8 or len(self.addElementChoicesPs) == 0: + flag = False + else: + flag = True + self.addElementButton.Enable(flag) + #print("%s - addElementChoicesPo=%s" % (func, self.addElementChoicesPo)) #DBGDBG + + # if a PS rules element doesn't exist, add it to the selections list + def rebuildAddElementChoicesForPsRules(self): + """rebuildAddElementChoicesForPsRules""" + func='rebuildAddElementChoicesForPsRules' + + #Element = DEFINES.ELEMENT # gets all the elements i.e. = PS rules + self.addElementChoicesPs = [] + self.addElementChoicesPs += DEFINES.ELEMENT # gets all the elements i.e. = PS rules + currentList = self.pdef.getCurrentListObject() + + for element in currentList.ElementDefData: + if element.Name in self.addElementChoicesPs: + self.addElementChoicesPs.remove(element.Name) + else: + print ("Element Name %s not found in Elements for PS rule" %(element.Name)) + + if len(currentList.ElementDefData) >= 8 or len(self.addElementChoicesPs) == 0: + flag = False + else: + flag = True + self.addElementButton.Enable(flag) + #print("%s - addElementChoicesPs=%s" % (func, self.addElementChoicesPs)) #DBGDBG + + def loadAndDisplayPlistDefFile(self, file, wx, pdef, statusBar, parent): + """ loadAndDisplayPlistDefFile - get a saved plistDef object from a PDEF file and update the list panel""" + func = 'loadAndDisplayPlistDefFile' + + self.pdef = pdef + self.StatusBar = statusBar + self.parent = parent + + print("%s load plistDef %d, NumLists=%d" % (func, pdef.CurrentListView, pdef.NumLists)) # DBGDBG + currentListObject = self.pdef.getCurrentListObject() + + + # If this list is to be the displayed list panel[ie pdef.CurrentListView] + # then restore the list panel & enable/disable the AddElement buttons + # restore the list's element panels that exist but hide them + # only show & restore the specified element [ie list.CurrentElementView] + # + print("%s thisListNum=%d, CurrentListView=%d" % (func, pdef.CurrentListView, pdef.CurrentListView)) # DBGDBG + if(self.listPanelWidgets == []): + self.createListPanel(wx, parent, pdef.CurrentListView, pdef, statusBar) + else: + # in case list or element panels all ready exist ... + self.hideListPanel() + for i in self.listPanelWidgets: + i.Show() + + self.setListPanelToCurrentListView() + #currentListObject.ListModified = False + + def printPlistDefs(self, pdef, f): + """printPlistDefs - write all created PLIST_DEFs to the specified human readable text file for printing""" + + # pdef.PolListInfo is a dictionary of 8 PLIST_DEF's from '0' to '7' + # or None if that list was not added + # i.e. {'0':PLIST_DEF or None, ... '7':PLIST_DEF or None} + # + i = '0' # i is 0 based index for loop control + cnt = '1' # cnt is 1 based 'i' for printing + while(i<'8'): + print("PlistInfo", cnt, " = ", pdef.PolListInfo[i], file=f) + if(pdef.PolListInfo[i] != None): + self.printPlistDef(pdef.PolListInfo[i], f) # write this PolListInfo[] + + i = str(int(i) + 1) + cnt = str(int(cnt) + 1) + + def printPlistDef(self, plistDef, f): + """printPlistDef - write this PLIST_DEF to the specified human readable text file for printing""" + + #print("printPlistDef - PLIST_DEF object: %s" % (plistDef)) # DBGDBG + + print("LdefSize", " = ", plistDef.LdefSize, file=f) + print("Tag", " = ", plistDef.Tag, file=f) + print("ListVersion", " = ", plistDef.ListVersionMajor, ".", plistDef.ListVersionMinor, sep='', file=f) + print("ListValid", " = ", plistDef.ListValid, file=f) + print("ListModified", " = ", plistDef.ListModified, file=f) + print("SigAlgorithm", " = ", hex(plistDef.SigAlgorithm), file=f) + print("sigAlgorithmHash", " = ", hex(plistDef.sigAlgorithmHash), file=f) + print("PolicyElementSize", " = ", plistDef.PolicyElementSize, file=f) + print("CurrentElementView", " = ", plistDef.CurrentElementView, file=f) + print("SyncRevCount", " = ", plistDef.SyncRevCount, file=f) + print("AllowedCounter", " = ", plistDef.RevokeCounter, file=f) + print("RevocationCounter", " = ", plistDef.RevocationCounter, file=f) + print("KeySize", " = ", plistDef.KeySize, file=f) + print("PubKeyFile", " = ", plistDef.PubKeyFile, file=f) + print("PvtKeyFile", " = ", plistDef.PvtKeyFile, file=f) + + currentListObject = plistDef + + # print the element summary showing which elements were created + # Lists always contain all elements, even if they haven't been added + # so need to check if they should be included + for element in plistDef.ElementDefData: + print("%s DefData[Index]"% (element.Name), " = ", element, file=f) + element.printDef(f) + print("\n", file=f) # for readability + + +# def enablePconfOverridePsPolicyCheckbox(self, value): +# """enablePconfOverridePsPolicyCheckbox - if current list has a PCONF element, enable its OverridePsPolicy checkbox""" +# +# currentList = self.pdef.getCurrentListObject() +# if(currentList.PconfDefData[DEFINES.DEFDATA_INDEX['SHA256']].IncludeInList == True): +# pconf256.enablePconfOverridePsPolicyCheckbox(value) +# if(currentList.PconfDefData[DEFINES.DEFDATA_INDEX['SHA1']].IncludeInList == True): +# pconf1.enablePconfOverridePsPolicyCheckbox(value) +# if(currentList.PconfLegacyDefData[DEFINES.DEFDATA_INDEX['SHA1']].IncludeInList == True): +# pconf0.enablePconfOverridePsPolicyCheckbox(value) + + + def hideAllPanels( self ): + """hideAllPanels - hide all the element panels""" + + for element in self.includedElements: + element.hidePanel() + + + def hideThisPanel( self, panelToHide ): + """hideThisPanel""" + + for element in self.includedElements: + found = element.isElementType(panelToHide) + if found: + element.hidePanel() + + print("hideThisPanel: %s" % (panelToHide)) # DBGDBG + + # the last function in the file doesn't show up in the scope list in Understand for some reason! + def stub(self): + pass + diff -Nru tboot-1.9.4/lcp-gen2/mleLegacy.py tboot-1.9.5/lcp-gen2/mleLegacy.py --- tboot-1.9.4/lcp-gen2/mleLegacy.py 1970-01-01 00:00:00.000000000 +0000 +++ tboot-1.9.5/lcp-gen2/mleLegacy.py 2016-12-17 03:19:38.000000000 +0000 @@ -0,0 +1,433 @@ +#!/usr/bin/python +# Copyright (c) 2013, Intel Corporation. All rights reserved. + +# using print() built infunction, disable print statement +from __future__ import print_function + +# +# wxPython is not part of the standard Python distribution and has to be downloaded and installed separately. +# Tell the user that wxPython is required but has not been found +# +try: + import wx +except ImportError: + raise ImportError, "Please download the appropriate version of wxPython from www.wxpython.org" + +try: + import os + import shutil +except ImportError: + raise ImportError, "import OS failed" + +from defines import DEFINES +from pdef import MLELEGACY_DEF +from ElementGui import * + +from util import UTILS +utilities = UTILS() + +try: + import cPickle as pickle +except ImportError: + import pickle # fall back on Python version + +# TXT Policy Generator Tool +# MLE Class - Policy Definition File Lists +# +class MLELegacy( ElementGui ): + + CONST_TITLE = "Choose Hash File" + CONST_WILDCARD = "Hash file (*.hash) | *.hash|" \ + "All Files (*.*) | *.*" + + """__init__() - MLE class constructor""" + def __init__( self ): + self.mlePanelWidgets = [] + self.panelCreated = False + + # + # create the MLE Panel + # + def createOrShowPanel(self, wx, listPanel, parent, pdef, statusBar): + """createMlePanel - create the List Panel""" + + #print("createOrShowPanel panelCreated == %s" % (self.panelCreated)) # DBGDBG + # 1st time, create the panel + # nth time, show the panel + if(self.panelCreated == True): + self.showPanel() + return + + self.pdef = pdef + self.parent = parent + self.listPanel = listPanel + self.StatusBar = statusBar + parentSizer = parent.GetSizer() + + currentList = self.pdef.getCurrentListObject() + self.myIndex = len(currentList.ElementDefData)-1 # Just added the element, the last one should be the one. + + # create the Mle Panel sizers + #self.mlePanelSizer = wx.BoxSizer(wx.VERTICAL) + self.mleGridSizer= wx.GridBagSizer(hgap=5, vgap=5) + #self.mleHorizSizer = wx.BoxSizer(wx.HORIZONTAL) + + self.mlePanel = wx.Panel(parent, -1) + self.mlePanel.SetSizer(self.mleGridSizer) + + mleLabelText1 = "MLE" + mleLabelText2 = "Element" + mleLabel1 = wx.StaticText(self.mlePanel, -1, mleLabelText1) + mleLabel2 = wx.StaticText(self.mlePanel, -1, mleLabelText2) + font = wx.Font( 18, wx.FONTFAMILY_DEFAULT, wx.NORMAL, wx.BOLD) + mleLabel1.SetFont( font ) + self.mleGridSizer.Add( mleLabel1, pos=(0, 3)) + self.mlePanelWidgets.append(mleLabel1) + mleLabel2.SetFont( font ) + self.mleGridSizer.Add( mleLabel2, pos=(0, 4)) + self.mlePanelWidgets.append(mleLabel2) + + typeLabel = wx.StaticText(self.mlePanel, label="Type") + self.mleGridSizer.Add( typeLabel, pos=(1,3)) + self.mlePanelWidgets.append(typeLabel) + typeEdit = wx.TextCtrl( self.mlePanel, value="MLE", size=(40, -1)) + typeEdit.Enable( False ) + self.mleGridSizer.Add( typeEdit, pos=(1,4)) + self.mlePanelWidgets.append(typeEdit) + + contolOptionsLabel = wx.StaticText(self.mlePanel, -1, "Control") + font = wx.Font( 10, wx.FONTFAMILY_DEFAULT, wx.NORMAL, wx.BOLD) + contolOptionsLabel.SetFont( font ) + + # override PS policy bit is applicable only if PO policy rules + self.overridePsPolicy = wx.CheckBox(self.mlePanel, label="Override PS Policy") + + if(self.pdef.Rules == DEFINES.PoRules): + self.overridePsPolicy.Enable( True ) + else: + self.overridePsPolicy.Enable( False ) + + self.mleGridSizer.Add(contolOptionsLabel, pos=(0,9), span=(1,2), flag=wx.BOTTOM, border=5) + self.mleGridSizer.Add(self.overridePsPolicy, pos=(1,9), span=(1,2), flag=wx.BOTTOM, border=5) + self.overridePsPolicy.Bind(wx.EVT_CHECKBOX, self.onOverridePsPolicy) + self.mlePanelWidgets.append(contolOptionsLabel) + self.mlePanelWidgets.append(self.overridePsPolicy) + + # STPM is required bit ElementPolicyControl[1] + #self.stmIsRequired = wx.CheckBox(self.mlePanel, label="STM is required") + #self.mleGridSizer.Add(self.stmIsRequired, pos=(2,9), span=(1,2), flag=wx.BOTTOM, border=5) + #self.stmIsRequired.Bind(wx.EVT_CHECKBOX, self.onOverridePsPolicy) # TODO: add function to handle event. + #self.mlePanelWidgets.append(self.stmIsRequired) + + hashList = ['SHA1'] + hashAlgLabel = wx.StaticText(self.mlePanel, label="Hash Algorithm") + font = wx.Font( 10, wx.FONTFAMILY_DEFAULT, wx.NORMAL, wx.BOLD) + hashAlgLabel.SetFont( font ) + self.mleGridSizer.Add(hashAlgLabel, pos=(0,20)) + self.mlePanelWidgets.append(hashAlgLabel) + + hashAlgEdit = wx.ComboBox( self.mlePanel, size=(75, -1), value="SHA1", choices=hashList, style=wx.CB_DROPDOWN ) + self.mleGridSizer.Add(hashAlgEdit, pos=(1,20)) + self.mlePanelWidgets.append(hashAlgEdit) + + minSinitVersionLabel = wx.StaticText(self.mlePanel, label="Min SINIT Version: ") + self.mleGridSizer.Add(minSinitVersionLabel, pos=(2,4)) + self.mlePanelWidgets.append(minSinitVersionLabel) + minSinitVersion = pdef.SinitMinVersion # get current value + currentList.ElementDefData[self.myIndex].SinitMinVersion = minSinitVersion + + self.minSinitVersionEdit = wx.TextCtrl( self.mlePanel, value=str(minSinitVersion), size=(30, -1)) + self.mleGridSizer.Add( self.minSinitVersionEdit, pos=(2,5)) + self.minSinitVersionEdit.Bind(wx.EVT_TEXT, self.onMinSinitVersion) + self.mlePanelWidgets.append(self.minSinitVersionEdit) + + self.addButton = wx.Button( self.mlePanel, -1, label=" Add ") + self.mleGridSizer.Add( self.addButton, pos=(4,3)) + self.mlePanelWidgets.append(self.addButton) + self.addButton.Bind(wx.EVT_BUTTON, self.onAddButtonClick) + self.mlePanelWidgets.append(self.addButton) + + self.removeButton = wx.Button( self.mlePanel, -1, label=" Remove ") + self.mleGridSizer.Add( self.removeButton, pos=(4,5)) + self.mlePanelWidgets.append(self.removeButton) + self.removeButton.Bind(wx.EVT_BUTTON, self.onRemoveButtonClick) + self.mlePanelWidgets.append(self.removeButton) + + self.hashListLabel = wx.StaticText(self.mlePanel, label=" Hash File List") + font = wx.Font( 10, wx.FONTFAMILY_DEFAULT, wx.NORMAL, wx.BOLD) + self.hashListLabel.SetFont( font ) + self.mleGridSizer.Add( self.hashListLabel, pos=(3,4)) + self.mlePanelWidgets.append(self.hashListLabel) + + self.fileCntLabel = wx.StaticText(self.mlePanel, label="Number of Files") + self.mleGridSizer.Add( self.fileCntLabel, pos=(5,3)) + self.mlePanelWidgets.append(self.fileCntLabel) + self.fileCntEdit = wx.TextCtrl( self.mlePanel, value="0", size=(40, -1)) + self.fileCntEdit.Enable( False ) + self.mleGridSizer.Add( self.fileCntEdit, pos=(5,4)) + self.mlePanelWidgets.append(self.fileCntEdit) + + hashFileList = [''] + + self.hashListBox = wx.TextCtrl( self.mlePanel, value="", size=(150, 120), style = wx.TE_MULTILINE) # Note: add |wx.HSCROLL to get a horiz scroll bar + # hashListBox must be enabled so can select items to remove + self.hashListBox.Bind(wx.EVT_TEXT, self.onHashListBoxEdit) + self.hashListBox.SetInsertionPoint(0) + self.mleGridSizer.Add( self.hashListBox, pos=(4,4)) + self.mlePanelWidgets.append(self.hashListBox) + + self.mlePanelWidgets.append(self.mlePanel) + + #self.mleHorizSizer.Add(self.mleGridSizer, 0, wx.ALL, 5) + #self.mlePanelSizer.Add(self.mleHorizSizer, 0, wx.ALL, 5) + #parent.SetSizerAndFit(self.mlePanelSizer) + parentSizer.Add(self.mlePanel) + w,h = parentSizer.GetMinSize() + parent.SetVirtualSize((w,h)) + print("parent sizer type = %s size = %d, %d" %(type(parentSizer).__name__, w, h)) + parent.Layout() + # call restorePanel to sync data to GUI + self.restorePanel(currentList, pdef.MaxHashes) + self.panelCreated = True + + def hidePanel(self): + """hidePanel - hide the Mle panel""" + + for i in self.mlePanelWidgets: + i.Hide() + + + def showPanel(self): + """showPanel - show the mle panel""" + + if self.panelCreated: + for i in self.mlePanelWidgets: + i.Show() + parentSizer = self.parent.GetSizer() + w,h = parentSizer.GetMinSize() + self.parent.SetVirtualSize((w,h)) + + + def setElementToDefaults(self): + """setElementToDefaults - MLE""" + + currentList = self.pdef.getCurrentListObject() + currentList.ElementDefData[self.myIndex].IncludeInList = False + currentList.ElementDefData[self.myIndex].HashAlg = 0 + currentList.ElementDefData[self.myIndex].SinitMinVersion = 0 + currentList.ElementDefData[self.myIndex].HashAlg = 0 + currentList.ElementDefData[self.myIndex].Control = 0 + currentList.ElementDefData[self.myIndex].NumbHashes = 0 + currentList.ElementDefData[self.myIndex].CurrentView = 0 + currentList.ElementDefData[self.myIndex].HashFiles = [] + + def onOverridePsPolicy(self, event): + currentList = self.pdef.getCurrentListObject() + self.setListModified() + # set/clear bit 0 per MLE Dev Guide PolEltControl def + if(event.Checked() == True): + currentList.MleLegacyDefData[self.myIndex].Control = 1 + else: + currentList.MleLegacyDefData[self.myIndex].Control = 0 + + def onMinSinitVersion(self, event): + value = event.GetString() + currentList = self.pdef.getCurrentListObject() + self.setListModified() + currentList.ElementDefData[self.myIndex].SinitMinVersion = int(value) + #print("MLE::onMinSinitVersion - SinitMinVersion = %d" % (currentList.ElementDefData[self.myIndex].SinitMinVersion)) # DBGDBG + + # only supports adding files with the add button, not entering the names directly + def onHashListBoxEdit(self, event): + """onHashListBoxEdit""" + #print("in MLE::onHashListBoxEdit") # DBGDBG + + # tell the user to add button and clear the field + self.StatusBar.SetStatusText("Please clear the entry, then use the Add button to add hash files to the list") + #self.hashListBox.Undo() + #TODO: wxPython: onHashListBoxEdit - Clear() and Undo() both generate an event causing: RuntimeError: maximum recursion depth exceeded + + def onAddButtonClick(self, event): + """onAddButtonClick - add a hash file to the list""" + + workdir = self.pdef.WorkingDirectory + filepath, filename = self.selectFile() + + if (filename == ''): + # selectFile() operation has been cancelled. + return + + # validate that the specified hash file is properly formatted + currentList = self.pdef.getCurrentListObject() + result = utilities.verifyHashFile(os.path.join(filepath, filename), currentList.ElementDefData[self.myIndex].HashAlg) + # Note: verifyHashFile() returns [FileValid, FileType], but only FileValid is used here + if( result[0] == False): + return + + self.copyFile(filepath, filename) + self.StatusBar.SetStatusText("Validated file %s." % (filename)) + + # update the file count and enable the remove button + lineCnt = currentList.ElementDefData[self.myIndex].NumbHashes + #print("onAddButtonClick: was %i lines" % (lineCnt)) # DBGDBG + lineCnt += 1 + + # MaxHashes = 0 means there is no limit on the number of hash files allowed + if(self.pdef.MaxHashes != 0): + if(lineCnt > self.pdef.MaxHashes): + self.StatusBar.SetStatusText("Only %d files can be added." % (self.pdef.MaxHashes)) + return + + #print("onAddButtonClick: now %i lines" % (lineCnt)) # DBGDBG + self.fileCntEdit.ChangeValue(str(lineCnt)) + self.removeButton.Enable(True) + + hashFileList = currentList.ElementDefData[self.myIndex].HashFiles + hashFileList.append(filename) + #print("new hashFileList = %s" % (hashFileList)) # DBGDBG + + # insert the new file into mle.HashFiles + self.setListModified() + currentList.ElementDefData[self.myIndex].HashFiles = hashFileList + currentList.ElementDefData[self.myIndex].NumbHashes = lineCnt + #print("MleLegacyDefData.NumbHashes=%i, HashFiles = %s" % (currentList.MleLegacyDefData[DEFINES.DEFDATA_INDEX['SHA1']].NumbHashes, currentList.MleLegacyDefData[DEFINES.DEFDATA_INDEX['SHA1']].HashFiles)) # DBGDBG + + # since hashListBox.AppendText() generates an event to onHashListBoxEdit() + # and since hashListBoxEdit has to be enabled so text can be selected for Remove + # and direct text entry by the user into hashListBoxEdit is not supported due the complexity of validating it ... + # + # hashListBox.ChangeValue() doesn't generate an event but only takes a string, not a hashFileList which is a list ie '[]' + # so form a single string containing everything in hashFileList and update hashListBox using ChangeValue(hashFileString) + hashFileString = '' + index = 0 + for eachString in hashFileList: + if(index != 0): # if not the 1st entry, need a LF before the new entry + hashFileString += "\n" + hashFileString += eachString + index += 1 + #print("thisString=%s, hashFileString=%s" % (eachString, hashFileString)) + + self.hashListBox.ChangeValue(hashFileString) + + def onRemoveButtonClick(self, event): + """onRemoveButtonClick - remove the selected entry from the hash file list""" + + # confirm the remove + dlg = wx.MessageDialog(None, "Confirm removal of selected file?", 'Confirm Remove', wx.YES_NO | wx.ICON_QUESTION) + response = dlg.ShowModal() + dlg.Destroy() + + if(response == wx.ID_NO): + self.StatusBar.SetStatusText( "Remove cancelled" ) + return + + selection = self.hashListBox.GetStringSelection() + self.StatusBar.SetStatusText("Removed selection %s" % (selection)) + + # selection may not be a full line ... See if the selection is contianed in any of hashFileList's entries + currentList = self.pdef.getCurrentListObject() + hashFileList = currentList.ElementDefData[self.myIndex].HashFiles + for entry in hashFileList: + #print("entry=%s" % (entry)) # DBGDBG + start = entry.find(selection) + if(start != -1): # -1 means not found, else find returns the starting index of selection + #print("Found: %s at %i" % (selection, start)) # DBGDBG + # entry was found, but was it a partial selection? + if(selection not in hashFileList): # is selection on the GUI in PDEF's hashFileList? + # partial selection + #print("Partial selection %s not found in %s." % (selection, hashFileList)) # DBGDBG + self.StatusBar.SetStatusText("Please select the entire line") + break + else: + # Full selection, so remove that entry + # decr mle.NumbHashes & update NumberOfFiles widget + fileCnt = int(self.fileCntEdit.GetValue()) + fileCnt -= 1 + self.fileCntEdit.ChangeValue(str(fileCnt)) + currentList.ElementDefData[self.myIndex].NumbHashes = fileCnt + + hashFileList.remove(selection) # remove the selection from the PDEF object + #print("hashFileList=%s" % (hashFileList)) # DBGDBG + + if(fileCnt == 0): # disable REMOVE if no more files left + self.removeButton.Enable(False) + self.hashListBox.ChangeValue('') + else: + # rebuild the content of hashFileEdit from hashFileList and update the screen with ChangeValue + # to avoid generating an event and to clear the previous LF + hashFileString = '' + index = 0 + for eachString in hashFileList: + if(index != 0): # if not the 1st entry, need a LF before the new entry + hashFileString += "\n" + hashFileString += eachString + index += 1 + #print("thisString=%s, hashFileString=%s" % (eachString, hashFileString)) # DBGDBG + + self.hashListBox.ChangeValue(hashFileString) + + #print("hashListBox=%s" % (self.hashListBox.GetValue())) # DBGDBG + self.setListModified() + currentList.ElementDefData[self.myIndex].HashFiles = hashFileList + break + else: + self.StatusBar.SetStatusText("Selection %s not found. Please select only a single line" % (selection)) # DBGDBG + + def writeMleDef(self, mleDefData, f): + """writeMleDef - write the Mle Def to the specified file""" + + #print("writeMleDef dump") # DBGDBG + pickle.dump(mleDefData, f) # write out the mleDefData object + + def setPanelToDefaults(self): + """setPanelToDefaults - restore defaults to mle panel widgets""" + + self.minSinitVersionEdit.ChangeValue("0") + self.addButton.Enable(True) + self.removeButton.Enable(False) + self.fileCntEdit.ChangeValue("0") + self.hashListBox.ChangeValue("") + + + def restorePanel(self, currentList, maxHashes): + """restorePanel - restore the MLE element panel from the specified PLIST_DEF""" + + print("restorePanel - MLE") # DBGDBG + # update Override PS Policy checkbox + self.overridePsPolicy.SetValue(currentList.ElementDefData[self.myIndex].Control) + listversion = str(currentList.ListVersionMajor)+'.'+str(currentList.ListVersionMinor) + if listversion == '2.0': + self.showV20Gui(True) + else: + self.showV20Gui(False) + self.minSinitVersionEdit.ChangeValue(str(currentList.ElementDefData[self.myIndex].SinitMinVersion)) + + # If MaxHashes not 0, Only enable Add if < MaxHashes files + numbHashes = currentList.ElementDefData[self.myIndex].NumbHashes + flag = True + if(maxHashes != 0): + if(numbHashes >= maxHashes): + flag = False # don't enable add + self.addButton.Enable(flag) + + # enable remove if >0 hashes + flag = True + if(numbHashes > 0): + flag = False + self.removeButton.Enable(flag) + self.fileCntEdit.ChangeValue(str(numbHashes)) + + # form a string from hashFileList and update hashListBox + string = utilities.formStringFromListOfStrings(currentList.ElementDefData[self.myIndex].HashFiles) + self.hashListBox.ChangeValue(string) + + #def setListModified(self): + # """setListModified - if list not modified yet, increment its rev cnt and set it to modified""" + # + # currentList = self.pdef.getCurrentListObject() + # #print("Mle setListModified - ListModified was %s" % (currentList.ListModified)) # DBGDBG + # if(currentList.ListModified == False): + # currentList.RevocationCounter += 1 + # self.listPanel.revocationCountEdit.ChangeValue(str(currentList.RevocationCounter)) # update the GUI + # currentList.ListModified = True + diff -Nru tboot-1.9.4/lcp-gen2/mle.py tboot-1.9.5/lcp-gen2/mle.py --- tboot-1.9.4/lcp-gen2/mle.py 1970-01-01 00:00:00.000000000 +0000 +++ tboot-1.9.5/lcp-gen2/mle.py 2016-12-17 03:19:38.000000000 +0000 @@ -0,0 +1,468 @@ +#!/usr/bin/python +# Copyright (c) 2013, Intel Corporation. All rights reserved. + +# using print() built infunction, disable print statement +from __future__ import print_function + +# +# wxPython is not part of the standard Python distribution and has to be downloaded and installed separately. +# Tell the user that wxPython is required but has not been found +# +try: + import wx +except ImportError: + raise ImportError, "Please download the appropriate version of wxPython from www.wxpython.org" + +try: + import os + import shutil +except ImportError: + raise ImportError, "import OS failed" + +from defines import DEFINES +from pdef import MLE_DEF +from ElementGui import * + +from util import UTILS +utilities = UTILS() + +try: + import cPickle as pickle +except ImportError: + import pickle # fall back on Python version + +# TXT Policy Generator Tool +# MLE Class - Policy Definition File Lists +# +class MLE( ElementGui ): + + CONST_TITLE = "Choose Hash File" + CONST_WILDCARD = "Hash file (*.hash) | *.hash|" \ + "All Files (*.*) | *.*" + + """__init__() - MLE class constructor""" + def __init__( self, hashAlg): + self.mlePanelWidgets = [] + self.panelCreated = False + + try: + # reverse lookup of the hash algorithm name(key) for the given HashAlg value + hashAlgName = (key for key,val in DEFINES.TPM_ALG_HASH.items() if (val == hashAlg)).next() + except StopIteration: + print("MLE::__init__ - invalid hashAlg=%d" % (hashAlg)) + return + + self.myIndex = DEFINES.DEFDATA_INDEX[hashAlgName] + #if( hashAlg == DEFINES.TPM_ALG_HASH['SHA256']): + # self.myIndex = DEFINES.DEFDATA_INDEX_SHA256 + #elif( hashAlg == DEFINES.TPM_ALG_HASH['SHA1']): + # self.myIndex = DEFINES.DEFDATA_INDEX_SHA1 + #else: + # print("MLE::__init__ - invalid hashAlg=%d" % (hashAlg)) + + self.myHashAlg = hashAlg + + # + # create the MLE Panel + # + def createOrShowPanel(self, wx, listPanel, parent, pdef, statusBar): + """createPanel - create the List Panel""" + + #print("createOrShowMlePanel hashAlg=%d, panelCreated == %s" % (self.myHashAlg, self.panelCreated)) # DBGDBG + # 1st time, create the panel + # nth time, show the panel + if(self.panelCreated == True): + self.showPanel() + return + + self.pdef = pdef + self.parent = parent + self.listPanel = listPanel + self.StatusBar = statusBar + parentSizer = parent.GetSizer() + + # Get the list corresponds to this element. + currentList = self.pdef.getCurrentListObject() + self.myIndex = len(currentList.ElementDefData)-1 # Just added the element, the last one should be the one. + + # create the Mle Panel sizers + #self.mlePanelSizer = wx.BoxSizer(wx.VERTICAL) + self.mleGridSizer= wx.GridBagSizer(hgap=5, vgap=5) + #self.mleHorizSizer = wx.BoxSizer(wx.HORIZONTAL) + + self.mlePanel = wx.Panel(parent, -1) + self.mlePanel.SetSizer(self.mleGridSizer) + + mleLabelText1 = "MLE" + mleLabelText2 = "Element" + mleLabel1 = wx.StaticText(self.mlePanel, -1, mleLabelText1) + mleLabel2 = wx.StaticText(self.mlePanel, -1, mleLabelText2) + font = wx.Font( 18, wx.FONTFAMILY_DEFAULT, wx.NORMAL, wx.BOLD) + mleLabel1.SetFont( font ) + self.mleGridSizer.Add( mleLabel1, pos=(0, 3)) + self.mlePanelWidgets.append(mleLabel1) + mleLabel2.SetFont( font ) + self.mleGridSizer.Add( mleLabel2, pos=(0, 4)) + self.mlePanelWidgets.append(mleLabel2) + + typeLabel = wx.StaticText(self.mlePanel, label="Type") + self.mleGridSizer.Add( typeLabel, pos=(1,3)) + self.mlePanelWidgets.append(typeLabel) + typeEdit = wx.TextCtrl( self.mlePanel, value="MLE", size=(40, -1)) + typeEdit.Enable( False ) + self.mleGridSizer.Add( typeEdit, pos=(1,4)) + self.mlePanelWidgets.append(typeEdit) + + contolOptionsLabel = wx.StaticText(self.mlePanel, -1, "Control") + font = wx.Font( 10, wx.FONTFAMILY_DEFAULT, wx.NORMAL, wx.BOLD) + contolOptionsLabel.SetFont( font ) + + # override PS policy bit is applicable only if PO policy rules + self.overridePsPolicy = wx.CheckBox(self.mlePanel, label="Override PS Policy") + + if(self.pdef.Rules == DEFINES.PoRules): + self.overridePsPolicy.Enable( True ) + else: + self.overridePsPolicy.Enable( False ) + + self.mleGridSizer.Add(contolOptionsLabel, pos=(0,9), span=(1,2), flag=wx.BOTTOM, border=5) + self.mleGridSizer.Add(self.overridePsPolicy, pos=(1,9), span=(1,2), flag=wx.BOTTOM, border=5) + self.overridePsPolicy.Bind(wx.EVT_CHECKBOX, self.onOverridePsPolicy) + self.mlePanelWidgets.append(contolOptionsLabel) + self.mlePanelWidgets.append(self.overridePsPolicy) + + # STPM is required bit ElementPolicyControl[1] + #self.stmIsRequired = wx.CheckBox(self.mlePanel, label="STM is required") + #self.mleGridSizer.Add(self.stmIsRequired, pos=(2,9), span=(1,2), flag=wx.BOTTOM, border=5) + #self.stmIsRequired.Bind(wx.EVT_CHECKBOX, self.onOverridePsPolicy) # TODO: add function to handle event. + #self.mlePanelWidgets.append(self.stmIsRequired) + + try: + # reverse lookup of the hash algorithm name(key) for the given HashAlg value + hashAlgStr = (key for key,val in DEFINES.TPM_ALG_HASH.items() if (val == self.myHashAlg)).next() + except StopIteration: + print("createOrShowMlePanel - invalid myHashAlg=%d" % (self.myHashAlg)) + + #if(self.myHashAlg == DEFINES.TPM_ALG_HASH['SHA256']): + # hashAlgStr = "SHA256" + #elif(self.myHashAlg == DEFINES.TPM_ALG_HASH['SHA1']): + # hashAlgStr = "SHA1" + #else: + # print("createOrShowMlePanel - invalid myHashAlg=%d" % (self.myHashAlg)) + + hashAlgLabel = wx.StaticText(self.mlePanel, label="Hash Algorithm") + font = wx.Font( 10, wx.FONTFAMILY_DEFAULT, wx.NORMAL, wx.BOLD) + hashAlgLabel.SetFont( font ) + self.mleGridSizer.Add(hashAlgLabel, pos=(0,20)) + self.mlePanelWidgets.append(hashAlgLabel) + + hashAlgEdit = wx.TextCtrl( self.mlePanel, size=(75, -1), value=hashAlgStr ) + hashAlgEdit.Enable(False) + self.mleGridSizer.Add(hashAlgEdit, pos=(1,20)) + self.mlePanelWidgets.append(hashAlgEdit) + + minSinitVersionLabel = wx.StaticText(self.mlePanel, label="Min SINIT Version: ") + self.mleGridSizer.Add(minSinitVersionLabel, pos=(2,4)) + self.mlePanelWidgets.append(minSinitVersionLabel) + minSinitVersion = pdef.SinitMinVersion # get current value + + #currentList.MleDefData[self.myIndex].SinitMinVersion = minSinitVersion + currentList.ElementDefData[self.myIndex].SinitMinVersion = minSinitVersion + self.minSinitVersionEdit = wx.TextCtrl( self.mlePanel, value=str(minSinitVersion), size=(30, -1)) + self.mleGridSizer.Add( self.minSinitVersionEdit, pos=(2,5)) + self.minSinitVersionEdit.Bind(wx.EVT_TEXT, self.onMinSinitVersion) + self.mlePanelWidgets.append(self.minSinitVersionEdit) + + self.addButton = wx.Button( self.mlePanel, -1, label=" Add ") + self.mleGridSizer.Add( self.addButton, pos=(4,3)) + self.mlePanelWidgets.append(self.addButton) + self.addButton.Bind(wx.EVT_BUTTON, self.onAddButtonClick) + + self.removeButton = wx.Button( self.mlePanel, -1, label=" Remove ") + self.removeButton.Enable(False) + self.mleGridSizer.Add( self.removeButton, pos=(4,5)) + self.mlePanelWidgets.append(self.removeButton) + self.removeButton.Bind(wx.EVT_BUTTON, self.onRemoveButtonClick) + + hashListLabel = wx.StaticText(self.mlePanel, label=" Hash File List") + font = wx.Font( 10, wx.FONTFAMILY_DEFAULT, wx.NORMAL, wx.BOLD) + hashListLabel.SetFont( font ) + self.mleGridSizer.Add( hashListLabel, pos=(3,4)) + self.mlePanelWidgets.append(hashListLabel) + + fileCntLabel = wx.StaticText(self.mlePanel, label="Number of Files") + self.mleGridSizer.Add( fileCntLabel, pos=(5,3)) + self.mlePanelWidgets.append(fileCntLabel) + self.fileCntEdit = wx.TextCtrl( self.mlePanel, value="0", size=(40, -1)) + self.fileCntEdit.Enable( False ) + self.mleGridSizer.Add( self.fileCntEdit, pos=(5,4)) + self.mlePanelWidgets.append(self.fileCntEdit) + hashFileList = [''] + + self.hashListBox = wx.TextCtrl( self.mlePanel, value="", size=(150, 120), style = wx.TE_MULTILINE) # Note: add |wx.HSCROLL to get a horiz scroll bar + # hashListBox must be enabled so can select items to remove + self.hashListBox.Bind(wx.EVT_TEXT, self.onHashListBoxEdit) + self.hashListBox.SetInsertionPoint(0) + self.mleGridSizer.Add( self.hashListBox, pos=(4,4)) + self.mlePanelWidgets.append(self.hashListBox) + + #print("MLE createPanel - len(Widgets)=%d" % (len(self.mlePanelWidgets))) #DBGDBG + #self.mleHorizSizer.Add(self.mleGridSizer, 0, wx.ALL, 5) + #self.mlePanelSizer.Add(self.mleHorizSizer, 0, wx.ALL, 5) + #parent.SetSizerAndFit(self.mlePanelSizer) + self.mlePanelWidgets.append(self.mlePanel) + + parentSizer.Add(self.mlePanel) + w,h = parentSizer.GetMinSize() + parent.SetVirtualSize((w,h)) + print("parent sizer type = %s size = %d, %d" %(type(parentSizer).__name__, w, h)) + parent.Layout() + # call restorePanel to sync data to GUI + self.restorePanel(currentList, pdef.MaxHashes) + self.panelCreated = True + + def hidePanel(self): + """hidePanel - hide the Mle panel""" + #print("MLE hidePanel - hashAlg=%d, len(Widgets)=%d" % (self.myHashAlg, len(self.mlePanelWidgets))) #DBGDBG + for i in self.mlePanelWidgets: + i.Hide() + + + def showPanel(self): + """showPanel - show the mle panel""" + #print("MLE showPanel - hashAlg=%d, len(Widgets)=%d" % (self.myHashAlg, len(self.mlePanelWidgets))) #DBGDBG + if self.panelCreated: + for i in self.mlePanelWidgets: + i.Show() + parentSizer = self.parent.GetSizer() + w,h = parentSizer.GetMinSize() + self.parent.SetVirtualSize((w,h)) + + + def setElementToDefaults(self): + """setElementToDefaults - MLE""" + + currentList = self.pdef.getCurrentListObject() + currentList.ElementDefData[self.myIndex].IncludeInList = False + currentList.ElementDefData[self.myIndex].HashAlg = self.myHashAlg + currentList.ElementDefData[self.myIndex].SinitMinVersion = 0 + currentList.ElementDefData[self.myIndex].Control = 0 + currentList.ElementDefData[self.myIndex].NumbHashes = 0 + currentList.ElementDefData[self.myIndex].CurrentView = 0 + currentList.ElementDefData[self.myIndex].HashFiles = [] + + def onOverridePsPolicy(self, event): + currentList = self.pdef.getCurrentListObject() + self.setListModified() + # set/clear bit 0 per MLE Dev Guide PolEltControl def + if(event.Checked() == True): + currentList.ElementDefData[self.myIndex].Control = 1 + else: + currentList.ElementDefData[self.myIndex].Control = 0 + + def onMinSinitVersion(self, event): + value = event.GetString() + currentList = self.pdef.getCurrentListObject() + self.setListModified() + currentList.ElementDefData[self.myIndex].SinitMinVersion = int(value) + #print("MLE::onMinSinitVersion - SinitMinVersion = %d" % (currentList.ElementDefData[self.myIndex].SinitMinVersion)) # DBGDBG + + # only supports adding files with the add button, not entering the names directly + def onHashListBoxEdit(self, event): + """onHashListBoxEdit""" + #print("in MLE::onHashListBoxEdit") # DBGDBG + + # tell the user to add button and clear the field + self.StatusBar.SetStatusText("Please clear the entry, then use the Add button to add hash files to the list") + #self.hashListBox.Undo() + #TODO: wxPython: onHashListBoxEdit - Clear() and Undo() both generate an event causing: RuntimeError: maximum recursion depth exceeded + + def onAddButtonClick(self, event): + """onAddButtonClick - add a hash file to the list""" + + filepath, filename = self.selectFile() + + if (filename == ''): + # selectFile() operation has been cancelled. + return + + # validate that the specified hash file is properly formatted + currentList = self.pdef.getCurrentListObject() + result = utilities.verifyHashFile(os.path.join(filepath, filename), currentList.ElementDefData[self.myIndex].HashAlg) + # Note: verifyHashFile() returns [FileValid, FileType], but only FileValid is used here + if( result[0] == False): + return + + self.copyFile(filepath, filename) + self.StatusBar.SetStatusText("Validated file %s." % (filename)) + + # update the file count and enable the remove button + lineCnt = currentList.ElementDefData[self.myIndex].NumbHashes + #print("onAddButtonClick: was %i lines" % (lineCnt)) # DBGDBG + lineCnt += 1 + + # MaxHashes = 0 means there is no limit on the number of hash files allowed + if(self.pdef.MaxHashes != 0): + if(lineCnt > self.pdef.MaxHashes): + self.StatusBar.SetStatusText("Only %d files can be added." % (self.pdef.MaxHashes)) + return + + #print("onAddButtonClick: now %i lines" % (lineCnt)) # DBGDBG + self.fileCntEdit.ChangeValue(str(lineCnt)) + self.removeButton.Enable(True) + + hashFileList = currentList.ElementDefData[self.myIndex].HashFiles + hashFileList.append(filename) + #print("new hashFileList = %s" % (hashFileList)) # DBGDBG + + # insert the new file into mle.HashFiles + self.setListModified() + currentList.ElementDefData[self.myIndex].HashFiles = hashFileList + currentList.ElementDefData[self.myIndex].NumbHashes = lineCnt + #print("ElementDefData[self.myIndex].NumbHashes=%i, HashFiles = %s" % + # (currentList.ElementDefData[self.myIndex].NumbHashes, currentList.ElementDefData[self.myIndex].HashFiles)) # DBGDBG + + # since hashListBox.AppendText() generates an event to onHashListBoxEdit() + # and since hashListBoxEdit has to be enabled so text can be selected for Remove + # and direct text entry by the user into hashListBoxEdit is not supported due the complexity of validating it ... + # + # hashListBox.ChangeValue() doesn't generate an event but only takes a string, not a hashFileList which is a list ie '[]' + # so form a single string containing everything in hashFileList and update hashListBox using ChangeValue(hashFileString) + hashFileString = '' + index = 0 + for eachString in hashFileList: + if(index != 0): # if not the 1st entry, need a LF before the new entry + hashFileString += "\n" + hashFileString += eachString + index += 1 + #print("thisString=%s, hashFileString=%s" % (eachString, hashFileString)) + + self.hashListBox.ChangeValue(hashFileString) + + def onRemoveButtonClick(self, event): + """onRemoveButtonClick - remove the selected entry from the hash file list""" + + # confirm the remove + dlg = wx.MessageDialog(None, "Confirm removal of selected file?", 'Confirm Remove', wx.YES_NO | wx.ICON_QUESTION) + response = dlg.ShowModal() + dlg.Destroy() + + if(response == wx.ID_NO): + self.StatusBar.SetStatusText( "Remove cancelled" ) + return + + selection = self.hashListBox.GetStringSelection() + self.StatusBar.SetStatusText("Removed selection %s" % (selection)) + + # selection may not be a full line ... See if the selection is contianed in any of hashFileList's entries + currentList = self.pdef.getCurrentListObject() + hashFileList = currentList.ElementDefData[self.myIndex].HashFiles + for entry in hashFileList: + #print("entry=%s" % (entry)) # DBGDBG + start = entry.find(selection) + if(start != -1): # -1 means not found, else find returns the starting index of selection + #print("Found: %s at %i" % (selection, start)) # DBGDBG + # entry was found, but was it a partial selection? + if(selection not in hashFileList): # is selection on the GUI in PDEF's hashFileList? + # partial selection + #print("Partial selection %s not found in %s." % (selection, hashFileList)) # DBGDBG + self.StatusBar.SetStatusText("Please select the entire line") + break + else: + # Full selection, so remove that entry + # decr mle.NumbHashes & update NumberOfFiles widget + fileCnt = int(self.fileCntEdit.GetValue()) + fileCnt -= 1 + self.fileCntEdit.ChangeValue(str(fileCnt)) + currentList.ElementDefData[self.myIndex].NumbHashes = fileCnt + + hashFileList.remove(selection) # remove the selection from the PDEF object + #print("hashFileList=%s" % (hashFileList)) # DBGDBG + + if(fileCnt == 0): # disable REMOVE if no more files left + self.removeButton.Enable(False) + self.hashListBox.ChangeValue('') + else: + # rebuild the content of hashFileEdit from hashFileList and update the screen with ChangeValue + # to avoid generating an event and to clear the previous LF + hashFileString = '' + index = 0 + for eachString in hashFileList: + if(index != 0): # if not the 1st entry, need a LF before the new entry + hashFileString += "\n" + hashFileString += eachString + index += 1 + #print("thisString=%s, hashFileString=%s" % (eachString, hashFileString)) # DBGDBG + + self.hashListBox.ChangeValue(hashFileString) + + #print("hashListBox=%s" % (self.hashListBox.GetValue())) # DBGDBG + self.setListModified() + currentList.ElementDefData[self.myIndex].HashFiles = hashFileList + break + else: + self.StatusBar.SetStatusText("Selection %s not found. Please select only a single line" % (selection)) # DBGDBG + + + def writeMleDef(self, mleDefData, f): + """writeMleDef - write the Mle Def to the specified file""" + + print("writeMleDef dump, hashAlg=%d" % (self.myHashAlg)) # DBGDBG + pickle.dump(mleDefData, f) # write out the mleDefData object + + def setPanelToDefaults(self): + """setPanelToDefaults - restore defaults to mle panel widgets""" + + self.minSinitVersionEdit.ChangeValue("0") + self.addButton.Enable(True) + self.removeButton.Enable(False) + self.fileCntEdit.ChangeValue("0") + self.hashListBox.ChangeValue("") + + def restorePanel(self, currentList, maxHashes): + """restorePanel - restore the MLE element panel from the specified PLIST_DEF""" + + print("restorePanel - MLE") # DBGDBG + # update Override PS Policy checkbox + self.overridePsPolicy.SetValue(currentList.ElementDefData[self.myIndex].Control) + listversion = str(currentList.ListVersionMajor)+'.'+str(currentList.ListVersionMinor) + if listversion == '2.0': + self.showV20Gui(True) + else: + self.showV20Gui(False) + self.minSinitVersionEdit.ChangeValue(str(currentList.ElementDefData[self.myIndex].SinitMinVersion)) + + # If MaxHashes not 0, Only enable Add if < MaxHashes files + numbHashes = currentList.ElementDefData[self.myIndex].NumbHashes + flag = True + if(maxHashes != 0): + if(numbHashes >= maxHashes): + flag = False # don't enable add + self.addButton.Enable(flag) + + # enable remove if >0 hashes + flag = False + if(numbHashes > 0): + flag = True + self.removeButton.Enable(flag) + self.fileCntEdit.ChangeValue(str(numbHashes)) + + # form a string from hashFileList and update hashListBox + string = utilities.formStringFromListOfStrings(currentList.ElementDefData[self.myIndex].HashFiles) + self.hashListBox.ChangeValue(string) + + #def setListModified(self): + # """setListModified - if list not modified yet, increment its rev cnt and set it to modified""" + # + # currentList = self.pdef.getCurrentListObject() + # #print("Mle setListModified - ListModified was %s" % (currentList.ListModified)) # DBGDBG + # if(currentList.ListModified == False): + # currentList.RevocationCounter += 1 + # self.listPanel.revocationCountEdit.ChangeValue(str(currentList.RevocationCounter)) # update the GUI + # currentList.ListModified = True + # self.pdef.Modified = True + + + # the last function in the file doesn't show up in the scope list in Understand for some reason! + def stub(self): + pass diff -Nru tboot-1.9.4/lcp-gen2/pconfLegacy.py tboot-1.9.5/lcp-gen2/pconfLegacy.py --- tboot-1.9.4/lcp-gen2/pconfLegacy.py 1970-01-01 00:00:00.000000000 +0000 +++ tboot-1.9.5/lcp-gen2/pconfLegacy.py 2016-12-17 03:19:38.000000000 +0000 @@ -0,0 +1,661 @@ +#!/usr/bin/python +# Copyright (c) 2013, Intel Corporation. All rights reserved. + +# using print() built infunction, disable print statement +from __future__ import print_function + +# +# wxPython is not part of the standard Python distribution and has to be downloaded and installed separately. +# Tell the user that wxPython is required but has not been found +# +try: + import wx +except ImportError: + raise ImportError, "Please download the appropriate version of wxPython from www.wxpython.org" + +try: + import os + import shutil +except ImportError: + raise ImportError, "import OS failed" + +from defines import DEFINES +from pdef import PCONFLEGACY_DEF +from pdef import PCONF_INFO +from ElementGui import * + +from util import UTILS +utilities = UTILS() + +try: + import cPickle as pickle +except ImportError: + import pickle # fall back on Python version + + +# +# TXT Policy Generator Tool +# PCONF Class - Policy Definition File Lists +# +class PCONFLegacy( ElementGui ): + + CONST_TITLE = "Choose PCR File" + CONST_WILDCARD = "Pcr file (*.pcr) | *.pcr|" \ + "All Files (*.*) | *.*" + + """__init__() - PCONF class constructor""" + def __init__( self ): + self.pconfPanelWidgets = [] + self.panelCreated = False + + # + # create the PCONF Panel + # + def createOrShowPanel(self, wx, listPanel, parent, pdef, statusBar): + """createPanel - create the List Panel""" + + print("createOrShowPanel panelCreated == %s" % (self.panelCreated)) # DBGDBG + # 1st time, create the panel + # nth time, show the panel + if(self.panelCreated == True): + self.pcrFileCombo.Clear() + self.showPanel() + return + + self.pdef = pdef + self.parent = parent + self.listPanel = listPanel + self.StatusBar = statusBar + parentSizer = parent.GetSizer() + + # Get the list corresponds to this element. + currentList = self.pdef.getCurrentListObject() + self.myIndex = len(currentList.ElementDefData)-1 # Just added the element, the last one should be the one. + + # create the PCONF Panel sizers + #self.pconfPanelSizer = wx.BoxSizer(wx.VERTICAL) + pconfGridSizer= wx.GridBagSizer(hgap=5, vgap=5) + #pconfHorizSizer = wx.BoxSizer(wx.HORIZONTAL) + + self.pconfPanel = wx.Panel(parent, -1) + self.pconfPanel.SetSizer(pconfGridSizer) + + pconfLabelText1 = "PCONF" + pconfLabelText2 = "Element" + pconfLabel1 = wx.StaticText(self.pconfPanel, -1, pconfLabelText1) + pconfLabel2 = wx.StaticText(self.pconfPanel, -1, pconfLabelText2) + font = wx.Font( 18, wx.FONTFAMILY_DEFAULT, wx.NORMAL, wx.BOLD) + pconfLabel1.SetFont( font ) + pconfGridSizer.Add( pconfLabel1, pos=(0, 3)) + self.pconfPanelWidgets.append(pconfLabel1) + pconfLabel2.SetFont( font ) + pconfGridSizer.Add( pconfLabel2, pos=(0, 4)) + self.pconfPanelWidgets.append(pconfLabel2) + + self.typeLabel = wx.StaticText(self.pconfPanel, label="Type") + pconfGridSizer.Add( self.typeLabel, pos=(1,3)) + self.pconfPanelWidgets.append(self.typeLabel) + self.typeEdit = wx.TextCtrl( self.pconfPanel, value="PCONF", size=(40, -1)) + self.typeEdit.Enable( False ) + pconfGridSizer.Add( self.typeEdit, pos=(1,4)) + self.pconfPanelWidgets.append(self.typeEdit) + + self.contolOptionsLabel = wx.StaticText(self.pconfPanel, -1, "Control") + font = wx.Font( 10, wx.FONTFAMILY_DEFAULT, wx.NORMAL, wx.BOLD) + self.contolOptionsLabel.SetFont( font ) + + # override PS policy bit is applicable only if PO policy rules + self.overridePsPolicy = wx.CheckBox(self.pconfPanel, label="Override PS Policy") + + if(self.pdef.Rules == DEFINES.PoRules): + self.overridePsPolicy.Enable( True ) + else: + self.overridePsPolicy.Enable( False ) + + pconfGridSizer.Add(self.contolOptionsLabel, pos=(0,8), span=(1,2), flag=wx.BOTTOM, border=5) + self.overridePsPolicy.Bind(wx.EVT_CHECKBOX, self.onOverridePsPolicy, self.overridePsPolicy) + pconfGridSizer.Add(self.overridePsPolicy, pos=(1,8), span=(1,2), flag=wx.BOTTOM, border=5) + self.pconfPanelWidgets.append(self.contolOptionsLabel) + self.pconfPanelWidgets.append(self.overridePsPolicy) + + hashList = ['SHA1'] + self.hashAlgLabel = wx.StaticText(self.pconfPanel, label="Hash Algorithm") + font = wx.Font( 10, wx.FONTFAMILY_DEFAULT, wx.NORMAL, wx.BOLD) + self.hashAlgLabel.SetFont( font ) + pconfGridSizer.Add(self.hashAlgLabel, pos=(0,20)) + self.pconfPanelWidgets.append(self.hashAlgLabel) + + # Style=wx.CB_READONLY same as wx.CB_DROPDOWN, + # Except only the strings specified as the combobox choices can be selected + hashAlgEdit = wx.ComboBox( self.pconfPanel, size=(75, -1), value="SHA1", choices=hashList, style=wx.CB_DROPDOWN ) + pconfGridSizer.Add(hashAlgEdit, pos=(1,20)) + self.pconfPanelWidgets.append(hashAlgEdit) + + pcrFile = "" + self.pcrFileFileLabel = wx.StaticText(self.pconfPanel, label="PCR File") + font = wx.Font( 10, wx.FONTFAMILY_DEFAULT, wx.NORMAL, wx.NORMAL) + self.pcrFileFileLabel.SetFont( font ) + pconfGridSizer.Add( self.pcrFileFileLabel, pos=(2,3)) + self.pconfPanelWidgets.append(self.pcrFileFileLabel) + + self.pcrFileCombo = wx.ComboBox( self.pconfPanel, value=pcrFile, size=(200, -1), choices=pcrFile, style=wx.CB_DROPDOWN) + self.pcrFileCombo.Enable( False ) # prevent selection since pulldown is empty + self.pcrFileCombo.Bind(wx.EVT_TEXT, self.onPcrFileCombo, self.pcrFileCombo) + pconfGridSizer.Add( self.pcrFileCombo, pos=(2,4)) + self.pconfPanelWidgets.append(self.pcrFileCombo) + + self.fileSelectionLabel = wx.StaticText(self.pconfPanel, label="Selected File") + pconfGridSizer.Add( self.fileSelectionLabel, pos=(7,3)) + self.pconfPanelWidgets.append(self.fileSelectionLabel) + self.fileSelectionEdit = wx.TextCtrl( self.pconfPanel, value=" ", size=(40, -1)) + self.fileSelectionEdit.Enable( False ) + pconfGridSizer.Add( self.fileSelectionEdit, pos=(7,4)) + self.pconfPanelWidgets.append(self.fileSelectionEdit) + + self.fileCntLabel = wx.StaticText(self.pconfPanel, label="Number of Files") + pconfGridSizer.Add( self.fileCntLabel, pos=(8,3)) + self.pconfPanelWidgets.append(self.fileCntLabel) + self.fileCntEdit = wx.TextCtrl( self.pconfPanel, value="0", size=(40, -1)) + self.fileCntEdit.Enable( False ) + pconfGridSizer.Add( self.fileCntEdit, pos=(8,4)) + self.pconfPanelWidgets.append(self.fileCntEdit) + + self.updateButton = wx.Button( self.pconfPanel, -1, label="Apply PCR Selection") + self.updateButton.Enable( False ) + pconfGridSizer.Add( self.updateButton, pos=(7,8)) + self.pconfPanelWidgets.append(self.updateButton) + self.updateButton.Bind(wx.EVT_BUTTON, self.onUpdateButtonClick) + self.pconfPanelWidgets.append(self.updateButton) + + self.addButton = wx.Button( self.pconfPanel, -1, label=" Add ") + pconfGridSizer.Add( self.addButton, pos=(3,4)) + self.pconfPanelWidgets.append(self.addButton) + self.addButton.Bind(wx.EVT_BUTTON, self.onAddButtonClick) + self.pconfPanelWidgets.append(self.addButton) + + self.removeButton = wx.Button( self.pconfPanel, -1, label=" Remove ") + self.removeButton.Enable( False ) + pconfGridSizer.Add( self.removeButton, pos=(4,4)) + self.pconfPanelWidgets.append(self.removeButton) + self.removeButton.Bind(wx.EVT_BUTTON, self.onRemoveButtonClick) + self.pconfPanelWidgets.append(self.removeButton) + + #self.pcrSelectionLabel = wx.StaticText(self.pconfPanel, -1, "PCR Selection") + #font = wx.Font( 10, wx.FONTFAMILY_DEFAULT, wx.NORMAL, wx.BOLD) + #self.pcrSelectionLabel.SetFont( font ) + self.pcrSelectionLabel1 = wx.StaticText(self.pconfPanel, -1, "PCR ") + font = wx.Font( 10, wx.FONTFAMILY_DEFAULT, wx.NORMAL, wx.BOLD) + self.pcrSelectionLabel1.SetFont( font ) + self.pcrSelectionLabel2 = wx.StaticText(self.pconfPanel, -1, "Selection") + self.pcrSelectionLabel2.SetFont( font ) + + self.pcr0 = wx.CheckBox(self.pconfPanel, label="0") + self.pcr1 = wx.CheckBox(self.pconfPanel, label="1") + self.pcr2 = wx.CheckBox(self.pconfPanel, label="2") + self.pcr3 = wx.CheckBox(self.pconfPanel, label="3") + self.pcr4 = wx.CheckBox(self.pconfPanel, label="4") + self.pcr5 = wx.CheckBox(self.pconfPanel, label="5") + self.pcr6 = wx.CheckBox(self.pconfPanel, label="6") + self.pcr7 = wx.CheckBox(self.pconfPanel, label="7") + + self.pcrSelectionCheckboxes =[self.pcr7, self.pcr6, self.pcr5, self.pcr4, + self.pcr3, self.pcr2, self.pcr1, self.pcr0] + + self.enableDisablePcrSelectionCheckBoxes(False) # disable the check boxes til the 1st file is added + + + #pconfGridSizer.Add(self.pcrSelectionLabel, pos=(2,8), span=(1,2), flag=wx.BOTTOM, border=5) + pconfGridSizer.Add(self.pcrSelectionLabel1, pos=(2,6), span=(1,2), flag=wx.BOTTOM, border=5) + pconfGridSizer.Add(self.pcrSelectionLabel2, pos=(2,8), span=(1,2), flag=wx.BOTTOM, border=5) + pconfGridSizer.Add(self.pcr7, pos=(3,6), span=(1,2), flag=wx.BOTTOM, border=5) + pconfGridSizer.Add(self.pcr6, pos=(4,6), span=(1,2), flag=wx.BOTTOM, border=5) + pconfGridSizer.Add(self.pcr5, pos=(5,6), span=(1,2), flag=wx.BOTTOM, border=5) + pconfGridSizer.Add(self.pcr4, pos=(6,6), span=(1,2), flag=wx.BOTTOM, border=5) + pconfGridSizer.Add(self.pcr3, pos=(3,8), span=(1,2), flag=wx.BOTTOM, border=5) + pconfGridSizer.Add(self.pcr2, pos=(4,8), span=(1,2), flag=wx.BOTTOM, border=5) + pconfGridSizer.Add(self.pcr1, pos=(5,8), span=(1,2), flag=wx.BOTTOM, border=5) + pconfGridSizer.Add(self.pcr0, pos=(6,8), span=(1,2), flag=wx.BOTTOM, border=5) + + #self.pconfPanelWidgets.append(self.pcrSelectionLabel) + self.pconfPanelWidgets.append(self.pcrSelectionLabel1) + self.pconfPanelWidgets.append(self.pcrSelectionLabel2) + self.pconfPanelWidgets.append(self.pcr0) + self.pconfPanelWidgets.append(self.pcr1) + self.pconfPanelWidgets.append(self.pcr2) + self.pconfPanelWidgets.append(self.pcr3) + self.pconfPanelWidgets.append(self.pcr4) + self.pconfPanelWidgets.append(self.pcr5) + self.pconfPanelWidgets.append(self.pcr6) + self.pconfPanelWidgets.append(self.pcr7) + + self.pconfPanelWidgets.append(self.pconfPanel) + + #pconfHorizSizer.Add(pconfGridSizer, 0, wx.ALL, 5) + #self.pconfPanelSizer.Add(pconfHorizSizer, 0, wx.ALL, 5) + #parent.SetSizerAndFit(self.pconfPanelSizer) + parentSizer.Add(self.pconfPanel) + w,h = parentSizer.GetMinSize() + parent.SetVirtualSize((w,h)) + parent.Layout() + # call restorePanel to sync data to GUI + self.restorePanel(restorePanel, pdef.MaxHashes) + self.panelCreated = True + + def hidePanel(self): + """hidePanel - hide the Pconf panel""" + + for i in self.pconfPanelWidgets: + i.Hide() + + + def showPanel(self): + """showPanel - show the Pconf panel""" + + if self.panelCreated: + for i in self.pconfPanelWidgets: + i.Show() + parentSizer = self.parent.GetSizer() + w,h = parentSizer.GetMinSize() + self.parent.SetVirtualSize((w,h)) + + + def setElementToDefaults(self): + """setElementToDefaults - PCONF""" + + self.pcrFileCombo.SetValue(' ') + self.clearPcrCheckBoxes() + + currentList = self.pdef.getCurrentListObject() + currentList.ElementDefData[self.myIndex].IncludeInList = False + currentList.ElementDefData[self.myIndex].HashAlg = 0 + currentList.ElementDefData[self.myIndex].Control = 0 + currentList.ElementDefData[self.myIndex].NumbHashes = 0 + currentList.ElementDefData[self.myIndex].CurrentView = 0 + currentList.ElementDefData[self.myIndex].PcrInfoSrc = [] + + def onOverridePsPolicy(self, event): + """onOverridePsPolicy - update the Control field""" + + # set/clear bit 0 per MLE Dev Guide PolEltControl def + currentList = self.pdef.getCurrentListObject() + self.setListModified() + currentList.ElementDefData[self.myIndex].Control = event.Checked() + #print("onOverridePsPolicy Control=%d Event=%d" % (currentList.ElementDefData[self.myIndex].Control , event.IsChecked())) + + + def onPcrFileCombo(self, event): + """onPcrFileCombo - update which PCR file is selected""" + # Get the PcrInfo entry selected by the user and save it in CurrentView + currentSelection = self.pcrFileCombo.GetSelection() + currentList = self.pdef.getCurrentListObject() + self.setListModified() + currentList.ElementDefData[self.myIndex].CurrentView = currentSelection + #print("onPcrFileCombo: currentSelection=%d, NumbHashes=%d" % (currentSelection, currentList.ElementDefData[self.myIndex].NumbHashes)) #DBGDBG + + # set the checkboxes to match the current selection and show which element is selected + self.showSelection(currentSelection) + pconf_info = currentList.ElementDefData[self.myIndex].PcrInfoSrc[currentSelection] + pcrSelection = pconf_info.pcrSelect[0] + self.setPcrSelectionCheckboxes(pcrSelection) + + def onUpdateButtonClick(self, event): + """onUpdateButtonClick - update the PCR select per the PCR0-7 checkboxes for the current file""" + self.updatePcrFileCombo() + + def updatePcrFileCombo(self): + # update the selected PcrInfoSrc[i].pcrSelect[0] with the PCR Selection info set by the user + # where i = currentList.ElementDefData[self.myIndex].CurrentView = user's current selection + # this indicates which PCRs in the file are evaluated + bit = 0 + byte = 0 + for eachCheckbox in self.pcrSelectionCheckboxes: + if(eachCheckbox.IsChecked() == True): + x = 1 << (7-bit) + #print("updatePcrFileCombo - bit %x is checked, x=%x" % (bit, x)) #DBGDBG + else: + x = 0 + + bit += 1 + byte |= x + + #print("updatePcrFileCombo - byte=%x" % (byte)) #DBGDBG + newPcrSelection = self.makeListWithEntryForEachBitInByte(byte) + + currentList = self.pdef.getCurrentListObject() + self.setListModified() + #currentEntrySelected = self.pcrFileCombo.GetSelection() + currentEntrySelected = currentList.ElementDefData[self.myIndex].CurrentView + #print("updatePcrFileCombo - currentEntrySelected=%x*****" % (currentEntrySelected)) #DBGDBG + pconf_info = currentList.ElementDefData[self.myIndex].PcrInfoSrc[currentEntrySelected] + pconf_info.pcrSelect[0] = newPcrSelection + #print("updatePcrFileCombo -currentEntrySelected=%d=%s newPcrSelection=%s" % (currentEntrySelected, pconf_info, newPcrSelection)) #DBGDBG + + filename = pconf_info.pcrFile + value = str(newPcrSelection) + " " + filename + + # replace the selection + # update the choices list + + #TODO: wxPython: updatePcrFileCombo - ComboBox.Replace doesn't work so doing .Clear() .Append's - better way? + # XXXXXXX self.pcrFileCombo.Replace( currentEntrySelected, value ) XXXXXXXXXX + # Since ComboBox.Replace doesn't work, + # Use .Clear() to clear the choices then iterate thru and reconstruct the choices with .Append(eachChoice) + + self.pcrFileCombo.Clear() + self.pcrFileCombo.SetValue( value ) + fileCnt = currentList.ElementDefData[self.myIndex].NumbHashes + i = 0 + #print("updatePcrFileCombo: NumbHashes=%d**StartOfWhile**" % (fileCnt)) #DBGDBG + while(i < fileCnt): + pconf_info = currentList.ElementDefData[self.myIndex].PcrInfoSrc[i] + #print("Update: Pconf_info%d=%s NumbHashes=%d, pcrFile=%s pcrSelect[0]=%s --start of loop--" % + # (i, pconf_info, fileCnt, pconf_info.pcrFile, pconf_info.pcrSelect[0])) # DBGDBG + bit = 0 + byte = 0 + for eachPcr in pconf_info.pcrSelect[0]: # pcrSelect[0] ordered 7:0, pcrSelectionCheckboxes ordered 0:7 + if(eachPcr == 1): + x = 1 << (7-bit) + #print("updatePcrFileCombo: i=%d: bit %x is set, x=%x byte=%x" % (i, 7-bit, x, byte)) #DBGDBG + else: + x = 0 + + bit += 1 + byte |= x + + #print("updatePcrFileCombo - byte=%x" % (byte)) #DBGDBG + newPcrSelection = self.makeListWithEntryForEachBitInByte(byte) + filename = pconf_info.pcrFile + value = str(newPcrSelection) + " " + filename + self.pcrFileCombo.Append(value) + #print("updatePcrFileCombo: i=%d value=%s --end of loop--" % (i, value )) # DBGDBG + i += 1 + + + def onAddButtonClick(self, event): + """onAddButtonClick - add a PCR file to the list""" + # Present dialogue for user to select a PCR file + # Leave PCR Selection checkboxes as is so same setting can be used on next file + + filepath, filename = self.selectFile() + + if (filename == ''): + # selectFile() operation has been cancelled. + return + + # validate that the specified PCR file is properly formatted + result = utilities.verifyPcrFile(os.path.join(filepath, filename), DEFINES.TPM_ALG_HASH['SHA1']) + if( result[0] == False): + return + + self.copyFile(filepath, filename) + self.StatusBar.SetStatusText("Validated file %s." % (filename)) + + # incr currentList.ElementDefData[self.myIndex].NumbHashes and update NumberOfFiles widget + currentList = self.pdef.getCurrentListObject() + self.setListModified() + fileCnt = currentList.ElementDefData[self.myIndex].NumbHashes + fileCnt += 1 + self.fileCntEdit.ChangeValue(str(fileCnt)) + currentList.ElementDefData[self.myIndex].NumbHashes = fileCnt + + # add a PCONF_INFO to PCONF_DEF.PcrInfoSrc[] for this PCR file + pconf_info = PCONF_INFO() # create a PCONF_INFO + currentList.ElementDefData[self.myIndex].PcrInfoSrc.append(pconf_info) + #print("pconf_info: NumbHahses=%x pcrSelect[0]=%x, pcrFile=%s" % (fileCnt, pconf_info.pcrSelect[0], pconf_info.pcrFile)) # DBGDBG + + pconf_info = currentList.ElementDefData[self.myIndex].PcrInfoSrc[fileCnt-1] # add the PCONF_INFO to PCONF_DEF + + # Set currentList.ElementDefData[self.myIndex].PcrInfoSrc[i].pcrSelect[0] = 0 + # Set currentList.ElementDefData[self.myIndex].PcrInfoSrc[i].pcrFile = the selected file + # where i = currentList.ElementDefData[self.myIndex].CurrentView = user's current selection + # Concatenate "PcrInfoSrc[i].pcrSelect" and "PcrInfoSrc[i].pcrFile" per fig 9 + # display/append that concatenated value to the comboBox. ex: "00000000 PlatformA_BiosD28.pcr" + pconf_info.pcrFile = filename + pcrSelectBits = [0,0,0,0,0,0,0,0] # list of each bit in pcrSelect[0] = 00000000 + pconf_info.pcrSelect[0] = pcrSelectBits + currentList.ElementDefData[self.myIndex].CurrentView = fileCnt-1 + print("Add: Pconf_info%d=%s NumbHashes=%d, pcrFile=%s pcrSelect[0]=%s" % + (fileCnt-1, pconf_info, fileCnt, pconf_info.pcrFile, pconf_info.pcrSelect[0])) # DBGDBG + + value = str(pcrSelectBits) + " " + filename + self.pcrFileCombo.SetValue( value ) + self.pcrFileCombo.Append( value ) + + # disable ADD button if NumbHashes now > MaxHashes, unless MaxHashes is 0 indicating no limit on the number of files + if(self.pdef.MaxHashes != 0): + if(fileCnt > self.pdef.MaxHashes): + self.addButton.Enable( False ) + + # enable REMOVE and UPDATE buttons and PCR File combo box ifNumbHashes > 1 + if(fileCnt > 0): + self.updateButton.Enable( True ) + self.removeButton.Enable( True ) + self.pcrFileCombo.Enable( True ) + self.enableDisablePcrSelectionCheckBoxes(True) + + self.showSelection(currentList.ElementDefData[self.myIndex].CurrentView) + + def onRemoveButtonClick(self, event): + """onRemoveButtonClick - Remove the current PCR file from the list""" + + # confirm the remove + dlg = wx.MessageDialog(None, "Confirm removal of selected PCR file?", 'Confirm Remove', wx.YES_NO | wx.ICON_QUESTION) + response = dlg.ShowModal() + dlg.Destroy() + + if(response == wx.ID_NO): + self.StatusBar.SetStatusText( "Remove cancelled" ) + return + + # remove the selected PCRInfoSrc entry from the comboBox, ie entry: currentList.ElementDefData[self.myIndex].CurrentView + currentList = self.pdef.getCurrentListObject() + self.setListModified() + currentSelection = currentList.ElementDefData[self.myIndex].CurrentView + self.pcrFileCombo.Delete(currentSelection) + + # show entry 0 + newView = 0 + self.pcrFileCombo.SetSelection(newView) + currentList.ElementDefData[self.myIndex].CurrentView = newView + + # also remove the entry from PconfDefData[] + del currentList.ElementDefData[self.myIndex].PcrInfoSrc[currentSelection] + + # decr currentList.ElementDefData[self.myIndex].NumbHashes and update currentList.ElementDefData[self.myIndex].CurrentView + # decr currentList.ElementDefData[self.myIndex].NumbHashes and update NumberOfFiles widget + fileCnt = currentList.ElementDefData[self.myIndex].NumbHashes + fileCnt -= 1 + self.fileCntEdit.ChangeValue(str(fileCnt)) + currentList.ElementDefData[self.myIndex].NumbHashes = fileCnt + + # DBGDBG + print("onRemoveButtonClick - removed %d, NumbHashes=%d currentSelection=%d" % (currentSelection, fileCnt, currentSelection)) #DBGDBG + if(fileCnt > 0): # DBGDBG - verify PconfDefData vs. Add's prints + i=0 # DBGDBG + while(i < fileCnt): # DBGDBG + pconf_info = currentList.ElementDefData[self.myIndex].PcrInfoSrc[i] # DBGDBG + print("Remove: Pconf_info%d=%s, pcrFile=%s pcrSelect[0]=%s" % (i, pconf_info, pconf_info.pcrFile, pconf_info.pcrSelect[0])) # DBGDBG + i += 1 # DBGDBG + # DBGDBG + + if(response == wx.ID_YES): + if(fileCnt > 0): + self.showSelection(newView) + # update the PCR Selection checkboxes to match the new selection + pconf_info = currentList.ElementDefData[self.myIndex].PcrInfoSrc[newView] + pcrSelection = pconf_info.pcrSelect[0] + self.setPcrSelectionCheckboxes(pcrSelection) + else: + # no more files, disable Remove & Update + self.updateButton.Enable( False ) + self.removeButton.Enable( False ) + self.pcrFileCombo.Enable( False ) + self.enableDisablePcrSelectionCheckBoxes(False) + self.fileSelectionEdit.ChangeValue("") + self.clearPcrCheckBoxes() + self.StatusBar.SetStatusText( "PCR file removed" ) + + # reenable ADD button if NumbHashes is now < MaxHashes + if(self.pdef.MaxHashes != 0): + if(fileCnt < self.pdef.MaxHashes): + self.addButton.Enable( True ) + + def clearPcrCheckBoxes(self): + """clearPcrCheckBoxes - clear the PCR check boxes""" + for eachBox in self.pcrSelectionCheckboxes: + eachBox.SetValue(False) + + # + # Form an 8 entry list where each member represents the value of each bit in the specified byte + # ordered from bit 7 to bit 0 + # Example: if byte = 0x35 Output is [0,0,1,1,0,1,0,1] + # + def makeListWithEntryForEachBitInByte(self, byte): + """makeListWithEntryForEachBitInByte - Form an 8 entry list where each member represents the value of each bit in the specified byte """ + + bit = 0x80 + cnt = 0 + pcrSelectBits = [0, 1, 2, 3, 4, 5, 6, 7] # initial values will be overwritten + #print("Bits=%s pcrSelectBits[cnt]=%x cnt=%x bit=%x byte=%x" % (pcrSelectBits, pcrSelectBits[cnt], cnt, bit, byte)) #DBGDBG + while(bit >= 0x01): # check each bit from bit 7 thru bit 0 + if(byte & bit != 0): + pcrSelectBits[cnt] = 1 + else: + pcrSelectBits[cnt] = 0 + #print("Bits=%s, pcrSelectBits[cnt]=%x, cnt=%x bit=%x byte=%x" % (pcrSelectBits, pcrSelectBits[cnt], cnt, bit, byte)) #DBGDBG + bit >>= 1 + cnt += 1 + + return(pcrSelectBits) + + + # show current selection and prompt user to select PCRs and click UPDATE for selected file + def showSelection(self, currentSelection): + """showSelection - show user which element is selected""" + self.StatusBar.SetStatusText("PCR File %d is selected. To change PCR Selections, Set the PCR[0-7] check boxes, and click Apply PCR Selection" + % (currentSelection+1) ) + self.fileSelectionEdit.ChangeValue(str(currentSelection+1)) + + def enableDisablePcrSelectionCheckBoxes(self, value): + """setPcrSelectionCheckBoxes - enable/disable the PCR Selection check boxes """ + for eachBox in self.pcrSelectionCheckboxes: + eachBox.Enable(value) + + def setPcrSelectionCheckboxes(self, pcrSelection): + """setPcrSelectionCheckboxes - set the PCR selection checkboxes per the pcrSelection list""" + i=0 + for eachCheckbox in self.pcrSelectionCheckboxes: + if(pcrSelection[i] == 1): + eachCheckbox.SetValue(True) + else: + eachCheckbox.SetValue(False) + + i += 1 + + + def writePconfDef(self, pconfDefData, f): + """writePconfDef - write the PCONF_DEF to the specified file""" + + #print("writePconfDef dump") # DBGDBG + pickle.dump(pconfDefData, f) # write out the pconfDefData object + + i = 0 + for eachPconfInfo in pconfDefData.PcrInfoSrc: + #print("writePconfDef: pconfInfo %x" % (i)) # for readability + self.writePconfInfo(eachPconfInfo, i, f) + i += 1 + + def writePconfInfo(self, pconfInfo, index, f): + """writePconfInfo - write the PCONF_INFO to the specified file""" + + #print("writePconfInfo dump") # DBGDBG + pickle.dump(pconfInfo, f) # write out the pconfInfo object + + def setPanelToDefaults(self): + """setPanelToDefaults - restore defaults to pconf panel widgets""" + + self.overridePsPolicy.SetValue(0) + self.pcrFileCombo.SetValue("") + self.addButton.Enable(True) + self.removeButton.Enable(False) + self.updateButton.Enable(False) + self.fileCntEdit.ChangeValue("0") + self.fileSelectionEdit.ChangeValue("") + self.enableDisablePcrSelectionCheckBoxes(False) + self.clearPcrCheckBoxes() + + def restorePanel(self, currentList, maxHashes): + """restorePanel - restore the PCONF element panel from the specified PLIST_DEF""" + + print("restorePanel - Rules=%d, PCONF Control=%d" % (self.pdef.Rules, currentList.ElementDefData[self.myIndex].Control)) # DBGDBG + + # update Override PS Policy checkbox + self.overridePsPolicy.SetValue(currentList.ElementDefData[self.myIndex].Control) + if(self.pdef.Rules == DEFINES.PoRules): + self.overridePsPolicy.Enable( True ) + else: + self.overridePsPolicy.Enable( False ) + + listversion = str(currentList.ListVersionMajor)+'.'+str(currentList.ListVersionMinor) + if listversion == '2.0': + self.showV20Gui(True) + else: + self.showV20Gui(False) + + # If MaxHashes not 0, Only enable Add if < MaxHashes files + numbHashes = currentList.ElementDefData[self.myIndex].NumbHashes + flag = True + if(maxHashes != 0): + if(numbHashes >= maxHashes): + flag = False # don't enable add + self.addButton.Enable(flag) + + # if >0 hashes + # enable remove and update + # select 1st file and set SelectedFile + flag = False + if(numbHashes > 0): + flag = True + self.pcrFileCombo.SetSelection(0) + self.pcrFileCombo.Enable(True) + self.fileSelectionEdit.ChangeValue("1") + + self.removeButton.Enable(flag) + self.updateButton.Enable(flag) + + # set Number of Files + self.fileCntEdit.ChangeValue(str(numbHashes)) + + # update PCR Selection checkboxes for selected file + currentEntrySelected = currentList.ElementDefData[self.myIndex].CurrentView + print("restorePanel - PCONF currentEntrySelected=%d numbHashes=%d" % (currentEntrySelected, numbHashes)) # DBGDBG + if(numbHashes > 0): + self.showSelection(currentEntrySelected) + pconf_info = currentList.ElementDefData[self.myIndex].PcrInfoSrc[currentEntrySelected] + pcrSelection = pconf_info.pcrSelect[0] + self.setPcrSelectionCheckboxes(pcrSelection) + self.pcrFileCombo.SetSelection(currentEntrySelected) + self.pcr0.Enable(True) + self.pcr1.Enable(True) + self.pcr2.Enable(True) + self.pcr3.Enable(True) + self.pcr4.Enable(True) + self.pcr5.Enable(True) + self.pcr6.Enable(True) + self.pcr7.Enable(True) + + # Now form PCR File combo selection and choices list + # ***Note that this code requires that the PCR Selection checkboxes have + # been updated all ready******************************************** + self.updatePcrFileCombo() + + #def setListModified(self): + # """setListModified - if list not modified yet, increment its rev cnt and set it to modified""" + # + # currentList = self.pdef.getCurrentListObject() + # + # #print("PCONF setListModified - ListModified was %s" % (currentList.ListModified)) # DBGDBG + # if(currentList.ListModified == False): + # currentList.RevocationCounter += 1 + # self.listPanel.revocationCountEdit.ChangeValue(str(currentList.RevocationCounter)) # update the GUI + # currentList.ListModified = True diff -Nru tboot-1.9.4/lcp-gen2/pconf.py tboot-1.9.5/lcp-gen2/pconf.py --- tboot-1.9.4/lcp-gen2/pconf.py 1970-01-01 00:00:00.000000000 +0000 +++ tboot-1.9.5/lcp-gen2/pconf.py 2016-12-17 03:19:38.000000000 +0000 @@ -0,0 +1,681 @@ +#!/usr/bin/python +# Copyright (c) 2013, Intel Corporation. All rights reserved. + +# using print() built infunction, disable print statement +from __future__ import print_function + +# +# wxPython is not part of the standard Python distribution and has to be downloaded and installed separately. +# Tell the user that wxPython is required but has not been found +# +try: + import wx +except ImportError: + raise ImportError, "Please download the appropriate version of wxPython from www.wxpython.org" + +try: + import os + import shutil +except ImportError: + raise ImportError, "import OS failed" + +from defines import DEFINES +from pdef import PCONF_DEF +from pdef import PCONF_INFO +from ElementGui import * + +from util import UTILS +utilities = UTILS() + +try: + import cPickle as pickle +except ImportError: + import pickle # fall back on Python version + +# +# TXT Policy Generator Tool +# PCONF Class - Policy Definition File Lists +# +class PCONF( ElementGui ): + + CONST_TITLE = "Choose PCR File" + CONST_WILDCARD = "Pcr file (*.pcr) | *.pcr|" \ + "All Files (*.*) | *.*" + + """__init__() - PCONF class constructor""" + def __init__( self, hashAlg ): + self.pconfPanelWidgets = [] + self.panelCreated = False + + try: + # reverse lookup of the hash algorithm name(key) for the given HashAlg value + hashAlgName = (key for key,val in DEFINES.TPM_ALG_HASH.items() if (val == hashAlg)).next() + except StopIteration: + print("PCONF::__init__ - invalid hashAlg=%d" % (hashAlg)) + return + + self.myIndex = -1 # myIndex is set in createOrShowPanel() + #if( hashAlg == DEFINES.TPM_ALG_HASH['SHA256']): + # self.myIndex = DEFINES.DEFDATA_INDEX_SHA256 + #elif( hashAlg == DEFINES.TPM_ALG_HASH['SHA1']): + # self.myIndex = DEFINES.DEFDATA_INDEX_SHA1 + #else: + # print("PCONF::__init__ - invalid hashAlg=%d" % (hashAlg)) + + self.myHashAlg = hashAlg + + # + # create the PCONF Panel + # + def createOrShowPanel(self, wx, listPanel, parent, pdef, statusBar): + """createOrShowPanel - create the List Panel""" + + #print("createOrShowPconfPanel hashAlg=%d, panelCreated == %s" % (self.myHashAlg, self.panelCreated)) # DBGDBG + # 1st time, create the panel + # nth time, show the panel + if(self.panelCreated == True): + self.pcrFileCombo.Clear() + self.showPanel() + return + + self.pdef = pdef + self.parent = parent + self.listPanel = listPanel + self.StatusBar = statusBar + parentSizer = parent.GetSizer() + + currentList = self.pdef.getCurrentListObject() + self.myIndex = len(currentList.ElementDefData)-1 # Just added the element, the last one should be the one. + + # create the PCONF Panel sizers + #self.pconfPanelSizer = wx.BoxSizer(wx.VERTICAL) + pconfGridSizer= wx.GridBagSizer(hgap=5, vgap=5) + #pconfHorizSizer = wx.BoxSizer(wx.HORIZONTAL) + + self.pconfPanel = wx.Panel(parent, -1) + self.pconfPanel.SetSizer(pconfGridSizer) + + pconfLabelText1 = "PCONF" + pconfLabelText2 = "Element" + pconfLabel1 = wx.StaticText(self.pconfPanel, -1, pconfLabelText1) + pconfLabel2 = wx.StaticText(self.pconfPanel, -1, pconfLabelText2) + font = wx.Font( 18, wx.FONTFAMILY_DEFAULT, wx.NORMAL, wx.BOLD) + pconfLabel1.SetFont( font ) + pconfGridSizer.Add( pconfLabel1, pos=(0, 3)) + self.pconfPanelWidgets.append(pconfLabel1) + pconfLabel2.SetFont( font ) + pconfGridSizer.Add( pconfLabel2, pos=(0, 4)) + self.pconfPanelWidgets.append(pconfLabel2) + + self.typeLabel = wx.StaticText(self.pconfPanel, label="Type") + pconfGridSizer.Add( self.typeLabel, pos=(1,3)) + self.pconfPanelWidgets.append(self.typeLabel) + self.typeEdit = wx.TextCtrl( self.pconfPanel, value="PCONF", size=(40, -1)) + self.typeEdit.Enable( False ) + pconfGridSizer.Add( self.typeEdit, pos=(1,4)) + self.pconfPanelWidgets.append(self.typeEdit) + + self.contolOptionsLabel = wx.StaticText(self.pconfPanel, -1, "Control") + font = wx.Font( 10, wx.FONTFAMILY_DEFAULT, wx.NORMAL, wx.BOLD) + self.contolOptionsLabel.SetFont( font ) + + # override PS policy bit is applicable only if PO policy rules + self.overridePsPolicy = wx.CheckBox(self.pconfPanel, label="Override PS Policy") + + if(self.pdef.Rules == DEFINES.PoRules): + self.overridePsPolicy.Enable( True ) + else: + self.overridePsPolicy.Enable( False ) + + pconfGridSizer.Add(self.contolOptionsLabel, pos=(0,8), span=(1,2), flag=wx.BOTTOM, border=5) + self.overridePsPolicy.Bind(wx.EVT_CHECKBOX, self.onOverridePsPolicy, self.overridePsPolicy) + pconfGridSizer.Add(self.overridePsPolicy, pos=(1,8), span=(1,2), flag=wx.BOTTOM, border=5) + self.pconfPanelWidgets.append(self.contolOptionsLabel) + self.pconfPanelWidgets.append(self.overridePsPolicy) + + hashAlgStr = self.getHashAlgName() + if hashAlgStr == None: + print("createOrShowPconfPanel - invalid myHashAlg=%d" % (self.myHashAlg)) + + self.hashAlgLabel = wx.StaticText(self.pconfPanel, label="Hash Algorithm") + font = wx.Font( 10, wx.FONTFAMILY_DEFAULT, wx.NORMAL, wx.BOLD) + self.hashAlgLabel.SetFont( font ) + pconfGridSizer.Add(self.hashAlgLabel, pos=(0,20)) + self.pconfPanelWidgets.append(self.hashAlgLabel) + + self.hashAlgEdit = wx.TextCtrl( self.pconfPanel, size=(75, -1), value=hashAlgStr ) + self.hashAlgEdit.Enable(False) + pconfGridSizer.Add(self.hashAlgEdit, pos=(1,20)) + self.pconfPanelWidgets.append(self.hashAlgEdit) + + pcrFile = "" + self.pcrFileFileLabel = wx.StaticText(self.pconfPanel, label="PCR File") + font = wx.Font( 10, wx.FONTFAMILY_DEFAULT, wx.NORMAL, wx.NORMAL) + self.pcrFileFileLabel.SetFont( font ) + pconfGridSizer.Add( self.pcrFileFileLabel, pos=(2,3)) + self.pconfPanelWidgets.append(self.pcrFileFileLabel) + + self.pcrFileCombo = wx.ComboBox( self.pconfPanel, value=pcrFile, size=(200, -1), choices=pcrFile, style=wx.CB_DROPDOWN) + self.pcrFileCombo.Enable( False ) # prevent selection since pulldown is empty + self.pcrFileCombo.Bind(wx.EVT_TEXT, self.onPcrFileCombo, self.pcrFileCombo) + pconfGridSizer.Add( self.pcrFileCombo, pos=(2,4)) + self.pconfPanelWidgets.append(self.pcrFileCombo) + + self.fileSelectionLabel = wx.StaticText(self.pconfPanel, label="Selected File") + pconfGridSizer.Add( self.fileSelectionLabel, pos=(7,3)) + self.pconfPanelWidgets.append(self.fileSelectionLabel) + self.fileSelectionEdit = wx.TextCtrl( self.pconfPanel, value=" ", size=(40, -1)) + self.fileSelectionEdit.Enable( False ) + pconfGridSizer.Add( self.fileSelectionEdit, pos=(7,4)) + self.pconfPanelWidgets.append(self.fileSelectionEdit) + + self.fileCntLabel = wx.StaticText(self.pconfPanel, label="Number of Files") + pconfGridSizer.Add( self.fileCntLabel, pos=(8,3)) + self.pconfPanelWidgets.append(self.fileCntLabel) + self.fileCntEdit = wx.TextCtrl( self.pconfPanel, value="0", size=(40, -1)) + self.fileCntEdit.Enable( False ) + pconfGridSizer.Add( self.fileCntEdit, pos=(8,4)) + self.pconfPanelWidgets.append(self.fileCntEdit) + + self.updateButton = wx.Button( self.pconfPanel, -1, label="Apply PCR Selection") + self.updateButton.Enable( False ) + pconfGridSizer.Add( self.updateButton, pos=(7,8)) + self.pconfPanelWidgets.append(self.updateButton) + self.updateButton.Bind(wx.EVT_BUTTON, self.onUpdateButtonClick, self.updateButton) + + self.addButton = wx.Button( self.pconfPanel, -1, label=" Add ") + pconfGridSizer.Add( self.addButton, pos=(3,4)) + self.pconfPanelWidgets.append(self.addButton) + self.addButton.Bind(wx.EVT_BUTTON, self.onAddButtonClick, self.addButton) + + self.removeButton = wx.Button( self.pconfPanel, -1, label=" Remove ") + self.removeButton.Enable( False ) + pconfGridSizer.Add( self.removeButton, pos=(4,4)) + self.pconfPanelWidgets.append(self.removeButton) + self.removeButton.Bind(wx.EVT_BUTTON, self.onRemoveButtonClick, self.removeButton) + + #self.pcrSelectionLabel = wx.StaticText(self.pconfPanel, -1, "PCR Selection") + #font = wx.Font( 10, wx.FONTFAMILY_DEFAULT, wx.NORMAL, wx.BOLD) + #self.pcrSelectionLabel.SetFont( font ) + self.pcrSelectionLabel1 = wx.StaticText(self.pconfPanel, -1, "PCR ") + font = wx.Font( 10, wx.FONTFAMILY_DEFAULT, wx.NORMAL, wx.BOLD) + self.pcrSelectionLabel1.SetFont( font ) + self.pcrSelectionLabel2 = wx.StaticText(self.pconfPanel, -1, "Selection") + self.pcrSelectionLabel2.SetFont( font ) + + self.pcr0 = wx.CheckBox(self.pconfPanel, label="0") + self.pcr1 = wx.CheckBox(self.pconfPanel, label="1") + self.pcr2 = wx.CheckBox(self.pconfPanel, label="2") + self.pcr3 = wx.CheckBox(self.pconfPanel, label="3") + self.pcr4 = wx.CheckBox(self.pconfPanel, label="4") + self.pcr5 = wx.CheckBox(self.pconfPanel, label="5") + self.pcr6 = wx.CheckBox(self.pconfPanel, label="6") + self.pcr7 = wx.CheckBox(self.pconfPanel, label="7") + + self.pcrSelectionCheckboxes =[self.pcr7, self.pcr6, self.pcr5, self.pcr4, + self.pcr3, self.pcr2, self.pcr1, self.pcr0] + + self.enableDisablePcrSelectionCheckBoxes(False) # disable the check boxes til the 1st file is added + + + #pconfGridSizer.Add(self.pcrSelectionLabel, pos=(2,8), span=(1,2), flag=wx.BOTTOM, border=5) + pconfGridSizer.Add(self.pcrSelectionLabel1, pos=(2,6), span=(1,2), flag=wx.BOTTOM, border=5) + pconfGridSizer.Add(self.pcrSelectionLabel2, pos=(2,8), span=(1,2), flag=wx.BOTTOM, border=5) + pconfGridSizer.Add(self.pcr7, pos=(3,6), span=(1,2), flag=wx.BOTTOM, border=5) + pconfGridSizer.Add(self.pcr6, pos=(4,6), span=(1,2), flag=wx.BOTTOM, border=5) + pconfGridSizer.Add(self.pcr5, pos=(5,6), span=(1,2), flag=wx.BOTTOM, border=5) + pconfGridSizer.Add(self.pcr4, pos=(6,6), span=(1,2), flag=wx.BOTTOM, border=5) + pconfGridSizer.Add(self.pcr3, pos=(3,8), span=(1,2), flag=wx.BOTTOM, border=5) + pconfGridSizer.Add(self.pcr2, pos=(4,8), span=(1,2), flag=wx.BOTTOM, border=5) + pconfGridSizer.Add(self.pcr1, pos=(5,8), span=(1,2), flag=wx.BOTTOM, border=5) + pconfGridSizer.Add(self.pcr0, pos=(6,8), span=(1,2), flag=wx.BOTTOM, border=5) + + #self.pconfPanelWidgets.append(self.pcrSelectionLabel) + self.pconfPanelWidgets.append(self.pcrSelectionLabel1) + self.pconfPanelWidgets.append(self.pcrSelectionLabel2) + self.pconfPanelWidgets.append(self.pcr0) + self.pconfPanelWidgets.append(self.pcr1) + self.pconfPanelWidgets.append(self.pcr2) + self.pconfPanelWidgets.append(self.pcr3) + self.pconfPanelWidgets.append(self.pcr4) + self.pconfPanelWidgets.append(self.pcr5) + self.pconfPanelWidgets.append(self.pcr6) + self.pconfPanelWidgets.append(self.pcr7) + + self.pconfPanelWidgets.append(self.pconfPanel) + #print("PCONF createPanel - hashAlg=%d, len(Widgets)=%d" % (self.myHashAlg, len(self.pconfPanelWidgets))) #DBGDBG + #pconfHorizSizer.Add(pconfGridSizer, 0, wx.ALL, 5) + #self.pconfPanelSizer.Add(pconfHorizSizer, 0, wx.ALL, 5) + #parent.SetSizerAndFit(self.pconfPanelSizer) + parentSizer.Add(self.pconfPanel) + w,h = parentSizer.GetMinSize() + parent.SetVirtualSize((w,h)) + print("parent sizer type = %s size = %d, %d" %(type(parentSizer).__name__, w, h)) + parent.Layout() + # call restorePanel to sync data to GUI + self.restorePanel(currentList, pdef.MaxHashes) + self.panelCreated = True + + def hidePanel(self): + """hidePanel - hide the Pconf panel""" + #print("PCONF hidePanel - hashAlg=%d, len(Widgets)=%d" % (self.myHashAlg, len(self.pconfPanelWidgets))) #DBGDBG + for i in self.pconfPanelWidgets: + i.Hide() + + + def showPanel(self): + """showPanel - show the Pconf panel""" + #print("PCONF showPanel - hashAlg=%d, len(Widgets)=%d" % (self.myHashAlg, len(self.pconfPanelWidgets))) #DBGDBG + if self.panelCreated: + for i in self.pconfPanelWidgets: + i.Show() + parentSizer = self.parent.GetSizer() + w,h = parentSizer.GetMinSize() + self.parent.SetVirtualSize((w,h)) + + + def setElementToDefaults(self): + """setElementToDefaults - PCONF""" + + self.pcrFileCombo.SetValue(' ') + self.clearPcrCheckBoxes() + + currentList = self.pdef.getCurrentListObject() + currentList.ElementDefData[self.myIndex].IncludeInList = False + currentList.ElementDefData[self.myIndex].HashAlg = self.myHashAlg + currentList.ElementDefData[self.myIndex].Control = 0 + currentList.ElementDefData[self.myIndex].NumbHashes = 0 + currentList.ElementDefData[self.myIndex].CurrentView = 0 + currentList.ElementDefData[self.myIndex].PcrInfoSrc = [] + + def onOverridePsPolicy(self, event): + """onOverridePsPolicy - update the Control field""" + + # set/clear bit 0 per MLE Dev Guide PolEltControl def + currentList = self.pdef.getCurrentListObject() + self.setListModified() + currentList.ElementDefData[self.myIndex].Control = event.Checked() + #print("onOverridePsPolicy Control=%d Event=%d" % (currentList.ElementDefData[self.myIndex].Control , event.IsChecked())) + + def onPcrFileCombo(self, event): + """onPcrFileCombo - update which PCR file is selected""" + # Get the PcrInfo entry selected by the user and save it in CurrentView + currentSelection = self.pcrFileCombo.GetSelection() + currentList = self.pdef.getCurrentListObject() + self.setListModified() + currentList.ElementDefData[self.myIndex].CurrentView = currentSelection + #print("onPcrFileCombo: currentSelection=%d, NumbHashes=%d" % (currentSelection, currentList.ElementDefData[self.myIndex].NumbHashes)) #DBGDBG + + # set the checkboxes to match the current selection and show which element is selected + self.showSelection(currentSelection) + pconf_info = currentList.ElementDefData[self.myIndex].PcrInfoSrc[currentSelection] + pcrSelection = pconf_info.pcrSelect[0] + self.setPcrSelectionCheckboxes(pcrSelection) + + def onUpdateButtonClick(self, event): + """onUpdateButtonClick - update the PCR select per the PCR0-7 checkboxes for the current file""" + self.updatePcrFileCombo() + + def updatePcrFileCombo(self): + # update the selected PcrInfoSrc[i].pcrSelect[0] with the PCR Selection info set by the user + # where i = currentList.ElementDefData[self.myIndex].CurrentView = user's current selection + # this indicates which PCRs in the file are evaluated + bit = 0 + byte = 0 + for eachCheckbox in self.pcrSelectionCheckboxes: + if(eachCheckbox.IsChecked() == True): + x = 1 << (7-bit) + #print("updatePcrFileCombo - bit %x is checked, x=%x" % (bit, x)) #DBGDBG + else: + x = 0 + + bit += 1 + byte |= x + + #print("updatePcrFileCombo - byte=%x" % (byte)) #DBGDBG + newPcrSelection = self.makeListWithEntryForEachBitInByte(byte) + + currentList = self.pdef.getCurrentListObject() + self.setListModified() + #currentEntrySelected = self.pcrFileCombo.GetSelection() + currentEntrySelected = currentList.ElementDefData[self.myIndex].CurrentView + #print("updatePcrFileCombo - currentEntrySelected=%x*****" % (currentEntrySelected)) #DBGDBG + pconf_info = currentList.ElementDefData[self.myIndex].PcrInfoSrc[currentEntrySelected] + pconf_info.pcrSelect[0] = newPcrSelection + #print("updatePcrFileCombo -currentEntrySelected=%d=%s newPcrSelection=%s" % (currentEntrySelected, pconf_info, newPcrSelection)) #DBGDBG + + filename = pconf_info.pcrFile + value = str(newPcrSelection) + " " + filename + + # replace the selection + # update the choices list + + #TODO: wxPython: updatePcrFileCombo - ComboBox.Replace doesn't work so doing .Clear() .Append's - better way? + # XXXXXXX self.pcrFileCombo.Replace( currentEntrySelected, value ) XXXXXXXXXX + # Since ComboBox.Replace doesn't work, + # Use .Clear() to clear the choices then iterate thru and reconstruct the choices with .Append(eachChoice) + + self.pcrFileCombo.Clear() + self.pcrFileCombo.SetValue( value ) + fileCnt = currentList.ElementDefData[self.myIndex].NumbHashes + i = 0 + #print("updatePcrFileCombo: NumbHashes=%d**StartOfWhile**" % (fileCnt)) #DBGDBG + while(i < fileCnt): + pconf_info = currentList.ElementDefData[self.myIndex].PcrInfoSrc[i] + #print("Update: Pconf_info%d=%s NumbHashes=%d, pcrFile=%s pcrSelect[0]=%s --start of loop--" % + # (i, pconf_info, fileCnt, pconf_info.pcrFile, pconf_info.pcrSelect[0])) # DBGDBG + bit = 0 + byte = 0 + for eachPcr in pconf_info.pcrSelect[0]: # pcrSelect[0] ordered 7:0, pcrSelectionCheckboxes ordered 0:7 + if(eachPcr == 1): + x = 1 << (7-bit) + #print("updatePcrFileCombo: i=%d: bit %x is set, x=%x byte=%x" % (i, 7-bit, x, byte)) #DBGDBG + else: + x = 0 + + bit += 1 + byte |= x + + #print("updatePcrFileCombo - byte=%x" % (byte)) #DBGDBG + newPcrSelection = self.makeListWithEntryForEachBitInByte(byte) + filename = pconf_info.pcrFile + value = str(newPcrSelection) + " " + filename + self.pcrFileCombo.Append(value) + #print("updatePcrFileCombo: i=%d value=%s --end of loop--" % (i, value )) # DBGDBG + i += 1 + + + def onAddButtonClick(self, event): + """onAddButtonClick - add a PCR file to the list""" + # Present dialogue for user to select a PCR file + # Leave PCR Selection checkboxes as is so same setting can be used on next file + + filepath, filename = self.selectFile() + + if (filename == ''): + # selectFile() operation has been cancelled. + return + + # validate that the specified PCR file is properly formatted + currentList = self.pdef.getCurrentListObject() + result = utilities.verifyPcrFile(os.path.join(filepath, filename), currentList.ElementDefData[self.myIndex].HashAlg) + # Note: verifyPcrFile() returns [FileValid, FileType], but only FileValid is used here + if( result[0] == False): + return + + self.copyFile(filepath, filename) + self.StatusBar.SetStatusText("Validated file %s." % (filename)) + + # incr currentList.ElementDefData[self.myIndex].NumbHashes and update NumberOfFiles widget + self.setListModified() + fileCnt = currentList.ElementDefData[self.myIndex].NumbHashes + fileCnt += 1 + self.fileCntEdit.ChangeValue(str(fileCnt)) + currentList.ElementDefData[self.myIndex].NumbHashes = fileCnt + + # add a PCONF_INFO to PCONF_DEF.PcrInfoSrc[] for this PCR file + pconf_info = PCONF_INFO() # create a PCONF_INFO + currentList.ElementDefData[self.myIndex].PcrInfoSrc.append(pconf_info) + #print("pconf_info: NumbHahses=%x pcrSelect[0]=%x, pcrFile=%s" % (fileCnt, pconf_info.pcrSelect[0], pconf_info.pcrFile)) # DBGDBG + + pconf_info = currentList.ElementDefData[self.myIndex].PcrInfoSrc[fileCnt-1] # add the PCONF_INFO to PCONF_DEF + + # Set currentList.ElementDefData[self.myIndex].PcrInfoSrc[i].pcrSelect[0] = 0 + # Set currentList.ElementDefData[self.myIndex].PcrInfoSrc[i].pcrFile = the selected file + # where i = currentList.ElementDefData[self.myIndex].CurrentView = user's current selection + # Concatenate "PcrInfoSrc[i].pcrSelect" and "PcrInfoSrc[i].pcrFile" per fig 9 + # display/append that concatenated value to the comboBox. ex: "00000000 PlatformA_BiosD28.pcr" + pconf_info.pcrFile = filename + pcrSelectBits = [0,0,0,0,0,0,0,0] # list of each bit in pcrSelect[0] = 00000000 + pconf_info.pcrSelect[0] = pcrSelectBits + currentList.ElementDefData[self.myIndex].CurrentView = fileCnt-1 + print("Add: Pconf_info%d=%s NumbHashes=%d, pcrFile=%s pcrSelect[0]=%s" % + (fileCnt-1, pconf_info, fileCnt, pconf_info.pcrFile, pconf_info.pcrSelect[0])) # DBGDBG + + value = str(pcrSelectBits) + " " + filename + self.pcrFileCombo.SetValue( value ) + self.pcrFileCombo.Append( value ) + + # disable ADD button if NumbHashes now > MaxHashes, unless MaxHashes is 0 indicating no limit on the number of files + if(self.pdef.MaxHashes != 0): + if(fileCnt > self.pdef.MaxHashes): + self.addButton.Enable( False ) + + # enable REMOVE and UPDATE buttons and PCR File combo box ifNumbHashes > 1 + if(fileCnt > 0): + self.updateButton.Enable( True ) + self.removeButton.Enable( True ) + self.pcrFileCombo.Enable( True ) + self.enableDisablePcrSelectionCheckBoxes(True) + + self.showSelection(currentList.ElementDefData[self.myIndex].CurrentView) + + def onRemoveButtonClick(self, event): + """onRemoveButtonClick - Remove the current PCR file from the list""" + + # confirm the remove + dlg = wx.MessageDialog(None, "Confirm removal of selected PCR file?", 'Confirm Remove', wx.YES_NO | wx.ICON_QUESTION) + response = dlg.ShowModal() + dlg.Destroy() + + if(response == wx.ID_NO): + self.StatusBar.SetStatusText( "Remove cancelled" ) + return + + # remove the selected PCRInfoSrc entry from the comboBox, ie entry: currentList.ElementDefData[self.myIndex].CurrentView + currentList = self.pdef.getCurrentListObject() + self.setListModified() + currentSelection = currentList.ElementDefData[self.myIndex].CurrentView + self.pcrFileCombo.Delete(currentSelection) + + # show entry 0 + newView = 0 + self.pcrFileCombo.SetSelection(newView) + currentList.ElementDefData[self.myIndex].CurrentView = newView + + # also remove the entry from ElementDefData[] + del currentList.ElementDefData[self.myIndex].PcrInfoSrc[currentSelection] + + # decr currentList.ElementDefData[self.myIndex].NumbHashes and update currentList.ElementDefData[self.myIndex].CurrentView + # decr currentList.ElementDefData[self.myIndex].NumbHashes and update NumberOfFiles widget + fileCnt = currentList.ElementDefData[self.myIndex].NumbHashes + fileCnt -= 1 + self.fileCntEdit.ChangeValue(str(fileCnt)) + currentList.ElementDefData[self.myIndex].NumbHashes = fileCnt + + # DBGDBG + print("onRemoveButtonClick - removed %d, NumbHashes=%d currentSelection=%d" % (currentSelection, fileCnt, currentSelection)) #DBGDBG + if(fileCnt > 0): # DBGDBG - verify ElementDefData vs. Add's prints + i=0 # DBGDBG + while(i < fileCnt): # DBGDBG + pconf_info = currentList.ElementDefData[self.myIndex].PcrInfoSrc[i] # DBGDBG + print("Remove: Pconf_info%d=%s, pcrFile=%s pcrSelect[0]=%s" % (i, pconf_info, pconf_info.pcrFile, pconf_info.pcrSelect[0])) # DBGDBG + i += 1 # DBGDBG + # DBGDBG + + if(response == wx.ID_YES): + if(fileCnt > 0): + self.showSelection(newView) + # update the PCR Selection checkboxes to match the new selection + pconf_info = currentList.ElementDefData[self.myIndex].PcrInfoSrc[newView] + pcrSelection = pconf_info.pcrSelect[0] + self.setPcrSelectionCheckboxes(pcrSelection) + else: + # no more files, disable Remove & Update + self.updateButton.Enable( False ) + self.removeButton.Enable( False ) + self.pcrFileCombo.Enable( False ) + self.enableDisablePcrSelectionCheckBoxes(False) + self.fileSelectionEdit.ChangeValue("") + self.clearPcrCheckBoxes() + self.StatusBar.SetStatusText( "PCR file removed" ) + + # reenable ADD button if NumbHashes is now < MaxHashes + if(self.pdef.MaxHashes != 0): + if(fileCnt < self.pdef.MaxHashes): + self.addButton.Enable( True ) + + def clearPcrCheckBoxes(self): + """clearPcrCheckBoxes - clear the PCR check boxes""" + for eachBox in self.pcrSelectionCheckboxes: + eachBox.SetValue(False) + + # + # Form an 8 entry list where each member represents the value of each bit in the specified byte + # ordered from bit 7 to bit 0 + # Example: if byte = 0x35 Output is [0,0,1,1,0,1,0,1] + # + def makeListWithEntryForEachBitInByte(self, byte): + """makeListWithEntryForEachBitInByte - Form an 8 entry list where each member represents the value of each bit in the specified byte """ + + bit = 0x80 + cnt = 0 + pcrSelectBits = [0, 1, 2, 3, 4, 5, 6, 7] # initial values will be overwritten + #print("Bits=%s pcrSelectBits[cnt]=%x cnt=%x bit=%x byte=%x" % (pcrSelectBits, pcrSelectBits[cnt], cnt, bit, byte)) #DBGDBG + while(bit >= 0x01): # check each bit from bit 7 thru bit 0 + if(byte & bit != 0): + pcrSelectBits[cnt] = 1 + else: + pcrSelectBits[cnt] = 0 + #print("Bits=%s, pcrSelectBits[cnt]=%x, cnt=%x bit=%x byte=%x" % (pcrSelectBits, pcrSelectBits[cnt], cnt, bit, byte)) #DBGDBG + bit >>= 1 + cnt += 1 + + return(pcrSelectBits) + + + # show current selection and prompt user to select PCRs and click UPDATE for selected file + def showSelection(self, currentSelection): + """showSelection - show user which element is selected""" + self.StatusBar.SetStatusText("PCR File %d is selected. To change PCR Selections, Set the PCR[0-7] check boxes, and click Apply PCR Selection" + % (currentSelection+1) ) + self.fileSelectionEdit.ChangeValue(str(currentSelection+1)) + + def enableDisablePcrSelectionCheckBoxes(self, value): + """setPcrSelectionCheckBoxes - enable/disable the PCR Selection check boxes """ + for eachBox in self.pcrSelectionCheckboxes: + eachBox.Enable(value) + + def setPcrSelectionCheckboxes(self, pcrSelection): + """setPcrSelectionCheckboxes - set the PCR selection checkboxes per the pcrSelection list""" + i=0 + for eachCheckbox in self.pcrSelectionCheckboxes: + if(pcrSelection[i] == 1): + eachCheckbox.SetValue(True) + else: + eachCheckbox.SetValue(False) + + i += 1 + + + def writePconfDef(self, pconfDefData, f): + """writePconfDef - write the PCONF_DEF to the specified file""" + + print("writePconfDef dump pconfDefData, hashAlg=%d" % (self.myHashAlg)) # DBGDBG + pickle.dump(pconfDefData, f) # write out the pconfDefData object + + i = 0 + for eachPconfInfo in pconfDefData.PcrInfoSrc: + #print("writePconfDef: pconfInfo %x" % (i)) # for readability + self.writePconfInfo(eachPconfInfo, i, f) + i += 1 + + def writePconfInfo(self, pconfInfo, index, f): + """writePconfInfo - write the PCONF_INFO to the specified file""" + + print("writePconfInfo dump pconfInfo") # DBGDBG + pickle.dump(pconfInfo, f) # write out the pconfInfo object + + def setPanelToDefaults(self): + """setPanelToDefaults - restore defaults to pconf panel widgets""" + + self.overridePsPolicy.SetValue(0) + self.pcrFileCombo.SetValue("") + self.addButton.Enable(True) + self.removeButton.Enable(False) + self.updateButton.Enable(False) + self.fileCntEdit.ChangeValue("0") + self.fileSelectionEdit.ChangeValue("") + self.enableDisablePcrSelectionCheckBoxes(False) + self.clearPcrCheckBoxes() + + def restorePanel(self, currentList, maxHashes): + """restorePanel - restore the PCONF element panel from the specified PLIST_DEF""" + + print("restorePanel - Rules=%d, PCONF Control=%d" % (self.pdef.Rules, currentList.ElementDefData[self.myIndex].Control)) # DBGDBG + + # update Override PS Policy checkbox + self.overridePsPolicy.SetValue(currentList.ElementDefData[self.myIndex].Control) + if(self.pdef.Rules == DEFINES.PoRules): + self.overridePsPolicy.Enable( True ) + else: + self.overridePsPolicy.Enable( False ) + + listversion = str(currentList.ListVersionMajor)+'.'+str(currentList.ListVersionMinor) + if listversion == '2.0': + self.showV20Gui(True) + else: + self.showV20Gui(False) + + # If MaxHashes not 0, Only enable Add if < MaxHashes files + numbHashes = currentList.ElementDefData[self.myIndex].NumbHashes + flag = True + if(maxHashes != 0): + if(numbHashes >= maxHashes): + flag = False # don't enable add + self.addButton.Enable(flag) + + # if >0 hashes + # enable remove and update + # select 1st file and set SelectedFile + flag = False + if(numbHashes > 0): + flag = True + self.pcrFileCombo.SetSelection(0) + self.pcrFileCombo.Enable(True) + self.fileSelectionEdit.ChangeValue("1") + + self.removeButton.Enable(flag) + self.updateButton.Enable(flag) + + # set Number of Files + self.fileCntEdit.ChangeValue(str(numbHashes)) + + # update PCR Selection checkboxes for selected file + currentEntrySelected = currentList.ElementDefData[self.myIndex].CurrentView + print("restorePanel - PCONF currentEntrySelected=%d numbHashes=%d" % (currentEntrySelected, numbHashes)) # DBGDBG + if(numbHashes > 0): + self.showSelection(currentEntrySelected) + pconf_info = currentList.ElementDefData[self.myIndex].PcrInfoSrc[currentEntrySelected] + pcrSelection = pconf_info.pcrSelect[0] + self.setPcrSelectionCheckboxes(pcrSelection) + self.pcrFileCombo.SetSelection(currentEntrySelected) + self.pcr0.Enable(True) + self.pcr1.Enable(True) + self.pcr2.Enable(True) + self.pcr3.Enable(True) + self.pcr4.Enable(True) + self.pcr5.Enable(True) + self.pcr6.Enable(True) + self.pcr7.Enable(True) + + # Now form PCR File combo selection and choices list + # ***Note that this code requires that the PCR Selection checkboxes have + # been updated all ready******************************************** + self.updatePcrFileCombo() + + + #def setListModified(self): + # """setListModified - if list not modified yet, increment its rev cnt and set it to modified""" + # + # currentList = self.pdef.getCurrentListObject() + # + # #print("PCONF setListModified - ListModified was %s" % (currentList.ListModified)) # DBGDBG + # if(currentList.ListModified == False): + # currentList.RevocationCounter += 1 + # self.listPanel.revocationCountEdit.ChangeValue(str(currentList.RevocationCounter)) # update the GUI + # currentList.ListModified = True + + # the last function in the file doesn't show up in the scope list in Understand for some reason! + def stub(self): + pass diff -Nru tboot-1.9.4/lcp-gen2/pdef.py tboot-1.9.5/lcp-gen2/pdef.py --- tboot-1.9.4/lcp-gen2/pdef.py 1970-01-01 00:00:00.000000000 +0000 +++ tboot-1.9.5/lcp-gen2/pdef.py 2016-12-17 03:19:38.000000000 +0000 @@ -0,0 +1,993 @@ +#!/usr/bin/python +# Copyright (c) 2013, Intel Corporation. All rights reserved. + +# using print() built infunction, disable print statement +from __future__ import print_function + +import os +import time + +from defines import DEFINES +from LcpPolicy import * +from util import UTILS +utilities = UTILS() + + +_GlobalHashData = [0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0] + +PCONF_ELEMENT2_HDR_SIZE = 16 # size of LCP_PCONF_ELEMENT2's fields except PcrInfo's + # i.e. sizeof(ElementSize+ElementType+ + # PolEltControl+HashAlg+NumPCRInfos) + +PCR_INFO2_HDR_SIZE = 12 # size of TPMS_QUOTE_INFO's fileds except buffer + # i.e. sizeof(count+hash+sizeOfSelect+pcrSelect+size) + +SHA1_PCR_INFO_SIZE = 26 # for PconfLegacyElement + + +# TXT Policy Generator Tool +# PDEF Class - Policy Definition File Structure +# +class PDEF( object ): + """ PDEF Class""" + + def __init__( self ): + """__init__() - PDEF class constructor""" + self.WorkingDirectory = "" + self.FileTypeSignature = "TXT Policy Definition v2" # CHAR8 array[24] + self.DefCompany = "Intel" # CHAR8 array[16] + self.StructVersion = 2 # incremented for any change to structure + # + # Structure capacity - can change without incrementing StructVersion + # + self.MaxLists = 8 # UINT8 MAX_LISTS = 8 - Max lists per policy + #self.MaxElements = 4 # UINT8 MAX_ELEMENTS = 4 - Max elements per list per element + self.MaxElements = 2 # only support SHA1 & SHA256 so far, not yet SHA384 & SHA512 + + self.MaxHashSize = 64 # UINT8 MAX_HASH_SIZE = 64 - Max allowed HASH size + self.MaxHashes = 16 # UINT16 MAX_HASHES = 16 - Max hashes per element, 0=unlimited + self.MaxFileNameSize = 32 # UINT8 MAX_FILENAME_SIZE 32 - Max size for a filename + # ReservedCap[6] 0, # UINT8 - reserved for future definition + # + # Start of variable data whose content can be changed by the tool + # + self.ToolDate = time.strftime("%Y%m%d") # UINT32 YYYYMMDD - Build date of the tool + #self.ToolVersion = 0x0200 # UINT16 Version of the tool + self.ToolVersionMajor = 02 + self.ToolVersionMinor = 00 + self.Rules = 1 # UINT8 Type of rules: 0=PS, 1=PO + self.Modified = 0 # BOOLEAN, True =changed since last 'BUILD' + # ReservedTool # UINT16 + # + # Start of Policy Definition - same as NV Policy Structure + # + #self.PolVersion = 0x0301 # UINT16 + self.PolVersionMajor = 03 + self.PolVersionMinor = 01 + self.HashAlg = DEFINES.TPM_ALG_HASH['SHA256'] # UINT16 TPM_ALG_XXXX + self.PolicyType = 1 # UINT8 0=LIST, 1=ANY + self.SinitMinVersion = 0 # UINT8 + self.DataRevocationCounters = [0,0,0,0,0,0,0,0] # UINT16 DataRevocationCounters[MAX_LISTS] Default is 0's + self.PolicyControl = 0 # UINT32 Encoding of (NPW, PCR17, Force PO) + self.MaxSinitMinVersion = 255 # UINT8 reserved in PS Policy + self.MaxBiosMinVersion = 255 # UINT8 reserved in PS Policy + # HashAlg is already defined above + # LcpHashAlgMask should be the content of CheckListBox + self.LcpHashAlgMask = DEFINES.TPM_ALG_HASH_MASK['SHA256'] # UINT16 TPM_ALG_HASH_MASK_XXXXX + # Should AuxHashAlgMask be renamed to ApAlg? + self.AuxHashAlgMask = DEFINES.TPM_ALG_HASH_MASK['SHA256'] # UINT16 TPM_ALG_HASH_MASK_XXXXX + self.LcpSignAlgMask = DEFINES.TPM_ALG_HASH_MASK['SHA256'] # UINT32 TPM_ALG_SIGN_MASK_XXXXX + + # save both the raw and hex formatted versions of the SHA1 and SHA256 hashes + #self.PolicyHashSha1 = [0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + # 0,0,0,0] # MAX_HASH = 20 for SHA1, + #self.PolicyHashSha1Hex = [0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + # 0,0,0,0] + #self.PolicyHashSha256 = [0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + # 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0] # MAX_HASH = 32 for SHA256 + #self.PolicyHashSha256Hex = [0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + # 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0] + # For Python, don't need multiple variable of different size to store hash values. + # Going forward, there will be more hash algorithms. + self.PolicyHash = [] + self.PolicyHashHex = [] + + # + # Start of Policy Data Structure Definition + # + #self.LastBuildDateStamp = 20000101 # UINT32 - YYYYMMDD - date of last build + self.LastBuildDateStampYear = 2000 # UINT16 - YYYY - year of last build + self.LastBuildDateStampMonth = 01 # UINT8 - MM - Month of last build + self.LastBuildDateStampDay = 01 # UINT8 - DD - Day of last build + #self.LastBuildTimeStamp = 00000000 # UINT32 - HHMMSS00 - time of last build + self.LastBuildTimeStampHour = 00 # UINT8 - HH - hour of last build + self.LastBuildTimeStampMinute = 00 # UINT8 - MM - minute of last build + self.LastBuildTimeStampSecond = 00 # UINT8 - SS - second of last build + self.LastBuildTimeStampLowByte = 00 # UINT8 - 00 - read only + # Reserved3 # UINT16 + self.CurrentListView = 0 # UINT8 - saves user state, indicates list to display + self.NumLists = 0 # UINT8 - Actual number of lists + # PLIST_DEF PolListInfo[0-7] # PLIST_DEF - dictionary containing policy is populated in addPlistDef + self.PolListInfo = {'0':None, '1':None, + '2':None, '3':None, + '4':None, '5':None, + '6':None, '7':None} + + # + # add PolListInfo[0-7] to the PDEF + # + def addPlistDef(self, listNumber): + """ addPlistDef - add a PLIST_DEF to the PDEF""" + print("PLIST_DEF::addPlistDef - list %i" % (listNumber)) + + if(listNumber > self.MaxLists): # should never get here if caller checked MAX_LISTS correctly ... + print("PLIST_DEF::addPlistDef - list %i > MAX=%i" % (listNumber, self.MaxLists)) + else: + self.PolListInfo[str(listNumber-1)] = PLIST_DEF() + #self.PolListInfo[str(listNumber-1)].append(PLIST_DEF()) + self.PolListInfo[str(listNumber-1)].ListValid = True + #print("addPlistDef %d = %s" % (listNumber, self.PolListInfo[str(listNumber-1)])) # DBGDBG + + # at the time when adding the list to policy, sync policy version number to list version number + policyversion = str(self.PolVersionMajor)+'.'+str(self.PolVersionMinor) + listversion = DEFINES.SUPPORTED_LCP_VERSION[policyversion] + majorstring, minorstring = listversion.split('.') + self.PolListInfo[str(listNumber-1)].ListVersionMajor = int(majorstring) + self.PolListInfo[str(listNumber-1)].ListVersionMinor = int(minorstring) + + + def getCurrentListObject(self): + """getCurrentListObject - return the current list object per CurrentListView""" + listNumber = self.CurrentListView + #print("getCurrentListObject - CurrentListView = %i" % (listNumber)) + + if(listNumber > self.MaxLists): # should never get here if CurrentListView was set correctly ... + print("PLIST_DEF::getCurrentListObject - list %i > MAX_LISTS" % (listNumber)) + elif(listNumber <= 0): + return self.PolListInfo[str(0)] + else: + return self.PolListInfo[str(listNumber-1)] + + +class PLIST_DEF( object ): + """PLIST_DEF class""" + + def __init__(self): + """___init__() = PLIST_DEF class constructor""" + #print("constructing a PLIST_DEF") + + self.LdefSize = 128 # UINT32 - number of bytes in this LIST def + self.Tag = "LIST" # UINT32 - confirms this is a LIST def struct + #self.ListVersion = 0x0201 # UINT16 - version 2.1 + self.ListVersionMajor = 02 + self.ListVersionMinor = 01 + self.ListValid = False # BOOLEAN - indicates if this list is to be included + self.ListModified = False # BOOLEAN - indicates if this list has changed since last build; only clear when building policy. + # Reserved[3] = 0 # UINT8 + self.SigAlgorithm = DEFINES.TPM_ALG_SIGN['NULL'] # UINT8 - USER: 0=Not signed, 1 = PSA PKCS15 + self.sigAlgorithmHash = DEFINES.TPM_ALG_HASH['SHA1'] # corresponds to 1 + self.PolicyElementSize = 0 # UINT32 - total size of all elements in this list + self.CurrentElementView = "None" # UINT8 - saves user state: 0=MLE, 1=PCONF, 3=SBIOS, 0xFF=None + # Reserved2[3] = 0 # UINT8 + + # start of signature + self.SyncRevCount = True # BOOLEAN - if true, updates Policy with RevocationCounter value + # Reserved3[3] = 0 # UINT8 + self.RevokeCounter = 0 # UINT16 - value to be populated in PDEF.RevocationCounter[n] + self.RevocationCounter = 0 # UINT16 + self.KeySize = 2048 # UINT16 - 1024, 2048 or 3072, default = 2048 + self.PubKeyFile = "" # CHAR16[MAX_FILENAME_SIZE=32] - filename of signing key + self.PvtKeyFile = "" + self.PubKeyData = "" # PubKeyData[KeySize] for RSA - as a binary string + # Not creating a separate class because the GUI will create and destroy when selecting between RSA and ECC signature algs + self.PubKeyQx = "" # PubKeyData[KeySize] for ECC x coord - as binary string + self.PubKeyQy = "" # PubKeyData[KeySize] for ECC y coord - as binary string + self.PvtKeyFileIsSignature = False # False: PvtKeyFile is a key file; True: PvtKeyFile is signature file + + # using one collection(list) to store all element definition data + # Python list guarantees the order. + self.ElementDefData = [] + + +# MLE Element definition - TYPE=0 +class MLE_DEF( object ): + """MLE_DEF class""" + + def __init__(self, hashAlg): + """__init__() = MLE_DEF class constructor""" + #print("constructing a MLE_DEF") + + try: + hashAlgName = (key for key,val in DEFINES.TPM_ALG_HASH.items() if hashAlg == val).next() + except StopIteration: + hashAlgname = "" + print("MLE_DEF::__init__ - invalid hashAlg=%d" % (hashAlg)) + + self.Name = "MLE-"+hashAlgName # String - Name used for GUI identification + self.InfoSize = 24 # UINT32 - number of bytes in this structure + self.Tag = "MLE_" # UINT32 - confirms this is a MLE_DEF + self.IncludeInList = False # BOOLEAN - indicates this LIST includes an MLE element + #Reserved3[5] = 0 # UINT8 + self.SinitMinVersion = 0 # UINT8 - USER + self.HashAlg = hashAlg # UINT16 - TPM_ALG_SHAXXXXX + self.Control = 0 # UINT32 - USER: Bit0: Ignore PS MLE elements + self.NumbHashes = 0 # UINT16 - Tracks number of valid entries in MleHashFiles[] + self.CurrentView = 0 # UINT16 - User state: last MleHashFiles[] selected + self.HashFiles = [] # variable size array containing filenames of hashes + + # Build the MLE element and return its size + # thisPdefList - is the list's source data from pdef.PolListInfo[list] + # policyElement - is the destination LCP POLICY element + # Return the elementSize built, or 0 if an error occurs + # + def build(self, thisPdefList, policyElements, cwd): + """buildMleElement - build the MLE element""" + func = 'buildMleElement' + + print("%s" %(func )) # DBGDBG + elementSize = 18 # size all fields except Hashes[] in bytes + + # build the element's data + #mleDefData = thisPdefList.MleDefData[index] + policyElement = LCP_MLE_ELEMENT2() + policyElement.PolEltControl = self.Control + policyElement.SINITMinVersion = self.SinitMinVersion + policyElement.HashAlg = self.HashAlg + policyElement.NumHashes = self.NumbHashes + print("%s - PolEltControl=%d, SINITMinVersion=%d from %d" % + (func, policyElement.PolEltControl, policyElement.SINITMinVersion, self.SinitMinVersion)) # DBGDBG + + hashAlg = self.HashAlg + try: + # reverse lookup of the hash algorithm name(key) for the given HashAlg value + hashAlgName = (key for key,val in DEFINES.TPM_ALG_HASH.items() if (val == hashAlg)).next() + except StopIteration: + print ("HashAlg=%d is not supported, aborting build" % (hashAlg)) + return 0 + + # Build the hashes from each HashFiles[] + for file in self.HashFiles: + hashdata = utilities.getHashFromFile(os.path.join(cwd, file), self.HashAlg) + if(len(hashdata) != DEFINES.DIGEST_SIZE[hashAlgName]): + #self.StatusBar.SetStatusText("Invalid hash file %s, aborting build" % (file)) + return 0 + + #policyElement.Hashes += _GlobalHashData # the hash data from the file + policyElement.Hashes.append(hashdata) + print("%s - policyElement.Hashes size=0x%x" % (func, len(policyElement.Hashes))) # DBGDBG + + # update elementSize + elementSize += DEFINES.DIGEST_SIZE[hashAlgName] * self.NumbHashes + + # ElementSize = 16 +HashSize* (PDEF.PolListInfo[i].MleDefData[index].NumbHashes) + # if HashAlg == SHA-1, HashSize=20 + policyElement.ElementSize = elementSize + print("%s - done, size=0x%x" % (func, elementSize)) + + policyElements.append(policyElement) + return(elementSize) + + def printDef(self, f): + """printDef - write the Mle Def to the specified human readable text file for printing""" + + #print("printMleDef - object: %s" % (mleDefData)) # DBGDBG + print("***MLE_DEF***", file=f) + print("InfoSize", " = ", self.InfoSize, file=f) + print("Tag", " = ", self.Tag, file=f) + #print("IncludeInList", " = ", self.IncludeInList, file=f) + print("SinitMinVersion", " = ", self.SinitMinVersion, file=f) + print("HashAlg", " = ", hex(self.HashAlg), file=f) + print("Control", " = ", self.Control, file=f) + print("NumbHashes", " = ", self.NumbHashes, file=f) + print("CurrentView", " = ", self.CurrentView, file=f) + print("HashFiles", " = ", self.HashFiles, file=f) + + +class MLELEGACY_DEF( object ): + """MLELEGACY_DEF class""" + + def __init__(self): + """__init__() = MLELEGACY_DEF class constructor""" + #print("constructing a MLELEGACY_DEF") + + self.Name = DEFINES.ELEMENT_NAME_MLE_LEGACY # String - Name used for GUI identification + self.InfoSize = 24 # UINT32 - number of bytes in this structure + self.Tag = "MLE_" # UINT32 - confirms this is a MLE_DEF + self.IncludeInList = False # BOOLEAN - indicates this LIST includes an MLE element + #Reserved3[5] = 0 # UINT8 + self.SinitMinVersion = 0 # UINT8 - USER + self.HashAlg = 0 # UINT8 - SHA1 + self.Control = 0 # UINT32 - USER: Bit0: Ignore PS MLE elements + self.NumbHashes = 0 # UINT16 - Tracks number of valid entries in MleHashFiles[] + self.CurrentView = 0 # UINT16 - User state: last MleHashFiles[] selected + self.HashFiles = [] # variable size array containing filenames of hashes + + # Build the MLE element and return its size + # thisPdefList - is the list's source data from pdef.PolListInfo[list] + # policyElement - is the destination LCP POLICY element + # Return the elementSize built, or 0 if an error occurs + # + def build(self, thisPdefList, policyElements, cwd): + """buildMleLegacyElement - build the MLE element""" + + func = "buildMleLegacyElement" + print("%s" %(func)) # DBGDBG + elementSize = 16 # size all fields except Hashes[] in bytes + + # build the element's data + #mleDefData = thisPdefList.MleLegacyDefData[DEFINES.DEFDATA_INDEX['SHA1']] + policyElement = LCP_MLE_ELEMENT() + policyElement.PolEltControl = self.Control + policyElement.SINITMinVersion = self.SinitMinVersion + policyElement.HashAlg = self.HashAlg + policyElement.NumHashes = self.NumbHashes + print("%s - PolEltControl=%d, SINITMinVersion=%d from %d" % + (func, policyElement.PolEltControl, policyElement.SINITMinVersion, self.SinitMinVersion)) # DBGDBG + + # Build the hashes from each HashFiles[] + for file in self.HashFiles: + hashdata = utilities.getHashFromFile(os.path.join(cwd, file), DEFINES.TPM_ALG_HASH['SHA1']) + if(len(hashdata) != DEFINES.DIGEST_SIZE['SHA1']): + print ("Invalid hash file %s, aborting build" % (file)) + return 0 + + policyElement.Hashes.append(hashdata) # the hash data from the file + print("%s - policyElement.Hashes size=0x%x" % (func, len(policyElement.Hashes))) # DBGDBG + + if(self.HashAlg == DEFINES.TPM_ALG_HASH['SHA1_LEGACY']): + # update elementSize + elementSize += DEFINES.DIGEST_SIZE['SHA1'] * self.NumbHashes + else: + print ("HashAlg=%d is not supported, aborting build" % (thisPdefList.HashAlg)) + return 0 + + # ElementSize = 16 +HashSize* (PDEF.PolListInfo[i].MleDefData.NumbHashes) + # if HashAlg == SHA-1, HashSize=20 + policyElement.ElementSize = elementSize + print("%s - done, size=0x%x" % (func, elementSize)) + + policyElements.append(policyElement) + return(elementSize) + + def printDef(self, f): + """printMleDef - write the Mle Def to the specified human readable text file for printing""" + + #print("printMleDef - object: %s" % (mleDefData)) # DBGDBG + + print("***MLELEGACY_DEF***", file=f) + print("InfoSize", " = ", self.InfoSize, file=f) + print("Tag", " = ", self.Tag, file=f) + #print("IncludeInList", " = ", self.IncludeInList, file=f) + print("SinitMinVersion", " = ", self.SinitMinVersion, file=f) + print("HashAlg", " = ", hex(self.HashAlg), file=f) + print("Control", " = ", self.Control, file=f) + print("NumbHashes", " = ", self.NumbHashes, file=f) + print("CurrentView", " = ", self.CurrentView, file=f) + print("HashFiles", " = ", self.HashFiles, file=f) + + +# STM Element definition - TYPE=0 +class STM_DEF( object ): + """STM_DEF class""" + + def __init__(self, hashAlg): + """__init__() = STM_DEF class constructor""" + #print("constructing a STM_DEF") + + try: + hashAlgName = (key for key,val in DEFINES.TPM_ALG_HASH.items() if hashAlg == val).next() + except StopIteration: + hashAlgname = "" + print("STM_DEF::__init__ - invalid hashAlg=%d" % (hashAlg)) + + self.Name = "STM-"+hashAlgName # String - Name used for GUI identification + self.InfoSize = 24 # UINT32 - number of bytes in this structure + self.Tag = "STM_" # UINT32 - confirms this is a MLE_DEF + self.IncludeInList = False # BOOLEAN - indicates this LIST includes an MLE element + #Reserved3[5] = 0 # UINT8 + self.HashAlg = hashAlg # UINT16 - TPM_ALG_SHAXXXXX + self.Control = 0 # UINT32 - USER: Bit0: Ignore PS MLE elements + self.NumbHashes = 0 # UINT16 - Tracks number of valid entries in MleHashFiles[] + self.CurrentView = 0 # UINT16 - User state: last MleHashFiles[] selected + self.HashFiles = [] + + def build(self, thisPdefList, policyElements, cwd): + """buildStmElement - build the STM element""" + + func='buildStmElement' + print("%s" % (func)) # DBGDBG + elementSize = 16 # size all fieds except Hashes[] in bytes + + # build the element's data + #stmDefData = thisPdefList.StmDefData[index] + policyElement = LCP_STM_ELEMENT2() + policyElement.PolEltControl = self.Control + policyElement.HashAlg = self.HashAlg + policyElement.NumHashes = self.NumbHashes + print("%s - PolEltControl=%d" % (func, policyElement.PolEltControl)) # DBGDBG + + + hashAlg = self.HashAlg + try: + # reverse lookup of the hash algorithm name(key) for the given HashAlg value + hashAlgName = (key for key,val in DEFINES.TPM_ALG_HASH.items() if (val == hashAlg)).next() + except StopIteration: + print ("HashAlg=%d is not supported, aborting build" % (hashAlg)) + return 0 + + # Build the hashes from each HashFiles[] + for file in self.HashFiles: + hashdata = utilities.getHashFromFile(os.path.join(cwd, file), self.HashAlg) + if(len(hashdata) != DEFINES.DIGEST_SIZE[hashAlgName]): + #self.StatusBar.SetStatusText("Invalid hash file %s, aborting build" % (file)) + return 0 + + #policyElement.Hashes += _GlobalHashData # the hash data from the file + policyElement.Hashes.append(hashdata) + print("%s - policyElement.Hashes size=0x%x" % (func, len(policyElement.Hashes))) # DBGDBG + + # update elementSize + elementSize += DEFINES.DIGEST_SIZE[hashAlgName] * self.NumbHashes + + # ElementSize = 16 +HashSize* (PDEF.PolListInfo[i].StmDefData[index].NumbHashes) + # if HashAlg == SHA-1, HashSize=20 + policyElement.ElementSize = elementSize + print("%s - done, size=0x%x" % (func, elementSize)) + + policyElements.append(policyElement) + return(elementSize) + + def printDef(self, f): + """printDef - write the Stm Def to the specified human readable text file for printing""" + + #print("printStmDef - object: %s" % (stmDefData)) # DBGDBG + + print("***STM_DEF***", file=f) + print("InfoSize", " = ", self.InfoSize, file=f) + print("Tag", " = ", self.Tag, file=f) + #print("IncludeInList", " = ", self.IncludeInList, file=f) + print("HashAlg", " = ", hex(self.HashAlg), file=f) + print("Control", " = ", self.Control, file=f) + print("NumbHashes", " = ", self.NumbHashes, file=f) + print("CurrentView", " = ", self.CurrentView, file=f) + print("HashFiles", " = ", self.HashFiles, file=f) + + +class PCONF_INFO( object ): + """PCONF_INFO definition""" + + def __init__(self): + """__init__() PCONF_INFO constructor""" + + self.pcrSelect = [1, 0, 0] # UINT8 - pcrSelect[0]=1 => pcr0-7 + #reserved = 0 # UINT8 + self.pcrFile = "myPcrFile.pcr" + + self.PCR0_BIT = 0x01 + self.PCR1_BIT = 0x02 + self.PCR2_BIT = 0x04 + self.PCR3_BIT = 0x08 + self.PCR4_BIT = 0x10 + self.PCR5_BIT = 0x20 + self.PCR6_BIT = 0x40 + self.PCR7_BIT = 0x80 + +class PCONF_DEF( object ): + """PCONF_DEF class""" + + def __init__(self, hashAlg): + """__init__() PCONF_DEF constructor""" + #print("constructing a PCONF_DEF") + + hashAlgName = "" + try: + hashAlgName = (key for key,val in DEFINES.TPM_ALG_HASH.items() if hashAlg == val).next() + except StopIteration: + print("PCONF_DEF::__init__ - invalid hashAlg=%d" % (hashAlg)) + + self.Name = "PCONF-"+hashAlgName # String - Name used for GUI identification + self.InfoSize = 24 # UINT32 - number of bytes in this struct + self.Tag = "PCON" # UINT32 - confirms that this is a PCONF policy defintion element + self.IncludeInList = False # BOOLEAN - indicates this LIST includes a PCONF element + # Reserved5[6] = 0 # UINT8 + self.HashAlg = hashAlg # UINT16 - TPM_ALG_SHAXXXX ... + self.Control = 0 # UINT32 - USER: Bit0: Ignore PS PCONF elements + self.NumbHashes = 0 # UINT16 - Tracks number of valid entries in PconfFiles[] + self.CurrentView = 0 # UINT16 - User state: last PconfFiles[] selected + #PCONF_INFO PcrInfoSrc[] # array of PCR selection and PCR dump file names + self.PcrInfoSrc = [] + + # Build the PCONF element and return its size + # thisPdefList - is the list's source data from pdef.PolListInfo[list] + # policyElement - is the destination LCP POLICY element + # listCnt - is the current list + # + def build(self, thisPdefList, policyElements, cwd): + """buildPconfElement - build the PCONF element""" + + func = "buildPconfElement" + print("%s" %(func)) # DBGDBG + # build the element's data + elementSize = PCONF_ELEMENT2_HDR_SIZE # size of all fields except PcrInfo's + #pconfDefData = thisPdefList.PconfDefData[index] + policyElement = LCP_PCONF_ELEMENT2() + policyElement.PolEltControl = self.Control + policyElement.HashAlg = self.HashAlg + policyElement.NumPCRInfos = self.NumbHashes # really number TPMS_QUOTE_INFO's + + # Build each policyElement.PCRInfos' TPMS_QUOTE_INFO + # for each pcr + i = 0 # number of PcrInfoSrc's in LCP_PCONF_ELEMENT + for pdefPcrInfo in self.PcrInfoSrc: + thisTpmsQuoteInfo = TPMS_QUOTE_INFO() + policyElement.PCRInfos.append(thisTpmsQuoteInfo) + thisTpmsQuoteInfo = policyElement.PCRInfos[i] + thisTpmlPcrSelection = thisTpmsQuoteInfo.pcrSelect # TPML_PCR_SELECTION() + thisTpm2bDigest = thisTpmsQuoteInfo.pcrDigest # TPM2B_DIGEST() + # Set pcrSelections (which is type: TPMS_PCR_SELECTION) in a TPML_PCR_SELECTION to indicate the selected PCRs. + # Hash is the same algorithm ID as HashAlg in LCP_PCONF_ELEMENT2 since TPML_PCR_SELECTION's count=1 + # Size of Select is always 3 + # (because the TPM has 24 PCRs and thus requires 24-bits to indicate which PCR) + # However the 2nd and 3rd bytes of pcrSelect[] are always 0x00 because the policy + # only selects between the first 8 PCRs. + # pcrSelect[0] is a bit mask formed from thisPdefList.PconfDefData[index].PcrInfoSrc[i].pcrSelect[0] + # which is an 8 element list corresponding to each selected pcr from 0-7 + # + thisTpmlPcrSelection.count = 1 # So 1 TPMS_PCR_SELECTION and HashAlg per PCONF, see Spec A.2.2.4 p31 + thisTpmsPcrSelection = thisTpmlPcrSelection.pcrSelections + thisTpmsPcrSelection.hash = policyElement.HashAlg + thisTpmsPcrSelection.sizeOfSelect = 0x0003 + + pcr0to7SelectionBitMask = 0 + numSelectedPcrs = 0 + thisBit = 0x80 + pcr0to7SelectionList = pdefPcrInfo.pcrSelect[0] + for eachBit in pcr0to7SelectionList: + if(eachBit == 1): + pcr0to7SelectionBitMask |= thisBit + numSelectedPcrs += 1 + thisBit >>= 1 + + thisTpmsPcrSelection.pcrSelect[0] = pcr0to7SelectionBitMask + thisTpmsPcrSelection.pcrSelect[1] = 0 + thisTpmsPcrSelection.pcrSelect[2] = 0 + print("%s - PCRInfos[%d], pcrSelect[0]=0x%x, numSelectedPcrs=%d" % + (func, i, thisTpmsPcrSelection.pcrSelect[0], numSelectedPcrs)) # DBGDBG + i += 1 + + # determine if pcrFile is a PCRD or PCR2 formatted file + file = pdefPcrInfo.pcrFile + file = os.path.join(cwd, file) + result = utilities.verifyPcrFile(file, policyElement.HashAlg) + fileType = result[1] + if(result[0] == False): + print("%s - verifyPcrFile says PCR file %s is invalid!!!" % (func, file)) # Should NEVER get here + return 0 + + # calculate thisTpm2bDigest.size and build TPM2B_DIGEST.buffer from the PCR data + # in this pdef list's selected pcrFiles + hashAlg = self.HashAlg + + try: + # reverse lookup of the hash algorithm name(key) for the given HashAlg value + hashAlgName = (key for key,val in DEFINES.TPM_ALG_HASH.items() if (val == hashAlg)).next() + except StopIteration: + print ("HashAlg=%d is not supported, aborting build" % (hashAlg)) + return 0 + + hashSize = DEFINES.DIGEST_SIZE[hashAlgName] + + # verify that the pcfFile contains numHashes PCR values. These checks weren't done by verifyPcrFile() + result = utilities.verifyPcrInfoNumHashes(file, fileType, hashAlg, pcr0to7SelectionBitMask) + if(result == False): + print("%s - verifyPcrInfoNumHashes says PCR file %s is invalid!!!" % (func, file)) + return 0 + + elementSize += PCR_INFO2_HDR_SIZE # includes thisTpm2bDigest.size but not buffer + if(pcr0to7SelectionBitMask == 0): # no pcr's selected + thisTpm2bDigest.size = 0 # buffer is empty + + else: + #thisTpm2bDigest.size = numSelectedPcrs * hashSize # sizeof(buffer) + thisTpm2bDigest.size = hashSize # There's only one composite hash + + # for each selected PCR from 0 to 7 + if(pcr0to7SelectionBitMask != 0): + # Build tpmPcrSelection.digestAtRelease from the PCR data in this pdef list's selected pcrFiles + hashdata = utilities.hashPcrInfoFromFile(os.path.join(cwd, file), pcr0to7SelectionBitMask, numSelectedPcrs) + if(len(hashdata) != hashSize): + print("%s - Invalid PCR file %s, aborting build" % (func, file)) + return 0 + + tempbuf = array('B') + tempbuf.fromstring(hashdata) + #thisTpm2bDigest.buffer += _GlobalPcrHash + thisTpm2bDigest.buffer += tempbuf + elementSize += thisTpm2bDigest.size + else: + print ("%s - Nothing to hash: pcr0to7SelectionBitMask=0" %(func)) # DBGDBG + print ("Note: No PCR was selected. If desired, select PCR's and click Update") + + #print("buildPconfElement - next pcrInfo i=%d" % (i)) # DBGDBG + # end of pcrInfo for loop + # update this element's size + policyElement.ElementSize = elementSize + print("%s - done, elementSize=0x%x" % (func, elementSize)) + + policyElements.append(policyElement) + return(elementSize) + + def printDef(self, f): + """printDef - write the PCONF_DEF to the specified file""" + + #print("printPconfDef - object: %s" % (pconfDefData)) # DBGDBG + + print("***PCONF_DEF***", file=f) + print("InfoSize", " = ", self.InfoSize, file=f) + print("Tag", " = ", self.Tag, file=f) + #print("IncludeInList", " = ", self.IncludeInList, file=f) + print("HashAlg", " = ", hex(self.HashAlg), file=f) + print("Control", " = ", self.Control, file=f) + print("NumbHashes", " = ", self.NumbHashes, file=f) + print("CurrentView", " = ", self.CurrentView, file=f) + + i = 0 + for eachPconfInfo in self.PcrInfoSrc: + print("\n", file=f) # for readability + self.printPconfInfo(eachPconfInfo, i, f) + i += 1 + + def printPconfInfo(self, pconfInfo, index, f): + """printPconfInfo - write the PCONF_INFO to the specified human readable text file for printing""" + + #print("printPconfInfo %d object: %s" % (index, pconfInfo)) # DBGDBG + + print("***PCONF_INFO", index, "***", file=f) + print("InfoSize", " = ", pconfInfo.pcrSelect, file=f) + print("Tag", " = ", pconfInfo.pcrFile, file=f) + + +class PCONFLEGACY_DEF( object ): + """PCONFLEGACY_DEF class""" + + def __init__(self): + """__init__() PCONFLEGACY_DEF constructor""" + #print("constructing a PCONFLEGACY_DEF") + + self.Name = DEFINES.ELEMENT_NAME_PCONF_LEGACY # String - Name used for GUI identification + self.InfoSize = 24 # UINT32 - number of bytes in this struct + self.Tag = "PCON" # UINT32 - confirms that this is a PCONF policy defintion element + self.IncludeInList = False # BOOLEAN - indicates this LIST includes a PCONF element + # Reserved5[6] = 0 # UINT8 + self.HashAlg = 0 # UINT8 - 0 = SHA1, others reserved for future use ... + self.Control = 0 # UINT32 - USER: Bit0: Ignore PS PCONF elements + self.NumbHashes = 0 # UINT16 - Tracks number of valid entries in PconfFiles[] + self.CurrentView = 0 # UINT16 - User state: last PconfFiles[] selected + #PCONF_INFO PcrInfoSrc[] # array of PCR selection and PCR dump file names + self.PcrInfoSrc = [] + + + # Build the PCONF element and return its size + # thisPdefList - is the list's source data from pdef.PolListInfo[list] + # policyElement - is the destination LCP POLICY element + # + def build(self, thisPdefList, policyElements, cwd): + """buildPconfLegacyElement - build the PCONF Legacy element""" + + func = "buildPconfLegacyElement" + print("%s" %(func)) # DBGDBG + elementSize = 14 # size of all fields except PcrInfo's + + # build the element's data + #pconfDefData = thisPdefList.PconfLegacyDefData + policyElement = LCP_PCONF_ELEMENT() + policyElement.PolEltControl = self.Control + policyElement.NumPCRInfos = self.NumbHashes + + # Build each policyElement.PCRInfos[NumPCRInfos] + # for each hash to NumbHashes-1 i.e. to NumPCRInfos-1 + # + i = 0 # number of PcrInfoSrc's in LCP_PCONF_ELEMENT + for pdefPcrInfo in self.PcrInfoSrc: + thisTpmPcrInfoShort = TPM_PCR_INFO_SHORT() + policyElement.PCRInfos.append(thisTpmPcrInfoShort) + thisTpmPcrInfoShort = policyElement.PCRInfos[i] + thisTpmPcrInfoShort.localityAtRelease = 0x1f # any locality + + # Set pcrSelection (which is type: TPM_PCR_SELECTION) to indicate the selected PCRs. + # Size of Select is always 3 + # (because the TPM has 24 PCRs and thus requires 24-bits to indicate which PCR) + # However the 2nd and 3rd bytes of pcrSelect[] are always 0x00 because the policy + # only selects between the first 8 PCRs. + # pcrSelect[0] is a bit mask formed from thisPdefList.PconfLegacyDefData[index].PcrInfoSrc[i].pcrSelect[0] + # which is an 8 element list corresponding to each selected pcr from 0-7 + # + thisTpmPcrSelection = thisTpmPcrInfoShort.pcrSelection + thisTpmPcrSelection.sizeOfSelect = 0x0003 + + pcr0to7SelectionBitMask = 0 + numSelectedPcrs = 0 + thisBit = 0x80 + pcr0to7SelectionList = pdefPcrInfo.pcrSelect[0] + for eachBit in pcr0to7SelectionList: + if(eachBit == 1): + pcr0to7SelectionBitMask |= thisBit + numSelectedPcrs += 1 + + thisBit >>= 1 + + thisTpmPcrSelection.pcrSelect[0] = pcr0to7SelectionBitMask + thisTpmPcrSelection.pcrSelect[1] = 0 + thisTpmPcrSelection.pcrSelect[2] = 0 + + print("%s - PCRInfos[%d], pcrSelect[0]=0x%x" % (func, i, thisTpmPcrSelection.pcrSelect[0])) # DBGDBG + i += 1 + + # Build tpmPcrSelection.digestAtRelease from the PCR data in this pdef list's selected pcrFiles + file = pdefPcrInfo.pcrFile + hashdata = utilities.hashPcrInfoFromFile(os.path.join(cwd, file), pcr0to7SelectionBitMask, numSelectedPcrs) + if(len(hashdata) != DEFINES.DIGEST_SIZE['SHA1']): + print("%s - Invalid PCR file %s, aborting build" % (func, file)) + return 0 + + thisTpmPcrInfoShort.digestAtRelease = hashdata # hash of the selected PCR data from the file + #print("buildPconfElement - digestAtRelease=%s, _GlobalPcrHash=%s" % ( thisTpmPcrInfoShort.digestAtRelease, _GlobalPcrHash)) + + if(self.HashAlg == DEFINES.TPM_ALG_HASH['SHA1_LEGACY']): + # ElementSize = 14 +PcrInfoSize* (PDEF.PolListInfo[i].PconfDefData[index].NumbHashes) + # if HashAlg == SHA-1, PcrInfoSize=26 + elementSize += SHA1_PCR_INFO_SIZE * self.NumbHashes + else: + print ("HashAlg=%d is not supported, aborting build" % (thisPdefList.HashAlg)) + return 0 + + # update this element's size + policyElement.ElementSize = elementSize + print("%s - done, size=0x%x" % (func, elementSize)) + + policyElements.append(policyElement) + return(elementSize) + + def printDef(self, f): + """printPconfDef - write the PCONF_DEF to the specified file""" + + #print("printPconfDef - object: %s" % (pconfDefData)) # DBGDBG + + print("***PCONFLegacy_DEF***", file=f) + print("InfoSize", " = ", self.InfoSize, file=f) + print("Tag", " = ", self.Tag, file=f) + print("IncludeInList", " = ", self.IncludeInList, file=f) + print("HashAlg", " = ", hex(self.HashAlg), file=f) + print("Control", " = ", self.Control, file=f) + print("NumbHashes", " = ", self.NumbHashes, file=f) + print("CurrentView", " = ", self.CurrentView, file=f) + + i = 0 + for eachPconfInfo in self.PcrInfoSrc: + print("\n", file=f) # for readability + self.printPconfInfo(eachPconfInfo, i, f) + i += 1 + + def printPconfInfo(self, pconfInfo, index, f): + """printPconfInfo - write the PCONF_INFO to the specified human readable text file for printing""" + + #print("printPconfInfo %d object: %s" % (index, pconfInfo)) # DBGDBG + + print("***PCONF_INFO", index, "***", file=f) + print("InfoSize", " = ", pconfInfo.pcrSelect, file=f) + print("Tag", " = ", pconfInfo.pcrFile, file=f) + + +class SBIOS_DEF( object ): + """SBIOS_DEF class""" + + def __init__(self, hashAlg): + """__init__() SBIOS_DEF constructor""" + #print("constructing a SBIOS_DEF") + + hashAlgName = "" + try: + hashAlgName = (key for key,val in DEFINES.TPM_ALG_HASH.items() if hashAlg == val).next() + except StopIteration: + print("SBIOS_DEF::__init__ - invalid hashAlg=%d" % (hashAlg)) + + self.Name = "SBIOS-"+hashAlgName # String - Name used for GUI identification + self.InfoSize = 56 # UINT32 - number of bytes in this struct + self.Tag = "SBIO" # UINT32 - confirms that this is a SBIOS policy defintion element + self.IncludeInList = False # BOOLEAN - indicates this LIST includes a SBIOS element + # Reserved5[6] = 0 # UINT8 + self.HashAlg = hashAlg # UINT16 - TPM_ALG_SHAXXXXX + self.FallBackHashFile = "" # FILEName - user - filename containing the fallback hash + self.Control = 0 # UINT32 - USER: There are no defined controls at this time + self.NumbHashes = 0 # UINT16 - Tracks number of valid entries in SbiosFiles[] + self.CurrentView = 0 # UINT16 - User state: last PconfFiles[] selected + self.SbiosFiles = [] # variable size array containing filenames of hashes + + # Build the SBIOS element and return its size + # thisPdefList - is the list's source data from pdef.PolListInfo[list] + # policyElement - is the destination LCP POLICY element + # Return the elementSize built, or 0 if an error occurs + # + def build(self, thisPdefList, policyElements, cwd): + """buildSbiosElement - build the SBIOS element""" + + func = "buildSbiosElement" + print("%s"%(func)) # DBGDBG + elementSize = 20 + + # build the element's data + #sbiosDefData = thisPdefList.SbiosDefData[index] + policyElement = LCP_SBIOS_ELEMENT2() + policyElement.PolEltControl = self.Control + policyElement.HashAlg = self.HashAlg + invalidMsg = "Invalid fallbackhash file, aborting build" + noneMsg = "No fallbackhash file was specified, aborting build" + + hashAlg = self.HashAlg + try: + # reverse lookup of the hash algorithm name(key) for the given HashAlg value + hashAlgName = (key for key,val in DEFINES.TPM_ALG_HASH.items() if (val == hashAlg)).next() + except StopIteration: + print ("HashAlg=%d is not supported, aborting build" % (hashAlg)) + return 0 + + # open the FallbackHash file and get the hash data + file = self.FallBackHashFile + if(file != ""): + hashdata = utilities.getHashFromFile(os.path.join(cwd, file), self.HashAlg) + if(len(hashdata) != DEFINES.DIGEST_SIZE[hashAlgName]): + print("%s" % (invalidMsg)) # also show in output window + return 0 + else: + print("%s" % (noneMsg)) # also show in output window + return 0 + + # if there was no fallback hash file specified, then hash 0's [the init value of _GlobalHashData + # otherwise use the value from that file + #policyElement.FallbackHash = _GlobalHashData # the hash data from the file + policyElement.FallbackHash = hashdata + policyElement.NumHashes = self.NumbHashes + + # print("buildSbiosElement: type=%d, Alg=%d, Fallback=%s, GlobalHash=%s, NumbHashes=%d" % + # (policyElement.ElementType, policyElement.HashAlg , + # policyElement.FallbackHash, _GlobalHashData, policyElement.NumHashes)) # DBGDBG + + # Build the hashes from each SbiosFiles[] + for file in self.SbiosFiles: + hashdata = utilities.getHashFromFile(os.path.join(cwd, file), self.HashAlg) + if(len(hashdata) != DEFINES.DIGEST_SIZE[hashAlgName]): + #self.StatusBar.SetStatusText("Invalid hash file %s, aborting build" % (file)) + return 0 + + #policyElement.Hashes += _GlobalHashData # the hash data from the file + policyElement.Hashes.append(hashdata) + print("%s - policyElement.Hashes size=0x%x" % (func,len(policyElement.Hashes))) # DBGDBG + + # update elementSize + elementSize += DEFINES.DIGEST_SIZE[hashAlgName] * (self.NumbHashes+1) # +1 for fallback hash + + # ElementSize = 20 +HashSize* (1+PDEF.PolListInfo[i].SbiosDefData[index].NumbHashes) + # if HashAlg == SHA-1, HashSize=20 + policyElement.ElementSize = elementSize + print("%s - done, size=0x%x" % (func, elementSize)) + + policyElements.append(policyElement) + return(elementSize) + + def printDef(self, f): + """printDef - write the Sbios Def to the specified human readable text file for printing""" + + #print("printSbiosDef - object: %s" % (sbiosDefData)) # DBGDBG + + print("***SBIOS_DEF***", file=f) + print("InfoSize", " = ", self.InfoSize, file=f) + print("Tag", " = ", self.Tag, file=f) + #print("IncludeInList", " = ", self.IncludeInList, file=f) + print("HashAlg", " = ", hex(self.HashAlg), file=f) + print("FallBackHashFile", " = ", self.FallBackHashFile, file=f) + print("Control", " = ", self.Control, file=f) + print("NumbHashes", " = ", self.NumbHashes, file=f) + print("CurrentView", " = ", self.CurrentView, file=f) + print("SbiosFiles", " = ", self.SbiosFiles, file=f) + + +class SBIOSLEGACY_DEF( object ): + """SBIOS_DEF class""" + + def __init__(self): + """__init__() SBIOSLEGACY_DEF constructor""" + #print("constructing a SBIOSLEGACY_DEF") + + self.Name = DEFINES.ELEMENT_NAME_SBIOS_LEGACY # String - Name used for GUI identification + self.InfoSize = 56 # UINT32 - number of bytes in this struct + self.Tag = "SBIO" # UINT32 - confirms that this is a SBIOS policy defintion element + self.IncludeInList = False # BOOLEAN - indicates this LIST includes a SBIOS element + # Reserved5[6] = 0 # UINT8 + self.HashAlg = 0 # UINT8 - 0 = SHA1, others reserved for future use ... + self.FallBackHashFile = "" # FILEName - user - filename containing the fallback hash + self.Control = 0 # UINT32 - USER: There are no defined controls at this time + self.NumbHashes = 0 # UINT16 - Tracks number of valid entries in SbiosFiles[] + self.CurrentView = 0 # UINT16 - User state: last PconfFiles[] selected + self.SbiosFiles = [] # variable size array containing filenames of hashes + + # Build the SBIOS element and return its size + # thisPdefList - is the list's source data from pdef.PolListInfo[list] + # policyElement - is the destination LCP POLICY element + # Return the elementSize built, or 0 if an error occurs + # + def build(self, thisPdefList, policyElements, cwd): + """buildSbiosElement - build the SBIOS element""" + + func = "buildSbiosLegacyElement" + print("%s" %(func)) + elementSize = 20 + + # build the element's data + #sbiosDefData = thisPdefList.SbiosLegacyDefData[DEFINES.DEFDATA_INDEX_SHA1] + policyElement = LCP_SBIOS_ELEMENT() + policyElement.PolEltControl = self.Control + policyElement.HashAlg = self.HashAlg + invalidMsg = "Invalid fallbackhash file, aborting build" + noneMsg = "No fallbackhash file was specified, aborting build" + + # open the FallbackHash file and get the hash data + file = self.FallBackHashFile + if(file != ""): + hashdata = utilities.getHashFromFile(os.path.join(cwd, file), DEFINES.TPM_ALG_HASH['SHA1']) + if(len(hashdata) != DEFINES.DIGEST_SIZE['SHA1']): + print("%s" % (invalidMsg)) # also show in output window + return 0 + else: + print("%s" % (noneMsg)) # also show in output window + return 0 + + # if there was no fallback hash file specified, then hash 0's [the init value of _GlobalHashData + # otherwise use the value from that file + policyElement.FallbackHash = hashdata # the hash data from the file + #policyElement.Hashes.append(hashdata) + + # print("buildSbiosElement: type=%d, Alg=%d, Fallback=%s, GlobalHash=%s, NumbHashes=%d" % + # (policyElement.ElementType, policyElement.HashAlg , + # policyElement.FallbackHash, _GlobalHashData, policyElement.NumHashes)) # DBGDBG + + policyElement.NumHashes = self.NumbHashes + # Build the hashes from each SbiosFiles[] + for file in self.SbiosFiles: + hashdata = utilities.getHashFromFile(os.path.join(cwd, file), DEFINES.TPM_ALG_HASH['SHA1']) + if(len(hashdata) != DEFINES.DIGEST_SIZE['SHA1']): + print ("Invalid hash file %s, aborting build" % (file)) + return 0 + + policyElement.Hashes.append(hashdata) # the hash data from the file + print("%s - policyElement.Hashes size=0x%x" % (func, len(policyElement.Hashes))) # DBGDBG + + if(self.HashAlg == DEFINES.TPM_ALG_HASH['SHA1_LEGACY']): + # update elementSize + elementSize += DEFINES.DIGEST_SIZE['SHA1'] * (self.NumbHashes+1) # +1 for fallback hash + else: + print("%s - HashAlg=%d is not supported, aborting build" % (func, thisPdefList.HashAlg)) + return 0 + + # ElementSize = 20 +HashSize* (1+PDEF.PolListInfo[i].SbiosDefData.NumbHashes) + # if HashAlg == SHA-1, HashSize=20 + policyElement.ElementSize = elementSize + print("%s - done, size=0x%x" % (func, elementSize)) + + policyElements.append(policyElement) + return(elementSize) + + def printDef(self, f): + """printSbiosDef - write the Sbios Def to the specified human readable text file for printing""" + + #print("printSbiosDef - object: %s" % (sbiosDefData)) # DBGDBG + + print("***SBIOSLEGACY_DEF***", file=f) + print("InfoSize", " = ", self.InfoSize, file=f) + print("Tag", " = ", self.Tag, file=f) + #print("IncludeInList", " = ", self.IncludeInList, file=f) + print("HashAlg", " = ", hex(self.HashAlg), file=f) + print("FallBackHashFile", " = ", self.FallBackHashFile, file=f) + print("Control", " = ", self.Control, file=f) + print("NumbHashes", " = ", self.NumbHashes, file=f) + print("CurrentView", " = ", self.CurrentView, file=f) + print("SbiosFiles", " = ", self.SbiosFiles, file=f) diff -Nru tboot-1.9.4/lcp-gen2/sbiosLegacy.py tboot-1.9.5/lcp-gen2/sbiosLegacy.py --- tboot-1.9.4/lcp-gen2/sbiosLegacy.py 1970-01-01 00:00:00.000000000 +0000 +++ tboot-1.9.5/lcp-gen2/sbiosLegacy.py 2016-12-17 03:19:38.000000000 +0000 @@ -0,0 +1,468 @@ +#!/usr/bin/python +# Copyright (c) 2013, Intel Corporation. All rights reserved. + +# using print() built infunction, disable print statement +from __future__ import print_function + +# +# wxPython is not part of the standard Python distribution and has to be downloaded and installed separately. +# Tell the user that wxPython is required but has not been found +# +try: + import wx +except ImportError: + raise ImportError, "Please download the appropriate version of wxPython from www.wxpython.org" + +try: + import os + import shutil +except ImportError: + raise ImportError, "import OS failed" + +from defines import DEFINES +from pdef import SBIOSLEGACY_DEF +from ElementGui import * + +from util import UTILS +utilities = UTILS() + +try: + import cPickle as pickle +except ImportError: + import pickle # fall back on Python version + +# TXT Policy Generator Tool +# SBIOS Class - Policy Definition File Lists +# +class SBIOSLegacy( ElementGui ): + + CONST_TITLE = "Choose Hash File" + CONST_WILDCARD = "Hash file (*.hash) | *.hash|" \ + "All Files (*.*) | *.*" + + """__init__() - SBIOS class constructor""" + def __init__( self ): + self.sbiosPanelWidgets = [] + self.panelCreated = False + + # + # create the SBIOS Panel + # + def createOrShowPanel(self, wx, listPanel, parent, pdef, statusBar): + """createSbiosPanel - create the SBIOS Panel""" + + #print("createOrShowSbiosPanel panelCreated == %s" % (self.panelCreated)) # DBGDBG + # 1st time, create the panel + # nth time, show the panel + if(self.panelCreated == True): + self.showPanel() + return + + self.pdef = pdef + self.parent = parent + self.listPanel = listPanel + self.StatusBar = statusBar + parentSizer = parent.GetSizer() + + # Get the list corresponds to this element. + currentList = self.pdef.getCurrentListObject() + self.myIndex = len(currentList.ElementDefData)-1 # Just added the element, the last one should be the one. + + # create the Sbios Panel sizers + #self.sbiosPanelSizer = wx.BoxSizer(wx.VERTICAL) + sbiosGridSizer= wx.GridBagSizer(hgap=5, vgap=5) + #sbiosHorizSizer = wx.BoxSizer(wx.HORIZONTAL) + + self.sbiosPanel = wx.Panel(parent, -1) + self.sbiosPanel.SetSizer(sbiosGridSizer) + + sbiosLabelText1 = "SBIOS" + sbiosLabelText2 = "Element" + sbiosLabel1 = wx.StaticText(self.sbiosPanel, -1, sbiosLabelText1) + sbiosLabel2 = wx.StaticText(self.sbiosPanel, -1, sbiosLabelText2) + font = wx.Font( 18, wx.FONTFAMILY_DEFAULT, wx.NORMAL, wx.BOLD) + sbiosLabel1.SetFont( font ) + sbiosGridSizer.Add( sbiosLabel1, pos=(0, 3)) + self.sbiosPanelWidgets.append(sbiosLabel1) + sbiosLabel2.SetFont( font ) + sbiosGridSizer.Add( sbiosLabel2, pos=(0, 4)) + self.sbiosPanelWidgets.append(sbiosLabel2) + + self.typeLabel = wx.StaticText(self.sbiosPanel, label="Type") + sbiosGridSizer.Add( self.typeLabel, pos=(1,3)) + self.sbiosPanelWidgets.append(self.typeLabel) + self.typeEdit = wx.TextCtrl( self.sbiosPanel, value="SBIOS", size=(40, -1)) + self.typeEdit.Enable( False ) + sbiosGridSizer.Add( self.typeEdit, pos=(1,4)) + self.sbiosPanelWidgets.append(self.typeEdit) + + self.contolOptionsLabel = wx.StaticText(self.sbiosPanel, -1, "Control") + font = wx.Font( 10, wx.FONTFAMILY_DEFAULT, wx.NORMAL, wx.BOLD) + self.contolOptionsLabel.SetFont( font ) + + self.overridePsPolicy = wx.CheckBox(self.sbiosPanel, label="Override PS Policy") + self.overridePsPolicy.Enable( False ) + + #Note: overridePsPolicy - control always disabled since there are no SBIOS specific controls - p12 + + sbiosGridSizer.Add(self.contolOptionsLabel, pos=(0,14), span=(1,2), flag=wx.BOTTOM, border=5) + sbiosGridSizer.Add(self.overridePsPolicy, pos=(1,14), span=(1,2), flag=wx.BOTTOM, border=5) + self.overridePsPolicy.Bind(wx.EVT_CHECKBOX, self.onOverridePsPolicy) + self.sbiosPanelWidgets.append(self.contolOptionsLabel) + self.sbiosPanelWidgets.append(self.overridePsPolicy) + + hashList = ['SHA1'] + self.hashAlgLabel = wx.StaticText(self.sbiosPanel, label="Hash Algorithm") + font = wx.Font( 10, wx.FONTFAMILY_DEFAULT, wx.NORMAL, wx.NORMAL) + self.hashAlgLabel.SetFont( font ) + sbiosGridSizer.Add(self.hashAlgLabel, pos=(0,20)) + self.sbiosPanelWidgets.append(self.hashAlgLabel) + + hashAlgEdit = wx.ComboBox( self.sbiosPanel, size=(75, -1), value="SHA1", choices=hashList, style=wx.CB_DROPDOWN ) + sbiosGridSizer.Add(hashAlgEdit, pos=(1,20)) + self.sbiosPanelWidgets.append(hashAlgEdit) + + self.fallbackFileLabel = wx.StaticText(self.sbiosPanel, label="Fallback\nHash") + font = wx.Font( 10, wx.FONTFAMILY_DEFAULT, wx.NORMAL, wx.NORMAL) + self.fallbackFileLabel.SetFont( font ) + sbiosGridSizer.Add( self.fallbackFileLabel, pos=(2,3)) + self.sbiosPanelWidgets.append(self.fallbackFileLabel) + + self.fallbackFileEdit = wx.TextCtrl( self.sbiosPanel, value="", size=(150, -1)) + self.fallbackFileEdit.Enable(False) # must use BROWSE to locate the fallback file + fallbackFile = currentList.ElementDefData[self.myIndex].FallBackHashFile + if (fallbackFile == "" or fallbackFile == None): + fallbackFile = "Fallback.hash" + self.fallbackFileEdit.AppendText(fallbackFile) + sbiosGridSizer.Add( self.fallbackFileEdit, pos=(2,4)) + self.sbiosPanelWidgets.append(self.fallbackFileEdit) + currentList.ElementDefData[self.myIndex].FallBackHashFile = fallbackFile + + self.browseButton = wx.Button( self.sbiosPanel, -1, label="Browse") + sbiosGridSizer.Add( self.browseButton, pos=(2,5)) + self.sbiosPanelWidgets.append(self.browseButton) + self.browseButton.Bind(wx.EVT_BUTTON, self.onBrowseButtonClick) + + self.fallbackRemoveButton = wx.Button( self.sbiosPanel, -1, label="Remove") + sbiosGridSizer.Add( self.fallbackRemoveButton, pos=(1,5)) + self.sbiosPanelWidgets.append(self.fallbackRemoveButton) + self.fallbackRemoveButton.Bind(wx.EVT_BUTTON, self.onFallbackRemoveButtonClick) + self.fallbackRemoveButton.Enable(True) + + self.addButton = wx.Button( self.sbiosPanel, -1, label=" Add ") + sbiosGridSizer.Add( self.addButton, pos=(4,3)) + self.sbiosPanelWidgets.append(self.addButton) + self.addButton.Bind(wx.EVT_BUTTON, self.onAddButtonClick) + self.sbiosPanelWidgets.append(self.addButton) + + self.removeButton = wx.Button( self.sbiosPanel, -1, label=" Remove ") + self.removeButton.Enable(False) # disable since nothing to remove yet + sbiosGridSizer.Add( self.removeButton, pos=(4,5)) + self.sbiosPanelWidgets.append(self.removeButton) + self.removeButton.Bind(wx.EVT_BUTTON, self.onRemoveButtonClick) + self.sbiosPanelWidgets.append(self.removeButton) + + self.hashListLabel = wx.StaticText(self.sbiosPanel, label=" Hash File List") + font = wx.Font( 10, wx.FONTFAMILY_DEFAULT, wx.NORMAL, wx.BOLD) + self.hashListLabel.SetFont( font ) + sbiosGridSizer.Add( self.hashListLabel, pos=(3,4)) + self.sbiosPanelWidgets.append(self.hashListLabel) + + self.fileCntLabel = wx.StaticText(self.sbiosPanel, label="Number of Files") + sbiosGridSizer.Add( self.fileCntLabel, pos=(5,3)) + self.sbiosPanelWidgets.append(self.fileCntLabel) + self.fileCntEdit = wx.TextCtrl( self.sbiosPanel, value="0", size=(40, -1)) + self.fileCntEdit.Enable( False ) + sbiosGridSizer.Add( self.fileCntEdit, pos=(5,4)) + self.sbiosPanelWidgets.append(self.fileCntEdit) + + self.hashListBox = wx.TextCtrl( self.sbiosPanel, value="", size=(150, 120), style = wx.TE_MULTILINE) # Note: add |wx.HSCROLL to get a horiz scroll bar + # hashListBox must be enabled so can select items to remove + self.hashListBox.Bind(wx.EVT_TEXT, self.onHashListBoxEdit) + self.hashListBox.SetInsertionPoint(0) + sbiosGridSizer.Add( self.hashListBox, pos=(4,4)) + self.sbiosPanelWidgets.append(self.hashListBox) + + self.sbiosPanelWidgets.append(self.sbiosPanel) + #sbiosHorizSizer.Add(sbiosGridSizer, 0, wx.ALL, 5) + #self.sbiosPanelSizer.Add(sbiosHorizSizer, 0, wx.ALL, 5) + #parent.SetSizerAndFit(self.sbiosPanelSizer) + parentSizer.Add(self.sbiosPanel) + w,h = parentSizer.GetMinSize() + parent.SetVirtualSize((w,h)) + parent.Layout() + # call restorePanel to sync data to GUI + self.restorePanel(currentList, pdef.MaxHashes) + self.panelCreated = True + + def hidePanel(self): + """hidePanel - hide the sbios panel""" + + for i in self.sbiosPanelWidgets: + i.Hide() + + def showPanel(self): + """showSbiosPanel - show the sbios panel""" + + if self.panelCreated: + for i in self.sbiosPanelWidgets: + i.Show() + parentSizer = self.parent.GetSizer() + w,h = parentSizer.GetMinSize() + self.parent.SetVirtualSize((w,h)) + + + def setElementToDefaults(self): + """setElementToDefaults - SBIOS_DEF""" + + currentList = self.pdef.getCurrentListObject() + currentList.ElementDefData[self.myIndex].IncludeInList = False + currentList.ElementDefData[self.myIndex].HashAlg = 0 + currentList.ElementDefData[self.myIndex].Control = 0 + currentList.ElementDefData[self.myIndex].NumbHashes = 0 + currentList.ElementDefData[self.myIndex].CurrentView = 0 + currentList.ElementDefData[self.myIndex].FallBackHashFile = "" + currentList.ElementDefData[self.myIndex].SbiosFiles = [] + + def onBrowseButtonClick(self, event): + """onBrowseButtonClick - browse to a fallback hash file""" + #self.StatusBar.SetStatusText("You clicked the Browse button") + + fileName = '' + workdir = self.pdef.WorkingDirectory + wildcard = "Hash file (*.hash) | *.hash|" \ + "All Files (*.*) | *.*" + dlg = wx.FileDialog(self.parent, "Choose the fallback hash file", workdir, "", wildcard, wx.OPEN) + + abortFlag = False # Set to True if Add dialogue doidn't complete successfully + if dlg.ShowModal() == wx.ID_OK: + filename = dlg.GetFilename() + dirname = dlg.GetDirectory() + else: + abortFlag = True # abort after destroying the dialogue + + if(filename != ''): + # validate that the specified hash file is properly formatted + currentList = self.pdef.getCurrentListObject() + result = utilities.verifyHashFile(os.path.join(dirname, filename), currentList.ElementDefData[self.myIndex].HashAlg) + # Note: verifyHashFile() returns [FileValid, FileType], but only FileValid is used here + if( result[0] == True): + # Copy file into working directory + if (dirname != workdir): + if (os.path.exists(os.path.join(workdir, filename))) : + cdlg = wx.MessageDialog(self.parent, filename+" already exists in working directory\nOverwrite file in working directory?", "Confirm Copy", wx.OK|wx.CANCEL|wx.ICON_QUESTION) + if (cdlg.ShowModal() == wx.ID_OK): + shutil.copyfile(os.path.join(dirname, filename), os.path.join(workdir, filename)) + else: + self.StatusBar.SetStatusText( "Add cancelled" ) + cdlg.Destroy() + else: + shutil.copyfile(os.path.join(dirname, filename), os.path.join(workdir, filename)) + self.StatusBar.SetStatusText("Validated file %s." % (filename)) + self.fallbackFileEdit.ChangeValue(filename) + currentList.ElementDefData[self.myIndex].FallBackHashFile = filename + self.setListModified() + self.fallbackRemoveButton.Enable(True) + + dlg.Destroy() + + def onFallbackRemoveButtonClick(self, event): + """onFallbackRemoveButtonClick - delete the fallback hash file""" + + self.StatusBar.SetStatusText("Fallback hash file %s removed." % (self.fallbackFileEdit.GetValue())) + self.fallbackFileEdit.ChangeValue("") + currentList = self.pdef.getCurrentListObject() + currentList.ElementDefData[self.myIndex].FallBackHashFile = "" + self.setListModified() + self.fallbackRemoveButton.Enable(False) + + # only supports adding files with the add button, not entering the names directly + def onHashListBoxEdit(self, event): + """onHashListBoxEdit""" + print("in SBIOS::onHashListBoxEdit") # DBGDBG + + # tell the user to add button and clear the field + self.StatusBar.SetStatusText("Please clear the entry, then use the Add button to add hash files to the list") + #self.hashListBox.Undo() + #TODO: wxPython: onHashListBoxEdit - Clear() and Undo() both generate an event causing: RuntimeError: maximum recursion depth exceeded + + def onAddButtonClick(self, event): + """onAddButtonClick - add a hash file to the list""" + + filepath, filename = self.selectFile() + + if (filename == ''): + # selectFile() operation has been cancelled. + return + + # validate that the specified hash file is properly formatted + currentList = self.pdef.getCurrentListObject() + result = utilities.verifyHashFile(os.path.join(filepath, filename), currentList.ElementDefData[self.myIndex].HashAlg) + # Note: verifyHashFile() returns [FileValid, FileType], but only FileValid is used here + if( result[0] == False): + return + + self.copyFile(filepath, filename) + self.StatusBar.SetStatusText("Validated file %s." % (filename)) + + # update the file count and enable the remove button + lineCnt = currentList.ElementDefData[self.myIndex].NumbHashes + #print("onAddButtonClick: was %i lines" % (lineCnt)) # DBGDBG + lineCnt += 1 + + # MaxHashes = 0 means there is no limit on the number of hash files allowed + if(self.pdef.MaxHashes != 0): + if(lineCnt > self.pdef.MaxHashes): + self.StatusBar.SetStatusText("Only %d files can be added." % (self.pdef.MaxHashes)) + return + + #print("onAddButtonClick: now %i lines" % (lineCnt)) # DBGDBG + self.fileCntEdit.ChangeValue(str(lineCnt)) + self.removeButton.Enable(True) + + hashFileList = currentList.ElementDefData[self.myIndex].SbiosFiles + hashFileList.append(filename) + #print("new hashFileList = %s" % (hashFileList)) # DBGDBG + + # insert the new file into sbios.SbiosFiles + self.setListModified() + currentList.ElementDefData[self.myIndex].SbiosFiles = hashFileList + currentList.ElementDefData[self.myIndex].NumbHashes = lineCnt + #print("ElementDefData[self.myIndex].NumbHashes=%i, SbiosFiles = %s" % (currentList.ElementDefData[self.myIndex].NumbHashes, currentList.ElementDefData[self.myIndex].SbiosFiles)) # DBGDBG + + # since hashListBox.AppendText() generates an event to onHashListBoxEdit() + # and since hashListBoxEdit has to be enabled so text can be selected for Remove + # and direct text entry by the user into hashListBoxEdit is not supported due the complexity of validating it ... + # + # hashListBox.ChangeValue() doesn't generate an event but only takes a string, not a hashFileList which is a list ie '[]' + # so form a single string containing everything in hashFileList and update hashListBox using ChangeValue(hashFileString) + string = utilities.formStringFromListOfStrings(hashFileList) + self.hashListBox.ChangeValue(string) + + def onRemoveButtonClick(self, event): + """onRemoveButtonClick - remove the selected entry from the hash file list""" + + # confirm the remove + dlg = wx.MessageDialog(None, "Confirm removal of selected file?", 'Confirm Remove', wx.YES_NO | wx.ICON_QUESTION) + response = dlg.ShowModal() + dlg.Destroy() + + if(response == wx.ID_NO): + self.StatusBar.SetStatusText( "Remove cancelled" ) + return + + selection = self.hashListBox.GetStringSelection() + self.StatusBar.SetStatusText("Removed selection %s" % (selection)) + + # selection may not be a full line ... See if the selection is contianed in any of hashFileList's entries + currentList = self.pdef.getCurrentListObject() + hashFileList = currentList.ElementDefData[self.myIndex].SbiosFiles + for entry in hashFileList: + #print("entry=%s" % (entry)) # DBGDBG + start = entry.find(selection) + if(start != -1): # -1 means not found, else find returns the starting index of selection + #print("Found: %s at %i" % (selection, start)) # DBGDBG + # entry was found, but was it a partial selection? + if(selection not in hashFileList): # is selection on the GUI in PDEF's hashFileList? + # partial selection + #print("Partial selection %s not found in %s." % (selection, hashFileList)) # DBGDBG + self.StatusBar.SetStatusText("Please select the entire line") + break + else: + # Full selection, so remove that entry + # decr sbios.NumbHashes & update NumberOfFiles widget + fileCnt = int(self.fileCntEdit.GetValue()) + fileCnt -= 1 + self.fileCntEdit.ChangeValue(str(fileCnt)) + currentList.ElementDefData[self.myIndex].NumbHashes = fileCnt + + hashFileList.remove(selection) # remove the selection from the PDEF object + #print("hashFileList=%s" % (hashFileList)) # DBGDBG + + if(fileCnt == 0): # disable REMOVE if no more files left + self.removeButton.Enable(False) + self.hashListBox.ChangeValue('') + else: + # rebuild the content of hashFileEdit from hashFileList and update the screen with ChangeValue + # to avoid generating an event and to clear the previous LF + hashFileString = '' + index = 0 + for eachString in hashFileList: + if(index != 0): # if not the 1st entry, need a LF before the new entry + hashFileString += "\n" + hashFileString += eachString + index += 1 + #print("thisString=%s, hashFileString=%s" % (eachString, hashFileString)) # DBGDBG + + self.hashListBox.ChangeValue(hashFileString) + + #print("hashListBox=%s" % (self.hashListBox.GetValue())) # DBGDBG + self.setListModified() + currentList.ElementDefData[self.myIndex].SbiosFiles = hashFileList + break + else: + self.StatusBar.SetStatusText("Selection %s not found. Please select only a single line" % (selection)) # DBGDBG + + def onOverridePsPolicy(self, event): + currentList = self.pdef.getCurrentListObject() + self.setListModified() + if(event.Checked() == True): + currentList.ElementDefData[self.myIndex].Control = 1 + else: + currentList.ElementDefData[self.myIndex].Control = 0 + + def writeSbiosDef(self, sbiosDefData, f): + """writeSbiosDef - write the Sbios Def to the specified file""" + + #print("writeSbiosLegacyDef dump") # DBGDBG + pickle.dump(sbiosDefData, f) # write out the sbiosDefData object + + def setPanelToDefaults(self): + """setPanelToDefaults - restore defaults to sbios panel widgets""" + + self.fallbackFileEdit.ChangeValue("") + self.addButton.Enable(True) + self.removeButton.Enable(False) + self.fileCntEdit.ChangeValue("0") + self.hashListBox.ChangeValue("") + + def restorePanel(self, currentList, maxHashes): + """restorePanel - restore the SBIOS element panel from the specified PLIST_DEF""" + + print("restorePanel - SBIOS") # DBGDBG + # update Override PS Policy checkbox + self.overridePsPolicy.SetValue(currentList.ElementDefData[self.myIndex].Control) + listversion = str(currentList.ListVersionMajor)+'.'+str(currentList.ListVersionMinor) + if listversion == '2.0': + self.showV20Gui(True) + else: + self.showV20Gui(False) + self.fallbackFileEdit.ChangeValue(currentList.ElementDefData[self.myIndex].FallBackHashFile) + + # If MaxHashes not 0, Only enable Add if < MaxHashes files + numbHashes = currentList.ElementDefData[self.myIndex].NumbHashes + flag = True + if(maxHashes != 0): + if(numbHashes >= maxHashes): + flag = False # don't enable add + self.addButton.Enable(flag) + + # enable remove if >0 hashes + if(numbHashes > 0): + self.removeButton.Enable(False) + self.fileCntEdit.ChangeValue(str(numbHashes)) + + # form a string from hashFileList and update hashListBox + string = utilities.formStringFromListOfStrings(currentList.ElementDefData[self.myIndex].SbiosFiles) + self.hashListBox.ChangeValue(string) + + #def setListModified(self): + # """setListModified - if list not modified yet, increment its rev cnt and set it to modified""" + # + # currentList = self.pdef.getCurrentListObject() + # #print("Sbios setListModified - ListModified was %s" % (currentList.ListModified)) # DBGDBG + # if(currentList.ListModified == False): + # currentList.RevocationCounter += 1 + # self.listPanel.revocationCountEdit.ChangeValue(str(currentList.RevocationCounter)) # update the GUI + # currentList.ListModified = True + diff -Nru tboot-1.9.4/lcp-gen2/sbios.py tboot-1.9.5/lcp-gen2/sbios.py --- tboot-1.9.4/lcp-gen2/sbios.py 1970-01-01 00:00:00.000000000 +0000 +++ tboot-1.9.5/lcp-gen2/sbios.py 2016-12-17 03:19:38.000000000 +0000 @@ -0,0 +1,510 @@ +#!/usr/bin/python +# Copyright (c) 2013, Intel Corporation. All rights reserved. + +# using print() built infunction, disable print statement +from __future__ import print_function + +# +# wxPython is not part of the standard Python distribution and has to be downloaded and installed separately. +# Tell the user that wxPython is required but has not been found +# +try: + import wx +except ImportError: + raise ImportError, "Please download the appropriate version of wxPython from www.wxpython.org" + +try: + import os + import shutil +except ImportError: + raise ImportError, "import OS failed" + +from defines import DEFINES +from pdef import SBIOS_DEF +from ElementGui import * + +from util import UTILS +utilities = UTILS() + +try: + import cPickle as pickle +except ImportError: + import pickle # fall back on Python version + + +# TXT Policy Generator Tool +# SBIOS Class - Policy Definition File Lists +# +class SBIOS( ElementGui ): + + CONST_TITLE = "Choose Hash File" + CONST_WILDCARD = "Hash file (*.hash) | *.hash|" \ + "All Files (*.*) | *.*" + + """__init__() - SBIOS class constructor""" + def __init__( self, hashAlg ): + self.sbiosPanelWidgets = [] + self.panelCreated = False + + try: + # reverse lookup of the hash algorithm name(key) for the given HashAlg value + hashAlgName = (key for key,val in DEFINES.TPM_ALG_HASH.items() if (val == hashAlg)).next() + except StopIteration: + print("SBIOS::__init__ - invalid hashAlg=%d" % (hashAlg)) + return + + self.myIndex = DEFINES.DEFDATA_INDEX[hashAlgName] + #if( hashAlg == DEFINES.TPM_ALG_HASH['SHA256']): + # self.myIndex = DEFINES.DEFDATA_INDEX_SHA256 + #elif( hashAlg == DEFINES.TPM_ALG_HASH['SHA1']): + # self.myIndex = DEFINES.DEFDATA_INDEX_SHA1 + #else: + # print("SBIOS::__init__ - invalid hashAlg=%d" % (hashAlg)) + + self.myHashAlg = hashAlg + + # + # create the SBIOS Panel + # + def createOrShowPanel(self, wx, listPanel, parent, pdef, statusBar): + """createOrShowPanel - create the SBIOS Panel""" + + #print("createOrShowSbiosPanel hashAlg=%d, panelCreated == %s" % (self.myHashAlg, self.panelCreated)) # DBGDBG + # 1st time, create the panel + # nth time, show the panel + if(self.panelCreated == True): + self.showPanel() + return + + self.pdef = pdef + self.parent = parent + self.listPanel = listPanel + self.StatusBar = statusBar + parentSizer = parent.GetSizer() + + # Get the list corresponds to this element. + currentList = self.pdef.getCurrentListObject() + self.myIndex = len(currentList.ElementDefData)-1 # Just added the element, the last one should be the one. + + # create the Sbios Panel sizers + #self.sbiosPanelSizer = wx.BoxSizer(wx.VERTICAL) + sbiosGridSizer= wx.GridBagSizer(hgap=5, vgap=5) + #sbiosHorizSizer = wx.BoxSizer(wx.HORIZONTAL) + + self.sbiosPanel = wx.Panel(parent, -1) + self.sbiosPanel.SetSizer(sbiosGridSizer) + + sbiosLabelText1 = "SBIOS" + sbiosLabelText2 = "Element" + sbiosLabel1 = wx.StaticText(self.sbiosPanel, -1, sbiosLabelText1) + sbiosLabel2 = wx.StaticText(self.sbiosPanel, -1, sbiosLabelText2) + font = wx.Font( 18, wx.FONTFAMILY_DEFAULT, wx.NORMAL, wx.BOLD) + sbiosLabel1.SetFont( font ) + sbiosGridSizer.Add( sbiosLabel1, pos=(0, 3)) + self.sbiosPanelWidgets.append(sbiosLabel1) + sbiosLabel2.SetFont( font ) + sbiosGridSizer.Add( sbiosLabel2, pos=(0, 4)) + self.sbiosPanelWidgets.append(sbiosLabel2) + + self.typeLabel = wx.StaticText(self.sbiosPanel, label="Type") + sbiosGridSizer.Add( self.typeLabel, pos=(1,3)) + self.sbiosPanelWidgets.append(self.typeLabel) + self.typeEdit = wx.TextCtrl( self.sbiosPanel, value="SBIOS", size=(40, -1)) + self.typeEdit.Enable( False ) + sbiosGridSizer.Add( self.typeEdit, pos=(1,4)) + self.sbiosPanelWidgets.append(self.typeEdit) + + self.contolOptionsLabel = wx.StaticText(self.sbiosPanel, -1, "Control") + font = wx.Font( 10, wx.FONTFAMILY_DEFAULT, wx.NORMAL, wx.BOLD) + self.contolOptionsLabel.SetFont( font ) + + self.overridePsPolicy = wx.CheckBox(self.sbiosPanel, label="Override PS Policy") + self.overridePsPolicy.Enable( False ) + + #Note: overridePsPolicy - control always disabled since there are no SBIOS specific controls - p12 + + sbiosGridSizer.Add(self.contolOptionsLabel, pos=(0,14), span=(1,2), flag=wx.BOTTOM, border=5) + sbiosGridSizer.Add(self.overridePsPolicy, pos=(1,14), span=(1,2), flag=wx.BOTTOM, border=5) + self.overridePsPolicy.Bind(wx.EVT_CHECKBOX, self.onOverridePsPolicy) + self.sbiosPanelWidgets.append(self.contolOptionsLabel) + self.sbiosPanelWidgets.append(self.overridePsPolicy) + hashAlgStr = self.getHashAlgName() + if(hashAlgStr == None): + print("createOrShowSbiosPanel - invalid myHashAlg=%d" % (self.myHashAlg)) + + self.hashAlgLabel = wx.StaticText(self.sbiosPanel, label="Hash Algorithm") + font = wx.Font( 10, wx.FONTFAMILY_DEFAULT, wx.NORMAL, wx.BOLD) + self.hashAlgLabel.SetFont( font ) + sbiosGridSizer.Add(self.hashAlgLabel, pos=(0,20)) + self.sbiosPanelWidgets.append(self.hashAlgLabel) + + self.hashAlgEdit = wx.TextCtrl( self.sbiosPanel, size=(75, -1), value=hashAlgStr ) + self.hashAlgEdit.Enable(False) + sbiosGridSizer.Add(self.hashAlgEdit, pos=(1,20)) + self.sbiosPanelWidgets.append(self.hashAlgEdit) + + self.fallbackFileLabel = wx.StaticText(self.sbiosPanel, label="Fallback\nHash") + font = wx.Font( 10, wx.FONTFAMILY_DEFAULT, wx.NORMAL, wx.NORMAL) + self.fallbackFileLabel.SetFont( font ) + sbiosGridSizer.Add( self.fallbackFileLabel, pos=(2,3)) + self.sbiosPanelWidgets.append(self.fallbackFileLabel) + + self.fallbackFileEdit = wx.TextCtrl( self.sbiosPanel, value="", size=(150, -1)) + self.fallbackFileEdit.Enable(False) # must use BROWSE to locate the fallback file + fallbackFile = currentList.ElementDefData[self.myIndex].FallBackHashFile + if (fallbackFile == "" or fallbackFile == None): + fallbackFile = "FallbackDflt" + hashAlgStr + ".hash" + #if(hashAlgStr == "SHA256"): + # fallbackFile = "FallbackDfltSha256.hash" + #elif(hashAlgStr == "SHA1"): + # fallbackFile = "FallbackDfltSha1.hash" + #else: + # print("Warning - unexpected hashAlgStr found when setting fallbackFile") + self.fallbackFileEdit.AppendText(fallbackFile) + sbiosGridSizer.Add( self.fallbackFileEdit, pos=(2,4)) + self.sbiosPanelWidgets.append(self.fallbackFileEdit) + currentList.ElementDefData[self.myIndex].FallBackHashFile = fallbackFile + + self.browseButton = wx.Button( self.sbiosPanel, -1, label="Browse") + sbiosGridSizer.Add( self.browseButton, pos=(2,5)) + self.sbiosPanelWidgets.append(self.browseButton) + self.browseButton.Bind(wx.EVT_BUTTON, self.onBrowseButtonClick) + + self.fallbackRemoveButton = wx.Button( self.sbiosPanel, -1, label="Remove") + sbiosGridSizer.Add( self.fallbackRemoveButton, pos=(1,5)) + self.sbiosPanelWidgets.append(self.fallbackRemoveButton) + self.fallbackRemoveButton.Bind(wx.EVT_BUTTON, self.onFallbackRemoveButtonClick) + self.fallbackRemoveButton.Enable(True) + + self.addButton = wx.Button( self.sbiosPanel, -1, label=" Add ") + sbiosGridSizer.Add( self.addButton, pos=(4,3)) + self.sbiosPanelWidgets.append(self.addButton) + self.addButton.Bind(wx.EVT_BUTTON, self.onAddButtonClick) + + self.removeButton = wx.Button( self.sbiosPanel, -1, label=" Remove ") + self.removeButton.Enable(False) # disable since nothing to remove yet + sbiosGridSizer.Add( self.removeButton, pos=(4,5)) + self.sbiosPanelWidgets.append(self.removeButton) + self.removeButton.Bind(wx.EVT_BUTTON, self.onRemoveButtonClick) + + self.hashListLabel = wx.StaticText(self.sbiosPanel, label=" Hash File List") + font = wx.Font( 10, wx.FONTFAMILY_DEFAULT, wx.NORMAL, wx.BOLD) + self.hashListLabel.SetFont( font ) + sbiosGridSizer.Add( self.hashListLabel, pos=(3,4)) + self.sbiosPanelWidgets.append(self.hashListLabel) + + self.fileCntLabel = wx.StaticText(self.sbiosPanel, label="Number of Files") + sbiosGridSizer.Add( self.fileCntLabel, pos=(5,3)) + self.sbiosPanelWidgets.append(self.fileCntLabel) + self.fileCntEdit = wx.TextCtrl( self.sbiosPanel, value="0", size=(40, -1)) + self.fileCntEdit.Enable( False ) + sbiosGridSizer.Add( self.fileCntEdit, pos=(5,4)) + self.sbiosPanelWidgets.append(self.fileCntEdit) + + self.hashListBox = wx.TextCtrl( self.sbiosPanel, value="", size=(150, 120), style = wx.TE_MULTILINE) # Note: add |wx.HSCROLL to get a horiz scroll bar + # hashListBox must be enabled so can select items to remove + self.hashListBox.Bind(wx.EVT_TEXT, self.onHashListBoxEdit) + self.hashListBox.SetInsertionPoint(0) + sbiosGridSizer.Add( self.hashListBox, pos=(4,4)) + self.sbiosPanelWidgets.append(self.hashListBox) + + self.sbiosPanelWidgets.append(self.sbiosPanel) + + #sbiosHorizSizer.Add(sbiosGridSizer, 0, wx.ALL, 5) + #self.sbiosPanelSizer.Add(sbiosHorizSizer, 0, wx.ALL, 5) + #parent.SetSizerAndFit(self.sbiosPanelSizer) + parentSizer.Add(self.sbiosPanel) + w,h = parentSizer.GetMinSize() + parent.SetVirtualSize((w,h)) + parent.Layout() + # call restorePanel to sync data to GUI + self.restorePanel(currentList, pdef.MaxHashes) + self.panelCreated = True + + def hidePanel(self): + """hidePanel - hide the sbios panel""" + #print("SBIOS hidePanel - hashAlg=%d, len(Widgets)=%d" % (self.myHashAlg, len(self.sbiosPanelWidgets))) #DBGDBG + for i in self.sbiosPanelWidgets: + i.Hide() + + def showPanel(self): + """showPanel - show the sbios panel""" + #print("SBIOS showPanel - hashAlg=%d, len(Widgets)=%d" % (self.myHashAlg, len(self.sbiosPanelWidgets))) #DBGDBG + if self.panelCreated: + for i in self.sbiosPanelWidgets: + i.Show() + parentSizer = self.parent.GetSizer() + w,h = parentSizer.GetMinSize() + self.parent.SetVirtualSize((w,h)) + + + def setElementToDefaults(self): + """setElementToDefaults - SBIOS_DEF""" + + currentList = self.pdef.getCurrentListObject() + currentList.ElementDefData[self.myIndex].IncludeInList = False + currentList.ElementDefData[self.myIndex].HashAlg = DEFINES.TPM_ALG_HASH['SHA256'] + currentList.ElementDefData[self.myIndex].Control = 0 + currentList.ElementDefData[self.myIndex].NumbHashes = 0 + currentList.ElementDefData[self.myIndex].CurrentView = 0 + currentList.ElementDefData[self.myIndex].FallBackHashFile = "" + currentList.ElementDefData[self.myIndex].SbiosFiles = [] + + def onBrowseButtonClick(self, event): + """onBrowseButtonClick - browse to a fallback hash file""" + #self.StatusBar.SetStatusText("You clicked the Browse button") + + #fileName = '' + #workdir = self.pdef.WorkingDirectory + #wildcard = "Hash file (*.hash) | *.hash|" \ + # "All Files (*.*) | *.*" + #dlg = wx.FileDialog(self.parent, "Choose the fallback hash file", workdir, "", wildcard, wx.OPEN) + # + #abortFlag = False # Set to True if Add dialogue doidn't complete successfully + #if dlg.ShowModal() == wx.ID_OK: + # filename = dlg.GetFilename() + # dirname = dlg.GetDirectory() + #else: + # abortFlag = True # abort after destroying the dialogue + # + #if(filename != ''): + # # validate that the specified hash file is properly formatted + # currentList = self.pdef.getCurrentListObject() + # result = utilities.verifyHashFile(os.path.join(dirname, filename), currentList.ElementDefData[self.myIndex].HashAlg) + # # Note: verifyHashFile() returns [FileValid, FileType], but only FileValid is used here + # if( result[0] == True): + # # Copy file into working directory + # if (dirname != workdir): + # if (os.path.exists(os.path.join(workdir, filename))) : + # cdlg = wx.MessageDialog(self.parent, filename+" already exists in working directory\nOverwrite file in working directory?", "Confirm Copy", wx.OK|wx.CANCEL|wx.ICON_QUESTION) + # if (cdlg.ShowModal() == wx.ID_OK): + # shutil.copyfile(os.path.join(dirname, filename), os.path.join(workdir, filename)) + # else: + # self.StatusBar.SetStatusText( "Add cancelled" ) + # cdlg.Destroy() + # else: + # shutil.copyfile(os.path.join(dirname, filename), os.path.join(workdir, filename)) + filepath, filename = self.selectFile() + + if (filename == ''): + # selectFile() operation has been cancelled. + return + + # validate that the specified hash file is properly formatted + currentList = self.pdef.getCurrentListObject() + result = utilities.verifyHashFile(os.path.join(filepath, filename), currentList.ElementDefData[self.myIndex].HashAlg) + # Note: verifyHashFile() returns [FileValid, FileType], but only FileValid is used here + if( result[0] == False): + return + + self.copyFile(filepath, filename) + self.StatusBar.SetStatusText("Validated file %s." % (filename)) + self.fallbackFileEdit.ChangeValue(filename) + currentList.ElementDefData[self.myIndex].FallBackHashFile = filename + self.setListModified() + self.fallbackRemoveButton.Enable(True) + + dlg.Destroy() + + def onFallbackRemoveButtonClick(self, event): + """onFallbackRemoveButtonClick - delete the fallback hash file""" + + self.StatusBar.SetStatusText("Fallback hash file %s removed." % (self.fallbackFileEdit.GetValue())) + self.fallbackFileEdit.ChangeValue("") + currentList = self.pdef.getCurrentListObject() + currentList.ElementDefData[self.myIndex].FallBackHashFile = "" + self.setListModified() + self.fallbackRemoveButton.Enable(False) + + # only supports adding files with the add button, not entering the names directly + def onHashListBoxEdit(self, event): + """onHashListBoxEdit""" + print("in SBIOS::onHashListBoxEdit") # DBGDBG + + # tell the user to add button and clear the field + self.StatusBar.SetStatusText("Please clear the entry, then use the Add button to add hash files to the list") + #self.hashListBox.Undo() + #TODO: wxPython: onHashListBoxEdit - Clear() and Undo() both generate an event causing: RuntimeError: maximum recursion depth exceeded + + def onAddButtonClick(self, event): + """onAddButtonClick - add a hash file to the list""" + + filepath, filename = self.selectFile() + + if (filename == ''): + # selectFile() operation has been cancelled. + return + + # validate that the specified hash file is properly formatted + currentList = self.pdef.getCurrentListObject() + result = utilities.verifyHashFile(os.path.join(filepath, filename), currentList.ElementDefData[self.myIndex].HashAlg) + # Note: verifyHashFile() returns [FileValid, FileType], but only FileValid is used here + if( result[0] == False): + return + + self.copyFile(filepath, filename) + self.StatusBar.SetStatusText("Validated file %s." % (filename)) + + # update the file count and enable the remove button + lineCnt = currentList.ElementDefData[self.myIndex].NumbHashes + #print("onAddButtonClick: was %i lines" % (lineCnt)) # DBGDBG + lineCnt += 1 + + # MaxHashes = 0 means there is no limit on the number of hash files allowed + if(self.pdef.MaxHashes != 0): + if(lineCnt > self.pdef.MaxHashes): + self.StatusBar.SetStatusText("Only %d files can be added." % (self.pdef.MaxHashes)) + return + + #print("onAddButtonClick: now %i lines" % (lineCnt)) # DBGDBG + self.fileCntEdit.ChangeValue(str(lineCnt)) + self.removeButton.Enable(True) + + #print("new hashFileList = %s" % (hashFileList)) # DBGDBG + + # insert the new file into sbios.SbiosFiles + self.setListModified() + currentList.ElementDefData[self.myIndex].SbiosFiles.append(filename) + currentList.ElementDefData[self.myIndex].NumbHashes = lineCnt + #print("ElementDefData[self.myIndex].NumbHashes=%i, SbiosFiles = %s" % (currentList.ElementDefData[self.myIndex].NumbHashes, currentList.ElementDefData[self.myIndex].SbiosFiles)) # DBGDBG + + # since hashListBox.AppendText() generates an event to onHashListBoxEdit() + # and since hashListBoxEdit has to be enabled so text can be selected for Remove + # and direct text entry by the user into hashListBoxEdit is not supported due the complexity of validating it ... + # + # hashListBox.ChangeValue() doesn't generate an event but only takes a string, not a hashFileList which is a list ie '[]' + # so form a single string containing everything in hashFileList and update hashListBox using ChangeValue(hashFileString) + string = utilities.formStringFromListOfStrings(currentList.ElementDefData[self.myIndex].SbiosFiles) + self.hashListBox.ChangeValue(string) + + def onRemoveButtonClick(self, event): + """onRemoveButtonClick - remove the selected entry from the hash file list""" + + # confirm the remove + dlg = wx.MessageDialog(None, "Confirm removal of selected file?", 'Confirm Remove', wx.YES_NO | wx.ICON_QUESTION) + response = dlg.ShowModal() + dlg.Destroy() + + if(response == wx.ID_NO): + self.StatusBar.SetStatusText( "Remove cancelled" ) + return + + selection = self.hashListBox.GetStringSelection() + self.StatusBar.SetStatusText("Removed selection %s" % (selection)) + + # selection may not be a full line ... See if the selection is contianed in any of hashFileList's entries + currentList = self.pdef.getCurrentListObject() + hashFileList = currentList.ElementDefData[self.myIndex].SbiosFiles + for entry in hashFileList: + #print("entry=%s" % (entry)) # DBGDBG + start = entry.find(selection) + if(start != -1): # -1 means not found, else find returns the starting index of selection + #print("Found: %s at %i" % (selection, start)) # DBGDBG + # entry was found, but was it a partial selection? + if(selection not in hashFileList): # is selection on the GUI in PDEF's hashFileList? + # partial selection + #print("Partial selection %s not found in %s." % (selection, hashFileList)) # DBGDBG + self.StatusBar.SetStatusText("Please select the entire line") + break + else: + # Full selection, so remove that entry + # decr sbios.NumbHashes & update NumberOfFiles widget + fileCnt = int(self.fileCntEdit.GetValue()) + fileCnt -= 1 + self.fileCntEdit.ChangeValue(str(fileCnt)) + currentList.ElementDefData[self.myIndex].NumbHashes = fileCnt + + hashFileList.remove(selection) # remove the selection from the PDEF object + #print("hashFileList=%s" % (hashFileList)) # DBGDBG + + if(fileCnt == 0): # disable REMOVE if no more files left + self.removeButton.Enable(False) + self.hashListBox.ChangeValue('') + else: + # rebuild the content of hashFileEdit from hashFileList and update the screen with ChangeValue + # to avoid generating an event and to clear the previous LF + hashFileString = '' + index = 0 + for eachString in hashFileList: + if(index != 0): # if not the 1st entry, need a LF before the new entry + hashFileString += "\n" + hashFileString += eachString + index += 1 + #print("thisString=%s, hashFileString=%s" % (eachString, hashFileString)) # DBGDBG + + self.hashListBox.ChangeValue(hashFileString) + + #print("hashListBox=%s" % (self.hashListBox.GetValue())) # DBGDBG + self.setListModified() + currentList.ElementDefData[self.myIndex].SbiosFiles = hashFileList + break + else: + self.StatusBar.SetStatusText("Selection %s not found. Please select only a single line" % (selection)) # DBGDBG + + def onOverridePsPolicy(self, event): + currentList = self.pdef.getCurrentListObject() + self.setListModified() + if(event.Checked() == True): + currentList.ElementDefData[self.myIndex].Control = 1 + else: + currentList.ElementDefData[self.myIndex].Control = 0 + + def writeSbiosDef(self, sbiosDefData, f): + """writeSbiosDef - write the Sbios Def to the specified file""" + + print("writeSbiosDef dump, hashAlg=%d" % (self.myHashAlg)) # DBGDBG + pickle.dump(sbiosDefData, f) # write out the sbiosDefData object + + def setPanelToDefaults(self): + """setPanelToDefaults - restore defaults to sbios panel widgets""" + + self.fallbackFileEdit.ChangeValue("") + self.addButton.Enable(True) + self.removeButton.Enable(False) + self.fileCntEdit.ChangeValue("0") + self.hashListBox.ChangeValue("") + + def restorePanel(self, currentList, maxHashes): + """restorePanel - restore the SBIOS element panel from the specified PLIST_DEF""" + + print("restorePanel - SBIOS") # DBGDBG + # update Override PS Policy checkbox + self.overridePsPolicy.SetValue(currentList.ElementDefData[self.myIndex].Control) + listversion = str(currentList.ListVersionMajor)+'.'+str(currentList.ListVersionMinor) + if listversion == '2.0': + self.showV20Gui(True) + else: + self.showV20Gui(False) + self.fallbackFileEdit.ChangeValue(currentList.ElementDefData[self.myIndex].FallBackHashFile) + + # If MaxHashes not 0, Only enable Add if < MaxHashes files + numbHashes = currentList.ElementDefData[self.myIndex].NumbHashes + flag = True + if(maxHashes != 0): + if(numbHashes >= maxHashes): + flag = False # don't enable add + self.addButton.Enable(flag) + + # enable remove if >0 hashes + if(numbHashes > 0): + self.removeButton.Enable(True) + self.fileCntEdit.ChangeValue(str(numbHashes)) + + # form a string from hashFileList and update hashListBox + string = utilities.formStringFromListOfStrings(currentList.ElementDefData[self.myIndex].SbiosFiles) + self.hashListBox.ChangeValue(string) + + #def setListModified(self): + # """setListModified - if list not modified yet, increment its rev cnt and set it to modified""" + # + # currentList = self.pdef.getCurrentListObject() + # #print("Sbios setListModified - ListModified was %s" % (currentList.ListModified)) # DBGDBG + # if(currentList.ListModified == False): + # currentList.RevocationCounter += 1 + # self.listPanel.revocationCountEdit.ChangeValue(str(currentList.RevocationCounter)) # update the GUI + # currentList.ListModified = True + + + # the last function in the file doesn't show up in the scope list in Understand for some reason! + def stub(self): + pass diff -Nru tboot-1.9.4/lcp-gen2/stm.py tboot-1.9.5/lcp-gen2/stm.py --- tboot-1.9.4/lcp-gen2/stm.py 1970-01-01 00:00:00.000000000 +0000 +++ tboot-1.9.5/lcp-gen2/stm.py 2016-12-17 03:19:38.000000000 +0000 @@ -0,0 +1,434 @@ +#!/usr/bin/python +# Copyright (c) 2013, Intel Corporation. All rights reserved. + +# using print() built infunction, disable print statement +from __future__ import print_function + +# +# wxPython is not part of the standard Python distribution and has to be downloaded and installed separately. +# Tell the user that wxPython is required but has not been found +# +try: + import wx +except ImportError: + raise ImportError, "Please download the appropriate version of wxPython from www.wxpython.org" + +try: + import os + import shutil +except ImportError: + raise ImportError, "import OS failed" + +from defines import DEFINES +from pdef import STM_DEF +from ElementGui import * + +from util import UTILS +utilities = UTILS() + +try: + import cPickle as pickle +except ImportError: + import pickle # fall back on Python version + +# TXT Policy Generator Tool +# STM Class - Policy Definition File Lists +# +class STM( ElementGui ): + + CONST_TITLE = "Choose Hash File" + CONST_WILDCARD = "Hash file (*.hash) | *.hash|" \ + "All Files (*.*) | *.*" + + """__init__() - STM class constructor""" + def __init__( self, hashAlg): + self.stmPanelWidgets = [] + self.panelCreated = False + + try: + # reverse lookup of the hash algorithm name(key) for the given HashAlg value + hashAlgName = (key for key,val in DEFINES.TPM_ALG_HASH.items() if (val == hashAlg)).next() + except StopIteration: + print("STM::__init__ - invalid hashAlg=%d" % (hashAlg)) + return + + self.myIndex = DEFINES.DEFDATA_INDEX[hashAlgName] + + #if( hashAlg == DEFINES.TPM_ALG_HASH['SHA256']): + # self.myIndex = DEFINES.DEFDATA_INDEX_SHA256 + #elif( hashAlg == DEFINES.TPM_ALG_HASH['SHA1']): + # self.myIndex = DEFINES.DEFDATA_INDEX_SHA1 + #else: + # print("STM::__init__ - invalid hashAlg=%d" % (hashAlg)) + + self.myHashAlg = hashAlg + + # + # create the STM Panel + # + def createOrShowPanel(self, wx, listPanel, parent, pdef, statusBar): + """createPanel - create the List Panel""" + + #print("createOrShowStmPanel hashAlg=%d, panelCreated == %s" % (self.myHashAlg, self.panelCreated)) # DBGDBG + # 1st time, create the panel + # nth time, show the panel + if(self.panelCreated == True): + self.showPanel() + return + + self.pdef = pdef + self.parent = parent + self.listPanel = listPanel + self.StatusBar = statusBar + parentSizer = parent.GetSizer() + + # Get the list corresponds to this element. + currentList = self.pdef.getCurrentListObject() + self.myIndex = len(currentList.ElementDefData)-1 # Just added the element, the last one should be the one. + + # create the Stm Panel sizers + #self.stmPanelSizer = wx.BoxSizer(wx.VERTICAL) + self.stmGridSizer= wx.GridBagSizer(hgap=5, vgap=5) + #self.stmHorizSizer = wx.BoxSizer(wx.HORIZONTAL) + + self.stmPanel = wx.Panel(parent, -1) + self.stmPanel.SetSizer(self.stmGridSizer) + + stmLabelText1 = "STM" + stmLabelText2 = "Element" + stmLabel1 = wx.StaticText(self.stmPanel, -1, stmLabelText1) + stmLabel2 = wx.StaticText(self.stmPanel, -1, stmLabelText2) + font = wx.Font( 18, wx.FONTFAMILY_DEFAULT, wx.NORMAL, wx.BOLD) + stmLabel1.SetFont( font ) + self.stmGridSizer.Add( stmLabel1, pos=(0, 3)) + self.stmPanelWidgets.append(stmLabel1) + stmLabel2.SetFont( font ) + self.stmGridSizer.Add( stmLabel2, pos=(0, 4)) + self.stmPanelWidgets.append(stmLabel2) + + typeLabel = wx.StaticText(self.stmPanel, label="Type") + self.stmGridSizer.Add( typeLabel, pos=(1,3)) + self.stmPanelWidgets.append(typeLabel) + typeEdit = wx.TextCtrl( self.stmPanel, value="STM", size=(40, -1)) + typeEdit.Enable( False ) + self.stmGridSizer.Add( typeEdit, pos=(1,4)) + self.stmPanelWidgets.append(typeEdit) + + contolOptionsLabel = wx.StaticText(self.stmPanel, -1, "Control") + font = wx.Font( 10, wx.FONTFAMILY_DEFAULT, wx.NORMAL, wx.BOLD) + contolOptionsLabel.SetFont( font ) + + # override PS policy bit is applicable only if PO policy rules + self.overridePsPolicy = wx.CheckBox(self.stmPanel, label="Override PS Policy") + + if(self.pdef.Rules == DEFINES.PoRules): + self.overridePsPolicy.Enable( True ) + else: + self.overridePsPolicy.Enable( False ) + + self.stmGridSizer.Add(contolOptionsLabel, pos=(0,9), span=(1,2), flag=wx.BOTTOM, border=5) + self.stmGridSizer.Add(self.overridePsPolicy, pos=(1,9), span=(1,2), flag=wx.BOTTOM, border=5) + self.overridePsPolicy.Bind(wx.EVT_CHECKBOX, self.onOverridePsPolicy) + self.stmPanelWidgets.append(contolOptionsLabel) + self.stmPanelWidgets.append(self.overridePsPolicy) + + hashAlgStr = self.getHashAlgName() + if hashAlgStr == None: + print("createOrShowStmPanel - invalid myHashAlg=%d" % (self.myHashAlg)) + + hashAlgLabel = wx.StaticText(self.stmPanel, label="Hash Algorithm") + font = wx.Font( 10, wx.FONTFAMILY_DEFAULT, wx.NORMAL, wx.BOLD) + hashAlgLabel.SetFont( font ) + self.stmGridSizer.Add(hashAlgLabel, pos=(0,20)) + self.stmPanelWidgets.append(hashAlgLabel) + + hashAlgEdit = wx.TextCtrl( self.stmPanel, size=(75, -1), value=hashAlgStr ) + hashAlgEdit.Enable(False) + self.stmGridSizer.Add(hashAlgEdit, pos=(1,20)) + self.stmPanelWidgets.append(hashAlgEdit) + + self.addButton = wx.Button( self.stmPanel, -1, label=" Add ") + self.stmGridSizer.Add( self.addButton, pos=(4,3)) + self.stmPanelWidgets.append(self.addButton) + self.addButton.Bind(wx.EVT_BUTTON, self.onAddButtonClick) + + self.removeButton = wx.Button( self.stmPanel, -1, label=" Remove ") + self.removeButton.Enable(False) + self.stmGridSizer.Add( self.removeButton, pos=(4,5)) + self.stmPanelWidgets.append(self.removeButton) + self.removeButton.Bind(wx.EVT_BUTTON, self.onRemoveButtonClick) + + hashListLabel = wx.StaticText(self.stmPanel, label=" Hash File List") + font = wx.Font( 10, wx.FONTFAMILY_DEFAULT, wx.NORMAL, wx.BOLD) + hashListLabel.SetFont( font ) + self.stmGridSizer.Add( hashListLabel, pos=(3,4)) + self.stmPanelWidgets.append(hashListLabel) + + fileCntLabel = wx.StaticText(self.stmPanel, label="Number of Files") + self.stmGridSizer.Add( fileCntLabel, pos=(5,3)) + self.stmPanelWidgets.append(fileCntLabel) + self.fileCntEdit = wx.TextCtrl( self.stmPanel, value="0", size=(40, -1)) + self.fileCntEdit.Enable( False ) + self.stmGridSizer.Add( self.fileCntEdit, pos=(5,4)) + self.stmPanelWidgets.append(self.fileCntEdit) + hashFileList = [''] + + self.hashListBox = wx.TextCtrl( self.stmPanel, value="", size=(150, 120), style = wx.TE_MULTILINE) # Note: add |wx.HSCROLL to get a horiz scroll bar + # hashListBox must be enabled so can select items to remove + self.hashListBox.Bind(wx.EVT_TEXT, self.onHashListBoxEdit) + self.hashListBox.SetInsertionPoint(0) + self.stmGridSizer.Add( self.hashListBox, pos=(4,4)) + self.stmPanelWidgets.append(self.hashListBox) + + self.stmPanelWidgets.append(self.stmPanel) + + #print("STM createPanel - len(Widgets)=%d" % (len(self.stmPanelWidgets))) #DBGDBG + #self.stmHorizSizer.Add(self.stmGridSizer, 0, wx.ALL, 5) + #self.stmPanelSizer.Add(self.stmHorizSizer, 0, wx.ALL, 5) + #parent.SetSizerAndFit(self.stmPanelSizer) + parentSizer.Add(self.stmPanel) + w,h = parentSizer.GetMinSize() + parent.SetVirtualSize((w,h)) + parent.Layout() + # call restorePanel to sync data to GUI + self.restorePanel(currentList, pdef.MaxHashes) + self.panelCreated = True + + def hidePanel(self): + """hidePanel - hide the Stm panel""" + #print("STM hidePanel - hashAlg=%d, len(Widgets)=%d" % (self.myHashAlg, len(self.stmPanelWidgets))) #DBGDBG + for i in self.stmPanelWidgets: + i.Hide() + + def showPanel(self): + """showPanel - show the stm panel""" + #print("STM showPanel - hashAlg=%d, len(Widgets)=%d" % (self.myHashAlg, len(self.stmPanelWidgets))) #DBGDBG + if self.panelCreated: + for i in self.stmPanelWidgets: + i.Show() + parentSizer = self.parent.GetSizer() + w,h = parentSizer.GetMinSize() + self.parent.SetVirtualSize((w,h)) + + + def setElementToDefaults(self): + """setElementToDefaults - STM""" + + currentList = self.pdef.getCurrentListObject() + currentList.ElementDefData[self.myIndex].IncludeInList = False + currentList.ElementDefData[self.myIndex].HashAlg = self.myHashAlg + currentList.ElementDefData[self.myIndex].Control = 0 + currentList.ElementDefData[self.myIndex].NumbHashes = 0 + currentList.ElementDefData[self.myIndex].CurrentView = 0 + currentList.ElementDefData[self.myIndex].HashFiles = [] + + def onOverridePsPolicy(self, event): + currentList = self.pdef.getCurrentListObject() + self.setListModified() + # set/clear bit 0 per STM Dev Guide PolEltControl def + if(event.Checked() == True): + currentList.ElementDefData[self.myIndex].Control = 1 + else: + currentList.ElementDefData[self.myIndex].Control = 0 + + def onMinSinitVersion(self, event): + value = event.GetString() + currentList = self.pdef.getCurrentListObject() + self.setListModified() + + # only supports adding files with the add button, not entering the names directly + def onHashListBoxEdit(self, event): + """onHashListBoxEdit""" + #print("in STM::onHashListBoxEdit") # DBGDBG + + # tell the user to add button and clear the field + self.StatusBar.SetStatusText("Please clear the entry, then use the Add button to add hash files to the list") + #self.hashListBox.Undo() + #TODO: wxPython: onHashListBoxEdit - Clear() and Undo() both generate an event causing: RuntimeError: maximum recursion depth exceeded + + def onAddButtonClick(self, event): + """onAddButtonClick - add a hash file to the list""" + + filepath, filename = self.selectFile() + + if (filename == ''): + # selectFile() operation has been cancelled. + return + + # validate that the specified hash file is properly formatted + currentList = self.pdef.getCurrentListObject() + result = utilities.verifyHashFile(os.path.join(filepath, filename), currentList.ElementDefData[self.myIndex].HashAlg) + # Note: verifyHashFile() returns [FileValid, FileType], but only FileValid is used here + if( result[0] == False): + return + + self.copyFile(filepath, filename) + self.StatusBar.SetStatusText("Validated file %s." % (filename)) + + # update the file count and enable the remove button + lineCnt = currentList.ElementDefData[self.myIndex].NumbHashes + #print("onAddButtonClick: was %i lines" % (lineCnt)) # DBGDBG + lineCnt += 1 + + # MaxHashes = 0 means there is no limit on the number of hash files allowed + if(self.pdef.MaxHashes != 0): + if(lineCnt > self.pdef.MaxHashes): + self.StatusBar.SetStatusText("Only %d files can be added." % (self.pdef.MaxHashes)) + return + + #print("onAddButtonClick: now %i lines" % (lineCnt)) # DBGDBG + self.fileCntEdit.ChangeValue(str(lineCnt)) + self.removeButton.Enable(True) + + hashFileList = currentList.ElementDefData[self.myIndex].HashFiles + hashFileList.append(filename) + #print("new hashFileList = %s" % (hashFileList)) # DBGDBG + + # insert the new file into stm.HashFiles + self.setListModified() + currentList.ElementDefData[self.myIndex].HashFiles = hashFileList + currentList.ElementDefData[self.myIndex].NumbHashes = lineCnt + #print("StmDefData[self.myIndex].NumbHashes=%i, HashFiles = %s" % + # (currentList.ElementDefData[self.myIndex].NumbHashes, currentList.ElementDefData[self.myIndex].HashFiles)) # DBGDBG + + # since hashListBox.AppendText() generates an event to onHashListBoxEdit() + # and since hashListBoxEdit has to be enabled so text can be selected for Remove + # and direct text entry by the user into hashListBoxEdit is not supported due the complexity of validating it ... + # + # hashListBox.ChangeValue() doesn't generate an event but only takes a string, not a hashFileList which is a list ie '[]' + # so form a single string containing everything in hashFileList and update hashListBox using ChangeValue(hashFileString) + hashFileString = '' + index = 0 + for eachString in hashFileList: + if(index != 0): # if not the 1st entry, need a LF before the new entry + hashFileString += "\n" + hashFileString += eachString + index += 1 + #print("thisString=%s, hashFileString=%s" % (eachString, hashFileString)) + + self.hashListBox.ChangeValue(hashFileString) + + def onRemoveButtonClick(self, event): + """onRemoveButtonClick - remove the selected entry from the hash file list""" + + # confirm the remove + dlg = wx.MessageDialog(None, "Confirm removal of selected file?", 'Confirm Remove', wx.YES_NO | wx.ICON_QUESTION) + response = dlg.ShowModal() + dlg.Destroy() + + if(response == wx.ID_NO): + self.StatusBar.SetStatusText( "Remove cancelled" ) + return + + selection = self.hashListBox.GetStringSelection() + self.StatusBar.SetStatusText("Removed selection %s" % (selection)) + + # selection may not be a full line ... See if the selection is contianed in any of hashFileList's entries + currentList = self.pdef.getCurrentListObject() + hashFileList = currentList.ElementDefData[self.myIndex].HashFiles + for entry in hashFileList: + #print("entry=%s" % (entry)) # DBGDBG + start = entry.find(selection) + if(start != -1): # -1 means not found, else find returns the starting index of selection + #print("Found: %s at %i" % (selection, start)) # DBGDBG + # entry was found, but was it a partial selection? + if(selection not in hashFileList): # is selection on the GUI in PDEF's hashFileList? + # partial selection + #print("Partial selection %s not found in %s." % (selection, hashFileList)) # DBGDBG + self.StatusBar.SetStatusText("Please select the entire line") + break + else: + # Full selection, so remove that entry + # decr stm.NumbHashes & update NumberOfFiles widget + fileCnt = int(self.fileCntEdit.GetValue()) + fileCnt -= 1 + self.fileCntEdit.ChangeValue(str(fileCnt)) + currentList.ElementDefData[self.myIndex].NumbHashes = fileCnt + + hashFileList.remove(selection) # remove the selection from the PDEF object + #print("hashFileList=%s" % (hashFileList)) # DBGDBG + + if(fileCnt == 0): # disable REMOVE if no more files left + self.removeButton.Enable(False) + self.hashListBox.ChangeValue('') + else: + # rebuild the content of hashFileEdit from hashFileList and update the screen with ChangeValue + # to avoid generating an event and to clear the previous LF + hashFileString = '' + index = 0 + for eachString in hashFileList: + if(index != 0): # if not the 1st entry, need a LF before the new entry + hashFileString += "\n" + hashFileString += eachString + index += 1 + #print("thisString=%s, hashFileString=%s" % (eachString, hashFileString)) # DBGDBG + + self.hashListBox.ChangeValue(hashFileString) + + #print("hashListBox=%s" % (self.hashListBox.GetValue())) # DBGDBG + self.setListModified() + currentList.ElementDefData[self.myIndex].HashFiles = hashFileList + break + else: + self.StatusBar.SetStatusText("Selection %s not found. Please select only a single line" % (selection)) # DBGDBG + + + def writeStmDef(self, stmDefData, f): + """writeStmDef - write the Stm Def to the specified file""" + + print("writeStmDef dump, hashAlg=%d" % (self.myHashAlg)) # DBGDBG + pickle.dump(stmDefData, f) # write out the stmDefData object + + def setPanelToDefaults(self): + """setPanelToDefaults - restore defaults to stm panel widgets""" + + self.addButton.Enable(True) + self.removeButton.Enable(False) + self.fileCntEdit.ChangeValue("0") + self.hashListBox.ChangeValue("") + + def restorePanel(self, currentList, maxHashes): + """restorePanel - restore the STM element panel from the specified PLIST_DEF""" + + print("restorePanel - STM") # DBGDBG + # update Override PS Policy checkbox + self.overridePsPolicy.SetValue(currentList.ElementDefData[self.myIndex].Control) + listversion = str(currentList.ListVersionMajor)+'.'+str(currentList.ListVersionMinor) + if listversion == '2.0': + self.showV20Gui(True) + else: + self.showV20Gui(False) + + # If MaxHashes not 0, Only enable Add if < MaxHashes files + numbHashes = currentList.ElementDefData[self.myIndex].NumbHashes + flag = True + if(maxHashes != 0): + if(numbHashes >= maxHashes): + flag = False # don't enable add + self.addButton.Enable(flag) + + # enable remove if >0 hashes + flag = False + if(numbHashes > 0): + flag = True + self.removeButton.Enable(flag) + self.fileCntEdit.ChangeValue(str(numbHashes)) + + # form a string from hashFileList and update hashListBox + string = utilities.formStringFromListOfStrings(currentList.ElementDefData[self.myIndex].HashFiles) + self.hashListBox.ChangeValue(string) + + #def setListModified(self): + # """setListModified - if list not modified yet, increment its rev cnt and set it to modified""" + # + # currentList = self.pdef.getCurrentListObject() + # #print("Stm setListModified - ListModified was %s" % (currentList.ListModified)) # DBGDBG + # if(currentList.ListModified == False): + # currentList.RevocationCounter += 1 + # self.listPanel.revocationCountEdit.ChangeValue(str(currentList.RevocationCounter)) # update the GUI + # currentList.ListModified = True + + + # the last function in the file doesn't show up in the scope list in Understand for some reason! + def stub(self): + pass diff -Nru tboot-1.9.4/lcp-gen2/tools.py tboot-1.9.5/lcp-gen2/tools.py --- tboot-1.9.4/lcp-gen2/tools.py 1970-01-01 00:00:00.000000000 +0000 +++ tboot-1.9.5/lcp-gen2/tools.py 2016-12-17 03:19:38.000000000 +0000 @@ -0,0 +1,183 @@ +#!/usr/bin/python +# Copyright (c) 2013, Intel Corporation. All rights reserved. + +# TXT Policy Generator Tool - tools invoked from tools menu +# Hash image +# Insert policy into image + +# using print() built infunction, disable print statement +from __future__ import print_function + +try: + import wx +except ImportWxError: + raise ImportWxError, "Please download the appropriate version of wxPython from www.wxpython.org" + +try: + import os +except ImportOsError: + raise ImportOsError, "import OS failed" + +import array +import M2Crypto +import struct + +# Pycrypto module from: https://www.dlitz.net/software/pycrypto/ is required +#try: +# from Crypto.Hash import SHA # SHA1 +# from Crypto.Hash import SHA256 # SHA256 +#except ImportError: +# raise ImportError, "PyCrypto import failed. Please install PyCrypto ..." + +from defines import DEFINES +from util import UTILS +utilities = UTILS() + + +class TOOLS(object): + + # hash a bios image 'file' [i.e. base.bin] from 'startOffset' for 'offsetSize' bytes, + # and write the hash to base.hash, as a LCP2 raw hash file, and base.dat as an 'ascii coded binary' + # I.e. if the image's hash starts with: 0xB0, 0x61, 0x52, ... + # then the .hash file starts with: B0 61 52 ... (i.e. the raw binary hash) + # and the .dat file starts with: 42 30 20 36 31 20 35 32 20 + # (i.e. each hex digit is represented by its ascii equivalent with an ascii space after each hex pair + + # Parameters + # biosFileName - name of the bios file to be hashed + # startOffset - offset into the file to start hashing from, aka base + # offsetSize - size to hash from startOffset + # hashAlg - hash algorithm to use, TPM_ALG_XXXX where XXXX is SHA1 or SHA256 + + # Return True on success or + # False on any error + # + def hashImage(self, biosFileName, startOffsetStr, offsetSizeStr, hashAlgStr): + """hashImage - generate the hash of the specified file from start address for size bytes""" + function = 'hashImage' + + biosPath = os.path.abspath(os.path.normpath(biosFileName)) + startOffset = int(startOffsetStr, 16) + offsetSize = int(offsetSizeStr, 16) + hashAlg = int(hashAlgStr, 16) + + MAX_BIOS_SIZE = 0x1000000; + print("%s - biosFile=%s, startOffset=0x%x, offsetSize=0x%x, hashAlg=%d" % + (function, biosPath, startOffset, offsetSize, hashAlg)) # DBGDBG + + # use biosFile's base name for the .tmp and .hash files + # biosFile - file to be hashed, ie if biosFileName = biosXYZ.bin then base = biosXYZ + # tempFile - base.tmp - temp file containing the data to hash + # i.e. biosFile's data from startOffset to startOffset+offsetSize + # hashFile - base.hash - output file containg the hash of tempFile + + # verify that biosFile can be opened + try: + biosFile = open(biosPath, 'rb') + except: + print("Unable to open specified file: %s" % (biosPath)) + return False + + # strip off the .ext leaving the base + if(biosFileName.endswith('.bin') == True): + base = os.path.basename(biosFileName).split('.bin') + else: + print("Expected .bin extention for Bios File %s" % (biosPath)) + return False + + #TODO: will all bios files have .bin extentions?????????????????????????????????????? + #print("%s - base=%s" % (function, base[0])) # DBGDBG + + # verify that .tmp, .dat and .hash files can be created in the current dir, else exit + tmpFileName = utilities.formFileName(base[0], "tmp") + hashFileName = utilities.formFileName(base[0], "hash") + datFileName = utilities.formFileName(base[0], "dat") + #print("%s - tmpFileName=%s, hashFileName=%s" % (function, tmpFileName, hashFileName)) # DBGDBG + try: + tmpFile = open(tmpFileName, 'wb') + except: + print("Unable to create file: %s" % (tmpFileName)) + biosFile.close() + return False + + try: + hashFile = open(hashFileName, 'wb') + except: + print("Unable to create file: %s" % (hashFileName)) + tmpFile.close() + biosFile.close() + return False + + try: + datFile = open(datFileName, 'wb') + except: + print("Unable to create file: %s" % (datFileName)) + tmpFile.close() + biosFile.close() + datFile.close() + return False + + # Determine biosFile's size + biosFile.seek (0, os.SEEK_END) + biosFileSize = biosFile.tell() + + # if startOffset > MAX_BIOS_SIZE, then adjust startOffset to be relative to 4Gb + if (startOffset > MAX_BIOS_SIZE): + print("The specified StartOffset(0x%x) is > than the max bios size(%x) Assuming StartOffset is relative to 4Gb" % + (startOffset, MAX_BIOS_SIZE)) + beginingOfBiosImage = 0x100000000 - biosFileSize; + startOffset = startOffset - beginingOfBiosImage; + print("%s - startOffset now 0x%x, MAX_BIOS_SIZE=0x%x" % (startOffset, MAX_BIOS_SIZE)) + + # If startOffset + offsetSize > biosFile's size, adjust offsetSize + if(startOffset + offsetSize > biosFileSize): + print("%s - The specified StartOffset(0x%x) + offsetSize(0x%x) is larger than biosFileSize(0x%x)" % + (function, startOffset, offsetSize, biosFileSize)) + offsetSize = biosFileSize - startOffset; + print("StartOffset+OffsetSize > BiosFileSize. Resetting OffsetSize to 0x%x" % (offsetSize)) + + #print("%s - biosFileSize=0x%x, startOffset+offsetSize=0x%x, MAX_BIOS_SIZE=0x%x" % (function, biosFileSize, startOffset+offsetSize, MAX_BIOS_SIZE)) # DBGDBG + # buffer the part of the bios that will be hashed in base.tmp + # open the bios file, + # set the read pointer to: startOffset + # read offsetSize bytes into tempFile + data = array.array ("B") + biosFile.seek(startOffset, os.SEEK_SET) + #print("%s - pos=0x%x" % (function, biosFile.tell())) # DBGDBG + data.fromfile(biosFile, offsetSize) + + # Initialize to None to check for supported HashAlg. + hashAlgName = None + # reverse lookup of the hash algorithm name(key) for the given HashAlg value + hashAlgName = (key for key,val in DEFINES.TPM_ALG_HASH.items() if (val == hashAlg)).next() + + if (hashAlgName != None): + # This handles all SHA hash algorithms. + hash = M2Crypto.EVP.MessageDigest(hashAlgName.lower()) + else: + self.StatusBar.SetStatusText("Hash Algorithm %d is not supported" % (hashAlg)) + return False + + hash.update(data) + hashdigest = hash.digest() # cannot call this M2Crypto function twice. + + print(data, end='', file=tmpFile ) # for testing that the right data was hashed + print(hashdigest, end='', file=hashFile ) + hexHash = hashdigest.encode('hex') + print("Image's hash: %s" % (hexHash)) + print("Generated hash files: %s.hash and %s.dat" % (base[0],base[0])) + + # generate the .dat from hexHash: convert each hex byte to a ascii digit followed by a space + i=0 + while(i < len(hexHash)): + print(hexHash[i].upper(), end='', file=datFile ) # 1st hexdigit as upper case ascii + print(hexHash[i+1].upper(), end='', file=datFile ) # 2nd hexdigit as upper case ascii + print(' ', end='', file=datFile ) # space after each pair + i += 2 + print('\n', end='', file=datFile ) # final LF to match WinLCP + + biosFile.close() + tmpFile.close() + hashFile.close() + datFile.close() + return True diff -Nru tboot-1.9.4/lcp-gen2/TxtPolicyGen2.py tboot-1.9.5/lcp-gen2/TxtPolicyGen2.py --- tboot-1.9.4/lcp-gen2/TxtPolicyGen2.py 1970-01-01 00:00:00.000000000 +0000 +++ tboot-1.9.5/lcp-gen2/TxtPolicyGen2.py 2016-12-17 03:19:38.000000000 +0000 @@ -0,0 +1,1921 @@ +#!/usr/bin/python +# Copyright (c) 2013, Intel Corporation. All rights reserved. + +# TXT Policy Generator Tool + +# using print() built-in function, disable print statement +from __future__ import print_function + +# +# wxPython is not part of the standard Python distribution and has to be downloaded and installed separately. +# Tell the user that wxPython is required but has not been found +# +try: + import wx +except ImportError: + raise ImportError, "Please download the appropriate version of wxPython from www.wxpython.org" + +try: + import os +except ImportError: + raise ImportError, "import OS failed" + +from defines import DEFINES +from pdef import PDEF +pdef = PDEF() + +from util import UTILS +utilities = UTILS() + +from build import Build +build = Build() + +from list import LIST +list = LIST() + +from tools import TOOLS +tools = TOOLS() + +# Note: using cPickle's default text format [vs. binary] since the former is portable across Python versions +try: + import cPickle as pickle +except ImportError: + import pickle # fall back on Python version + +import datetime +import sys + +filename = "NewPlatform.pdef" +dirname = os.getcwd() + + + +# builds can be initiated from clicking the build button or +# specifying a batch build on the command line +BUILD_BATCH = 0 # same a BUILD_BUTTON but initi8ated from the command line +BUILD_BUTTON = 1 # build both the NV_POLICY (.pol) and POLICY DATA file (.dat) +BUILD_NV_POLICY_ONLY = 2 # build only the NV POLICY file (.pol) +BUILD_POLICY_DATA_ONLY = 3 # build only the POLICY DATA file (.dat) + # + # MyFrame class contains: + # File and Help menu pull downs + # [Menu Tool bar] + # BUILD button + # Policy Panel + # PS/PO Policy type checkbox + # ... + # +class MyFrame(wx.Frame): + + def __init__(self, parent, id, title): + # First, call the base class' __init__ method to create the frame + wx.Frame.__init__(self, parent, id, title, size=(820, 450)) + + global dirname, filename + + self.StatusBar = self.CreateStatusBar() # Add a Statusbar in the bottom of the window + self.createMenuBar() # Add a menu bar with File & Help menus + #self.createToolBar() # Add a tool bar + #TODO: TBD: $$$$ to purchase toolbar icons if toolbar is to be enabled + self.createPolicyPanel() # add initial policy panel + + # CLI syntax: + # 'TxtPolGen2.py -open MySystem.pdef -build' does a batch build of MySystem.pdef + # 'TxtPolGen2.py -hash file.bin startOffset offsetSize hashAlgorithm' + # + hashImageSyntax = "'TxtPolGen2 -hash file.bin startOffset offsetSize hashAlgorithm'\n" + if(len(sys.argv) == 1): + # Invoke GUI + pass + elif((sys.argv[1] == '-open') or (sys.argv[1] == '-hash')): # CLI cmd + filepath = os.path.abspath(os.path.normpath(sys.argv[2])) + dirname = os.path.dirname(filepath) + filename = os.path.basename(filepath) + + if(sys.argv[1] == '-open'): + msg = "Batch build of %s" % (filename) + if(self.verifyPdefFile() == True): + status = True + print("len(sys.argv) = %d, args=%s" % (len(sys.argv), sys.argv)) # DBGDBG + if(len(sys.argv) > 3): + if(sys.argv[3] == '-build'): + print("Starting %s ..." % (msg)) + self.batchBuild() + print("%s complete" % (msg)) + sys.exit() # exit if batch build succeeded + else: + status = False + else: + status = False + + if(status == False): + error = " failed. Expected a '-build' option" + print("%s %s" % (msg, error)) + sys.exit() # exit + else: + error = " failed. Invalid pdef file." + print("%s %s" % (msg, error)) + sys.exit() # exit + elif(sys.argv[1] == '-hash'): + if(len(sys.argv) < 5): + # invalid -hash syntax + print("%s" % (hashImageSyntax)) + else: + tools.hashImage(sys.argv[2], sys.argv[3], sys.argv[4], sys.argv[5]) + sys.exit() # exit + else: + print("%s" % (hashImageSyntax)) + sys.exit() + + else: # invalid CLI syntax, using GUI, print syntax help + help = "\n'TxtPolGen2' - invoke GUI\n'TxtPolGen2 -open File.pdef -build' - performs a batch build of File.pdef\n" + print("%s%s" % (help, hashImageSyntax)) + sys.exit() + + # verify the .pdef file to be opened for a batch build + def verifyPdefFile(self): + """verifyPdefFile - verify the file in argv[2] exists and has a .pdef extention""" + + if(len(sys.argv) > 2): + # chk for a .pdef ext + base, ext, = filename.rsplit('.', 1) + if(ext == "pdef"): + # chk the file exists by opening it + try: + f = open(os.path.join(dirname, filename), 'r') + except: + print("Error opening file %s" % (filename)) + return(False) # open failed so nothing to close + + f.close() + + else: + return False # invalid extention + + return True # ok + + # + # Create the menu bar with file & help menus. + # + def createMenuBar( self ): + """createMenuBar - create the Menu Bar""" + FileMenu = wx.Menu() + HelpMenu = wx.Menu() + BuildMenu = wx.Menu() + ToolMenu = wx.Menu() + + FileMenuNew = FileMenu.Append(wx.ID_NEW, "&New", " Create a new Policy") + FileMenuOpen = FileMenu.Append(wx.ID_OPEN, "&Open", " Open a saved PDEF file") + FileMenuSave = FileMenu.Append(wx.ID_SAVE, "&Save", " Save Policy to a PDEF file") + FileMenuSaveAs= FileMenu.Append(wx.ID_SAVEAS, "&Save As", " Save Policy to a PDEF file") + FileMenuPrint = FileMenu.Append(wx.ID_PRINT, "&Print", " Save Policy to a printable text file") + FileMenuClose = FileMenu.Append(wx.ID_EXIT, "&Close", " Close the Policy and exit") + + # Creating the menubar. + MenuBar = wx.MenuBar() + MenuBar.Append(FileMenu, "&File") # Adding the "FileMenu" to the MenuBar + + BuildMenuBuildNvPolicy = BuildMenu.Append(wx.ID_ANY, "&Build just NV Policy File", "Build only the NV Policy") + BuildMenuBuildPolicyDataStruct = BuildMenu.Append(wx.ID_ANY, "&Build just Policy Data File", "Build only the Policy Data Struct") + BuildMenuBuildBoth = BuildMenu.Append(wx.ID_ANY, "&Build Policy (both files)", "Build the full Policy") + MenuBar.Append(BuildMenu, "&Build") + + #ToolMenuHashFile = ToolMenu.Append(wx.ID_ANY, "&Hash a file", "Create a hash from the specified file") + #ToolMenuInsertPolicy = ToolMenu.Append(wx.ID_ANY, "&Insert policy", "Insert a policy into an image per its FIT7 record") + #MenuBar.Append(ToolMenu, "&Tools") # Adding the "ToolMenu" to the MenuBar + + HelpMenuToolInfo = HelpMenu.Append(wx.ID_ABOUT, "&Tool Info", " Display information about this tool") + HelpMenuLicense = HelpMenu.Append(wx.ID_ANY, "&License", " Display the license") + HelpMenuKeyGen = HelpMenu.Append(wx.ID_ANY, "&Key Generation", " How to generatekeys with OpenSSL") + HelpMenuBatch = HelpMenu.Append(wx.ID_ANY, "Batch Build Help", "Build from the command line") + HelpMenuHash = HelpMenu.Append(wx.ID_ANY, "Hash Image Help", "Hash an image from the command line") + HelpMenuGuide = HelpMenu.Append(wx.ID_ANY, "&Guide", " Open the User Guide") + HelpMenuTutorial = HelpMenu.Append(wx.ID_ANY, "&Tutorial", " Open the Tutorial") + MenuBar.Append(HelpMenu, "&Help") # Adding the "HelpMenu" to the MenuBar + + self.SetMenuBar(MenuBar) # Adding the MenuBar to the Frame content. + + # + # Menu events + # + self.Bind(wx.EVT_MENU, self.onNew, FileMenuNew) + self.Bind(wx.EVT_MENU, self.onOpen, FileMenuOpen) + self.Bind(wx.EVT_MENU, self.onSave, FileMenuSave) + self.Bind(wx.EVT_MENU, self.onSaveAs, FileMenuSaveAs) + self.Bind(wx.EVT_MENU, self.onPrint, FileMenuPrint) + self.Bind(wx.EVT_MENU, self.onExit, FileMenuClose) + + self.Bind(wx.EVT_MENU, self.onAbout, HelpMenuToolInfo) + self.Bind(wx.EVT_MENU, self.onLicense, HelpMenuLicense) + self.Bind(wx.EVT_MENU, self.onKeyGen, HelpMenuKeyGen) + self.Bind(wx.EVT_MENU, self.batchBuildHelp, HelpMenuBatch) + self.Bind(wx.EVT_MENU, self.hashImageHelp, HelpMenuHash) + self.Bind(wx.EVT_MENU, self.onGuide, HelpMenuGuide) + self.Bind(wx.EVT_MENU, self.onTutorial, HelpMenuTutorial) + + self.Bind(wx.EVT_MENU, self.onBuildButtonClick, BuildMenuBuildBoth) + self.Bind(wx.EVT_MENU, self.onBuildNvPolicy, BuildMenuBuildNvPolicy) + self.Bind(wx.EVT_MENU, self.onBuildPolicyDataStruct, BuildMenuBuildPolicyDataStruct) + + #self.Bind(wx.EVT_MENU, self.onHashFile, ToolMenuHashFile) + #self.Bind(wx.EVT_MENU, self.onInsertPolicy, ToolMenuInsertPolicy) + + # + # Create the ToolBar + # + def createToolBar( self ): + """createToolBar - create the Tool Bar""" + toolbar = self.CreateToolBar() + for each in self.toolBarData(): + self.createSimpleTool( toolbar, *each ) + toolbar.AddSeparator() + toolbar.Realize() + + #exitTool = ToolBar.AddLabelTool( wx.ID_ANY, 'Exit', wx.Bitmap('texit.png')) + #ToolBar.Realize() + #self.Bind(wx.EVT_TOOL, self.OnExit, ExitTool) + + def createSimpleTool( self, toolbar, label, filename, help, handler): + """createSimpleTool - create a simple tool for the Tool Bar""" + bmp = wx.Image( filename, wx.BITMAP_TYPE_BMP).ConvertToBitmap() + tool = toolbar.AddSimpleTool( -1, bmp, label, help) + #tool = toolbar.AddSimpleTool( -1, wx.NullBitmap, label, help) + self.Bind( wx.EVT_MENU, handler, tool ) + + def toolBarData( self ): + # label, filename, help, handler + return(("New", "new.bmp", "Create a new Policy", self.onNew), + ("Open", "open.bmp", "Open a saved PDEF file", self.onOpen), + ("Save", "save.bmp", "Save Policy to a PDEF file", self.onSave), + ("Save as a printable text file", "save.bmp", "Save Policy to a printable text file", self.onPrint), + # ("Tool Info", "help.bmp", "Tool info", self.onAbout) + ) + + + # + # Create the Default Policy Panel + # + # Policy Rules Version Control Options Policy Type Hash Alg + # [rnd chk box text box sq chkbox rnd chk box pulldown] + # -------------------------------------------------------------------------- + # PS Version 2.2 Allow NPW LIST SHA1 + # PO MinSINITVer 0 SINIT Cap... ANY + # + # Number of View List Add List Delete List ACM Revocation Limits [text] + # Lists BIOS SINIT + # [text box text box button button text box text box] + # + def createPolicyPanel( self ): + """ createPolicyPanel - create the Policy Panel""" + # Create a ScrolledWindow with a BoxSizer to contain every panel + self.scrollableWindow = wx.ScrolledWindow(self, wx.ID_ANY, style=wx.TAB_TRAVERSAL) + self.scrollableWindow.SetScrollbars(1, 1, 1, 1) + self.scrollableWindow.SetScrollRate(10, 10) + self.scrollableWindow.SetAutoLayout(1) + self.scrollableWindowSizer = wx.BoxSizer(wx.VERTICAL) + self.scrollableWindow.SetSizer(self.scrollableWindowSizer) + + # create the Policy Panel with a GridBagSizers + self.policyPanel = wx.Panel(self.scrollableWindow, -1) + self.policyPanelSizer = wx.GridBagSizer(hgap=5, vgap=5) + self.policyPanel.SetSizer(self.policyPanelSizer) + + policyLabel = wx.StaticText(self.policyPanel, -1, "Policy") + font18 = wx.Font( 18, wx.FONTFAMILY_DEFAULT, wx.NORMAL, wx.BOLD) + policyLabel.SetFont( font18 ) + self.policyPanelSizer.Add( policyLabel, pos=(1, 0)) + + pdefFileLabel = wx.StaticText(self.policyPanel, label="PDEF File: ") + self.policyPanelSizer.Add( pdefFileLabel, pos=(0,4)) + self.pdefFileName = wx.TextCtrl( self.policyPanel, value='None', size=(140, -1)) + self.pdefFileName.Enable( False ) # Version cannot be modified + self.policyPanelSizer.Add( self.pdefFileName, pos=(0,7)) + + # PS/PO Policy Rules Radio Buttons - PDEF.Rules + self.psRadioButton = wx.RadioButton( self.policyPanel, -1, "PS Policy Rules", style=wx.RB_GROUP) + self.poRadioButton = wx.RadioButton( self.policyPanel, -1, "PO Policy Rules") + self.poRadioButton.SetValue( True ) + + self.policyPanelSizer.Add( self.psRadioButton, pos=(2,0), span=(1,2)) + self.policyPanelSizer.Add( self.poRadioButton, pos=(3,0), span=(1,2)) + + self.Bind(wx.EVT_RADIOBUTTON, self.onPolicyRulesRadioClick, self.psRadioButton) + self.Bind(wx.EVT_RADIOBUTTON, self.onPolicyRulesRadioClick, self.poRadioButton) + + # Version text boxes: Version [PDEF.PolVersion] & Min SINIT Version [PDEF.SINITMinVersion] + self.versionLabel = wx.StaticText(self.policyPanel, label="Version: ") + self.policyPanelSizer.Add( self.versionLabel, pos=(1,3)) + supportedversions = sorted(DEFINES.SUPPORTED_LCP_VERSION.keys(), reverse=True) + defaultversion = supportedversions[0] + self.versionEdit = wx.ComboBox( self.policyPanel, size=(60, -1), value=defaultversion, choices=supportedversions, style=wx.CB_READONLY) + #self.versionEdit.Enable( False ) # Version cannot be modified + self.policyPanelSizer.Add( self.versionEdit, pos=(1,4)) + self.Bind(wx.EVT_TEXT, self.onPolicyVersion, self.versionEdit) + majorstring, minorstring = defaultversion.split('.') + pdef.PolVersionMajor = int(majorstring) + pdef.PolVersionMinor = int(minorstring) + + self.minSinitVersionLabel = wx.StaticText(self.policyPanel, label="Min SINIT Version: ") + self.policyPanelSizer.Add(self.minSinitVersionLabel, pos=(2,3)) + minSinitVersion = pdef.SinitMinVersion # get current value + self.minSinitVersionEdit = wx.TextCtrl( self.policyPanel, value=str(minSinitVersion), size=(30, -1)) + self.policyPanelSizer.Add( self.minSinitVersionEdit, pos=(2,4)) + self.Bind(wx.EVT_TEXT, self.onMinSinitVersion, self.minSinitVersionEdit) + + # Control Options - Checkboxes - PDEF.PolicyControl + contolOptionsLabel = wx.StaticText(self.policyPanel, -1, "Control Options") + font10 = wx.Font( 10, wx.FONTFAMILY_DEFAULT, wx.NORMAL, wx.BOLD) + contolOptionsLabel.SetFont( font10 ) + + self.allowNPW = wx.CheckBox(self.policyPanel, label="Allow NPW") + self.sinitCapabilites = wx.CheckBox(self.policyPanel, label="SINIT Capabilities in PCR17") + self.auxDelete = wx.CheckBox(self.policyPanel, label="AUX Delete") + self.auxDelete.Enable( False ) + + self.forceOwnerPolicyValue = False + self.forcePsPconfValue = True + pdef.PolicyControl |= DEFINES.PolicyControlForceOwnerBitMask # Initialize PolicyConrol with forcePsPconf bit set. + self.forcePsOrPo = wx.CheckBox(self.policyPanel, label="Force PS PCONF") # inverse of Force Owner Policy + self.forcePsOrPo.SetValue( self.forcePsPconfValue ) # defaults to checked => bit=0 + #self.forceOwnerPolicy = wx.CheckBox(self.policyPanel, label="Force Owner Policy") # inverse of Force PS PCONFIG + #self.forceOwnerPolicy.Hide() + self.ignorePsStm = wx.CheckBox(self.policyPanel, label="Ignore PS STM") + self.ignorePsPconf = wx.CheckBox(self.policyPanel, label="Ignore PS PCONF") + self.ignorePsMle = wx.CheckBox(self.policyPanel, label="Ignore PS MLE") + + self.Bind(wx.EVT_CHECKBOX, self.onNpwPolicyControl, self.allowNPW) + self.Bind(wx.EVT_CHECKBOX, self.onPcr17PolicyControl, self.sinitCapabilites) + self.Bind(wx.EVT_CHECKBOX, self.onForcePsOrPoPolicyControl, self.forcePsOrPo) + #self.Bind(wx.EVT_CHECKBOX, self.onForceOwnerPolicyControl, self.forceOwnerPolicy) + self.Bind(wx.EVT_CHECKBOX, self.onAuxDelete, self.auxDelete) + self.Bind(wx.EVT_CHECKBOX, self.onIgnorePsStm, self.ignorePsStm) + self.Bind(wx.EVT_CHECKBOX, self.onIignorePsPconf, self.ignorePsPconf) + self.Bind(wx.EVT_CHECKBOX, self.onIgnorePsMle, self.ignorePsMle) + + self.policyPanelSizer.Add(contolOptionsLabel, pos=(3,7), span=(1,2), flag=wx.BOTTOM, border=5) + self.policyPanelSizer.Add(self.allowNPW, pos=(4,7), span=(1,2), flag=wx.BOTTOM, border=5) + self.policyPanelSizer.Add(self.sinitCapabilites, pos=(5,7), span=(1,2), flag=wx.BOTTOM, border=5) + self.policyPanelSizer.Add(self.auxDelete, pos=(6,7), span=(1,2), flag=wx.BOTTOM, border=5) + self.policyPanelSizer.Add(self.forcePsOrPo, pos=(7,7), span=(1,2), flag=wx.BOTTOM, border=5) + #self.policyPanelSizer.Add(self.forceOwnerPolicy, pos=(7,7), span=(1,2), flag=wx.BOTTOM, border=5) + self.policyPanelSizer.Add(self.ignorePsStm, pos=(8,7), span=(1,2), flag=wx.BOTTOM, border=5) + self.policyPanelSizer.Add(self.ignorePsPconf, pos=(9,7), span=(1,2), flag=wx.BOTTOM, border=5) + self.policyPanelSizer.Add(self.ignorePsMle, pos=(10,7), span=(1,2), flag=wx.BOTTOM, border=5) + + # Hide ignoreXXX GUI if it's not LCP policy version 3.1 + if defaultversion == '3.1': + self.showV31Gui(True) + else: + self.showV31Gui(False) + + # Policy Type Radios List: LIST, ANY - PDEF.PolicyType + policyTypeLabel = wx.StaticText(self.policyPanel, -1, "Policy Type") + policyTypeLabel.SetFont( font10 ) + + self.listRadioButton = wx.RadioButton( self.policyPanel, -1, "LIST", style=wx.RB_GROUP) + self.anyRadioButton = wx.RadioButton( self.policyPanel, -1, "ANY") + self.anyRadioButton.SetValue( True ) + self.selectedPolicyType = self.anyRadioButton + + self.Bind(wx.EVT_RADIOBUTTON, self.onPolicyTypeRadioClick, self.listRadioButton) + self.Bind(wx.EVT_RADIOBUTTON, self.onPolicyTypeRadioClick, self.anyRadioButton) + + self.policyPanelSizer.Add(policyTypeLabel, pos=(5,0), span=(1,2), flag=wx.BOTTOM, border=5) + self.policyPanelSizer.Add(self.listRadioButton, pos=(7,0), span=(1,2), flag=wx.BOTTOM, border=5) + self.policyPanelSizer.Add(self.anyRadioButton, pos=(6,0), span=(1,2), flag=wx.BOTTOM, border=5) + + # Hash Alg combobox Control + hashList = DEFINES.SUPPORTED_HASHES + self.hashAlgLabel = wx.StaticText(self.policyPanel, label="Hash\nAlgorithm") + self.hashAlgLabel.SetFont( font10 ) + self.policyPanelSizer.Add(self.hashAlgLabel, pos=(0,10)) + + self.hashAlgEdit = wx.ComboBox( self.policyPanel, size=(75, -1), value="SHA256", choices=hashList, style=wx.CB_READONLY ) + self.hashAlgEdit.Enable( False ) # disabled since Policy Type: ANY is default + self.policyPanelSizer.Add(self.hashAlgEdit, pos=(1,10)) + self.Bind(wx.EVT_TEXT, self.onHashAlg, self.hashAlgEdit) + + # Algorithm for Auto-Promotion + self.algForApLabel = wx.StaticText(self.policyPanel, label="Algorithm for\nAuto-Promotion") + self.algForApLabel.SetFont( font10 ) + self.policyPanelSizer.Add(self.algForApLabel, pos=(0,13)) + + self.algForApEdit = wx.ComboBox( self.policyPanel, size=(75, -1), value="SHA256", choices=hashList, style=wx.CB_READONLY ) + self.algForApEdit.Enable( True ) # disabled since Policy Type: ANY is default + self.policyPanelSizer.Add(self.algForApEdit, pos=(1,13)) + self.Bind(wx.EVT_TEXT, self.onAlgForAp, self.algForApEdit) + + # Algorithm Allowed for LCP + self.algAllowedForLcpLabel = wx.StaticText(self.policyPanel, label="Algorithms Allowed for\nLaunch Control Policy") + self.algAllowedForLcpLabel.SetFont( font10 ) + self.policyPanelSizer.Add(self.algAllowedForLcpLabel, pos=(2,10), span=(1,2)) + + hashList = DEFINES.ALLOWED_HASHES + self.algAllowedForLcpEdit = wx.CheckListBox( self.policyPanel, -1, size=wx.DefaultSize, choices=hashList, style=wx.LB_MULTIPLE) + self.policyPanelSizer.Add(self.algAllowedForLcpEdit, pos=(3,10), span=(8,3)) + self.Bind(wx.EVT_CHECKLISTBOX, self.onAlgAllowedForLcp, self.algAllowedForLcpEdit) + + # Set the default value from PDEF structure + checkedLCP = [] + for item in DEFINES.TPM_ALG_HASH_MASK.keys(): + if(pdef.LcpHashAlgMask & DEFINES.TPM_ALG_HASH_MASK[item]): + checkedLCP.append(item) + self.algAllowedForLcpEdit.SetCheckedStrings(checkedLCP) + + # Allowed Signature Schemes + self.allowedSigSchemesLabel = wx.StaticText(self.policyPanel, label="Allowed Signature\nSchemes") + self.allowedSigSchemesLabel.SetFont( font10 ) + self.policyPanelSizer.Add(self.allowedSigSchemesLabel, pos=(2,13)) + + sigList = DEFINES.ALLOWED_SIGNATURE_SCHEMES + self.allowedSigSchemesEdit = wx.CheckListBox( self.policyPanel, -1, size=wx.DefaultSize, choices=sigList, style=wx.LB_MULTIPLE) + self.policyPanelSizer.Add(self.allowedSigSchemesEdit, pos=(3,13), span=(8,3)) + self.Bind(wx.EVT_CHECKLISTBOX, self.onAllowedSigSchemes, self.allowedSigSchemesEdit) + + checkedSign = [] + for item in DEFINES.TPM_ALG_SIGN_MASK.keys(): + if(pdef.LcpSignAlgMask & DEFINES.TPM_ALG_SIGN_MASK[item]): + checkedSign.append(item) + self.allowedSigSchemesEdit.SetCheckedStrings(checkedSign) + + # Number of Lists text box + self.numOfListsLabel = wx.StaticText(self.policyPanel, label="Number of Lists") + self.policyPanelSizer.Add( self.numOfListsLabel, pos=(8,3)) + self.numOfListsEdit = wx.TextCtrl( self.policyPanel, value="", size=(30, -1)) + self.numOfListsLabel.Enable( False ) + self.numOfListsEdit.Enable( False ) + self.policyPanelSizer.Add( self.numOfListsEdit, pos=(8,4)) + + # View List text box + self.viewListLabel = wx.StaticText(self.policyPanel, label="View List") + self.policyPanelSizer.Add( self.viewListLabel, pos=(9,3)) + self.viewListEdit = wx.TextCtrl( self.policyPanel, value="", size=(30, -1)) + self.viewListLabel.Enable( False ) + self.viewListEdit.Enable( False ) + self.policyPanelSizer.Add( self.viewListEdit, pos=(9,4)) + self.Bind(wx.EVT_TEXT, self.onViewList, self.viewListEdit) + + # Add and Delete List buttons + self.addListButton = wx.Button( self.policyPanel, -1, label="Add List ", style=wx.BU_EXACTFIT) + self.addListButton.Enable( False ) + self.policyPanelSizer.Add( self.addListButton, pos=(8, 0)) + self.Bind(wx.EVT_BUTTON, self.onAddListButtonClick, self.addListButton) # add event handler + + self.deleteListButton = wx.Button( self.policyPanel, -1, label="Delete List", style=wx.BU_EXACTFIT) + self.deleteListButton.Enable( False ) + self.policyPanelSizer.Add( self.deleteListButton, pos=(9, 0)) + self.Bind(wx.EVT_BUTTON, self.onDeleteListButtonClick, self.deleteListButton) # add event handler + + # ACM Revocation Limits static text [PDEF.MaxBiosMinVersion & PDEF.MaxSinitMinVersion ] + self.acmRevLabel = wx.StaticText(self.policyPanel, -1, "ACM Revocation Limits") + self.acmRevLabel.SetFont( font10 ) + self.policyPanelSizer.Add( self.acmRevLabel, pos=(3, 3), span=(1,4)) + + # BIOS text box + self.biosLabel = wx.StaticText(self.policyPanel, label="BIOS") + self.policyPanelSizer.Add( self.biosLabel, pos=(4,3)) + value = pdef.MaxBiosMinVersion # get current value + self.biosEdit = wx.TextCtrl( self.policyPanel, value=str(value), size=(40, -1)) + self.policyPanelSizer.Add( self.biosEdit, pos=(4,4)) + self.Bind(wx.EVT_TEXT, self.onBiosRevLimit, self.biosEdit) + + # SINIT text box + self.sinitLabel = wx.StaticText(self.policyPanel, label="SINIT") + self.policyPanelSizer.Add( self.sinitLabel, pos=(5,3)) + value = pdef.MaxSinitMinVersion # get current value + self.sinitEdit = wx.TextCtrl( self.policyPanel, value=str(value), size=(40, -1)) + self.policyPanelSizer.Add( self.sinitEdit, pos=(5,4)) + self.Bind(wx.EVT_TEXT, self.onSinitRevLimit, self.sinitEdit) + + #self.policyPanelSizer.Add(policyGridSizer, 0, wx.ALL, 5) + #policyHorizSizer.Add(policyGridSizer, 0, wx.ALL, 5) + #self.policyPanelSizer.Add(policyHorizSizer, 0, wx.ALL, 5) + #self.scrollableWindow.SetSizerAndFit(self.policyPanelSizer) + self.scrollableWindowSizer.Add(self.policyPanel, 0, wx.ALL, 5) + w,h = self.scrollableWindowSizer.GetMinSize() + self.scrollableWindow.SetVirtualSize((w,h)) + self.scrollableWindow.Layout() + + self.StatusBar.SetStatusText( "FileTypeSignature = %s, DefCompany = %s, StructVersion = %s" % + (pdef.FileTypeSignature, pdef.DefCompany, pdef.StructVersion)) + + ############################ + # File Menu Event Handlers # + ############################ + def onNew(self, event): + """ onNew - Create a new PDEF file""" + + global pdef, list + + if(pdef.Modified == True): + self.StatusBar.SetStatusText( "Save current PDEF file first?." ) + self.savePdefFile(title="Save current PDEF file?", name=filename) + self.StatusBar.SetStatusText( "" ) + + if(pdef.NumLists != 0): + list.hideListPanel() + w,h = self.scrollableWindowSizer.GetMinSize() + self.scrollableWindow.SetVirtualSize((w,h)) + self.scrollableWindow.Layout() + + pdef = PDEF() + list = LIST() + self.PolListInfo = {'0':None, '1':None, '2':None, '3':None, + '4':None, '5':None, '6':None, '7':None } + #self.setDefaultPdef() + self.restorePanel() + # Create a new PDEF project file with default settings. + # The selected directory will be the working directory. + self.savePdefFile(title="New PDEF project", name="NewPlatform.pdef") + + def onOpen(self, event): + """ onOpen - Open an existing PDEF file""" + global filename, dirname, pdef + + #self.dirname = '' # current owrking directory + wildcard = "PDEF file (*.pdef) | *.pdef|" \ + "All Files (*.*) | *.*" + dlg = wx.FileDialog(self, "Choose the PDEF file", dirname, "", wildcard, wx.FD_OPEN) + + if dlg.ShowModal() == wx.ID_OK: + filename = dlg.GetFilename() + dirname = dlg.GetDirectory() + pdef = PDEF() # loadAndDisplayPdefFile use pickle to load the saved file, does it overwrite pdef entirely? + self.pdefFileName.ChangeValue(filename) + self.loadAndDisplayPdefFile() + pdef.WorkingDirectory = dirname + dlg.Destroy() + + # + # If the PDEF has been modified, save it to specified name and return True + # if not modified, return False + # + def savePdefFile(self, title, name): + """ savePdefFile - perform Save or SaveAs""" + + global filename, dirname + + wildcard = "PDEF file (*.pdef) | *.pdef|" \ + "All Files (*.*) | *.*" + dlg = wx.FileDialog(self, title, dirname, name, wildcard, wx.FD_SAVE|wx.FD_OVERWRITE_PROMPT) + + if dlg.ShowModal() == wx.ID_OK: + filename = dlg.GetFilename() + dirname = dlg.GetDirectory() + pdef.Modified = False + pdef.WorkingDirectory = dirname + self.pdefFileName.ChangeValue(filename) + self.writePdefFile() + self.printPdefTextFile() + if (self.listRadioButton.GetValue() == True ): + self.enableDisableListWidgets( True ) + else: + self.enableDisableListWidgets( False ) + # originally, filename had no extension so strip it off keeping the user supplied base name + #filename, ext = filename.rsplit('.', 1) + print("DEBUG TxtPolicyGen2: Working Directory = %s" %dirname) + else: + print("savePdefFile: user cancelled, PDEF not saved") # DBGDBG + + dlg.Destroy() + #print("savePdefFile - done. filename=%s" % (filename)) # DBGDBG + return True + + def confirmSavePdefFile(self, title, name): + """ savePdefFile - perform Save or SaveAs""" + + dlg = wx.MessageDialog(self, name+" Exists.\nOverwrite existing file?", title, wx.OK|wx.CANCEL|wx.ICON_QUESTION) + + if dlg.ShowModal() == wx.ID_OK: + pdef.Modified = False # Want to save this status + self.writePdefFile() + self.printPdefTextFile() + print("DEBUG TxtPolicyGen2: Working Directory = %s" %dirname) + else: + print("savePdefFile: user cancelled, PDEF not saved") # DBGDBG + + dlg.Destroy() + return True + + def onSave(self, event): + """ onSave - Save a file""" + base = self.getBasePdefFile() + if (self.pdefFileName.GetValue() == "None"): + self.savePdefFile(title="Save PDEF File", name=base) + return True + else: + self.confirmSavePdefFile(title="Confirm Overwrite", name=filename) + return True + + def onSaveAs(self, event): + """ onSaveAs - Save a file as ...""" + base = self.getBasePdefFile() + self.savePdefFile(title="Save PDEF File As", name=base) + + def onPrint(self, event): + """ onPrint - save policy as a printable text file""" + self.printPdefFile() + + def onExit(self, event): + """ onExit - close any open PDEF's and exit""" + if(pdef.Modified == True): + self.savePdefFile(title="Save Policy before exiting?", name=filename) + + self.Close(True) # Close the frame. + + ############################ + # Help Menu Event Handlers # + ############################ + def onAbout(self, event): + """ onAbout - provide Help/About info""" + # A message dialog box with an OK button. + dlg = wx.MessageDialog( self, "TXT Policy Generator v%d, Release %s, Build date %s" % + (DEFINES.LCP_VERSION, DEFINES.TOOL_VERSION, DEFINES.BUILD_DATE), + "About TXT Policy Generator" ) + + dlg.ShowModal() # Show dialog & wait for OK or Cancel + dlg.Destroy() # finally destroy it when finished. + + def onLicense(self, event): + """ onLicense - display the license""" + + license = 'Win LCP Generator License.pdf' + self.openPdf(license) + + def openPdf(self, file): + """openPdf - display the specified pdf file""" + + #import subprocess + #from subprocess import CalledProcessError + + # make sure the file is present + try: + f = open(file, 'r') + except: + msg = "File %s not found" % (file) + self.StatusBar.SetStatusText("%s" % (msg)) + print("%s" % (msg)) + return + + f.close() + + self.StatusBar.SetStatusText( "Opening Acrobat reader to display file %s..." % (file)) + + # form the aboslute path to the pdf and pass that to acrobat + try: + if os.name == 'nt': + #subprocess.check_call(['C:\Program Files (x86)\Adobe\Reader 10.0\Reader\AcroRd32.exe', os.path.join(os.getcwd(),file)]) + os.startfile(file) + else: + #subprocess.check_call(['evince', os.path.join(os.getcwd(),file)]) + os.system('xdg-open ' + file) + except Exception as e: + print(e.returncode) + + self.StatusBar.SetStatusText( "" ) + + def onKeyGen(self, event): + """ onKeyGen - Generating keys with OpenSSL""" + + dlg = wx.MessageDialog( self, + "To create public and private keys with OpenSSL:\n openssl genrsa -out PrivateKeyFile.pem [1024,2048,3072]\n openssl rsa -pubout -in PrivateKeyFile.pem -out PublicKeyFile.pem\n", + "Key Generation") + dlg.ShowModal() # Show dialog & wait for OK or Cancel + dlg.Destroy() # finally destroy it when finished. + + def batchBuildHelp(self, event): + """ batchBuildHelp - help for batch builds""" + + dlg = wx.MessageDialog( self, + "To perform a build of a previously saved pdef file from the command line or a script:\ttxtPolGen2 -open MySystem.pdef -build\n", + "Batch Build Help") + dlg.ShowModal() # Show dialog & wait for OK or Cancel + dlg.Destroy() # finally destroy it when finished. + + def hashImageHelp(self, event): + """ hashImageHelp - help for hashing image from cmd line""" + + dlg = wx.MessageDialog( self, + "To hash an image from the command line or a script:\ttxtPolGen2 -hash image.bin startOffset offsetSize hashAlgorithm\nwhere 4=SHA1, 0xb=SHA256", + "Hash Image Help") + dlg.ShowModal() # Show dialog & wait for OK or Cancel + dlg.Destroy() # finally destroy it when finished. + + def onGuide(self, event): + """ onGuide - Open the User Guide""" + file = 'UserGuide.txt' + self.openPdf(file) + + def onTutorial(self, event): + """ onTutorial - Open the Tutorial""" + #TODO: NiceToHave: onTutorial - implement HelpMenu: Tutorial + self.StatusBar.SetStatusText("No Tutorial yet.") + + #def onHashFile(self, event): + # """onHashFile - hash the specified file""" + # self.StatusBar.SetStatusText( "This feature is not implemented from GUI, please use command line." ) + # + # #from tools import TOOLS + # #tools = TOOLS() + # # + # #TODO: For GUI, need to get the parameters:biosFileName, startOffset, offsetSize and hashAlg from the user + # # + # #tools.hashImage(biosFileName, startOffset, offsetSize, hashAlg) + # + #def onInsertPolicy(self, event): + # """onInsertPolicy - insert a policy into an image per the FIT type 7 record""" + # self.StatusBar.SetStatusText( "This feature is not implemented yet." ) + + ######################## + ###GUI Event Handlers### + ######################## + + # + # LIST or ANY Policy Type Radio buttons clicked + # + def onPolicyTypeRadioClick(self, event): + """ onPolicyTypeRadioClick - LIST or ANY Policy Type radio button selected, enable /disable widgets """ + #self.StatusBar.SetStatusText( "You clicked a Policy Type Radio Button! id %i, LIST id= %i" % ( event.GetId(), self.listRadioButton.GetId() ) ) + #print("in onPolicyTypeRadioClick") # DBGDBG + + #pdef.Modified = True + if event.GetId() == self.listRadioButton.GetId() : + # Policy Type: LIST selected, enable LIST widgets + if(self.pdefFileName.GetValue() == "None"): + # Force user to create a new empty .pdef file for project working directory. + value = False + else: + value = True + self.hashAlgEdit.Enable( True ) # enable Hash Algorithm ComboBox when switch from ANY to LIST + pdef.PolicyType = DEFINES.LIST + if(pdef.NumLists > 0): + list.showListPanel() + else : + # Policy Type: ANY selected, disable LIST widgets & LIST panel + value = False + self.hashAlgEdit.Enable( False ) # disabled since Policy Type: ANY is default + pdef.PolicyType = DEFINES.ANY + list.hideListPanel() + + self.enableDisableListWidgets( value ) + policyTypeRadioSelected = event.GetEventObject() + + def setPsRulesMode(self): + """ setPsRulesMode - set for PS rules""" + # PS Policy Rules selected, enable forceOwnerPolicy + #self.forceOwnerPolicy.Enable( True ) + #self.forcePsPconf.Enable( False ) + + # Cannot place 2 widgets in the same location, so remove one + self.forcePsOrPo.SetLabel("Force Owner Policy") + self.forcePsOrPo.SetValue(self.forceOwnerPolicyValue) + #self.forcePsPconf.Hide() + #self.forceOwnerPolicy.Hide() + #self.policyPanelSizer.Remove(self.forcePsPconf) # remove both checkboxes and add one back to avoid error + #self.policyPanelSizer.Remove(self.forceOwnerPolicy) + #self.policyPanelSizer.CheckForIntersection(self.forceOwnerPolicy, excludeItem=self.forcePsPconf) + #self.policyPanelSizer.Add(self.forceOwnerPolicy, pos=(7,7), span=(1,2), flag=wx.BOTTOM, border=5) + #self.forceOwnerPolicy.Show() + + self.ignorePsStm.Enable( False ) + self.ignorePsPconf.Enable( False ) + self.ignorePsMle.Enable( False ) + + self.auxDelete.Enable( True ) + #self.acmRevLabel.Enable( False ) + self.biosEdit.Enable( False ) + self.sinitEdit.Enable( False ) + #self.biosLabel.Enable( False ) + #self.sinitLabel.Enable( False ) + self.policyPanelSizer.Layout() + + # update pdef.PolicyControl after switching to PS Policy Rule radio button. + if(self.forcePsOrPo.GetValue() == 1): + pdef.PolicyControl |= DEFINES.PolicyControlForceOwnerBitMask + else: + pdef.PolicyControl &= ~DEFINES.PolicyControlForceOwnerBitMask + + if(self.auxDelete.GetValue() == 1): + pdef.PolicyControl |= DEFINES.PolicyControlAUXDeletionControl + else: + pdef.PolicyControl &= ~DEFINES.PolicyControlAUXDeletionControl + + # Clear Ignore_PS_xxx bits + pdef.PolicyControl &= ~DEFINES.PolicyControlIgnorePsStmBitMask + pdef.PolicyControl &= ~DEFINES.PolicyControlIgnorePsPconfBitMask + pdef.PolicyControl &= ~DEFINES.PolicyControlIgnorePsMleBitMask + + self.StatusBar.SetStatusText("PDEF.PolicyControl = 0x%x" % (pdef.PolicyControl) ) + + # if current list has a PCONF element, disable its OverridePsPolicy checkbox + #if((1 <= pdef.CurrentListView) and (pdef.CurrentListView <= pdef.NumLists)): + # list.enablePconfOverridePsPolicyCheckbox(False) + + def setPoRulesMode(self): + """ setPoRulesMode - set for PO rules""" + # PO Policy Rules selected, disable forceOwnerPolicy + #self.forceOwnerPolicy.Enable( False ) + #self.forcePsPconf.Enable( True ) + + # Cannot place 2 widgets in the same location, so destroy and recreate + + self.forcePsOrPo.SetLabel("Force PS PCONF") + self.forcePsOrPo.SetValue(self.forcePsPconfValue) + #self.forceOwnerPolicy.Hide() + #self.forcePsPconf.Hide() + #self.policyPanelSizer.Remove(self.forceOwnerPolicy) + #self.policyPanelSizer.Remove(self.forcePsPconf) # remove both checkboxes and add one back to avoid error + #self.policyPanelSizer.CheckForIntersection(self.forcePsPconf, excludeItem=self.forceOwnerPolicy) + #self.policyPanelSizer.Add(self.forcePsPconf, pos=(7,7), span=(1,2), flag=wx.BOTTOM, border=5) + #self.forcePsPconf.Show() + + self.ignorePsStm.Enable( True ) + self.ignorePsPconf.Enable( True ) + self.ignorePsMle.Enable( True ) + + self.auxDelete.Enable( False ) + #self.acmRevLabel.Enable( True ) + self.biosEdit.Enable( True ) + self.sinitEdit.Enable( True ) + #self.biosLabel.Enable( True ) + #self.sinitLabel.Enable( True ) + self.policyPanelSizer.Layout() + + # update pdef.PolicyControl after switching to PO Policy Rule radio button + if(self.forcePsOrPo.GetValue() == 1): + pdef.PolicyControl |= DEFINES.PolicyControlForceOwnerBitMask + else: + pdef.PolicyControl &= ~DEFINES.PolicyControlForceOwnerBitMask + + if(self.ignorePsStm.GetValue() == 1): + pdef.PolicyControl |= DEFINES.PolicyControlIgnorePsStmBitMask + else: + pdef.PolicyControl &= ~DEFINES.PolicyControlIgnorePsStmBitMask + + if(self.ignorePsPconf.GetValue() == 1): + pdef.PolicyControl |= DEFINES.PolicyControlIgnorePsPconfBitMask + else: + pdef.PolicyControl &= ~DEFINES.PolicyControlIgnorePsPconfBitMask + + if(self.ignorePsMle.GetValue() == 1): + pdef.PolicyControl |= DEFINES.PolicyControlIgnorePsMleBitMask + else: + pdef.PolicyControl &= ~DEFINES.PolicyControlIgnorePsMleBitMask + + # clear AuxDelete bit + pdef.PolicyControl &= ~DEFINES.PolicyControlAUXDeletionControl + + self.StatusBar.SetStatusText("PDEF.PolicyControl = 0x%x" % (pdef.PolicyControl) ) + + # if current list has a PCONF element, enable its OverridePsPolicy checkbox +# if((1 <= pdef.CurrentListView) and (pdef.CurrentListView <= pdef.NumLists)): +# list.enablePconfOverridePsPolicyCheckbox(True) + + # + # PS or PO Policy Rules Radio buttons clicked + # + def onPolicyRulesRadioClick(self, event): + """ onPolicyRulesRadioClick - PS or PO Policy Rules Radio button selected, enable/disable widgets """ + #print("in onPolicyRulesRadioClick") # DBGDBG + + pdef.Modified = True + if event.GetId() == self.psRadioButton.GetId() : + self.setPsRulesMode() + pdef.Rules = DEFINES.PsRules + + # if the list panel has been created, and no Sbios panel exists, enable the Add SBIOS button + if(pdef.NumLists > 0): + currentListObject = pdef.getCurrentListObject() + list.rebuildAddElementChoicesForPsRules() # add SBIOS if they don't exist + + # Does all element has PS Policy override checkbox? + # earlier code only enable/disable OverridePsPolicy for SBOS and MLE + list.syncVersion(pdef.Rules) + #for element in list.includedElements: + # element.enableDisableOverridePsPolicy(False) + else : + self.setPoRulesMode() + pdef.Rules = DEFINES.PoRules + + # if the list panel has been created, remove the SBIOS entries + if(pdef.NumLists > 0): + currentListObject = pdef.getCurrentListObject() + list.rebuildAddElementChoicesForPoRules() + + list.syncVersion(pdef.Rules) + #for element in list.includedElements: + # element.enableDisableOverridePsPolicy(True) + + + def onHashAlg(self, event): + """onHashAlg - update pdef.HashAlg""" + pdef.HashAlg = DEFINES.TPM_ALG_HASH[event.GetString()] + #if(event.GetString() == "SHA1"): + # pdef.HashAlg = DEFINES.TPM_ALG_SHA1 + #elif(event.GetString() == "SHA256"): + # pdef.HashAlg = DEFINES.TPM_ALG_SHA256 + #elif(event.GetString() == "SHA384"): + # pdef.HashAlg = DEFINES.TPM_ALG_SHA384 + #elif(event.GetString() == "SHA512"): + # pdef.HashAlg = DEFINES.TPM_ALG_SHA512 + pdef.Modified = True + self.StatusBar.SetStatusText( "HashAlg=%d" %(pdef.HashAlg)) + + def onAlgForAp(self, event): + """onAlgForAp - update algorithm for auto promotion""" + + pdef.AuxHashAlgMask = DEFINES.TPM_ALG_HASH_MASK[event.GetString()] + #if(event.GetString() == "SHA1"): + # pdef.AuxHashAlgMask = DEFINES.TPM_ALG_HASH_MASK_SHA1 + #elif(event.GetString() == "SHA256"): + # pdef.AuxHashAlgMask = DEFINES.TPM_ALG_HASH_MASK_SHA256 + pdef.Modified = True + self.StatusBar.SetStatusText( "AuxHashAlgMask=0x%X" %(pdef.AuxHashAlgMask)) + + def onAlgAllowedForLcp(self, event): + """onAlgAllowedForLcp - update algorithm allowed for launch control policy (pdef.LcpHashAlgMask)""" + + checkedList = self.algAllowedForLcpEdit.GetCheckedStrings() + mask = 0 + for item in checkedList: + mask = mask | DEFINES.TPM_ALG_HASH_MASK[item] + + pdef.LcpHashAlgMask = mask + pdef.Modified = True + #print("DEBUG onAlgAllowedForLcp: mask = 0x%08x" %mask) + self.StatusBar.SetStatusText("LcpHashAlgMask=0x%X" %(pdef.LcpHashAlgMask)) + + def onAllowedSigSchemes(self, event): + """onAllowedSigSchemes - update allowed signature schemes (pdef.LcpSignAlgMask)""" + + checkedList = self.allowedSigSchemesEdit.GetCheckedStrings() + mask = 0 + for item in checkedList: + mask = mask | DEFINES.TPM_ALG_SIGN_MASK[item] + + pdef.LcpSignAlgMask = mask + pdef.Modified = True + self.StatusBar.SetStatusText("LcpSignAlgMask=0x%X" %(pdef.LcpSignAlgMask)) + #print("DEBUG onAllowedSigSchemes: mask = 0x%08x" %mask) + + # + # BUILD Button clicked + # + # Update pdef.LastBuild[Date,Time]Stamp + # if modified, Save .pdef [& .pdef.txt] use that base name for .dat, .pol & .txt + # else prompt for a base name + # + # Generate a .dat [LCP_POLICY_DATA] which includes building the elements and hashing the signed and unsigned lists + # Generate .pol and txt of the LCP_POLICY + # + def onBuildButtonClick(self, event): + """ onBuildButtonClick - BUILD button clicked, build the current definition """ + status = self.build(BUILD_BUTTON) # doing a build from a button click event + if (status == True): + dlg = wx.MessageDialog(self, "Build Completed", "Build Status", wx.OK|wx.ICON_INFORMATION) + dlg.ShowModal() + dlg.Destroy() + else: + dlg = wx.MessageDialog(self, "Build Failed", "Build Status", wx.OK|wx.ICON_INFORMATION) + dlg.ShowModal() + dlg.Destroy() + currentList = pdef.getCurrentListObject() + list.restoreListPanel(currentList) # Update revocation number + + def onBuildNvPolicy(self, event): + """ onBuildNvPolicy - build just the NV Policy""" + status = self.build(BUILD_NV_POLICY_ONLY) + if (status == True): + dlg = wx.MessageDialog(self, "Build Completed", "Build Status", wx.OK|wx.ICON_INFORMATION) + dlg.ShowModal() + dlg.Destroy() + else: + dlg = wx.MessageDialog(self, "Build Failed", "Build Status", wx.OK|wx.ICON_INFORMATION) + dlg.ShowModal() + dlg.Destroy() + currentList = pdef.getCurrentListObject() + list.restoreListPanel(currentList) # Update revocation number + + def onBuildPolicyDataStruct(self, event): + """ onBuildPolicyDataStruct - build just the Policy Data Struct""" + status = self.build(BUILD_POLICY_DATA_ONLY) + if (status == True): + dlg = wx.MessageDialog(self, "Build Completed", "Build Status", wx.OK|wx.ICON_INFORMATION) + dlg.ShowModal() + dlg.Destroy() + else: + dlg = wx.MessageDialog(self, "Build Failed", "Build Status", wx.OK|wx.ICON_INFORMATION) + dlg.ShowModal() + dlg.Destroy() + currentList = pdef.getCurrentListObject() + list.restoreListPanel(currentList) # Update revocation number + + # buildMode can be: + # BUILD_BATCH if build initiated from cmd line: + # txtPolicyGen.py -open MySystem.pdef -build + # BUILD_BUTTON - if build initiated by clicking the build button or build both build menu + # BUILD_NV_POLICY_ONLY - if build initiated by clicking the 'build just NV Policy' build menu (.pol) + # BUILD_POLICY_DATA_ONLY- if build initiated by clicking the 'build just POLICY DATA' build menu (.dat) + # + def build(self, buildMode): + """build - perform a build""" + + global filename, dirname + + # update the build time and date stamps + # Per TXT Policy Generator 5.3.1, clear the PDEF's Data Revocation Counters + # if PolicyType = LIST, and at least 1 list, then update the list and pdef RevocationCounters + # do all this now so it is in the pdef and pdef.txt saved below + self.updateLastBuildDateAndTimeStamps() + pdef.DataRevocationCounters = [0,0,0,0,0,0,0,0] + if(pdef.PolicyType == DEFINES.LIST): + if(pdef.NumLists > 0): + list.onBuildButtonClick(pdef) + + # don't need to save current pdef if doing a batch build + if((buildMode == BUILD_BUTTON) or + (buildMode == BUILD_NV_POLICY_ONLY) or + (buildMode == BUILD_POLICY_DATA_ONLY)): + # if needed save the current PDEF to base.pdef & base.pdef.txt + # NOTE: in the saved PDEF's, the PolicyHash has not been calculated yet + # + if(self.checkModified() == True): + base = filename # default base filename + if(self.confirmSavePdefFile(title="Save Policy before building?", name=filename) == True): + # True returned if PDEF was modified and so was saved + # False returned if not modified so no save needed + # + # Note: saving the .pdef and .pdef.txt files here ensures that + # their LastBuild[Time,Date]Stamp's are updated for this build + + # reuse the base name [with .pdef.txt extention] provided above + # and don't prompt for a file name again + #filename = utilities.formFileName(filename, "txt") + self.printPdefTextFile() + + # originally, filename had no extention so strip it off keeping the user supplied base name + #filename, ext, ext1 = filename.rsplit('.', 1) + + else: + # If PDEF not saved, then get the base name for the LCP_POLICY & LCP_POLICY_DATA files to build + wildcard = "LCP_POLICY (*.pol) | *.pol|" \ + "All Files (*.*) | *.*" + title = "Please specify a name for the the LCP_POLICY and LCP_POLICY_DATA files to build." + dlg = wx.FileDialog(self, title, dirname, filename, wildcard, wx.SAVE|wx.OVERWRITE_PROMPT) + + if dlg.ShowModal() == wx.ID_OK: + filename = dlg.GetFilename() + dirname = dlg.GetDirectory() + dlg.Destroy() + else: # user didn't click OK + dlg.Destroy() + self.StatusBar.SetStatusText( "No file specified, aborting build" ) + return False + + # originally, filename had no extension so strip it off keeping the user supplied base name + #filename, ext = filename.rsplit('.', 1) + + elif(buildMode == BUILD_BATCH): + # originally, filename had no extention so strip it off keeping the user supplied base name + #filename, ext = filename.rsplit('.', 1) + pass + + else: # should never get here + print("build - unknown buildMode=%d!!!!!!!**********" % (buildMode)) + + build.filename = filename + build.dirname = dirname + + # If PolicyType==LIST, build the LCP_POLICY_DATA struct, + # which includes creating the LIST_MEASUREMENTS[] used to calculate the pdef.PolicyHash + # + text1 = "Building LCP_POLICY files " + text2 = ".[pol and txt]" + self.StatusBar.SetStatusText("%s %s %s" % (text1, build.filename, text2)) + #print("build - BuildMode=%d" % (buildMode)) # DBGDBG + + if(build.buildLcpPolicyDataStruct(pdef, self.StatusBar) == False): + # Abort build if there was a failure, Build can fail reading hash or pcr files + print("build failed, aborting build") + return False + + if(buildMode != BUILD_NV_POLICY_ONLY): + # warn if PolicyType == ANY but BUILD_POLICY_DATA_ONLY was requested + # since # If PolicyType == ANY, there is no policy data file + if((buildMode == BUILD_POLICY_DATA_ONLY) and (pdef.PolicyType == DEFINES.ANY)): + self.StatusBar.SetStatusText("Warning - No Policy Data File (.dat) is built when Policy Type is ANY") + + elif(pdef.PolicyType == DEFINES.LIST): + # Per TXT SW Dev Guide 3.1.1.1 p50: if PolicyType is ANY, no LCP_POLICY_DATA is expected + # If PolicyType == ANY, there is no policy data file + build.buildLcpPolicyDataFile(pdef) + + if(buildMode != BUILD_POLICY_DATA_ONLY): + # generate the LCP_POLICY files + if(build.buildRawLcpPolicyFile(pdef, self.StatusBar) == True): # abort if error + build.buildTxtLcpPolicyFile(pdef) + #build.buildXmlLcpPolicyFile(pdef) # XML output file not requied for LCP2 + else: + return False + # Complete build successfully. Save Pdef file again because pdef.Modified and list.ListModified bits are set False during the build. + self.writePdefFile() + return True + + + # + # Do a batch build - defind as: + # when tool invoked from cmd line as: txtpolgen2 -open MySystem.pdef -build + # validate the specified file ends with .pdef and exists + # open it + # do a build + # Assumes file in argv[2] exists and has a .pdef extention + # + def batchBuild(self): + """batchBuild - open and buiild the specified file""" + #global filename + + # TODO: validate the .pdef, then open it + #filename = sys.argv[2] + print("Opening file: %s\%s" % (dirname, filename)) + self.loadAndDisplayPdefFile() + + print("Building") + self.build(BUILD_BATCH) # doing a batch build + + # + # Add List Button clicked + # + def onAddListButtonClick(self, event): + """ onAddListButtonClick - Add List button clicked """ + + maxLists = pdef.MaxLists + listNumber = pdef.NumLists # current number of lists + pdef.Modified = True + + if( listNumber+1 == maxLists ): # if only space for 1 more list, disable ADD LIST button + self.addListButton.Enable( False ) + if( listNumber < maxLists ): # create 1st list panel or update Nth panel + listNumber += 1 + self.StatusBar.SetStatusText( "Adding List: %i MaxLists=%i" % (listNumber, maxLists)) + self.numOfListsEdit.ChangeValue(str(listNumber)) # update the number of Lists widget + pdef.NumLists = listNumber + pdef.CurrentListView = listNumber + + # NOTE: ChangeValue() does NOT trigger an event [as if the field was edited by the user] as SetValue() does + self.viewListEdit.ChangeValue( str(listNumber)) + pdef.addPlistDef(listNumber) + if(listNumber == 1): # create list panel 1 + # need to enable delete and view list controls + self.deleteListButton.Enable( True ) # enable Delete List button + self.viewListEdit.Enable( True ) # enable the view list button + + self.viewListLabel.Enable( True ) # enable the view list label + + list.createListPanel(wx, self.scrollableWindow, listNumber, pdef, self.StatusBar) + else: # update list panel N [< max] to defaults + # PDEF object's LIST section should always contain current values + list.setListPanelToDefaults(wx, self.scrollableWindow, listNumber, pdef) + + #w, h = self.scrollableWindow.GetMinSize() + #self.scrollableWindow.SetVirtualSize( (w, h) ) + self.scrollableWindow.Layout() + #self.Layout() + #print("AddList: pdef.PolListInfo now = %s" % (pdef.PolListInfo)) # DBGDBG + + # + # Delete List Button clicked + # + def onDeleteListButtonClick(self, event): + """ onDeleteListButtonClick - Delete List button clicked """ + + dlg = wx.MessageDialog(None, "Deleted Lists cannot be recovered. Continue?", 'Confirm List Deletion', wx.YES_NO | wx.ICON_QUESTION) + response = dlg.ShowModal() + dlg.Destroy() + + if(response == wx.ID_NO): + self.StatusBar.SetStatusText( "List Deletion cancelled" ) + else: + self.StatusBar.SetStatusText( "Deleted List %i, NumLists now %i" % (pdef.CurrentListView, pdef.NumLists-1)) + + pdef.Modified = True + + # sanity check: chk that current list indicated by view list is between 1 & PDEF.NumLists + if((1 <= pdef.CurrentListView) and (pdef.CurrentListView <= pdef.NumLists)): + currentListObject = pdef.getCurrentListObject() # delete the current list indicated by view list + del currentListObject + else: + self.StatusBar.SetStatusText( "List Deletion cancelled. CurrentListView=%i, NumLists=%i??" % (pdef.CurrentListView, pdef.NumLists)) + + # decrement PDEF.NumLists, if now = 0, ViewList and DeleteList are disabled + # otherwise, update CurrentListView and display it + deletedList = pdef.CurrentListView + pdef.NumLists -= 1 + if(pdef.NumLists == 0): + pdef.PolListInfo[str(pdef.CurrentListView-1)] = None + + self.viewListLabel.Enable( False ) + self.viewListEdit.Enable( False ) + self.viewListEdit.ChangeValue("") + self.addListButton.Enable( True ) + self.deleteListButton.Enable( False ) + pdef.CurrentListView = 0 + pdef.NumLists = 0 + self.numOfListsEdit.ChangeValue(str(pdef.NumLists)) + list.hideListPanel() + self.scrollableWindow.Layout() + #TODO: WxPython: onDeleteListButtonClick - Layout() didn't resize policyPanel after deleting the last list? Due to Show/Hide? + + print("DeleteList=0: NumLists=%i CurrentListView=%i" % (pdef.NumLists, pdef.CurrentListView)) # DBGDBG + print("Delete List: pdef.PolListInfo now = %s" % (pdef.PolListInfo)) # DBGDBG + + else: + #pdef.PolListInfo[str(pdef.CurrentListView-1)] = None + + pdef.CurrentListView -= 1 + if(pdef.CurrentListView == 0): + pdef.CurrentListView = 1 # if list 1 was deleted, and there are >1 lists left, show new list 1 + currentListStr = str(pdef.CurrentListView) + self.viewListEdit.ChangeValue(currentListStr) + self.numOfListsEdit.ChangeValue(str(pdef.NumLists)) + list.listLabelNum.ChangeValue(currentListStr) + + print("DeleteList>0: NumLists=%i CurrentListView=%i" % (pdef.NumLists, pdef.CurrentListView)) # DBGDBG + print("\nDeleted List %i: NumLists=%i\npdef.PolListInfo was %s" % (deletedList, pdef.NumLists, pdef.PolListInfo)) # DBGDBG + i=deletedList + end = pdef.NumLists+1 + for i in range(i, end): + pdef.PolListInfo[str(i-1)] = pdef.PolListInfo[str(i)] + print("shift %i to %i" % (i, i-1)) # DBGDBG + i += 1 + pdef.PolListInfo[str(end-1)] = None + print("delete %i" % (end)) # DBGDBG + print("pdef.PolListInfo now %s\n" % (pdef.PolListInfo)) # DBGDBG + + + def onPolicyVersion(self, event): + policyversion = event.GetString() + majorstring, minorstring = policyversion.split('.') + pdef.PolVersionMajor = int(majorstring) + pdef.PolVersionMinor = int(minorstring) + if policyversion == '3.0': + self.showV31Gui(False) + else: + self.showV31Gui(True) + + # go thru each list and change list version number + listversion = DEFINES.SUPPORTED_LCP_VERSION[policyversion] + majorstring, minorstring = listversion.split('.') + for listobj in pdef.PolListInfo.values(): + if listobj != None: + listobj.ListVersionMajor = int(majorstring) + listobj.ListVersionMinor = int(minorstring) + # refresh text in the current list displayed + if pdef.NumLists != 0: + list.syncVersion(pdef.Rules) + pdef.Modified = True + + # + # MinSinitVersion value changed - update PDEF.SINITMinVersion + # + def onMinSinitVersion(self, event): + """ onMinSinitVersion - MinSinitVersion value was changed""" + #self.StatusBar.SetStatusText( "You changed MinSinitVersion to %s" % ( event.GetString() )) + #print("in onMinSinitVersion") # DBGDBG + + string = event.GetString() + try: + value = int(string) + except: + self.StatusBar.SetStatusText( "%s is invalid, Please enter only digits between 0 and 9" % (string)) + else: + if(int(value) > DEFINES.maxVersion): + self.StatusBar.SetStatusText( "%i is too large, the max value for MinSinitVersion is %i" % ( int(value), DEFINES.maxVersion )) + else: + pdef.SinitMinVersion = int(value) + pdef.Modified = True + self.StatusBar.SetStatusText("") # clear any warnings + pdef.Modified = True + + # + # Allow NPW, SINIT cap. in PCR17 or Force Owner Policy 'Policy Control' check box changed + # + def setPolicyControl(self, event, bit): + """ setPolicyControl - the control bits in pdef.PolicyControl. + This function is call by all CheckBox callback functions for the policy Control Options. + """ + policyControl = pdef.PolicyControl + if(event.IsChecked()): + policyControl |= bit + else: + policyControl &= ~bit + + pdef.PolicyControl = policyControl + pdef.Modified = True + self.StatusBar.SetStatusText("PDEF.PolicyControl = 0x%x" % (policyControl) ) + + + def onNpwPolicyControl(self, event): + """ onNpwPolicyControl - Allow NPW change""" + + self.setPolicyControl(event, DEFINES.PolicyControlAllowNpwBitMask) + + + def onPcr17PolicyControl(self, event): + """ onPcr17PolicyControl - Allow SINIT Capability in PCR17 change""" + + self.setPolicyControl(event, DEFINES.PolicyControlPcr17BitMask) + + + # 'Force Owner Policy' is inverse of 'Force PS PCONFIG', + # i.e. they share the same bit in the Control word, and their checkboxes are always opposite values + # Enable Force Owner Policy, if PS rules + # Enable Force PS PCONFIG, if PO rules + # +# def onForceOwnerPolicyControl(self, event): +# """ onForceOwnerPolicyControl - Force Owner Policy change""" +# +# if(event.IsChecked()): +# self.forceOwnerPolicyValue = True +# else: +# self.forceOwnerPolicyValue = False +# self.setPolicyControl(event, DEFINES.PolicyControlForceOwnerBitMask) + + + def onForcePsOrPoPolicyControl(self, event): + """ onForcePsPconfPolicyControl - Force PS PCONF change""" + + if pdef.Rules == DEFINES.PsRules: + if(event.IsChecked()): + self.forceOwnerPolicyValue = True + else: + self.forceOwnerPolicyValue = False + else: + if(event.IsChecked()): + self.forcePsPconfValue = True + else: + self.forcePsPconfValue = False + self.setPolicyControl(event, DEFINES.PolicyControlForceOwnerBitMask) + + + def onAuxDelete(self, event): + """ onAuxDelete - AuxDelete Policy change""" + + self.setPolicyControl(event, DEFINES.PolicyControlAUXDeletionControl) + + + def onIgnorePsStm(self, event): + """ onIgnorePsStm - AuxDelete Policy change""" + + self.setPolicyControl(event, DEFINES.PolicyControlIgnorePsStmBitMask) + + + def onIignorePsPconf(self, event): + """ onIignorePsPconf - AuxDelete Policy change""" + + self.setPolicyControl(event, DEFINES.PolicyControlIgnorePsPconfBitMask) + + + def onIgnorePsMle(self, event): + """ onIgnorePsMle - AuxDelete Policy change""" + + self.setPolicyControl(event, DEFINES.PolicyControlIgnorePsMleBitMask) + + + def onBiosRevLimit(self, event): + """ onBiosRevLimit - BIOS Revocation Limit change""" + #print("in onBiosRevLimit") # DBGDBG + + string = event.GetString() + try: + value = int(string) + except: + self.StatusBar.SetStatusText( "%s is invalid, Please enter only digits between 0 and 9" % (string)) + else: + if(int(value) > DEFINES.maxVersion): + self.StatusBar.SetStatusText( "%i is too large, the max value for BIOS Revocation Limit is %i" % ( int(value),DEFINES. maxVersion )) + else: + pdef.MaxBiosMinVersion = int(value) + pdef.Modified = True + self.StatusBar.SetStatusText("") # clear any warnings + + def onSinitRevLimit(self, event): + """ onSinitRevLimit SINIT Revocation Limit change""" + #print("in onSinitRevLimit") # DBGDBG + + string = event.GetString() + try: + value = int(string) + except: + self.StatusBar.SetStatusText( "%s is invalid, Please enter only digits between 0 and 9" % (string)) + else: + if(int(value) > DEFINES.maxVersion): + self.StatusBar.SetStatusText( "%i is too large, the max value for SINIT Revocation Limit is %i" % ( int(value), DEFINES.maxVersion )) + else: + pdef.MaxSinitMinVersion = int(value) + pdef.Modified = True + self.StatusBar.SetStatusText("") # clear any warnings + + def onViewList(self, event): + """ onViewList - View List value changed""" + #print("in onViewList") # DBGDBG + self.StatusBar.SetStatusText("You changed the View List value to %s" % ( event.GetString() )) + + maxValue = pdef.NumLists + string = event.GetString() + try: + value = int(string) + except: + self.StatusBar.SetStatusText( "%s is invalid, Please enter only digits between 0 and %i" % (string, maxValue)) + else: + if(value == 0): + self.StatusBar.SetStatusText( "List number must be > 0" ) + self.viewListEdit.ChangeValue(str(pdef.CurrentListView)) # restore previous value + elif(value > maxValue): + self.StatusBar.SetStatusText( "List %i has not been added yet" % ( int(value) )) + self.viewListEdit.ChangeValue(str(pdef.CurrentListView)) # restore previous value + else: + pdef.CurrentListView = int(value) + pdef.Modified = True + list.setListPanelToCurrentListView( ) # update the list panel to the specified list + self.StatusBar.SetStatusText( "Viewing List %d" % ( pdef.CurrentListView )) + + + def setAlgMask(self, event, bit, algsAllowed, which): + """setAlgMask - common code for setting LCP/AutoProtection Algorithms Allowed masks""" + + if(event.IsChecked()): + newValue = algsAllowed | bit + else: + newValue = algsAllowed & ~bit + + if(which == "LCP"): + pdef.LcpHashAlgMask = newValue + self.StatusBar.SetStatusText("Algorithm for %s = %d" % (which, pdef.LcpHashAlgMask)) + elif(which == "AP"): + pdef.AuxHashAlgMask = newValue + self.StatusBar.SetStatusText("Algorithm for %s = %d" % (which, pdef.AuxHashAlgMask)) + else: + self.StatusBar.SetStatusText("ERROR: Illegal value = %s passed to setAlgMask(), expected LCP or AP") + + pdef.Modified = True + + + print("setAlgMask: LcpHashAlgMask=%x, AuxHashAlgMask=%x" % (pdef.LcpHashAlgMask, pdef.AuxHashAlgMask)) # DBGDBG + + # + # Utility Functions + # + def enableDisableListWidgets( self, value ) : + """ enableDisableListWidgets """ + self.addListButton.Enable( value ) + self.hashAlgEdit.Enable( value ) + self.numOfListsLabel.Enable( value ) + + # if value = True, set NumberOfLists to 0 + if( value == True ): + self.numOfListsEdit.ChangeValue("0") + + # + # reset policy panel (& PDEF object) to default vaules + # + def setDefaultPdef(self): + """ setDefaultPdef - set the PDEF to default values""" + pdef.Modified = False + + self.poRadioButton.SetValue( True ) + pdef.Rules = 1 + + pdef.MaxBiosMinVersion = 255 + self.biosEdit.ChangeValue(str(pdef.MaxBiosMinVersion)) + pdef.MaxSinitMinVersion = 255 + self.sinitEdit.ChangeValue(str(pdef.MaxSinitMinVersion)) + + pdef.SinitMinVersion = 0 + self.minSinitVersionEdit.ChangeValue(str(pdef.SinitMinVersion)) + + pdef.PolicyControl = 0 + self.allowNPW.SetValue(False) + self.sinitCapabilites.SetValue(False) + self.auxDelete.SetValue(False) + self.forceOwnerPolicyValue = False + self.forcePsPconfValue = True + self.forcePsOrPo.label = "Force PS PCONF" + self.forcePsOrPo.SetValue(self.forcePsPconfValue) + self.setPoRulesMode() + + self.anyRadioButton.SetValue( True ) + pdef.PolicyType = 1 + + self.hashAlgEdit.Enable( False ) + pdef.HashAlg = DEFINES.TPM_ALG_HASH['SHA256'] + + self.numOfListsLabel.Enable( False ) + self.numOfListsEdit.Enable( False ) + self.numOfListsEdit.ChangeValue("") + self.viewListLabel.Enable( False ) + self.viewListEdit.Enable( False ) + self.addListButton.Enable( False ) + self.deleteListButton.Enable( False ) + + self.biosEdit.ChangeValue("255") + self.sinitEdit.ChangeValue("255") + self.acmRevLabel.Enable( True ) + self.biosEdit.Enable( True ) + self.sinitEdit.Enable( True ) + self.biosLabel.Enable( True ) + self.sinitLabel.Enable( True ) + + pdef.LcpHashAlgMask = DEFINES.TPM_ALG_HASH_MASK['SHA256'] + pdef.AuxHashAlgMask = DEFINES.TPM_ALG_HASH_MASK['SHA256'] + + checkedSign = [] + for item in DEFINES.TPM_ALG_SIGN_MASK.keys(): + if(pdef.LcpSignAlgMask & DEFINES.TPM_ALG_SIGN_MASK[item]): + checkedSign.append(item) + self.allowedSigSchemesEdit.SetCheckedStrings(checkedSign) + + checkedLCP = [] + for item in DEFINES.TPM_ALG_HASH_MASK.keys(): + if(pdef.LcpHashAlgMask & DEFINES.TPM_ALG_HASH_MASK[item]): + checkedLCP.append(item) + self.algAllowedForLcpEdit.SetCheckedStrings(checkedLCP) + + #self.algAllowedForLcpEdit.SetCheckedStrings("") + #self.allowedSigSchemesEdit.SetCheckedStrings("") + pdef.PolicyHash = 0 + pdef.LastBuildDateStampYear = 2000 + pdef.LastBuildDateStampMonth = 01 + pdef.LastBuildDateStampDay = 01 + pdef.LastBuildTimeStampHour = 00 + pdef.LastBuildTimeStampMinute = 00 + pdef.LastBuildTimeStampSecond = 00 + pdef.LastBuildTimeStampLowByte = 00 + pdef.CurrentListView = 0 + pdef.NumLists = 0 + + # refresh GUI + + + def loadAndDisplayPdefFile(self): + """ loadAndDisplayPdefFile - get a saved pdef object from a PDEF file and update the policy panel""" + + global pdef + file = None + try: + fullFileName = os.path.join(dirname, filename) + file = open(fullFileName, 'r') + self.StatusBar.SetStatusText("Opened file: %s" % (filename)) + #TODO: WxPython: loadAndDisplayPdefFile - append current filename to the frame title instead showing in the StatusBar or add a widget? + pdef = PDEF() + pdef = pickle.load(file) # load pdef from file + list.hideListPanel() + print("loadDisplayPdefFile load PDEF") # DBGDBG + except IOError: + self.openError(filename, "IOError") + #except PickleError: # not defined in this Python ... + # self.openError(filename, "PickleError") + except AttributeError: + self.openError(filename, "AttributeError") + except EOFError: + self.openError(filename, "EOFError") + except ImportError: + self.openError(filename, "ImportError") + except IndexError: + self.openError(filename, "IndexError") + except: + self.openError(filename, "") + + # Note: list numbering is 1 based. If pdef.NumLists is less than 1, it must be policy type of Any + listNum = 1 + if pdef.NumLists >= listNum: + list.loadAndDisplayPlistDefFile(file, wx, pdef, self.StatusBar, self.scrollableWindow) + file.close() + self.restorePanel() + + def openError(self, file, exception): + """openError - tell user that open failed""" + self.StatusBar.SetStatusText("Open of pdef file: %s failed. Exception: %s" % (file, exception)) + print("Open of pdef file: %s failed. Exception: %s" % (file, exception)) # DBGDBG + + # + # write the current PDEF object to a file + # the policy panel should always display the PDEF object's state + # + # file format: + # Header + # memberName '=' 'value + # ... + # + def writePdefFile(self) : + """ writePdefFile - write the current PDEF object to a file""" + global dirname, filename + + try: + f = open(os.path.join(dirname, filename), 'w') + except IOError: + self.openError(filename, "IOError") + #except PickleError: # not defined in this Python ... + # self.openError(filename, "PickleError") + except AttributeError: + self.openError(filename, "AttributeError") + except EOFError: + self.openError(filename, "EOFError") + except ImportError: + self.openError(filename, "ImportError") + except IndexError: + self.openError(filename, "IndexError") + except: + self.openError(filename, "") + + pickle.dump(pdef, f) # write out the pdef object + + print("writePdefFile: file: %s" % (filename)) # DBGDBG + #print("writePdefFile: Rules=%x, PolicyType=%x PolicyControl=%x, NumLists=%x, CurrentListView=%x, MaxBiosMinVersion=%x, MaxSinitMinVersion=%x" % + # (pdef.Rules, pdef.PolicyType, pdef.PolicyControl, pdef.NumLists, pdef.CurrentListView, + # pdef.MaxBiosMinVersion, pdef.MaxSinitMinVersion)) # DBGDBG + + # Write the PLIST_DEF's + # pickle.dump of pdef should be sufficient to dump the entire structure. + f.close() + + + def checkModified(self): + """checkModified - return True if the Policy, List or Element panels were modified, else False""" + + if(pdef.Modified == True): + #print("checkModified - return PDEF was Modified" ) # DBGDBG + return True + elif(list.checkListModified(pdef) == True): + #print("checkModified - return list was Modified" ) # DBGDBG + return True + else: + #print("checkModified - return nothing Modified" ) # DBGDBG + return False + + + def showV31Gui(self, enable): + if enable: + self.ignorePsMle.Show() + self.ignorePsPconf.Show() + self.ignorePsStm.Show() + else: + self.ignorePsMle.Hide() + self.ignorePsPconf.Hide() + self.ignorePsStm.Hide() + + + def restorePanel(self): + """restorePanel - restore the policy panel""" + + print("restorePolicyPanel: Rules=%x, PolicyType=%x PolicyControl=%x, NumLists=%x, CurrentListView=%x, MaxBiosMinVersion=%x, MaxSinitMinVersion=%x" % + (pdef.Rules, pdef.PolicyType, pdef.PolicyControl, pdef.NumLists, pdef.CurrentListView, + pdef.MaxBiosMinVersion, pdef.MaxSinitMinVersion)) # DBGDBG + + if(pdef.Rules == DEFINES.PoRules): # 0=PS, 1=PO + self.poRadioButton.SetValue(True) + self.psRadioButton.SetValue(False) + self.setPoRulesMode() + else: + self.psRadioButton.SetValue(True) + self.poRadioButton.SetValue(False) + self.setPsRulesMode() + + policyversion = str(pdef.PolVersionMajor)+'.'+str(pdef.PolVersionMinor) + if policyversion in DEFINES.SUPPORTED_LCP_VERSION: + self.versionEdit.SetStringSelection(policyversion) + else: + print("Invalid Policy version number %s" %(policyversion)) + + self.biosEdit.ChangeValue(str(pdef.MaxBiosMinVersion)) + self.sinitEdit.ChangeValue(str(pdef.MaxSinitMinVersion)) + + self.minSinitVersionEdit.ChangeValue(str(pdef.SinitMinVersion)) + + if(pdef.PolicyControl & DEFINES.PolicyControlAllowNpwBitMask): + self.allowNPW.SetValue(True) + if(pdef.PolicyControl & DEFINES.PolicyControlPcr17BitMask): + self.sinitCapabilites.SetValue(True) + if(pdef.PolicyControl & DEFINES.PolicyControlForceOwnerBitMask): + if(pdef.Rules == 0): # ps rule + self.setPsRulesMode() + else: + self.setPoRulesMode() + + if(pdef.PolicyControl & DEFINES.PolicyControlAUXDeletionControl): + self.auxDelete.SetValue(True) + + policyversion = str(pdef.PolVersionMajor)+'.'+str(pdef.PolVersionMinor) + if policyversion == '3.0': + self.showV31Gui(False) + else: + self.showV31Gui(True) + + if(pdef.PolicyType == DEFINES.ANY): + self.anyRadioButton.SetValue( True ) + self.listRadioButton.SetValue( False ) + self.enableDisableListWidgets( False ) + else: + self.anyRadioButton.SetValue( False ) + self.listRadioButton.SetValue( True ) + self.enableDisableListWidgets( True ) + + + try: + # Set GUI for Hash Algorithm ComboBox + hashAlgName = (key for key,val in DEFINES.TPM_ALG_HASH.items() if (val == pdef.HashAlg)).next() + self.hashAlgEdit.SetStringSelection(hashAlgName) + except StopIteration: + self.StatusBar.SetStatusText("HashAlg=%d for Hash Algorithm is not supported" % (pdef.HashAlg)) + + try: + # Set GUI Algorithm for Auto-Promotion ComboBox + hashAlgName = (key for key,val in DEFINES.TPM_ALG_HASH_MASK.items() if (val == pdef.AuxHashAlgMask)).next() + self.algForApEdit.SetStringSelection(hashAlgName) + except StopIteration: + self.StatusBar.SetStatusText("HashAlg=%d for Auto-Promotion is not supported" % (pdef.AuxHashAlgMask)) + + checkedLCP = [] + for item in DEFINES.TPM_ALG_HASH_MASK.keys(): + if(pdef.LcpHashAlgMask & DEFINES.TPM_ALG_HASH_MASK[item]): + checkedLCP.append(item) + self.algAllowedForLcpEdit.SetCheckedStrings(checkedLCP) + + checkedSign = [] + for item in DEFINES.TPM_ALG_SIGN_MASK.keys(): + if(pdef.LcpSignAlgMask & DEFINES.TPM_ALG_SIGN_MASK[item]): + checkedSign.append(item) + self.allowedSigSchemesEdit.SetCheckedStrings(checkedSign) + + self.numOfListsEdit.ChangeValue(str(pdef.NumLists)) + self.viewListEdit.ChangeValue(str(pdef.CurrentListView)) + if(pdef.NumLists > 0): + self.deleteListButton.Enable() + self.viewListEdit.Enable() + else: + self.deleteListButton.Disable() + self.viewListEdit.Disable() + + self.biosEdit.ChangeValue(str(pdef.MaxBiosMinVersion)) + self.sinitEdit.ChangeValue(str(pdef.MaxSinitMinVersion)) + pdef.Modified = False; + + # + # save the current PDEF object to human readable textfile for printing + # the policy panel should always display the PDEF object's state + # + # file format: + # Header + # memberName '=' 'value + # ... + # + def printPdefFile(self): + """ printPdefFile - save the current PDEF object to human readable textfile for printing""" + global filename, dirname + + if(self.checkModified() == False): + self.StatusBar.SetStatusText( "Current file not modified" ) + return + else: + #wildcard = "PDEF text file (*.pdef.txt) | *.pdef.txt|" \ + # "All Files (*.*) | *.*" + #title = "Please specify a text file (.txt) to save the PDEF to. This file can be printed from your OS." + + #base = self.getBasePdefFile() + #dlg = wx.FileDialog(self, title, dirname, base, wildcard, wx.SAVE|wx.OVERWRITE_PROMPT) + + #if dlg.ShowModal() == wx.ID_OK: + # filename = dlg.GetFilename() + # dirname = dlg.GetDirectory() + self.printPdefTextFile() + # # originally, filename had no extention so strip it off keeping the user supplied base name + # filename, ext, ext1 = filename.rsplit('.', 1) + + #print("printPdefFile - done. filename=%s" % (filename)) # DBGDBG + #dlg.Destroy() + + def printPdefTextFile(self): + basefilename, ext = filename.rsplit('.', 1) + textfile = utilities.formFileName(basefilename, "pdef.txt") + self.StatusBar.SetStatusText( "Policy saved as text file: %s, which can be printed from your OS" % (textfile )) + #print("printPdefTextFile: file: %s, PDEF object: %s" % (textfile, pdef)) # DBGDBG + print("printPdefTextFile: file: %s" % (textfile)) # DBGDBG + + try: + f = open(os.path.join(dirname, textfile), 'w') + print("PDEF file: ", textfile, " written on: ", wx.Now(), file=f ) + print("\n", file=f) # for readability + + print("FileTypeSignature", " = ", pdef.FileTypeSignature, file=f) + print("DefCompany", " = ", pdef.DefCompany, file=f) + print("StructVersion", " = ", pdef.StructVersion, file=f) + print("MaxLists", " = ", pdef.MaxLists, file=f) + print("MaxElements", " = ", pdef.MaxElements, file=f) + print("MaxHashSize", " = ", pdef.MaxHashSize, file=f) + print("MaxHashes", " = ", pdef.MaxHashes, file=f) + print("MaxFileNameSize", " = ", pdef.MaxFileNameSize, file=f) + print("ToolDate", " = ", pdef.ToolDate, file=f) + print("ToolVersion", " = ", pdef.ToolVersionMajor, ".", pdef.ToolVersionMinor, sep='', file=f) # suppress separator so 2.2 + print("Rules", " = ", pdef.Rules, file=f) + print("Modified", " = ", pdef.Modified, file=f) + print("PolVersion", " = ", pdef.PolVersionMajor, ".", pdef.PolVersionMinor, sep='', file=f) # suppress separator so 1.0 + print("HashAlg", " = ", pdef.HashAlg, file=f) + print("PolicyType", " = ", pdef.PolicyType, file=f) + print("SinitMinVersion", " = ", pdef.SinitMinVersion, file=f) + print("DataRevocationCounters", " = ", pdef.DataRevocationCounters, file=f) # this is a list! + print("PolicyControl", " = ", pdef.PolicyControl, file=f) + print("MaxSinitMinVersion", " = ", pdef.MaxSinitMinVersion, file=f) + print("MaxBiosMinVersion", " = ", pdef.MaxBiosMinVersion, file=f) + print("LcpHashAlgMask", " = ", pdef.LcpHashAlgMask, file=f) + print("LcpSignAlgMask", " = ", pdef.LcpSignAlgMask, file=f) + print("AuxHashAlgMask", " = ", pdef.AuxHashAlgMask, file=f) + if(pdef.HashAlg == DEFINES.TPM_ALG_HASH_MASK['SHA256']): + print("PolicyHash", " = ", pdef.PolicyHashSha256Hex, file=f) # need to print the hex hash + elif(pdef.HashAlg == DEFINES.TPM_ALG_HASH_MASK['SHA1']): + print("PolicyHash", " = ", pdef.PolicyHashSha1Hex, file=f) # need to print the hex hash + + # make sure MM, DD, HH, MM and SS fields print as 2 digits with leading 0 ie YYMMDD and HHMMSS + month = '%02d' % (pdef.LastBuildDateStampMonth) + day = '%02d' % (pdef.LastBuildDateStampDay) + print("LastBuildDateStamp (YYYYMMDD)", " = ", pdef.LastBuildDateStampYear, month, day, sep='', file=f) + hour = '%02d' % (pdef.LastBuildTimeStampHour) + minute = '%02d' % (pdef.LastBuildTimeStampMinute) + second = '%02d' % (pdef.LastBuildTimeStampSecond) + print("LastBuildTimeStamp (HHMMSS)", " = ", hour, minute, second, sep='', file=f) + print("CurrentListView", " = ", pdef.CurrentListView, file=f) + print("NumLists", " = ", pdef.NumLists, file=f) + + # Show summary: which lists have been added + print("PolListInfo[0]", " = ", pdef.PolListInfo['0'], file=f) + print("PolListInfo[1]", " = ", pdef.PolListInfo['1'], file=f) + print("PolListInfo[2]", " = ", pdef.PolListInfo['2'], file=f) + print("PolListInfo[3]", " = ", pdef.PolListInfo['3'], file=f) + print("PolListInfo[4]", " = ", pdef.PolListInfo['4'], file=f) + print("PolListInfo[5]", " = ", pdef.PolListInfo['5'], file=f) + print("PolListInfo[6]", " = ", pdef.PolListInfo['6'], file=f) + print("PolListInfo[7]", " = ", pdef.PolListInfo['7'], file=f) + + print("\n", file=f) # for readability + + # print each PLIST_DEF that has been added + list.printPlistDefs(pdef, f) + + except IOError: + self.StatusBar.SetStatusText("IOError") + finally: + f.close() + + def updateLastBuildDateAndTimeStamps(self): + """updateLastBuildDateAndTimeStamps - update the LastBuildDateStamp and LastBuildTimeStamp pdef fields""" + + # update the LastBuild[Time,Date]Stamp's + # Get a datetime object and convert each value to its decimal equivalent + now = datetime.datetime.now() + pdef.LastBuildDateStampYear = int('%04d' % (now.year)) # YYYY as decimal + pdef.LastBuildDateStampMonth = int('%02d' % (now.month)) # MM as decimal + pdef.LastBuildDateStampDay = int('%02d' % (now.day)) # DD as decimal + pdef.LastBuildTimeStampHour = int('%02d' % (now.hour)) # HH as decimal + pdef.LastBuildTimeStampMinute = int('%02d' % (now.minute)) # MM as decimal + pdef.LastBuildTimeStampSecond = int('%02d' % (now.second)) # SS as decimal + + #print("updateLastBuildDateAndTimeStamps - YYYY=%04d, MM=%02d, DD=%02d, HH=%02d, MM=%02d, SS=%02d 00=%02d" % + # (pdef.LastBuildDateStampYear, pdef.LastBuildDateStampMonth, pdef.LastBuildDateStampDay, + # pdef.LastBuildTimeStampHour, pdef.LastBuildTimeStampMinute, + # pdef.LastBuildTimeStampSecond, pdef.LastBuildTimeStampLowByte)) # DBGDBG + + def getBasePdefFile(self): + """getBasePdefFile - get the current pdef file base or use default""" + + # use the current pdef file, if one has been specified + file = self.pdefFileName.GetValue() + if(file == 'None'): + base = "NewPlatform" + else: + base, ext = file.rsplit('.', 1) + + return(base) + +################# +## MyApp class ## +################# +class MyApp(wx.App): + + def OnInit(self): + """ onInit - wxWindows calls this method to initialize the application""" + + # Create an instance of our customized Frame class + frame = MyFrame(None, -1, "TXT Policy Generator") + frame.Show(True) + + # Tell wxWindows that this is our main window + self.SetTopWindow(frame) + + # Return a success flag + return True + +app = MyApp(0) # Create an instance of the application class +#import wx.lib.inspection +#wx.lib.inspection.InspectionTool().Show() +app.MainLoop() # Tell it to start processing events + +#TODO: Med: Open tool by double clicking a .pdef file or dropping one on the tool - WxPython book p530 + diff -Nru tboot-1.9.4/lcp-gen2/UserGuide.txt tboot-1.9.5/lcp-gen2/UserGuide.txt --- tboot-1.9.4/lcp-gen2/UserGuide.txt 1970-01-01 00:00:00.000000000 +0000 +++ tboot-1.9.5/lcp-gen2/UserGuide.txt 2016-12-17 03:19:38.000000000 +0000 @@ -0,0 +1,247 @@ +#This is a UserGuide for LCP v3 Creator + +LCP v3 Creation Tool User Guide + +1. Introduction + + This document describes how to install and use the 2nd generation of Launch Control Policy creation tool + for creating Intel® TXT launch control policies for use with TPM 2.0 family devices. + This LCP tool can be used to build one or more Policy Definition (PDEF) files and, using a PDEF file, + can create policy files for use with Intel TXT. Intel TXT launch control policy consists of NV Policy Data + stored in the TPM NVRAM and a Policy List Structure file that is stored either in the BIOS flash ROM (for + Platform Supplier policy) or in the boot directory of the target platform (for Platform Owner policy). + This tool creates/edits a Policy Definition File (PDEF). The PDEF identifies files that contain the data for + building the NV Policy Data and Data List Structure. All source data files must be in the working directory. + The GUI updates the PDEF structure and when the user selects “BUILD”, the tool creates the policy files based + on the information in the PDEF file. + + The tool allows the user to: + + - Open an existing PDEF file or create a new one. + - Save the open definition to a new file name. + - Build the NV Policy Data and Policy List Structure based on the open PDEF. + + The output files are: + + - *.txt – TPM NV Policy data in readable text format (for DOS provisioning tools) + - *.pol – TPM NV Policy data in raw format for provisioning tools that take unformatted data. + - *.dat – file that contains the associated Policy List Structure + +2. Installation + + This tool is written in Python, so Python 2.7.x installation is needed to run the tool. + Besides Python 2.7, following Python packages installation are required as well: + - python-wxpython28 + - M2Crypto + - PyAsn1 + +3. Running the tool + + The tool provides a Graphical User Interface (GUI) to edit and create the launch control policies. + The tool can be started by typing following command in a termainal from tool's working directory: + ./TxtPolicyGen2.py + +4. LCP Creation + +4.1 Menu Bar + + The menu bar of the tool provides the 3 dropdown menus: File, Build, and Help + +4.1.1 File Menu + + The FILE menu provides standard file operations of New; Open; Save; Save As; Print; Close. + • New: Resets policy to the default policy and if the current policy had been modified, it prompts + to save it to a file. + • Open: allows you to open a previously created PDEF file to modify and/or build. + • Save & Save As: allows you to save the PDEF file to the existing or a new file name respectively. + • Print: Creates an ASCII printable file of the PDEF content that can be printed. Note that this + command does NOT send the file to a printer. + • Close: Exits the program and, if there were changes, prompts to save the PDEF file. + +4.1.2 Build Menu + + The BUILD menu allows you to build the NV Policy Data file, the Policy List Structure file, or both. Note + that a policy list structure file will not be built when PDEF Policy Type is ANY. + +4.1.3 Help Menu + + The HELP menu provides information about the tool, key generation, command line options, and allows + you to open this user guide. + +4.2 Main Screen + + This screen edits the data that is to be placed in the TPM NV policy data. This tool does not write to + the TPM, but it does create the data to be written to it. Other utilities, such as the TPM2 Provisioning + tool can take this output and write the TPM NV index. + +4.2.1 Selecting Rules + + The user selects either PS Policy Rules (for Platform Supplier – OEM) or PO Policy Rules (for platform + Owner – OS/Datacenter). Various information and allowed actions will be updated based on this selection. + Selecting the appropriate rules should be done first since it affects what can be selected and/or changed + in policy definition. + +4.2.2 Min SINIT Version + + This box allows the user to specify the minimum allowed version for the SINT ACM that will be allowed to + perform a measured launch. + +4.2.3 ACM Revocation Limits + + These values allow the user to limit ACM self-revocation for the BIOS ACM and SINIT ACM. These values + specify the maximum version level that can be revoked. A value of 5 means that ACM versions up to 4 + can be revoked, however versions 5 and above cannot be revoked. Thus, a value of zero prohibits ACM + revocation and a value of 255 allows all revocations. These fields are only valid for PO Policy. + +4.2.4 Control Options + + These check boxes allow the user to select various control options. Certain options will not be available + depending on the rules selected. + +4.2.5 Policy Type + + User selects if policy is ANY or LIST. When LIST is selected, the screen displays list information and + allows the user to create up to 8 lists. Additionally, when LIST is selected, the build command will create + a policy list structure. Note that for PS policy, the policy list structure needs to be included as part of + the flash image and for PO policy, the policy list structure needs to be copied to the boot directory of the + target platform(s). + +4.2.6 Hash Algorithm + + Use this box to select the hash algorithm that will protect the policy list structure. This value is only used + if Policy Type is LIST. It is recommended that this be the strongest algorithm supported by the tool. + +4.2.7 Algorithm for Auto-Promotion + + Allows you to specify which hash algorithm the BIOS ACM uses for calculating the auto-promotion measurement. + You must select one – even when Signed SBIOS Policy is used instead of Auto-Promotion. When there are both PS + and PO policies, the selection in the PO policy takes precedence. + +4.2.8 Algorithms Allowed for Launch Control Policy + + These check boxes allow you to select various hash algorithms that may be evaluated when the SINIT ACM processes + LCP policy list structures. If an algorithm is not selected, then any element in the list using that element will + be ignored. + +4.2.9 Allowed Signature Schemes + + These check boxes allow you to select various signing schemes that will be allowed when the ACM processes policy + list structures. If an algorithm is not selected, then measurements in any list signed using that scheme will be + ignored. + +4.2.10 Adding and Removing a List + + Before you can add a list, you must select Policy Type = LIST and then click the Add List button. If this is the + first list, the window will expand to include the List dialogue. A policy may have up to 8 lists. The Number of + Lists box indicates the total number of lists. + When there is more than one list, select the list number you wish to view/edit via the View List box. + To delete a list, select the list via the View List box and click the Delete List button. + +4.2.10.1 Signing a List + + Each list may be signed or unsigned. For an unsigned list, set Signing Algorithm to “None”. Otherwise select the + desired Signing Algorithm, specify the Key Size, and then the file names for the Public and Private Keys. Changing + key size clears the key file names. Click HELP: Key Generation for information on how to generate signing keys. + +4.2.10.2 List Revocation + + This only applies to signed lists. The tool automatically increments the Revocation Count field each time the list + is successfully built (and there were changes). The Allowed box specifies the minimum Revocation Count that is + allowed (to protect against unauthorized list roll-back) and its value is populated in the corresponding TPM NV + Policy Revocation Counter array. When the Sync box is checked, the Allowed box will automatically track the Revocation + Count. The RESET button will reset the Revocation Count to 0. This should only be used for pre-production testing. + +4.2.11 Adding and Deleting an Element + + To add an element to the current list, click on the Add Element button. A dropdown menu appears and allows you to + select the element type and hash algorithm. Only one of each combination is allowed in a list. That is, a policy + may have at most one of each combination of Element Type-HashAlg. The Number of Elements box indicates the total + number of elements in the selected list. Select the element you wish to view/edit via the View Element box. + To delete an element, select the element via the View Element box and click the Delete Element button. + +4.2.11.1 SBIOS Element + + This is an element that provides a list of valid measurements for the Stat-up BIOS Code. That is, the code that + must be trusted to clear memory when there is a Reset Attack. + This element is only valid in the PS Policy and typically it is only found in signed lists. The exception is when + the element specifies only a Fallback Hash. You must specify a Fallback Hash, and if you don’t support BIOS fallback, + then specify a null hash of the appropriate size to match the hash algorithm. There is only one Fallback Hash + measurement and may be multiple SBIOS hash measurements. + The Hash File List box allows you to add or remove known good SBIOS measurements by specifying the filename of the + file containing the hash. Each time you build the PDEF, the tool will open the specified files and use their current + content to build the policy list structure. + + If there are no SBIOS elements or if none of the SBIOS elements contain any SBIOS measurements (other than the fallback + hash) then the BIOS ACM uses auto-promotion. When there is at least one SBIOS Element with at least one hash file listed, + then the BIOS ACM does not use auto-promotion. + +4.2.11.2 PCONF Element + + This is an element that provides a list of valid platform configuration measurements. Each PCONF measurement is a list + of selected PCRs and their composite hash (in a structure referred to as a PCRINFO). You will need to use a tool such + as PCRDump2 to create PCR dump files from the target platform(s). Each PCR dump file contains the PCR values for all 24 + of the PCRs (for the bank specified by its hashing algorithm). However, the tool only allows selection of the first 8 + (PCR0-7). + A PO Policy has the option to override the PS Policy. When the Override PS Policy box is checked in the PO Policy, the + SINIT ACM will not process any PCONF elements in the PS Policy and rely solely on PCONF elements in the PO Policy. + + The PCR File box allows you to add or remove known good PCONF measurements (i.e., PCRINFOs) by specifying the filename + of the PCR Dump file and selecting the PCRs to include. The PCR Selection boxes allow you to specify which PCRs are + evaluated. Click Add button to add a PCRINFO and select the PCR Dump filename. Next check the PCR Selection boxes for + the PCR numbers you wish to include and then click Apply PCR Selection. To add another PCRINFO, repeat this procedure. + Note that the information in the PCR File box indicates the selected PCRs and the PCR Dump filename. The tool allows + each PCRINFO to have a different set of selected PCRs. To remove a PCONF PCRINFO from the element, you first select i + the entry from the PCR File dropdown box and then click on Remove. When you build the PDEF, for each entry in the PCR + File list, the tool will open the specified file, generate a composite hash using the selected PCRs, and build the + PCRINFO including it in the policy list structure. + Note: If there are no PCONF elements in the PO Policy, then the SINIT ACM allows any platform configuration. + Typically, PCRINFOs in the PS Policy only specify PCR0. + +4.2.11.3 MLE Element + This is an element that provides a list of valid OS/VMM measurements. The OSV or VMV should provide a list of known good + MLE measurements. + A PO Policy has the option to override the PS Policy. When the Override PS Policy box is checked in the PO Policy, the + SINIT ACM will not process any MLE elements in the PS Policy and rely solely on MLE elements in the PO Policy. The Hash + File List box allows you to add or remove known good MLE measurements. Click Add to add a measurement by selecting the + filename of the file containing the hash. Repeat to add additional measurements. To remove an MLE measurement from the + element, select the filename from the Hash File List box and click Remove. Each time you build the PDEF, the tool will + open the specified files and use their current content to build the policy list structure. + If there are no MLE elements in the PO Policy, then the SINIT ACM allows any OS to perform the measured launch. + +4.2.11.4 STM Element + + This is an element that provides a list of valid SMM Transfer monitor (STM) measurements. The platform vendor should + provide a list of known good STM measurements. Note that this element is not used on servers and high end workstations. + A PO Policy has the option to override the PS Policy. When this box is checked, the SINIT ACM will not process any STM + elements in the PS Policy and rely solely on STM elements in the PO Policy. + The Hash File List box allows you to add or remove known good STM measurements. Click Add to add a measurement and select + the filename of the file containing the hash. Each time you build the PDEF, the tool will open the specified files and use + their current content to build the policy list structure. + To remove an STM measurement from the element, select the filename in the Hash File List box and click on Remove. + +4.2.12 Saving the Definition File + + You can save the PDEF file using the FILE tab on the menu bar. Specify an appropriate filename and the tool saves the file + with a file extension of *.pdef in your tool working directory. + +4.2.13 Opening a Definition File + + You can open a saved PDEF file using the FILE tab on the menu bar. Click OPEN and select the filename. + +4.2.14 Generating Policy files + + First open the desired PDEF file and, from the BUILD tab on the menu bar, select if you want to build either the NV + Policy, the Policy Data File, or both. The tool will generate the NV Policy data in 2 different formats (for various + provisioning tools - .dat & .txt) and builds the policy list structure as .dat. + +Troubleshooting + +- The tool can only be run from its working directory +- It is preferred to run the tool as a non-root user +- Create a new PDEF before editing the policy in tool's GUI + + + + + + diff -Nru tboot-1.9.4/lcp-gen2/util.py tboot-1.9.5/lcp-gen2/util.py --- tboot-1.9.4/lcp-gen2/util.py 1970-01-01 00:00:00.000000000 +0000 +++ tboot-1.9.5/lcp-gen2/util.py 2016-12-17 03:19:38.000000000 +0000 @@ -0,0 +1,925 @@ +#!/usr/bin/python +# Copyright (c) 2013, Intel Corporation. All rights reserved. + +# using print() built infunction, disable print statement +from __future__ import print_function + +try: + import os, sys +except ImportError: + raise ImportError, "import OS failed" + +from defines import DEFINES +from struct import pack, unpack +import array +import M2Crypto + +from asn1spec import * + +# utility routines +class UTILS( object ): + + def checkFileTag(self, file, expectedTag): + """checkFileTag - Return True if the specified file starts with the specified tag, else False""" + + # expectedTag either: + # PCRD+TAG = "PCRD" for .pcr files + # HASH_TAG = "HASH" for .hash files + # read the 1st 4 bytes from the file (i.e. the actualTag) and compare that to the expectedTag + # + tagLength = 4 + myFile = open(file, "rb") + actualTag = myFile.read(tagLength) + myFile.close() + #print("UTILS::checkFileTag: file=%s expectedTag=%s actualTag=%s" % (file, expectedTag, actualTag)) # DBGDBG + + if(actualTag == expectedTag): + return True + else: + return False + + def invalidHashFileMsg(self, file, actHashAlg, expHashAlg, hashFileLength): + """invalidHashFileMsg - display status bar msg if hash file is invalid""" + + print ("Invalid hash format for this element's HashAlg. file %s, Exp Alg=%d, Act Alg=%d, Length=%d" % + (file, expHashAlg, actHashAlg, hashFileLength)) + + # Some functions, such as Wx's ListBox.ChangeValue() takes a string + # But the data is stored as a list of strins + # so form a single string containing everything in list + def formStringFromListOfStrings(self, list): + """formStringFromListOfStrings - return a single string formed from a list of strings""" + + string = '' + index = 0 + for eachString in list: + if(index != 0): # if not the 1st entry, need a LF before the new entry + string += "\n" + string += eachString + index += 1 + #print("thisString=%s, string=%s" % (eachString, string)) + + return string + + def formFileName(self, base, ext): + """formFileName - return name formed from base.ext""" + + seperator = '.' + filenameList = [base, ext] + return(seperator.join(filenameList)) + + + # return True if file verified and key was extracted, else False + def verifyKeyFile(self, file, type, currentList): + """verifyKeyFile - verify the key file and extract the key""" + + # Need currentList.KeySize and currentList.PubKeyQx + key = self.getKeyFromFile(file, type) + expectedKeySize = int(currentList.KeySize) / 8 + + if type == DEFINES.KEY_FILE_TYPE['PUBLIC_ECDSA']: + # ECC public key is two value of the key size + match = len(key) == expectedKeySize *2 + if match: + # key is flipped for little endian so the latter half is the Qx + currentList.PubKeyQx = key[expectedKeySize:expectedKeySize*2] + currentList.PubKeyQy = key[0:expectedKeySize] + + elif type == DEFINES.KEY_FILE_TYPE['PUBLIC_RSASSA']: + match = len(key) == expectedKeySize + if match: + currentList.PubKeyData = key + else: + keylength = len(key) + match = len(key) == expectedKeySize + + if not match: + print("Key size mismatch actual=%d expected=%d" %(len(key), expectedKeySize)) + #if(type == KEY_FILE_TYPE_PRIVATE): + # expectedHeader = "-----BEGIN RSA PRIVATE KEY-----" + # expectedFooter = "-----END RSA PRIVATE KEY-----" + # expectedType = "Private" + #elif(type == KEY_FILE_TYPE_PUBLIC): + # expectedHeader = "-----BEGIN PUBLIC KEY-----" + # expectedFooter = "-----END PUBLIC KEY-----" + # expectedType = "Public" + #else: + # print("invalid key file parameter = %d specified" % (type)) # DBGDBG + # return False + # + #expHdrLen = len(expectedHeader) + #try: + # f = open(file, "rb") + # actualHeader = f.read(expHdrLen) + #except: + # self.StatusBar.SetStatusText("Error opening key file %s" % (file)) + # # open failed, can't close + # return False + # + #if(actualHeader == expectedHeader): + # self.StatusBar.SetStatusText("") # clear any previous error msgs + #else: + # self.StatusBar.SetStatusText("File %s is not a %s key file. Expected header %s" % (file, expectedType, expectedHeader)) + # f.close() + # return False + # + ## key file header is OK + ## read the rest of the file, including line endings + ## then strip out the line endings and the footer + ## Expect Unix style line emdings: 0x0A" per openssl .pem format + ## but also handle Windows style line endings: 0x0D, 0x0A + ## max file length for keySize=3072 is <3072 since could have different + ## number of characters on each line and different len endings (0A or 0D0A) + ## just don't want to read in a [potentially very large] user specified file size + #maxLength = 3072 + #f.seek (0, os.SEEK_END) + #actualFileSize = f.tell() - expHdrLen - 1 # size of the rest of the file + #if(actualFileSize < maxLength): + # maxLength = actualFileSize + # + ## read the base64 encoded data from the key file into a binary string + #f.seek (expHdrLen+1, os.SEEK_SET) # back to just after the header + #try: + # rawData = f.read(maxLength) + #except: + # self.StatusBar.SetStatusText("Error reading key data from file %s" % (file)) + # f.close() + # return False + # + ##print("verifyKeyFile: read %d bytes:\n%s" % (len(rawData), rawData)) # DBGDBG + ##print("verifyKeyFile: read %d" % (len(rawData))) # DBGDBG + ## Verify the footer + #if expectedFooter in rawData: + # self.StatusBar.SetStatusText("") # clear any previous error msgs + #else: + # self.StatusBar.SetStatusText("File %s is not a %s key file. Expected footer %s" % + # (file, expectedType, expectedFooter)) + # f.close() + # return False + # + ## strip off the footer + #footerPos = rawData.find('-') # find 1st '-' + #rawData = rawData[0:footerPos-1] + ##print("verifyKeyFile: w/o footer %d bytes:\n%s" % (len(rawData), rawData)) # DBGDBG + ##print("verifyKeyFile: w/o footer %d bytes" % (len(rawData))) # DBGDBG + # + ## Verify that the file matches the current KeySize + ## + ## Key File sizes: 1024 2048 3072 for key + footer incl. LR/CR + ## public file range: 240-260 420-440 590-610 + ## private file range: 850-870 1640-1685 2390-2430 + ## + #keySize = self.keySizeEdit.GetValue() + ##print("verifyKeyFile: keySize = %s, type = %s, .pem's length = %d" % (keySize, expectedType, maxLength)) # DBGDBG + #currentList = self.pdef.getCurrentListObject() + #misMatch = False + #if(expectedType == "Public"): + # if(keySize == "1024"): + # if not ((240 <= maxLength) and (maxLength <= 260)): + # print("verifyKeyFile: Public key file, size not 1024!") # DBGDBG + # misMatch = True + # elif(keySize == "2048"): + # if not ((420 <= maxLength) and (maxLength <= 440)): + # print("verifyKeyFile: Public key file, size not 2048!") # DBGDBG + # misMatch = True + # elif(keySize == "3072"): + # if not ((590 <= maxLength) and (maxLength <= 610)): + # print("verifyKeyFile: Public key file, size not 3072!") # DBGDBG + # misMatch = True + # if(misMatch == True): + # self.StatusBar.SetStatusText("Key size mismatch. File %s is not %s." % (file, keySize)) + # self.pubKeyFileEdit.SetValue("") + # f.close() + # return False + # else: + # keyData = self.decodePublicKeyModulus(file, keySize, expectedHeader, expectedFooter) + # currentList.PubKeyData = keyData # save the public key modulus + # #print("verifyKeyFile: Public Key. Length: %d. Data:\n%s" % (len(keyData), currentList.PubKeyData)) # DBGDBG + # + #elif(expectedType == "Private"): + # if(keySize == "1024"): + # if not ((850 <= maxLength) and (maxLength <= 870)): + # print("verifyKeyFile: Private key file, size not 1024!") # DBGDBG + # misMatch = True + # elif(keySize == "2048"): + # if not ((1640 <= maxLength) and (maxLength <= 1685)): + # print("verifyKeyFile: Private key file, size not 20481") # DBGDBG + # misMatch = True + # elif(keySize == "3072"): + # if not ((2390 <= maxLength) and (maxLength <= 2430)): + # print("verifyKeyFile: Private key file, size not 3072!") # DBGDBG + # misMatch = True + # if(misMatch == True): + # self.StatusBar.SetStatusText("Key size mismatch. File %s is not %s." % (file, keySize)) + # self.pvtKeyFileEdit.SetValue("") + # f.close() + # return False + # # Note: Don't need to save the private key data, pycrypto reads it from the file directly + # + #f.close() + return match + + + # Verify that the file is a valid HASH_FILE with a HASH_TAG, hashAlg and hashSize + # [with 1 or more SHA1 hashes] - legacy support from the TPM1.2 LCP1 Spec + # or a raw data file [i.e. no header] with ONLY 1 20 bit SHA1 or 32 bit SHA256 hash + # + # if OK, return a list containing: [True, HashFileModeXXX] defined in defines.py + # else return a list containing: [False, HashFileModeNull] + # if file format or length is invalid + # or if the length indicates the hash does not correspond to the elements.HashAlg + # + #TODO: Bill: verifyHashFile- LCP2 spec deletes the HASH_FILE struct def for files with multiple hashes?? + #TODO: Bill: verifyHashFile- still supporting files with multiple SHA1 hashes [with the hdr] or raw SHA1 or 256 files + # + def verifyHashFile(self, file, hashAlg): + """verifyHashFile - return a list indicating if the file is valid and its type""" + + # HASH_FILE's are structured as: + # - SHA1 or SHA256 hash data only, for raw SHA1 or SHA256 files with 1 hash + # - SHA1 hash files with a header [defined below] containing 1 or more SHA1 hashes + # + # Where the header is: + # HASH_TAG = 0x48534148 = "HASH" + # typedef struct { + # UINT32 tag HASH_TAG; # 4 bytes "HASH" + # UINT8 hashAlg ; # 1 byte SHA1_ALG = 4 + # UINT8 hashSize ; # 1 byte SHA1 = 20 + # UINT8 reserve[10] ; # 12 bytes + # SHA1 - SHA256 hash ; # 20 bytes + # } HASH_FILE; # ________ + # File Size # 36 bytes + # read the 1st 4 bytes from the file (i.e. the actualTag) and compare that to the expectedTag + # + function = "verifyHashFile" + mode = DEFINES.HashFileMode['RawSHA256'] # default + + hashFileLengthHdrSha1 = 36 # header + SHA1 hash data + hashFileLengthRawSha1 = DEFINES.DIGEST_SIZE['SHA1'] # raw hash files have only the hash data, no header + hashFileLengthRawSha256 = DEFINES.DIGEST_SIZE['SHA256'] + #hashFileLengthRawSha384 = 48 + #hashFileLengthRawSha512 = 64 + + try: + f = open(file, "rb") + except: + print("Error opening hash file %s" % (file)) + return [False, DEFINES.HashFileMode['HdrNull']] + + try: + hashAlgStr = (key for key,val in DEFINES.TPM_ALG_HASH.items() if hashAlg == val).next() + if hashAlgStr == 'SHA1_LEGACY': + hashAlgStr = 'SHA1' + except StopIteration: + print("Unsupported hash algorithm (%d)" %(hashAlg)) + return [False, DEFINES.HashFileMode['HdrNull']] + + # + # check the file size to determine the type of file being read + # + f.seek (0, os.SEEK_END) + actualSize = f.tell() + + if(actualSize == hashFileLengthHdrSha1): + mode = DEFINES.HashFileMode['HdrSHA1'] + hashFileLength = hashFileLengthHdrSha1 + + # read the data + # + f.seek (0, os.SEEK_SET) # back to the begininng + data = array.array ("B") # Load file into data array + try: + data.fromfile (f, hashFileLength) + except: + print ("Error reading hash from file %s" % (file)) + f.close() + return [False, DEFINES.HashFileMode['HdrNull']] + + if(hashAlg != DEFINES.TPM_ALG_HASH['SHA1'] and hashAlg != DEFINES.TPM_ALG_HASH['SHA1_LEGACY']): + self.invalidHashFileMsg(file, hashAlg, DEFINES.TPM_ALG_HASH['SHA1'], hashFileLength) + return [False, DEFINES.HashFileMode['HdrNull']] + + expectedHashTag = "HASH" # 0x48415348 + expectedSha1HashAlg = 4 # '\x04' + expectedSha1HashSize = 20 # '\x14' + + actualHashTag = data[0:4].tostring() # 0:3 inclusive = 0:4 exclusive of 4 + actualHashAlg = data[4] + actualHashSize = data[5] + + if(actualHashTag != expectedHashTag): + # check if a raw file matching the element's HashAlg length + print ("File: %s invalid tag = %s, expected %s" % (file, actualHashTag, expectedHashTag)) + return [False, DEFINES.HashFileMode['HdrNull']] + + if(actualHashAlg != expectedSha1HashAlg): + print ("File: %s invalid hashAlg = 0x%x, expected 0x%x" % + (file, actualHashAlg, expectedSha1HashAlg)) + return [False, DEFINES.HashFileMode['HdrNull']] + + if(actualHashSize != expectedSha1HashSize): + print ("File: %s invalid hashSize = 0x%x, expected 0x%x" % + (file, actualHashSize, expectedSha1HashSize)) + return [False, DEFINES.HashFileMode['HdrNull']] + + elif actualSize == DEFINES.DIGEST_SIZE[hashAlgStr]: + modeStr = 'Raw' + hashAlgStr + mode = DEFINES.HashFileMode[modeStr] + hashFileLength = DEFINES.DIGEST_SIZE[hashAlgStr] + else: + self.invalidHashFileMsg(file, hashAlg, DEFINES.TPM_ALG_HASH[hashAlgStr], actualSize) + print ("File: %s invalid size = %d, expected %d" % (file, actualSize, DEFINES.DIGEST_SIZE[hashAlgStr])) + return [False, DEFINES.HashFileMode['HdrNull']] + + print("verifyHashFile - HashAlg=%d, Mode=%d, Len=%d" % (hashAlg, mode, hashFileLength)) # DBGDBG + + f.close() + # handle SHA1 files with headers + #if(mode == DEFINES.HashFileMode['HdrSHA1']): + # + #else: + # print("verifyHashFile - Error: invalid mode = %d, aborting." % (mode)) + # return [False, DEFINES.HashFileMode['HdrNull']] + + return [True, mode] + + + # Determine the type of and validate the pcrFile, except for the numHashes field + # This includes checking that the file's type and hashAlg matches the element's expected HashAlg + # Return [True, PcrFileModePcrXShaYYY if ok, see defines.py + # [False, PcrFileModeNull] othewise + # + def verifyPcrFile(self, file, elementExpAlg): + """verifyPcrFile - Validate the pcrFile""" + + # 2 types of PCR dump files are supported: PCRD and PCR2 + # PCR Dump File format + # typedef struct { + # UINT32 tag PCRD_TAG; # 4 bytes "PCRD" = 0x44524350 + # UINT8 hashAlg ; # 1 byte SHA1_ALG = 4 SHA256_ALG = 0x0b + # UINT8 hashSize ; # 1 byte SHA1 = 20 SHA256 = 32 + # UINT8 numHashes ; # 1 byte number of hashes in the file + # UINT8 reserve[9] ; # 9 bytes + # SHA1 pcrs[24] ; # 20 bytes * numHashes + # } HASH_FILE; # ________ + # File Size # 16 + (NumHashes * HashSize) bytes + # Typically all 24 PCRs included so size for SHA1 = 16 + 24*20 = 496 = 0x1f0 + # LCP tool only requires the 1st 8 PCRs, if they are selected via pcr0to7SelectionBitMask + # I.e. if the bit mask 0-7 = 1 then that PCR is required + # + + # - PCR2 PCR dump File format - from App. C.1.2 + # typedef struct { + # UINT32 tag PCR2_TAG; # 4 bytes "PCR2" = 0x32524350 + # UINT16 hashAlg ; # 2 bytes TPM_ALG_SHAXXXXX + # UINT8 count ; # 1 byte number of valid digests + # UINT8 reserve ; # 1 byte + # UINT16 size ; # 2 bytes size of hash + # union { + # HASH20 pcrs[24] ; # 20 bytes * 24 of which count are used per the pcrSelection mash + # HASH32 pcrs[24] ; # 32 bytes * 24 of which count are used per the pcrSelection mash + # } HASH_FILE; # ________ + # File Size # 8 + (count * HashSize) bytes, assuming no holes in the mask + function = "verifyPcrFile" + expectedPcrdTag = "PCRD" # 0x44524350 + expectedPcr2Tag = "PCR2" # 0x32524350 + + try: + f = open(file, "rb") + except: + print ("Error opening PCR data file %s" % (file)) + return [False, DEFINES.PcrFileMode['Null']] + + # Determine if this is a PCRD or PCR2 file + # Based on the type, ensure the file's HaskAlg matches the element's ExpAlg + f.seek (0, os.SEEK_SET) # back to the begininng + data = array.array ("B") # Load file into data array + try: + data.fromfile (f, DEFINES.PCRFileMinHdrSize) + except: + print ("Error reading PCR data from file %s" % (file)) + f.close() + return [False, DEFINES.PcrFileMode['Null']] + + try: + elementExpAlgStr = (key for key,val in DEFINES.TPM_ALG_HASH.items() if val == elementExpAlg).next() + except StopIteration: + print ("Unsupported hash algorithm %d" %(elementExpAlg)) + + fileHashTag = data[0:4].tostring() # 0:3 inclusive = 0:4 exclusive of 4 + numHashes = data[6] # PCRD 'numHashes' same as PCR2 'count' + fileType = DEFINES.PcrFileMode['Null'] + if(fileHashTag == expectedPcrdTag): # PCRD file + fileType = DEFINES.PcrFileMode['PcrdSHA1'] + fileActualHashAlg = data[4] # HashAlg is a UINT8 + if(elementExpAlg != DEFINES.TPM_ALG_HASH['SHA1']): + print ("%s file %s SHA1 hash algorithm does not match the PCONF element's expected algorithm: 0x%x" % + (expectedPcrdTag, file, elementExpAlg)) + return [False, DEFINES.PcrFileMode['Pcrd']] + else: + actAlg = DEFINES.TPM_ALG_HASH['SHA1'] # LCP2 PCRD format only supports SHA1 per C.1.1 + minFileLength = DEFINES.PCRDFileHdrSize + (8*DEFINES.DIGEST_SIZE['SHA1']) # min PCRD SHA1 file has 8 hash's + + elif(fileHashTag == expectedPcr2Tag): # PCR2 file + # HashAlg in [4:5] is little endian so for current algs high byte=data[5]=0 and low byte=hashAlg + fileActualHashAlg = unpack('= %d" % (file, actualFileSize, minFileLength)) + f.close() + return [False, DEFINES.PcrFileMode['Null']] + + # file looks ok, except for the numHashes field which is checked by build.hashPcrInfoFromFile() when it reads the data + # can't check that yet since don't know which PCRs will be selected + f.close() + return [True, fileType] + + # Verify that the pcr file contains the expected number of pcr hashes + # Return True if ok or if no PCR's are selected, else return False + # + # file - is the specified pcr file + # fileType - indicates the type of PCR data file per the PcrFileModeXXXXX defines + # pcr0to7SelectionBitMask - is a mask indicating the selected PCRs + # + def verifyPcrInfoNumHashes(self, file, fileType, hashAlg, pcr0to7SelectionBitMask): + """verifyPcrInfoNumHashes - verify the pcr file contains enough hashes""" + function = "verifyPcrInfoNumHashes" + + # check for case when no PCR's were selected + # nothing to hash in that case + if(pcr0to7SelectionBitMask == 0): + print("Warning: No PCR was selected. Nothing to hash: pcr0to7SelectionBitMask=0") + print ("Note: No PCR was selected. If desired, select PCR's and click 'Apply PCR Selection'") + return True + + try: + hashAlgStr = (key for key,val in DEFINES.TPM_ALG_HASH.items() if val == hashAlg).next() + except StopIteration: + print("verifyPcrInfoNumHashes - invalid fileType=%x hash alg!!!" % (file, fileType, hashAlg)) # Should NEVER get here + + if(fileType == DEFINES.PcrFileMode['Pcrd']): + minFileLength = DEFINES.PCRDFileHdrSize + (8*DEFINES.DIGEST_SIZE['SHA1']) # min PCRD SHA1 file has 8 hash's + elif(fileType == DEFINES.PcrFileMode['Pcr2']): + minFileLength = DEFINES.PCR2FileHdrSize + (8*DEFINES.DIGEST_SIZE[hashAlgStr]) # min PCR2 SHA1 file has 8 hash's + else: + print("verifyPcrInfoNumHashes - invalid fileType=%x!!!" % (file, fileType)) # Should NEVER get here + + print("verifyPcrInfoNumHashes %s, type %d, pcr0to7SelectionBitMask=0x%x" % (file, fileType, pcr0to7SelectionBitMask)) # DBGDBG + try: + f = open(file, "rb") + except: + print ("Error opening PCR data file %s" % (file)) + return False + + f.seek (0, os.SEEK_END) + actualFileSize = f.tell () + f.seek (0, os.SEEK_SET) # back to the begininng + data = array.array ("B") # Load file into data array + try: + data.fromfile (f, minFileLength) + except: + print ("Error reading PCR data from file %s" % (file)) + f.close() + return False + + f.close() + numHashes = data[6] # same for both PCRD and PCR2 files + + # now that we have NumHashes, check the actual file size + #print("verifyPcrInfoNumHashes - numHashes=%x" % (numHashes)) # DBGDBG + if(numHashes == 0): + print ("File: %s invalid numHashes = 0" % (file)) + return False + + if(fileType == DEFINES.PcrFileMode['Pcrd']): + expectedFileSize = DEFINES.PCRDFileHdrSize + (numHashes * DEFINES.DIGEST_SIZE['SHA1']) + elif(fileType == DEFINES.PcrFileMode['Pcr2']): + expectedFileSize = DEFINES.PCR2FileHdrSize + (numHashes * DEFINES.DIGEST_SIZE[hashAlgStr]) + else: + print("verifyPcrInfoNumHashes - invalid fileType=%d" % (fileType)) # DBGDBG Should NEVER get here + return False + + if(actualFileSize < expectedFileSize): + print ("File: %s invalid File size = 0x%x=%i, expected 0x%x" % + (file, actualFileSize, actualFileSize, expectedFileSize)) + return False + + # verify that numHashes >= the largest selected hash + # must have at least that many hashes in the PCR dump file + #print("verifyPcrInfoNumHashes - verify numHashes are in the file") # DBGDBG + mask = 0x80 + bit = 8 + while(bit > 0): + if(mask & pcr0to7SelectionBitMask): + break # found the largest selected PCR + else: + bit -= 1 + mask >>= 1 + + if(bit > numHashes): # not enough hashes in the PCR dump file, abort + print ("Too few hashes in PCR dump file: %s, numHashes = 0x%x, but max selected hash = 0x%x" % + (file, numHashes, bit)) + return False + + return True + + + # Get hash data from the specified file and return it using global _GlobalHashData + # Note: no file format checking is done here as files were validated when added to the list + # Return False if the hash couldn't be extracted, else return True + # + def getHashFromFile(self, file, hashAlg): + """getHashFromFile - validate the hash file and extract the hash data""" + + global _GlobalHashData + + print("getHashFromFile - file %s, HashAlg=%d" % (file, hashAlg)) # DBGDBG + result = self.verifyHashFile(file, hashAlg) + # verifyHashFile() returns a list with [status, fileType] + fileType = result[1] + if(result[0] == False): + return [] # should have detected this when file was selected + fileType = result[1] + data = array.array ("B") # Load file into data array + + try: + hashAlgStr = (key for key,val in DEFINES.TPM_ALG_HASH.items() if hashAlg == val).next() + except StopIteration: + print("Unsupported hash algorithm (%d)" %(hashAlg)) + + if(fileType == DEFINES.HashFileMode['HdrNull']): + print("getHashFromFile - Error: invalid mode = %d, aborting." % (result[1])) + return [] + elif(fileType == DEFINES.HashFileMode['HdrSHA1']): + hashFileLength = 36 + elif(fileType in DEFINES.HashFileMode.values()): # All other raw modes + hashFileLength = DEFINES.DIGEST_SIZE[hashAlgStr] + else: + print("getHashFromFile - Error: invalid mode = %d, aborting." % (result[1])) + return [] + + try: + f = open(file, "rb") + f.seek (0, os.SEEK_SET) # beginning of file + data.fromfile (f, hashFileLength) + except: + print("getHashFromFile - Error reading hash from file %s" % (file)) + f.close() + return [] + + f.close() + #print("getHashFromFile - data = %s, len=%d" % (data, len(data))) # DBGDBG + + # handle all the flavors of hash files + if(fileType == DEFINES.HashFileMode['HdrSHA1']): + _GlobalHashData = data[16:36].tolist() # 20 bytes 16:36 exclusive + print("getHashFromFile: %s, Hdr tag=%s alg=%i, size=%i, hash=%s, len=%d" % + (file, data[0:4].tostring(), data[4], data[5], _GlobalHashData, len(_GlobalHashData))) # DBGDBG + else: + _GlobalHashData = data.tolist() + assert len(data) == DEFINES.DIGEST_SIZE[hashAlgStr], "Error: File size (%d bytes) mismatch with %s size (%d bytes)" %(len(data), hashAlgStr, DEFINES.DIGEST_SIZE[hashAlgStr]) + print("getHashFromFile: %s, raw %s hash=%s, len=%d" % (file, hashAlgStr, _GlobalHashData, len(_GlobalHashData))) # DBGDBG + + return _GlobalHashData; + + # Get the specified PCR data (indicated by the thisPcr mask) + # Return False if couldn't read the hashes from the PCR file + # othewise return True + # + # file - is the specified pcr file + # fileType - indicates the type of PCR data file per the PcrFileModeXXXXX defines + # thisPcr - the specified PCR data to find [0 < thisPcr < 8] + # hashSize - is the size of the pcr data to extract + # + def getPcrInfoFromFile(self, file, fileType, thisPcr, hashSize, statusBar): + """getPcrInfoFromFile - get the pcr data from the specified file""" + + global _GlobalPcrHash + + if(fileType == DEFINES.PcrFileMode['Pcrd']): + hdrSize = DEFINES.PCRDFileHdrSize + elif(fileType == DEFINES.PcrFileMode['Pcr2']): + hdrSize = DEFINES.PCR2FileHdrSize + else: + print("verifyPcrInfoNumHashes - invalid fileType=%d" % (fileType)) # DBGDBG Should NEVER get here + return False + + #print("getPcrInfoFromFile %s type %d, pcr %d, hashSize=%d" % (file, fileType, thisPcr, hashSize)) # DBGDBG + pcrData = array.array ("B") + try: + f = open(file, "rb") + except: + print("getPcrInfoFromFile: open of file %s failed" % (file)) # should never get here, file's been opened for verif. earlier + return False + + # read TPM1 or TPM2 PCR tag to determine the file format to use? + tag = f.read(4) + + # read the selected pcr's hash data + if tag == 'PCR2': + # PCR2 file format + pos = hdrSize + (thisPcr * (hashSize + 2)) # There's a 2 byte size field precedes each PCR value. + f.seek (pos, os.SEEK_SET) + # Read the size of the PCR value and compare to the expected hash size + size = f.read(2) + pcrSize = unpack("= the largest selected hash + # must have at least that many hashes in the PCR dump file + mask = 0x80 + bit = 8 + while(bit > 0): + if(mask & pcr0to7SelectionBitMask): + break # found the largest selected PCR + else: + bit -= 1 + mask >>= 1 + + if(bit > numHashes): # not enough hashes in the PCR dump file, abort + print ("Too few hashes in PCR dump file: %s, numHashes = 0x%x, but max selected hash = 0x%x" % + (file, numHashes, bit)) + return False + + # file looks ok, get the data + temp = array.array ("B") # temp array + hashLength = expectedPcrHashSize + numSelectedPcrs = 0 + + mask = 0x01 + bit = 0 + pos = 0 + while(bit < 8): + if(mask & pcr0to7SelectionBitMask): + if tag == 'PCR2': + pos = pcrStartPos + 2 + bit * (2 + hashLength) + elif tag == 'PCRD': + pos = pcrStartPos + bit * hashLength + + temp += data[pos:pos+hashLength] + numSelectedPcrs += 1 + print("hashPcrInfoFromFile - Read hash %d, mask 0x%x from file %s, select=0x%x, numSelectedPcrs=%d, len(temp)=%d" % + (bit, mask, file, pcr0to7SelectionBitMask, numSelectedPcrs, len(temp))) # DBGDBG + + mask <<= 1 + bit += 1 + pos += hashLength + + #print("hashPcrInfoFromFile TypeOf: tempList=%s, tempList[0]=%s, _GlobalPcrHash=%s, _GlobalPcrHash[0]=%s" % + # (type(tempList), type(tempList[0]), type(_GlobalPcrHash), type(_GlobalPcrHash[0]))) # DBGDBG + #pcrHash = hashlib.sha1() + hashAlg = header[4] # TODO: is hashAlg determined by GUI or from PCR file. + hashAlgStr = None + try: + hashAlgStr = (key for key,val in DEFINES.TPM_ALG_HASH.items() if hashAlg == val).next() + except StopIteration: + print ("Error unsupported hash algorithm (%d)" %(hashAlg)) + + # Set hash algorithm + pcrHash = None + if 'SM3' in hashAlgStr: + pcrHash = sm3() + else: + pcrHash = M2Crypto.EVP.MessageDigest(hashAlgStr.lower()) + + if tag == 'PCR2': + pcrHash.update(temp) + elif tag == 'PCRD': + #pcrHash = hashlib.sha1() + pcrHash = M2Crypto.EVP.MessageDigest('sha1') + # The PCR composite hash consists of: TPM_PCR_COMPOSITE structure + # UINT16 sizeOfSelect # BigEndian = 00 03 + # UINT8 pcr_select[3] + # UINT32 valueSize # BigEndian = 20 * NumberOfSelectedHashes + # UINT8 pcrValue[] # all the selected PCR hashes + data = pack("L", valueSize) # Note '>' for BigEndian packing of valueSize + pcrHash.update(data) + # pack pcrValue[] + pcrHash.update(temp) + + # hash.digest() Returns the digest of the strings passed to the update() method so far. + # This is a string of digest_size bytes [which may contain non-ASCII characters, including null bytes] + # Note: cannot pass this string thru struct.pack() which takes ints + _GlobalPcrHash = pcrHash.digest() + + #print("hashPcrInfoFromFile: %s, Generated hash: Length=%d HexData=%s " % + # (file, hashLength, pcrHash.hexdigest())) # DBGDBG + + return _GlobalPcrHash + + + def getKeyFromFile(self, file, type): + # Read the key file from the + with open(file, 'rb') as kf: + mb = M2Crypto.BIO.MemoryBuffer(kf.read()) + + kf.close() + pem = mb.getvalue() + pem_lines = pem.split('\n') + key = None + # Find line index of BEGIN and END header/footer + der = '' + foundbegin = False + for line in pem_lines: + if ('END' in line) and ('PUBLIC' in line or 'PRIVATE' in line): + break + if foundbegin: + der += line.strip() + if ('BEGIN' in line) and ('PUBLIC' in line or 'PRIVATE' in line): + foundbegin = True + + try: # in case ASN1 can't decode the ASN1 notation.. + if type == DEFINES.KEY_FILE_TYPE['PRIVATE_RSASSA']: + asn, substrate = der_decoder.decode(der.decode('base64'), asn1Spec=RSAPrivateKey()) + rsapvt = asn.getComponentByName('privateExponent') # returns univ.Integer() + octet = univ.OctetString(hexValue=format(int(rsapvt), '0x')) # convert to Octet + key = octet.asOctets() + elif type == DEFINES.KEY_FILE_TYPE['PUBLIC_RSASSA']: + # This decodes DER encoded ASN1 public key + asn, substrate = der_decoder.decode(der.decode('base64'), asn1Spec=SubjectPublicKeyInfo()) + bits = asn.getComponentByName('subjectPublicKey') + + # second level decode for RSAPublicKey() + bits_string = ''.join(map(str, bits)) + octet = univ.OctetString(binValue=bits_string) + + rsaasn, substrate = der_decoder.decode(octet.asOctets(), asn1Spec=RSAPublicKey()) + rsapub = rsaasn.getComponentByName('modulus') # returns univ.Integer() + octet = univ.OctetString(hexValue=format(int(rsapub), '0x')) # convert to Octet + key = octet.asOctets() + + elif type == DEFINES.KEY_FILE_TYPE['PRIVATE_ECDSA']: + asn, substrate = der_decoder.decode(der.decode('base64'), asn1Spec=ECPrivateKey()) + ecpvt = asn.getComponentByName('privateKey') # returns univ.OctetString() + key = ecpvt.asOctets() + + elif type == DEFINES.KEY_FILE_TYPE['PUBLIC_ECDSA']: + # This decodes DER encoded ASN1 public key + asn, substrate = der_decoder.decode(der.decode('base64'), asn1Spec=SubjectPublicKeyInfo()) + bits = asn.getComponentByName('subjectPublicKey') # returns univ.BitString() + + # DSAPublicKey is Integer() so no decoding is needed, but need to remove the prefix 0x04. + bits_string = ''.join(map(str, bits[8:])) # the first byte specifies the compress alg? + octet = univ.OctetString(binValue=bits_string) + key = octet.asOctets() + + except Exception as ex: + print ("Exception: unable to decode pem file") + print (ex) + + if key != None: + keyLE = key[::-1] # little endian + else: + keyLE = '' + + return keyLE + + + # the last function in the file doesn't show up in the scope list in Understand for some reason! + def stub(self): + pass diff -Nru tboot-1.9.4/tboot/20_linux_tboot tboot-1.9.5/tboot/20_linux_tboot --- tboot-1.9.4/tboot/20_linux_tboot 2016-08-06 12:51:16.000000000 +0000 +++ tboot-1.9.5/tboot/20_linux_tboot 2016-12-20 22:29:15.000000000 +0000 @@ -199,7 +199,7 @@ tboot_dirname=`dirname ${current_tboot}` rel_tboot_dirname=`make_system_path_relative_to_its_root $tboot_dirname` # tboot_version=`echo $tboot_basename | sed -e "s,.gz$,,g;s,^tboot-,,g"` - tboot_version="1.9.4" + tboot_version="1.9.5" echo "submenu \"tboot ${tboot_version}\" {" while [ "x$list" != "x" ] ; do linux=`version_find_latest $list` diff -Nru tboot-1.9.4/tboot/20_linux_xen_tboot tboot-1.9.5/tboot/20_linux_xen_tboot --- tboot-1.9.4/tboot/20_linux_xen_tboot 2016-08-06 12:51:16.000000000 +0000 +++ tboot-1.9.5/tboot/20_linux_xen_tboot 2016-12-20 22:29:54.000000000 +0000 @@ -214,7 +214,7 @@ tboot_basename=`basename ${current_tboot}` tboot_dirname=`dirname ${current_tboot}` rel_tboot_dirname=`make_system_path_relative_to_its_root $tboot_dirname` - tboot_version="1.9.4" + tboot_version="1.9.5" list="${linux_list}" echo "submenu \"Xen ${xen_version}\" \"Tboot ${tboot_version}\"{" while [ "x$list" != "x" ] ; do diff -Nru tboot-1.9.4/tboot/common/boot.S tboot-1.9.5/tboot/common/boot.S --- tboot-1.9.4/tboot/common/boot.S 2016-08-06 12:51:16.000000000 +0000 +++ tboot-1.9.5/tboot/common/boot.S 2016-12-17 03:19:38.000000000 +0000 @@ -68,6 +68,7 @@ .section ".tboot_multiboot_header","w" .align 4 /* multiboot header */ +multiboot_header: #define MULTIBOOT_HEADER_FLAGS (MULTIBOOT_HEADER_MODS_ALIGNED | \ MULTIBOOT_HEADER_WANT_MEMORY) /* magic number for multiboot header */ @@ -95,7 +96,6 @@ ENTRY(start) ENTRY(_start) -ENTRY(_stext) jmp __start diff -Nru tboot-1.9.4/tboot/common/elf.c tboot-1.9.5/tboot/common/elf.c --- tboot-1.9.4/tboot/common/elf.c 2016-08-06 12:51:16.000000000 +0000 +++ tboot-1.9.5/tboot/common/elf.c 2016-12-17 03:19:38.000000000 +0000 @@ -145,9 +145,7 @@ return false; } -#if 0 -static bool get_elf_image_range(const elf_header_t *elf, void **start, - void **end) +bool get_elf_image_range(const elf_header_t *elf, void **start, void **end) { uint32_t u_start, u_end; @@ -188,7 +186,6 @@ return true; } } -#endif bool expand_elf_image(const void *image, void **entry_point) { diff -Nru tboot-1.9.4/tboot/common/linux.c tboot-1.9.5/tboot/common/linux.c --- tboot-1.9.4/tboot/common/linux.c 2016-08-06 12:51:16.000000000 +0000 +++ tboot-1.9.5/tboot/common/linux.c 2016-12-17 03:19:38.000000000 +0000 @@ -307,6 +307,9 @@ printk(TBOOT_INFO"Linux cmdline placed in header: "); printk_long(kernel_cmdline); printk(TBOOT_INFO"\n"); + + memset((void *)hdr->cmd_line_ptr,0,TBOOT_KERNEL_CMDLINE_SIZE); + memcpy((void *)hdr->cmd_line_ptr, kernel_cmdline, strlen(kernel_cmdline)); /* need to put boot_params in real mode area so it gets mapped */ diff -Nru tboot-1.9.4/tboot/common/loader.c tboot-1.9.5/tboot/common/loader.c --- tboot-1.9.4/tboot/common/loader.c 2016-08-06 12:51:16.000000000 +0000 +++ tboot-1.9.5/tboot/common/loader.c 2016-12-17 03:19:38.000000000 +0000 @@ -3,6 +3,7 @@ * binaries * * Copyright (c) 2006-2013, Intel Corporation + * Copyright (c) 2016 Real-Time Systems GmbH * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -55,6 +56,7 @@ #include #include #include +#include /* copy of kernel/VMM command line so that can append 'tboot=0x1234' */ static char *new_cmdline = (char *)TBOOT_KERNEL_CMDLINE_ADDR; @@ -64,7 +66,7 @@ /* multiboot struct saved so that post_launch() can use it (in tboot.c) */ extern loader_ctx *g_ldr_ctx; - +extern bool get_elf_image_range(const elf_header_t *elf, void **start, void **end); extern bool is_elf_image(const void *image, size_t size); extern bool expand_elf_image(const elf_header_t *elf, void **entry_point); extern bool expand_linux_image(const void *linux_image, size_t linux_size, @@ -769,6 +771,104 @@ return PAGE_UP(end); } +/* + * Move all mbi components/modules/mbi to end of memory + */ +static bool move_modules_to_high_memory(loader_ctx *lctx) +{ + uint64_t max_ram_base = 0, + max_ram_size = 0; + uint32_t memRequired = 0; + + uint32_t module_count = get_module_count(lctx); + + for ( unsigned int i = 0; i < module_count; i++ ) + { + module_t *m = get_module(lctx,i); + memRequired += PAGE_UP(m->mod_end - m->mod_start); + } + + get_highest_sized_ram(memRequired, 0x100000000ULL, &max_ram_base, &max_ram_size); + if(!max_ram_base || !max_ram_size) + { + printk(TBOOT_INFO"ERROR No suitable memory area found for image relocation!\n"); + printk(TBOOT_INFO"required 0x%X\n", memRequired); + return false; + } + + printk(TBOOT_INFO"highest suitable area @ 0x%llX (size 0x%llX)\n", max_ram_base, max_ram_size); + + unsigned long target_addr = PAGE_DOWN(max_ram_base + max_ram_size); + + for ( unsigned int i = 0; i < module_count; i++ ) + { + unsigned long base, size; + module_t *m = get_module(lctx,i); + base = m->mod_start; + size = m->mod_end - m->mod_start; + printk(TBOOT_INFO"moving module %u (%lu bytes) from 0x%08X ", i, size, (uint32_t)base); + + //calculate target addresses + target_addr = PAGE_DOWN(target_addr - size); + printk(TBOOT_INFO"to 0x%08X\n", (uint32_t)target_addr); + + memcpy((void *)target_addr, (void *)base, size); + m->mod_start = target_addr; + m->mod_end = target_addr + size; + } + + return true; +} + +/* + * Move any mbi components/modules/mbi that just above the kernel + */ +static bool move_modules_above_elf_kernel(loader_ctx *lctx, elf_header_t *kernel_image) +{ + if (LOADER_CTX_BAD(lctx)) + return false; + + /* get end address of loaded elf image */ + void *elf_start=NULL, *elf_end=NULL; + if ( !get_elf_image_range(kernel_image, &elf_start, &elf_end) ) + { + printk(TBOOT_INFO"ERROR: failed tget elf image range\n"); + } + + printk(TBOOT_INFO"ELF kernel top is at 0x%X\n", (uint32_t)elf_end); + + uint32_t target_addr = (uint32_t)elf_end; + + /* stay above tboot if elf kernel is loaded below tboot */ + if ( target_addr < get_tboot_mem_end() ) + target_addr = get_tboot_mem_end(); + + /* keep modules page aligned */ + target_addr = PAGE_UP(target_addr); + + uint32_t module_count = get_module_count(lctx); + + for ( unsigned int i = 0; i < module_count; i++ ) + { + unsigned long base, size; + module_t *m = get_module(lctx,i); + base = m->mod_start; + size = m->mod_end - m->mod_start; + printk(TBOOT_INFO"moving module %u (%lu bytes) from 0x%08X ", i, size, (uint32_t)base); + + //calculate target addresses + printk(TBOOT_INFO"to 0x%08X\n", (uint32_t)target_addr); + + memcpy((void *)target_addr, (void *)base, size); + m->mod_start = target_addr; + m->mod_end = target_addr + size; + + target_addr = PAGE_UP(target_addr + size); + } + + return true; +} + static void fixup_modules(loader_ctx *lctx, size_t offset) { unsigned int module_count = get_module_count(lctx); @@ -1194,6 +1294,18 @@ void *kernel_entry_point; uint32_t mb_type = MB_NONE; + + if (g_tpm_family != TPM_IF_20_CRB ) { + if (!release_locality(g_tpm->cur_loc)) + printk(TBOOT_ERR"Release TPM FIFO locality %d failed \n", g_tpm->cur_loc); + } + else { + if (!tpm_relinquish_locality_crb(g_tpm->cur_loc)) + printk(TBOOT_ERR"Relinquish TPM CRB locality %d failed \n", g_tpm->cur_loc); + if (!tpm_workaround_crb()) + printk(TBOOT_ERR"CRB workaround failed \n"); + } + if ( !verify_loader_context(g_ldr_ctx) ) return false; @@ -1244,6 +1356,11 @@ /* fix for GRUB2, which may load modules into memory before tboot */ move_modules(g_ldr_ctx); + + /* move modules out of the way (to top og memory below 4G) */ + printk(TBOOT_INFO"move modules to high memory\n"); + if(!move_modules_to_high_memory(g_ldr_ctx)) + return false; } else { printk(TBOOT_INFO"assuming kernel is Linux format\n"); @@ -1262,6 +1379,11 @@ if ( !expand_elf_image((elf_header_t *)kernel_image, &kernel_entry_point) ) return false; + + /* move modules on top of expanded kernel */ + if(!move_modules_above_elf_kernel(g_ldr_ctx, (elf_header_t *)kernel_image)) + return false; + printk(TBOOT_INFO"transfering control to kernel @%p...\n", kernel_entry_point); /* (optionally) pause when transferring to kernel */ @@ -1272,9 +1394,18 @@ MB_MAGIC : MB2_LOADER_MAGIC); } else if ( kernel_type == LINUX ) { - m = get_module(g_ldr_ctx,0); - void *initrd_image = (void *)m->mod_start; - size_t initrd_size = m->mod_end - m->mod_start; + void *initrd_image; + size_t initrd_size; + + if ( get_module_count(g_ldr_ctx) == 0 ) { + initrd_size = 0; + initrd_image = 0; + } + else { + m = get_module(g_ldr_ctx,0); + initrd_image = (void *)m->mod_start; + initrd_size = m->mod_end - m->mod_start; + } expand_linux_image(kernel_image, kernel_size, initrd_image, initrd_size, diff -Nru tboot-1.9.4/tboot/common/lz.c tboot-1.9.5/tboot/common/lz.c --- tboot-1.9.4/tboot/common/lz.c 2016-08-06 12:51:16.000000000 +0000 +++ tboot-1.9.5/tboot/common/lz.c 2016-12-17 03:19:38.000000000 +0000 @@ -113,7 +113,7 @@ * _LZ_WriteVarSize() - Write unsigned integer with variable number of * bytes depending on value. *************************************************************************/ - +/*will write at most 5 bytes to buf*/ static int _LZ_WriteVarSize( unsigned int x, char * buf ) { unsigned int y; @@ -184,10 +184,12 @@ * out - Output (compressed) buffer. This buffer must be 0.4% larger * than the input buffer, plus one byte. * insize - Number of input bytes. -* The function returns the size of the compressed data. +* outsize - Number of bytes that can be stored in the output buffer. +* The function returns the size of the compressed data or (-1) if there +* is insufficient space in the output buffer. *************************************************************************/ -int LZ_Compress( char *in, char *out, unsigned int insize ) +int LZ_Compress( char *in, char *out, unsigned int insize, unsigned int outsize) { char marker, symbol; unsigned int inpos, outpos, bytesleft, i; @@ -202,6 +204,11 @@ return 0; } + if( outsize < 1 ) + { + return -1; + } + /* Create histogram */ for( i = 0; i < 256; ++ i ) { @@ -271,6 +278,9 @@ ((bestlength == 6) && (bestoffset <= 0x001fffff)) || ((bestlength == 7) && (bestoffset <= 0x0fffffff)) ) { + if( (outpos + 1 + 5 + 5) > outsize ) + return -1; + out[ outpos ++ ] = (char) marker; outpos += _LZ_WriteVarSize( bestlength, &out[ outpos ] ); outpos += _LZ_WriteVarSize( bestoffset, &out[ outpos ] ); @@ -279,6 +289,9 @@ } else { + if( (outpos + 2) > outsize ) + return -1; + /* Output single byte (or two bytes if marker byte) */ symbol = in[ inpos ++ ]; out[ outpos ++ ] = symbol; @@ -292,6 +305,9 @@ while( bytesleft > 3 ); /* Dump remaining bytes, if any */ + if( (outpos + bytesleft*2) > outsize ) + return -1; + while( inpos < insize ) { if( in[ inpos ] == marker ) @@ -315,9 +331,12 @@ * out - Output (uncompressed) buffer. This buffer must be large * enough to hold the uncompressed data. * insize - Number of input bytes. +* outsize - Number of bytes that can be stored in the output buffer. +* The function returns the size of the uncompressed data or (-1) if there +* is insufficient space in the output buffer. *************************************************************************/ -void LZ_Uncompress( char *in, char *out, unsigned int insize ) +int LZ_Uncompress( char *in, char *out, unsigned int insize, unsigned int outsize ) { char marker, symbol; unsigned int i, inpos, outpos, length, offset; @@ -325,7 +344,7 @@ /* Do we have anything to uncompress? */ if( insize < 1 ) { - return; + return -1; } /* Get marker symbol from input stream */ @@ -336,6 +355,8 @@ outpos = 0; do { + if( outpos >= outsize ) + return -1; symbol = in[ inpos ++ ]; if( symbol == marker ) { @@ -352,6 +373,8 @@ inpos += _LZ_ReadVarSize( &length, &in[ inpos ] ); inpos += _LZ_ReadVarSize( &offset, &in[ inpos ] ); + if( outpos + length > outsize ) + return -1; /* Copy corresponding data from history window */ for( i = 0; i < length; ++ i ) { @@ -367,4 +390,6 @@ } } while( inpos < insize ); + + return outpos; } diff -Nru tboot-1.9.4/tboot/common/policy.c tboot-1.9.5/tboot/common/policy.c --- tboot-1.9.4/tboot/common/policy.c 2016-08-06 12:51:16.000000000 +0000 +++ tboot-1.9.5/tboot/common/policy.c 2016-12-17 03:19:38.000000000 +0000 @@ -444,7 +444,7 @@ case TB_EXTPOL_AGILE: { - hash_list_t img_hl; + hash_list_t img_hl, final_hl; if ( !g_tpm->hash(g_tpm, 2, (const unsigned char *)cmdline, strlen(cmdline), hl) ) { if ( !g_tpm->hash(g_tpm, 2, base, size, hl) ) @@ -464,8 +464,17 @@ copy_hash((tb_hash_t *)buf + get_hash_size(hl->entries[i].alg), &img_hl.entries[j].hash, hl->entries[i].alg); if ( !g_tpm->hash(g_tpm, 2, buf, - 2*get_hash_size(hl->entries[i].alg), hl) ) + 2*get_hash_size(hl->entries[i].alg), &final_hl) ) return false; + + for (unsigned int k=0; kentries[i].alg == final_hl.entries[k].alg) { + copy_hash(&hl->entries[i].hash, + &final_hl.entries[k].hash, + hl->entries[i].alg); + break; + } + } break; } diff -Nru tboot-1.9.4/tboot/common/printk.c tboot-1.9.5/tboot/common/printk.c --- tboot-1.9.4/tboot/common/printk.c 2016-08-06 12:51:16.000000000 +0000 +++ tboot-1.9.5/tboot/common/printk.c 2016-12-17 03:19:38.000000000 +0000 @@ -91,32 +91,64 @@ /* allocate a 32K temp buffer for compressed log */ static char buf[32*1024]; char *out=buf; - uint32_t zip_size; + int zip_size; + uint32_t zip_pos; + bool log_reset_flag; if ( g_log == NULL || count > g_log->max_size ) return; - /* do a compression of the log if curr_pos + count > max_size */ - if (g_log->curr_pos + count > g_log->max_size) { - zip_size = LZ_Compress(&g_log->buf[g_log->zip_pos[g_log->zip_count]], out, g_log->curr_pos - g_log->zip_pos[g_log->zip_count]); - if ((g_log->zip_pos[g_log->zip_count] + zip_size + count < g_log->max_size) && (g_log->zip_count < ZIP_COUNT_MAX)) { - memcpy(&g_log->buf[g_log->zip_pos[g_log->zip_count]], out, zip_size); - g_log->zip_size[g_log->zip_count] = zip_size; - g_log->zip_count++; - g_log->zip_pos[g_log->zip_count] = g_log->zip_pos[g_log->zip_count - 1] + zip_size; - g_log->curr_pos = g_log->zip_pos[g_log->zip_count]; - if (g_log->buf[g_log->zip_pos[g_log->zip_count] - 1] !='\0') - g_log->buf[g_log->zip_pos[g_log->zip_count]] = '\0'; - else { - g_log->zip_pos[g_log->zip_count]--; - g_log->curr_pos--; + /* Check if there is space for the new string and a null terminator */ + if (g_log->curr_pos + count + 1> g_log->max_size) { + + /* If there are space issues, only then log will be reset */ + log_reset_flag = false; + + /* Check if there is space to add another compressed chunk */ + if(g_log->zip_count >= ZIP_COUNT_MAX) + log_reset_flag = true; + else{ + /* Get the start position of the new compressed chunk */ + zip_pos = g_log->zip_pos[g_log->zip_count]; + + /* Compress the last part of the log buffer that is not compressed, + and put the compressed output in out (buf) */ + zip_size = LZ_Compress(&g_log->buf[zip_pos], out, (g_log->curr_pos - zip_pos), sizeof(buf) ); + + /* Check if buf was large enough for LZ_compress to succeed */ + if( zip_size < 0 ) + log_reset_flag = true; + else{ + /* Check if there is space to add the compressed string, the + new string and a null terminator to the log */ + if( (zip_pos + zip_size + count + 1) > g_log->max_size ) + log_reset_flag = true; + else{ + /* Add the new compressed chunk to the log buffer, + over-writing the last part of the log that was just + compressed */ + memcpy(&g_log->buf[zip_pos], out, zip_size); + g_log->zip_size[g_log->zip_count] = zip_size; + g_log->zip_count++; + g_log->curr_pos = zip_pos + zip_size; + + /* Set a NULL ending */ + g_log->buf[g_log->curr_pos] ='\0'; + + /* Only if there is space to add another compressed chunk, + prepare its start position. */ + if( g_log->zip_count < ZIP_COUNT_MAX ) + g_log->zip_pos[g_log->zip_count] = g_log->curr_pos; + } } } - else { - g_log->curr_pos = 0; - for ( uint8_t i = 0; i < ZIP_COUNT_MAX; i++ ) g_log->zip_pos[i] = 0; - for ( uint8_t i = 0; i < ZIP_COUNT_MAX; i++ ) g_log->zip_size[i] = 0; - g_log->zip_count = 0; + + /* There was some space-shortage problem. Reset the log. */ + if ( log_reset_flag ){ + g_log->curr_pos = 0; + for( uint8_t i = 0; i < ZIP_COUNT_MAX; i++ ) g_log->zip_pos[i] = 0; + for( uint8_t i = 0; i < ZIP_COUNT_MAX; i++ ) g_log->zip_size[i] = 0; + g_log->zip_count = 0; } } diff -Nru tboot-1.9.4/tboot/common/tboot.c tboot-1.9.5/tboot/common/tboot.c --- tboot-1.9.4/tboot/common/tboot.c 2016-08-06 12:51:18.000000000 +0000 +++ tboot-1.9.5/tboot/common/tboot.c 2016-12-17 03:19:38.000000000 +0000 @@ -378,6 +378,10 @@ if ( !copy_e820_map(g_ldr_ctx) ) apply_policy(TB_ERR_FATAL); } + /* make TPM ready for measured launch */ + if (!tpm_detect()) + apply_policy(TB_ERR_TPM_NOT_READY); + /* we need to make sure this is a (TXT-) capable platform before using */ /* any of the features, incl. those required to check if the environment */ /* has already been launched */ @@ -390,12 +394,9 @@ apply_policy(TB_ERR_SINIT_NOT_PRESENT); if (!verify_acmod(g_sinit)) apply_policy(TB_ERR_ACMOD_VERIFY_FAILED); - } + } - /* make TPM ready for measured launch */ - if (!tpm_detect()) - apply_policy(TB_ERR_TPM_NOT_READY); /* read tboot verified launch control policy from TPM-NV (will use default if none in TPM-NV) */ err = set_policy(); @@ -551,14 +552,22 @@ cpu_relax(); /* ensure localities 0, 1 are inactive (in case kernel used them) */ - + /* request TPM current locality to be active */ if (g_tpm_family != TPM_IF_20_CRB ) { - release_locality(0); - release_locality(1); + if (!release_locality(0)) + printk(TBOOT_ERR"Release TPM FIFO locality 0 failed \n"); + if (!release_locality(1)) + printk(TBOOT_ERR"Release TPM FIFO locality 1 failed \n"); + if (!tpm_wait_cmd_ready(g_tpm->cur_loc)) + printk(TBOOT_ERR"Request TPM FIFO locality %d failed \n", g_tpm->cur_loc); } else { - tpm_relinquish_locality_crb(0); - tpm_relinquish_locality_crb(1); + if (!tpm_relinquish_locality_crb(0)) + printk(TBOOT_ERR"Release TPM CRB locality 0 failed \n"); + if (!tpm_relinquish_locality_crb(1)) + printk(TBOOT_ERR"Release TPM CRB locality 1 failed \n"); + if (!tpm_request_locality_crb(g_tpm->cur_loc)) + printk(TBOOT_ERR"Request TPM CRB locality %d failed \n", g_tpm->cur_loc); } if ( _tboot_shared.shutdown_type == TB_SHUTDOWN_S3 ) { @@ -567,7 +576,7 @@ /* save kernel/VMM resume vector for sealing */ g_post_k_s3_state.kernel_s3_resume_vector = _tboot_shared.acpi_sinfo.kernel_s3_resume_vector; - + /* create and seal memory integrity measurement */ if ( !seal_post_k_state() ) apply_policy(TB_ERR_S3_INTEGRITY); /* OK to leave key in memory on failure since if user cared they diff -Nru tboot-1.9.4/tboot/common/tboot.lds.x tboot-1.9.5/tboot/common/tboot.lds.x --- tboot-1.9.4/tboot/common/tboot.lds.x 2016-08-06 12:51:18.000000000 +0000 +++ tboot-1.9.5/tboot/common/tboot.lds.x 2016-12-17 03:19:38.000000000 +0000 @@ -25,16 +25,12 @@ . = ALIGN(4096); *(.mlept) - _stext = .; /* text */ _mle_start = .; /* beginning of MLE pages */ - *(.text) *(.fixup) *(.gnu.warning) } :text = 0x9090 - _etext = .; /* end of text section */ - .rodata : { *(.rodata) *(.rodata.*) } . = ALIGN(4096); diff -Nru tboot-1.9.4/tboot/common/tpm.c tboot-1.9.5/tboot/common/tpm.c --- tboot-1.9.4/tboot/common/tpm.c 2016-08-06 12:51:18.000000000 +0000 +++ tboot-1.9.5/tboot/common/tpm.c 2016-12-17 03:19:38.000000000 +0000 @@ -300,7 +300,7 @@ } -static bool tpm_wait_cmd_ready(uint32_t locality) +bool tpm_wait_cmd_ready(uint32_t locality) { uint32_t i; tpm_reg_access_t reg_acc; @@ -801,6 +801,30 @@ } +bool tpm_workaround_crb(void) +{ + tpm_reg_ctrl_cmdsize_t CmdSize; + tpm_reg_ctrl_cmdaddr_t CmdAddr; + tpm_reg_ctrl_rspsize_t RspSize; + tpm_reg_ctrl_rspaddr_t RspAddr; + u32 locality = 0; + + if (!tpm_request_locality_crb(locality)) + return false; + + CmdAddr.cmdladdr = TPM_LOCALITY_CRB_BASE_N(locality) | TPM_CRB_DATA_BUFFER; + CmdAddr.cmdhaddr = 0; + RspAddr.rspaddr = TPM_LOCALITY_CRB_BASE_N(locality) | TPM_CRB_DATA_BUFFER; + CmdSize.cmdsize = TPMCRBBUF_LEN; + RspSize.rspsize = TPMCRBBUF_LEN; + + write_tpm_reg(locality, TPM_CRB_CTRL_CMD_ADDR, &CmdAddr); + write_tpm_reg(locality, TPM_CRB_CTRL_CMD_SIZE, &CmdSize); + write_tpm_reg(locality, TPM_CRB_CTRL_RSP_ADDR, &RspAddr); + write_tpm_reg(locality, TPM_CRB_CTRL_RSP_SIZE, &RspSize); + + return true; +} bool tpm_detect(void) { diff -Nru tboot-1.9.4/tboot/Config.mk tboot-1.9.5/tboot/Config.mk --- tboot-1.9.4/tboot/Config.mk 2016-08-06 12:51:16.000000000 +0000 +++ tboot-1.9.5/tboot/Config.mk 2016-12-17 03:19:38.000000000 +0000 @@ -33,7 +33,7 @@ CFLAGS += $(call cc-option,$(CC),-fno-stack-check,) # changeset variable for banner -CFLAGS += -DTBOOT_CHANGESET=\""$(shell ((hg parents --template "{isodate|isodate} {rev}:{node|short}" >/dev/null && hg parents --template "{isodate|isodate} {rev}:{node|short}") || echo "2016-05-18 12:00 -0800 1.9.4") 2>/dev/null)"\" +CFLAGS += -DTBOOT_CHANGESET=\""$(shell ((hg parents --template "{isodate|isodate} {rev}:{node|short}" >/dev/null && hg parents --template "{isodate|isodate} {rev}:{node|short}") || echo "2016-12-16 12:00 -0800 1.9.5") 2>/dev/null)"\" AFLAGS += -D__ASSEMBLY__ diff -Nru tboot-1.9.4/tboot/include/linux_defns.h tboot-1.9.5/tboot/include/linux_defns.h --- tboot-1.9.4/tboot/include/linux_defns.h 2016-08-06 12:51:18.000000000 +0000 +++ tboot-1.9.5/tboot/include/linux_defns.h 2016-12-17 03:19:38.000000000 +0000 @@ -84,14 +84,16 @@ uint32_t ramdisk_size; /* initrd size (set by boot loader) */ uint32_t bootsect_kludge;/* DO NOT USE - for bootsect.S use only */ uint16_t heap_end_ptr; /* Free memory after setup end */ - uint16_t pad1; /* Unused */ + uint8_t ext_loader_ver; /* Boot Protocol: 2.02+ */ + uint8_t ext_loader_type;/* Boot Protocol: 2.02+ */ uint32_t cmd_line_ptr; /* 32-bit pointer to the kernel command line */ uint32_t initrd_addr_max;/* Highest legal initrd address */ uint32_t kernel_alignment; /* Physical addr alignment required for kernel */ uint8_t relocatable_kernel; /* Whether kernel is relocatable or not */ - uint8_t pad2[3]; /* Unused */ + uint8_t min_alignment; /* Boot Protocol: 2.10+ */ + uint16_t xloadflags; /* Boot Protocol: 2.12+ */ uint32_t cmdline_size; /* Maximum size of the kernel command line */ uint32_t hardware_subarch; /* Hardware subarchitecture */ @@ -99,6 +101,9 @@ uint32_t payload_offset; uint32_t payload_length; uint64_t setup_data; + uint64_t pref_address; + uint32_t init_size; + uint32_t handover_offset; } linux_kernel_header_t; typedef struct __attribute__ ((packed)) { diff -Nru tboot-1.9.4/tboot/include/lz.h tboot-1.9.5/tboot/include/lz.h --- tboot-1.9.4/tboot/include/lz.h 2016-08-06 12:51:18.000000000 +0000 +++ tboot-1.9.5/tboot/include/lz.h 2016-12-17 03:19:38.000000000 +0000 @@ -41,8 +41,8 @@ * Function prototypes *************************************************************************/ -int LZ_Compress( char *in, char *out, unsigned int insize ); -void LZ_Uncompress( char *in, char *out, unsigned int insize ); +int LZ_Compress( char *in, char *out, unsigned int insize, unsigned int outsize ); +int LZ_Uncompress( char *in, char *out, unsigned int insize, unsigned int outsize ); #ifdef __cplusplus diff -Nru tboot-1.9.4/tboot/include/tpm.h tboot-1.9.5/tboot/include/tpm.h --- tboot-1.9.4/tboot/include/tpm.h 2016-08-06 12:51:18.000000000 +0000 +++ tboot-1.9.5/tboot/include/tpm.h 2016-12-17 03:19:38.000000000 +0000 @@ -492,8 +492,11 @@ extern void tpm_print(struct tpm_if *ti); extern bool tpm_submit_cmd(u32 locality, u8 *in, u32 in_size, u8 *out, u32 *out_size); extern bool tpm_submit_cmd_crb(u32 locality, u8 *in, u32 in_size, u8 *out, u32 *out_size); +extern bool tpm_wait_cmd_ready(uint32_t locality); +extern bool tpm_request_locality_crb(uint32_t locality); extern bool tpm_relinquish_locality_crb(uint32_t locality); extern bool txt_is_launched(void); +extern bool tpm_workaround_crb(void); //#define TPM_UNIT_TEST 1 diff -Nru tboot-1.9.4/tboot/txt/heap.c tboot-1.9.5/tboot/txt/heap.c --- tboot-1.9.4/tboot/txt/heap.c 2016-08-06 12:51:18.000000000 +0000 +++ tboot-1.9.5/tboot/txt/heap.c 2016-12-17 03:19:38.000000000 +0000 @@ -257,13 +257,15 @@ printk(TBOOT_DETA"\t\t\t Event:\n"); printk(TBOOT_DETA"\t\t\t PCRIndex: %u\n", *((uint32_t *)next)); - if ( *((uint32_t *)next) > 24 ) { - printk(TBOOT_DETA"\t\t\t Wrong Event Log.\n"); - return; - } - + + if ( *((uint32_t *)next) > 24 && *((uint32_t *)next) != 0xFF ) { + printk(TBOOT_DETA"\t\t\t Wrong Event Log.\n"); + return; + } + next += sizeof(uint32_t); printk(TBOOT_DETA"\t\t\t Type: 0x%x\n", *((uint32_t *)next)); + if ( *((uint32_t *)next) > 0xFFF ) { printk(TBOOT_DETA"\t\t\t Wrong Event Log.\n"); return; @@ -302,7 +304,7 @@ printk(TBOOT_DETA"\t\t\t Log Descrption:\n"); printk(TBOOT_DETA"\t\t\t Alg: %u\n", log_descr->alg); printk(TBOOT_DETA"\t\t\t Size: %u\n", log_descr->size); - printk(TBOOT_DETA"\t\t\t EventsOffset: [%u,%u)\n", + printk(TBOOT_DETA"\t\t\t EventsOffset: [%u,%u]\n", log_descr->pcr_events_offset, log_descr->next_event_offset); @@ -317,10 +319,26 @@ return; void *curr, *next; - curr = (void *)(unsigned long)log_descr->phys_addr + + + curr = (void *)(unsigned long)log_descr->phys_addr + log_descr->pcr_events_offset; next = (void *)(unsigned long)log_descr->phys_addr + log_descr->next_event_offset; + + //It is required for each of the non-SHA1 event log the first entry to be the following + //TPM1.2 style TCG_PCR_EVENT record specifying type of the log: + //TCG_PCR_EVENT.PCRIndex = 0 + //TCG_PCR_EVENT.EventType = 0x03 // EV_NO_ACTION per TCG EFI + // Platform specification + //TCG_PCR_EVENT.Digest = {00…00} // 20 zeros + //TCG_PCR_EVENT.EventDataSize = sizeof(TCG_LOG_DESCRIPTOR). + //TCG_PCR_EVENT.EventData = TCG_LOG_DESCRIPTOR + //The digest of this record MUST NOT be extended into any PCR. + + if (log_descr->alg != TB_HALG_SHA1){ + print_event_2(curr, TB_HALG_SHA1); + curr += sizeof(tpm12_pcr_event_t) + sizeof(tpm20_log_descr_t); + } while ( curr < next ) { print_event_2(curr, log_descr->alg); diff -Nru tboot-1.9.4/tboot/txt/txt.c tboot-1.9.5/tboot/txt/txt.c --- tboot-1.9.4/tboot/txt/txt.c 2016-08-06 12:51:18.000000000 +0000 +++ tboot-1.9.5/tboot/txt/txt.c 2016-12-17 03:19:38.000000000 +0000 @@ -240,12 +240,6 @@ evt_log->event_log_descr[i].size = 4096; evt_log->event_log_descr[i].pcr_events_offset = 0; evt_log->event_log_descr[i].next_event_offset = 0; - if (g_tpm->algs_banks[i] != TB_HALG_SHA1) { - evt_log->event_log_descr[i].pcr_events_offset = - 32 + sizeof(tpm20_log_descr_t); - evt_log->event_log_descr[i].next_event_offset = - 32 + sizeof(tpm20_log_descr_t); - } } break; case TB_EXTPOL_EMBEDDED: @@ -256,12 +250,6 @@ evt_log->event_log_descr[i].size = 4096; evt_log->event_log_descr[i].pcr_events_offset = 0; evt_log->event_log_descr[i].next_event_offset = 0; - if (g_tpm->algs[i] != TB_HALG_SHA1) { - evt_log->event_log_descr[i].pcr_events_offset = - 32 + sizeof(tpm20_log_descr_t); - evt_log->event_log_descr[i].next_event_offset = - 32 + sizeof(tpm20_log_descr_t); - } } break; case TB_EXTPOL_FIXED: @@ -271,12 +259,6 @@ evt_log->event_log_descr[0].size = 4096; evt_log->event_log_descr[0].pcr_events_offset = 0; evt_log->event_log_descr[0].next_event_offset = 0; - if (g_tpm->cur_alg != TB_HALG_SHA1) { - evt_log->event_log_descr[0].pcr_events_offset = - 32 + sizeof(tpm20_log_descr_t); - evt_log->event_log_descr[0].next_event_offset = - 32 + sizeof(tpm20_log_descr_t); - } break; default: return; @@ -361,6 +343,11 @@ *((u64 *)(&next)) = log_descr->phys_addr + log_descr->next_event_offset; + if ( log_descr->alg != TB_HALG_SHA1 ) { + print_event_2(curr, TB_HALG_SHA1); + curr += sizeof(tpm12_pcr_event_t) + sizeof(tpm20_log_descr_t); + } + while ( curr < next ) { print_event_2(curr, log_descr->alg); data_size = *(uint32_t *)(curr + 2*sizeof(uint32_t) + hash_size); @@ -398,7 +385,7 @@ *((u32 *)next) = type; next += sizeof(u32); memcpy((uint8_t *)next, hash, hash_size); - next += hash_size/sizeof(uint32_t); + next += hash_size; *((u32 *)next) = 0; cur_desc->next_event_offset += 3*sizeof(uint32_t) + hash_size; diff -Nru tboot-1.9.4/utils/txt-stat.c tboot-1.9.5/utils/txt-stat.c --- tboot-1.9.4/utils/txt-stat.c 2016-08-06 12:51:18.000000000 +0000 +++ tboot-1.9.5/utils/txt-stat.c 2016-12-17 03:19:38.000000000 +0000 @@ -243,12 +243,20 @@ /* to uncompress tboot log */ if (log->zip_count > 0) { for ( i = 0; i< log->zip_count; i++) { - LZ_Uncompress(&log_buf[log->zip_pos[i]], out, log->zip_size[i]); + int length = LZ_Uncompress(&log_buf[log->zip_pos[i]], out, log->zip_size[i], sizeof(pbuf)); + if ( length < 0 ) + continue; /* log is too big for single printk(), so break it up */ /* print out the uncompressed log */ - for ( unsigned int curr_pos = 0; curr_pos < 32*1024; curr_pos += sizeof(buf)-1 ) { - strncpy(buf, out + curr_pos, sizeof(buf)-1); - buf[sizeof(buf)-1] = '\0'; + for ( int curr_pos = 0; curr_pos < length; curr_pos += sizeof(buf)-1 ) { + if ( length - curr_pos >= (int)sizeof(buf) - 1 ) { + strncpy(buf, out + curr_pos, sizeof(buf)-1); + buf[sizeof(buf)-1] = '\0'; + } + else { + strncpy(buf, out + curr_pos, length - curr_pos); + buf[length - curr_pos] = '\0'; + } printf("%s", buf); } }