Skip to content

Commit

Permalink
utils: add function to generate an EK
Browse files Browse the repository at this point in the history
Signed-off-by: Erik Larsson <who+github@cnackers.org>
  • Loading branch information
whooo committed Dec 6, 2021
1 parent ba2dd5c commit d16411f
Show file tree
Hide file tree
Showing 2 changed files with 223 additions and 0 deletions.
95 changes: 95 additions & 0 deletions test/test_utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -430,6 +430,101 @@ def test_tpm_export_rsa_child_rsa_parent_with_inner_key(self):
hashes.SHA256(),
)

def test_create_ek_ecc(self):
ecc_template = create_ek_template(self.ectx)
_, ecc, _, _, _ = self.ectx.create_primary(
TPM2B_SENSITIVE_CREATE(), ecc_template, ESYS_TR.ENDORSEMENT
)

self.assertEqual(ecc.publicArea.type, TPM2_ALG.ECC)

ecc_nv_nonce = TPM2B_NV_PUBLIC(
nvPublic=TPMS_NV_PUBLIC(
nvIndex=0x1C0000B,
nameAlg=TPM2_ALG.SHA256,
attributes=TPMA_NV.AUTHWRITE | TPMA_NV.AUTHREAD,
dataSize=15,
)
)
eh = self.ectx.nv_define_space(b"", ecc_nv_nonce, ESYS_TR.OWNER)
self.ectx.nv_write(eh, b"\xFF" * 15)
ecc_nonce_template = create_ek_template(self.ectx)
_, ecc_nonce, _, _, _ = self.ectx.create_primary(
TPM2B_SENSITIVE_CREATE(), ecc_nonce_template, ESYS_TR.ENDORSEMENT
)
self.assertNotEqual(
ecc_nonce.publicArea.unique.ecc.x, ecc.publicArea.unique.ecc.x
)
self.assertNotEqual(
ecc_nonce.publicArea.unique.ecc.y, ecc.publicArea.unique.ecc.y
)

def test_create_ek_rsa(self):
rsa_template = create_ek_template(self.ectx, TPM2_ALG.RSA)
_, rsa, _, _, _ = self.ectx.create_primary(
TPM2B_SENSITIVE_CREATE(), rsa_template, ESYS_TR.ENDORSEMENT
)
self.assertEqual(rsa.publicArea.type, TPM2_ALG.RSA)

rsa_nv_nonce = TPM2B_NV_PUBLIC(
nvPublic=TPMS_NV_PUBLIC(
nvIndex=0x1C00003,
nameAlg=TPM2_ALG.SHA256,
attributes=TPMA_NV.AUTHWRITE | TPMA_NV.AUTHREAD,
dataSize=127,
)
)
rh = self.ectx.nv_define_space(b"", rsa_nv_nonce, ESYS_TR.OWNER)
self.ectx.nv_write(rh, b"\xFF" * 127)
rsa_nonce_template = create_ek_template(self.ectx, TPM2_ALG.RSA)
_, rsa_nonce, _, _, _ = self.ectx.create_primary(
TPM2B_SENSITIVE_CREATE(), rsa_nonce_template, ESYS_TR.ENDORSEMENT
)
self.assertNotEqual(rsa_nonce.publicArea.unique.rsa, rsa.publicArea.unique.rsa)

def test_create_ek_template(self):
template = TPMT_PUBLIC(
type=TPM2_ALG.KEYEDHASH,
nameAlg=TPM2_ALG.SHA256,
objectAttributes=TPMA_OBJECT.FIXEDTPM
| TPMA_OBJECT.FIXEDPARENT
| TPMA_OBJECT.SENSITIVEDATAORIGIN
| TPMA_OBJECT.ADMINWITHPOLICY
| TPMA_OBJECT.RESTRICTED
| TPMA_OBJECT.SIGN_ENCRYPT,
parameters=TPMU_PUBLIC_PARMS(
keyedHashDetail=TPMS_KEYEDHASH_PARMS(
scheme=TPMT_KEYEDHASH_SCHEME(
scheme=TPM2_ALG.HMAC,
details=TPMU_SCHEME_KEYEDHASH(
hmac=TPMS_SCHEME_HASH(hashAlg=TPM2_ALG.SHA256),
),
)
),
),
)
tb = template.marshal()
nv_template = TPM2B_NV_PUBLIC(
nvPublic=TPMS_NV_PUBLIC(
nvIndex=0x1C0000C,
nameAlg=TPM2_ALG.SHA256,
attributes=TPMA_NV.AUTHWRITE | TPMA_NV.AUTHREAD,
dataSize=len(tb),
)
)
tnh = self.ectx.nv_define_space(b"", nv_template, ESYS_TR.OWNER)
self.ectx.nv_write(tnh, tb)
templpub = create_ek_template(self.ectx)
_, templ, _, _, _ = self.ectx.create_primary(
TPM2B_SENSITIVE_CREATE(), templpub, ESYS_TR.ENDORSEMENT
)
self.assertEqual(templ.publicArea.type, TPM2_ALG.KEYEDHASH)

def test_create_ek_bad(self):
with self.assertRaises(ValueError) as e:
create_ek_template(self.ectx, TPM2_ALG.NULL)
self.assertEqual(str(e.exception), "unsupported EK algorithm null")


if __name__ == "__main__":
unittest.main()
128 changes: 128 additions & 0 deletions tpm2_pytss/utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,8 @@
_hmac,
)
from .types import *
from .ESAPI import ESAPI
from .constants import ESYS_TR, TPM2_CAP, TPM2_HT, TPM2_PT_NV, TPM2_ECC
from cryptography.hazmat.primitives import constant_time as ct
from cryptography.hazmat.primitives import hashes
from cryptography.hazmat.backends import default_backend
Expand Down Expand Up @@ -226,3 +228,129 @@ def unwrap(
)

return s


def create_ek_template(
ectx: ESAPI, ekalg: TPM2_ALG = TPM2_ALG.ECC, session: ESYS_TR = ESYS_TR.NONE
) -> TPM2B_PUBLIC:
"""Creates an Endorsenment Key template which when created matches the EK certificate
The template is created according to TCG EK Credential Profile For TPM Family 2.0:
- https://trustedcomputinggroup.org/resource/tcg-ek-credential-profile-for-tpm-family-2-0/
Args:
ectx (ESAPI): The ESAPI instance used to look for a possible template and nonce in NV areas
ekalg: (TPM2_ALG.ECC or TPM2_ALG.RSA): Type of template to create, defaults to TPM2_ALG.ECC
session: (ESYS_TR): Optional session, for encrypt/decrypt and audit sessions, defaults to ESYS_TR.NONE
Returns:
TPM2B_PUBLIC FIXME
"""
symmetric = TPMT_SYM_DEF_OBJECT(
algorithm=TPM2_ALG.AES,
keyBits=TPMU_SYM_KEY_BITS(aes=128),
mode=TPMU_SYM_MODE(aes=TPM2_ALG.CFB),
)
attrs = (
TPMA_OBJECT.FIXEDTPM
| TPMA_OBJECT.FIXEDPARENT
| TPMA_OBJECT.SENSITIVEDATAORIGIN
| TPMA_OBJECT.ADMINWITHPOLICY
| TPMA_OBJECT.RESTRICTED
| TPMA_OBJECT.DECRYPT
)
policy = b"\x83q\x97gD\x84\xb3\xf8\x1a\x90\xcc\x8dF\xa5\xd7$\xfdR\xd7n\x06R\x0bd\xf2\xa1\xda\x1b3\x14i\xaa"
ecc_template = TPM2B_PUBLIC(
publicArea=TPMT_PUBLIC(
type=TPM2_ALG.ECC,
nameAlg=TPM2_ALG.SHA256,
objectAttributes=attrs,
authPolicy=policy,
parameters=TPMU_PUBLIC_PARMS(
eccDetail=TPMS_ECC_PARMS(
symmetric=symmetric,
scheme=TPMT_ECC_SCHEME(scheme=TPM2_ALG.NULL),
curveID=TPM2_ECC.NIST_P256,
kdf=TPMT_KDF_SCHEME(scheme=TPM2_ALG.NULL),
)
),
unique=TPMU_PUBLIC_ID(ecc=TPMS_ECC_POINT(x=b"\x00" * 32, y=b"\x00" * 32)),
)
)
rsa_template = TPM2B_PUBLIC(
publicArea=TPMT_PUBLIC(
type=TPM2_ALG.RSA,
nameAlg=TPM2_ALG.SHA256,
objectAttributes=attrs,
authPolicy=policy,
parameters=TPMU_PUBLIC_PARMS(
rsaDetail=TPMS_RSA_PARMS(
symmetric=symmetric,
scheme=TPMT_RSA_SCHEME(scheme=TPM2_ALG.NULL),
keyBits=2048,
),
),
unique=TPMU_PUBLIC_ID(rsa=b"\x00" * 256),
)
)
if ekalg == TPM2_ALG.ECC:
nvbase = 0x1C0000A
template = ecc_template
elif ekalg == TPM2_ALG.RSA:
nvbase = 0x1C00002
template = rsa_template
else:
raise ValueError(f"unsupported EK algorithm {ekalg}")

nvnonce = nvbase + 1
nvtemplate = nvbase + 2

indices = []
more = True
while more:
more, data = ectx.get_capability(
TPM2_CAP.HANDLES,
TPM2_HT.NV_INDEX << 24,
TPM2_PT_NV.INDEX_MAX,
session1=session,
)
handles = list(data.data.handles)
indices.extend(handles)

if nvtemplate in indices:
thandle = ectx.tr_from_tpmpublic(nvtemplate, session1=session)
tpub, _ = ectx.nv_read_public(thandle, session1=session)
left = tpub.nvPublic.dataSize
mtempl = b""
while left > 0:
off = tpub.nvPublic.dataSize - left
size = 0x300 if left > 0x300 else left
data = ectx.nv_read(thandle, size, off, session2=session)
mtempl = mtempl + bytes(data)
left = left - len(data)
templ, _ = TPMT_PUBLIC.unmarshal(mtempl)
template = TPM2B_PUBLIC(publicArea=templ)

nonce = b""
if nvnonce in indices:
nhandle = ectx.tr_from_tpmpublic(nvnonce, session1=session)
npub, _ = ectx.nv_read_public(nhandle, session1=session)
left = npub.nvPublic.dataSize
while left > 0:
off = npub.nvPublic.dataSize - left
size = 0x300 if left > 0x300 else left
data = ectx.nv_read(nhandle, size, off, session2=session)
nonce = nonce + bytes(data)
left = left - len(data)

if len(nonce) > 0 and template.publicArea.type == TPM2_ALG.RSA:
template.publicArea.unique.rsa = nonce + ((256 - len(nonce)) * b"\x00")
elif (
len(nonce) > 0
and template.publicArea.type == TPM2_ALG.ECC
and template.publicArea.parameters.eccDetail.curveID == TPM2_ECC.NIST_P256
):
template.publicArea.unique.ecc.x = nonce + ((32 - len(nonce)) * b"\x00")
template.publicArea.unique.ecc.y = b"\x00" * 32

return template

0 comments on commit d16411f

Please sign in to comment.