def load_key_template(ectx, b64template, hierarchy): template = TPM2B_PUBLIC() b64unmarshal(b64template, template) insensitive = TPM2B_SENSITIVE_CREATE(size=0) outsideinfo = TPM2B_DATA(size=0) creationpcr = TPML_PCR_SELECTION(count=0) obj = ectx.ESYS_TR_PTR() with ExitStack() as stack: outpublic = stack.enter_context(TPM2B_PUBLIC_PTR_PTR()) creationdata = stack.enter_context(TPM2B_CREATION_DATA_PTR_PTR()) creationhash = stack.enter_context(TPM2B_DIGEST_PTR_PTR()) creationtkt = stack.enter_context(TPMT_TK_CREATION_PTR_PTR()) ectx.CreatePrimary( hierarchy, ESYS_TR_PASSWORD, ESYS_TR_NONE, ESYS_TR_NONE, insensitive, template, outsideinfo, creationpcr, obj, outpublic, creationdata, creationhash, creationtkt, ) return obj.value()
def run(self, tmp=None, task_vars=None): changed = False keytype = self._task.args.get('type', 'rsa') templ_index = self._task.args.get('index') capath = self._task.args.get('capath') crlpath = self._task.args.get('crlpath') templpath = self._task.args.get('template_path') publicpath = self._task.args.get('public_path') if keytype not in ('rsa', 'ecc', 'high'): raise AnsibleError("Bad key type: {}".format(keytype)) elif keytype == 'high' and not templ_index: raise AnsibleError('EK template NV index required') elif not capath: raise AnsibleError('capath is required') elif not os.path.isfile(capath): raise AnsibleError("capath {} is not a file".format(capath)) elif crlpath and not os.path.isfile(crlpath): raise AnsibleError("crlpath {} is not a file".format(crlpath)) if templpath and os.path.lexists(templpath): return dict() margs = dict( type=keytype, index=templ_index, ) mres = self._execute_module( module_name='tpm2_get_certificate', module_args=margs, task_vars=task_vars ) if mres.get('failed', False) == True: raise AnsibleError("failed to fetch EK: {}".format(mres.get('msg'))) pem = to_bytes(mres.get('cert')) cert = load_pem_x509_certificate(pem, default_backend()) public = TPM2B_PUBLIC() b64unmarshal(mres.get('public'), public) key = public_to_crypto(public) self.compare_cert_key(cert, key) self.verify_cert(capath, pem, crlpath) template = to_bytes(mres.get('template')) if templpath: self.save_template(templpath, template, 'ek_template') changed = True p = to_bytes(mres.get('public')) if publicpath: self.save_template(publicpath, p, 'ek_public') changed = True return dict(changed=changed, certificat=pem, template=template, public=p)
def load_key_context(ectx, b64context): ctx = TPMS_CONTEXT() b64unmarshal(b64context, ctx) obj = ectx.ESYS_TR_PTR() self.ectx.ContextLoad( ctx, obj, ) return obj.value()
def load_key_pair(ectx, b64public, b64private, parent, parentauth): public = TPM2B_PUBLIC() b64unmarshal(b64public, public) private = TPM2B_PRIVATE() b64unmarshal(b64private, private) obj = ectx.ESYS_TR_PTR() ectx.Load( parent, parentauth, ESYS_TR_NONE, ESYS_TR_NONE, private, public, obj ) return obj.value()
def run(self, tmp=None, task_vars=None): ak_path = self._task.args.get('ak') with open(ak_path) as f: keys = json.load(f) ak_public = keys.get('public') ak_private = keys.get('private') ek_template = keys.get('parent_template') qdata = secrets.token_bytes(32) margs = dict( qdata=b64encode(qdata).decode('ascii'), ak_public=ak_public, ak_private=ak_private, ek_template=ek_template, ) mres = self._execute_module( module_name='tpm2_quote', module_args=margs, task_vars=task_vars, ) b64attest = mres.get('attest') attest = TPM2B_ATTEST() b64unmarshal(b64attest, attest) attb = buffer_to_bytes(attest, 'attestationData') b64sig = mres.get('signature') sig = TPMT_SIGNATURE() b64unmarshal(b64sig, sig) public = TPM2B_PUBLIC() b64unmarshal(ak_public, public) verify_signature(sig, public, attb) att = TPMS_ATTEST() unmarshal(attb, att) self.check_attest(att, qdata) pcrs = mres.get('pcrs') h = public.publicArea.parameters.asymDetail.scheme.details.anySig.hashAlg halg = tpm2_to_crypto_alg(h) self.check_pcrs(pcrs, att.attested.quote, halg) # add clock info here? results = dict( pcrs=pcrs, firmware_version=att.firmwareVersion, ) return results
def run(self, tmp=None, task_vars=None): ek_templ_path = self._task.args.get('ek_template') ek_public_path = self._task.args.get('ek_public') ak_path = self._task.args.get('ak') keytype = self._task.args.get('type', 'rsa') templ = self._task.args.get('template') if not ek_templ_path: raise AnsibleError('ek template is required') elif not os.path.isfile(ek_templ_path): raise AnsibleError("ek template {} is not a regular file".format(ek_templ)) if not templ: template = get_ak_template(keytype) b64templ = b64marshal(template) else: # parse template here pass # check AK files here if ak_path and os.path.lexists(ak_path): return dict(changed=False) with open(ek_templ_path, 'r') as f: ek_templ = f.read() with open(ek_public_path, 'r') as f: ek_public64 = f.read() ek_public = TPM2B_PUBLIC() b64unmarshal(ek_public64, ek_public) margs = dict( ek_template=ek_templ, ak_template=b64templ.decode('ascii'), ) mres = self._execute_module( module_name='tpm2_generate_ak', module_args=margs, task_vars=task_vars ) if mres.get('failed', False): raise AnsibleError("failed to generate AK: {}".format(mres.get('msg'))) b64private = mres.get('private') b64public = mres.get('public') public = TPM2B_PUBLIC() b64unmarshal(b64public, public) try: compare_public(public, template) except Exception as e: raise AnsibleError("AK key does not match template: {}".format(e)) private = TPM2B_PRIVATE() b64unmarshal(b64private, private) cv = secrets.token_bytes(32) template.publicArea.unique = public.publicArea.unique ak_name = get_name(template.publicArea) halg = tpm2_to_crypto_alg(ek_public.publicArea.nameAlg) seed, enc_seed = create_seed(ek_public, b"IDENTITY\x00") symbits = ek_public.publicArea.parameters.asymDetail.symmetric.keyBits.sym symkey = kdfa(halg, seed, b"STORAGE", ak_name, b"", symbits) enc_cred = encrypt(symkey, cv) hmackey = kdfa(halg, seed, b"INTEGRITY", b"", b"", halg.digest_size * 8) outerhmac = hmac(halg, hmackey, enc_cred, ak_name) hmac2b = TPM2B_DIGEST(buffer=outerhmac) hmacdata = marshal(hmac2b) credblob = TPM2B_ID_OBJECT(credential=hmacdata + enc_cred) secret = TPM2B_ENCRYPTED_SECRET(secret=enc_seed) b64credblob = b64marshal(credblob).decode('ascii') b64secret = b64marshal(secret).decode('ascii') margs = dict( ek_template=ek_templ, ak_public=b64public, ak_private=b64private, credblob=b64credblob, secret=b64secret ) mres = self._execute_module( module_name='tpm2_activatecred', module_args=margs, task_vars=task_vars ) rcv = to_bytes(mres.get('cv')) if rcv != cv: raise AnsibleError('cv nonce does not match') if ak_path: self.save_ak(ak_path, b64public, b64private, ek_templ) return dict(changed=True, public=b64public, private=b64private)