"Kevin O'Connor" <kevin@koconnor.net> wrote on 01/06/2016 03:20:56 PM:

>
> On Wed, Jan 06, 2016 at 01:15:55PM -0500, Stefan Berger wrote:
> > From: Stefan Berger <stefanb@linux.vnet.ibm.com>
> >
> > Extend assert_physical_presence with checks for hardware physical presence
> > support. If no hardware physical presence is asserted and the SW assertion
> > is disable, -1 is returned.
> >
> > Signed-off-by: Stefan Berger <stefanb@linux.vnet.ibm.com>
> > ---
> >  src/std/tcg.h |  2 ++
> >  src/tcgbios.c | 61 ++++++++++++++++++++++++++++++++++++++++++++++
> +++++++++++--
> >  2 files changed, 61 insertions(+), 2 deletions(-)
> >
> > diff --git a/src/std/tcg.h b/src/std/tcg.h
> > index 9f7f021..00be533 100644
> > --- a/src/std/tcg.h
> > +++ b/src/std/tcg.h
> > @@ -70,6 +70,7 @@
> >  
> >  /* TPM command error codes */
> >  #define TPM_INVALID_POSTINIT             0x26
> > +#define TPM_BAD_PRESENCE                 0x2d
> >  #define TPM_BAD_LOCALITY                 0x3d
> >  
> >  /* TPM command tags */
> > @@ -285,6 +286,7 @@ enum permFlagsIndex {
> >      PERM_FLAG_IDX_ALLOW_MAINTENANCE,
> >      PERM_FLAG_IDX_PHYSICAL_PRESENCE_LIFETIME_LOCK,
> >      PERM_FLAG_IDX_PHYSICAL_PRESENCE_HW_ENABLE,
> > +    PERM_FLAG_IDX_PHYSICAL_PRESENCE_CMD_ENABLE,
> >  };
> >  
> >  
> > diff --git a/src/tcgbios.c b/src/tcgbios.c
> > index d6a8495..6a6b6b0 100644
> > --- a/src/tcgbios.c
> > +++ b/src/tcgbios.c
> > @@ -446,7 +446,7 @@ err_exit:
> >      return -1;
> >  }
> >  
> > -static u32
> > +static int
> >  read_stclear_flags(char *buf, int buf_len)
> >  {
> >      memset(buf, 0, buf_len);
> > @@ -480,7 +480,32 @@ read_permanent_flags(char *buf, int buf_len)
> >      return 0;
> >  }
> >  
> > -static u32
> > +static int
> > +has_hw_physical_presence(struct tpm_permanent_flags *pf, int *has_hw_pp)
> > +{
> > +    u32 ordinal;
> > +
> > +    /* We cannot read hardware physical presence from a flag;
> > +     * it has to be inferred from the error code to a command that
> > +     * needs physical presence
> > +     */
> > +    if (pf->flags[PERM_FLAG_IDX_DISABLE])
> > +        ordinal = TPM_ORD_PhysicalDisable;
> > +    else
> > +        ordinal = TPM_ORD_PhysicalEnable;
> > +
> > +    int ret = tpm_send_cmd(0, ordinal, NULL, 0, TPM_DURATION_TYPE_SHORT);
>
> I'm leery of code that automatically issues a command that nominally
> alters non-volatile memory as I fear it could cause the hardware to
> wear out.  So, I'd avoid doing this unless the above is definitely not
> an issue.


It's implementation-dependent what the TPM will do once a permanent flag is set to the
same value it already is. It may write it back into NVRAM or not.

>
> If you want the menu to also be usable on machines with hardware
> physical presence, then I'm fine with enabling the menu after just
> checking that HW_ENABLE is true.


In this case we may encounter errors if hardware physical presence is not actually set.

>
> [...]
> > +static int
> >  assert_physical_presence(int verbose)
> >  {
> >      struct tpm_stclear_flags stcf;
> > @@ -492,6 +517,38 @@ assert_physical_presence(int verbose)
> >          /* physical presence already asserted */
> >          return 0;
>
> I don't think we need to read stclear flags here - I think it would be
> simpler to just issue PhysicalPresence_PRESENT.  If it succeeds then
> we've successfully asserted physical presence, and if it fails then go
> on to read permanent flags.


Ok.

>
> > +    struct tpm_permanent_flags pf;
> > +    ret = read_permanent_flags((char *)&pf, sizeof(pf));
> > +    if (ret)
> > +        return -1;
> > +
> > +    /* check if hardware physical presence is supported and asserted */
> > +    if (pf.flags[PERM_FLAG_IDX_PHYSICAL_PRESENCE_HW_ENABLE]) {
> > +        int has_hw_pp;
> > +        ret = has_hw_physical_presence(&pf, &has_hw_pp);
> > +        if (verbose && !has_hw_pp)
> > +            printf("Hardware physical presence is not asserted.\n\n");
> > +        if (ret)
> > +            return ret;
> > +
> > +        if (has_hw_pp)
> > +            return 0;
> > +
> > +        if (!pf.flags[PERM_FLAG_IDX_PHYSICAL_PRESENCE_CMD_ENABLE]) {
> > +            /* cannot enable phys. presence using command */
> > +            if (verbose)
> > +                printf("Error: Physical presence SW assertion is
> disabled.\n\n");
> > +            return -1;
> > +        }
> > +    }
> > +
> > +    if (stcf.flags[STCLEAR_FLAG_IDX_PHYSICAL_PRESENCE_LOCK]) {
> > +        /* physical presence cannot be changed anymore */
> > +        if (verbose)
> > +            printf("Error: Physical presence assertion is locked.\n\n");
> > +        return -1;
> > +    }
> > +
> >      ret = tpm_send_check_cmd(0, TPM_ORD_PhysicalPresence,
> >                               PhysicalPresence_CMD_ENABLE,
> >                               sizeof(PhysicalPresence_CMD_ENABLE),
>
> This seems to issue CMD_ENABLE even if CMD_ENABLE may have already
> been on - I'm leery of that.


I'll remove that.

>
> To summarize, what about this sequence during startup:
>
>     PhysicalPresence_PRESENT
>     if fail:
>        flags = read_permanent_flags()
>        if flags.HW_ENABLE:
>            return success
>        if !flags.CMD_ENABLE && !flags.LOCK:
>            PhysicalPresence_CMD_ENABLE
>            PhysicalPresence_PRESENT
>
> Then we don't have to issue PRESENT or CMD_ENABLE anywhere else in the
> code.


Ok.

    Stefan