Ejemplo n.º 1
0
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()
Ejemplo n.º 2
0
    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)
Ejemplo n.º 3
0
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()
Ejemplo n.º 4
0
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()
Ejemplo n.º 5
0
    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
Ejemplo n.º 6
0
    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)