All of lore.kernel.org
 help / color / mirror / Atom feed
From: "Michael S. Tsirkin" <mst@redhat.com>
To: Stefan Berger <stefanb@linux.vnet.ibm.com>
Cc: Stefan Berger <stefanb@us.ibm.com>,
	qemu-devel@nongnu.org, quan.xu@intel.com
Subject: Re: [Qemu-devel] [PATCH 2/3] tpm: Probe for connected TPM 1.2 or TPM 2
Date: Tue, 14 Apr 2015 07:48:23 +0200	[thread overview]
Message-ID: <20150414074646-mutt-send-email-mst@redhat.com> (raw)
In-Reply-To: <1427830813-639306-3-git-send-email-stefanb@linux.vnet.ibm.com>

On Tue, Mar 31, 2015 at 03:40:12PM -0400, Stefan Berger wrote:
> In the TPM passthrough backend driver, modify the probing code so
> that we can check whether a TPM 1.2 or TPM 2 is being used
> and adapt the behavior of the TPM TIS accordingly.
> 
> Move the code that tested for a TPM 1.2 into tpm_utils.c
> and extend it with test for probing for TPM 2. Have the
> function return the version of TPM found.
> 
> Signed-off-by: Stefan Berger <stefanb@us.ibm.com>
> ---
>  hw/tpm/Makefile.objs     |   2 +-
>  hw/tpm/tpm_int.h         |   6 +++
>  hw/tpm/tpm_passthrough.c |  59 +++-------------------
>  hw/tpm/tpm_util.c        | 126 +++++++++++++++++++++++++++++++++++++++++++++++
>  hw/tpm/tpm_util.h        |  28 +++++++++++
>  5 files changed, 167 insertions(+), 54 deletions(-)
>  create mode 100644 hw/tpm/tpm_util.c
>  create mode 100644 hw/tpm/tpm_util.h
> 
> diff --git a/hw/tpm/Makefile.objs b/hw/tpm/Makefile.objs
> index 99f5983..64cecc3 100644
> --- a/hw/tpm/Makefile.objs
> +++ b/hw/tpm/Makefile.objs
> @@ -1,2 +1,2 @@
>  common-obj-$(CONFIG_TPM_TIS) += tpm_tis.o
> -common-obj-$(CONFIG_TPM_PASSTHROUGH) += tpm_passthrough.o
> +common-obj-$(CONFIG_TPM_PASSTHROUGH) += tpm_passthrough.o tpm_util.o
> diff --git a/hw/tpm/tpm_int.h b/hw/tpm/tpm_int.h
> index 24e12ce..edab824 100644
> --- a/hw/tpm/tpm_int.h
> +++ b/hw/tpm/tpm_int.h
> @@ -66,4 +66,10 @@ struct tpm_resp_hdr {
>  #define TPM_ORD_ContinueSelfTest  0x53
>  #define TPM_ORD_GetTicks          0xf1
>  
> +
> +/* TPM2 defines */
> +#define TPM_ST_NO_SESSIONS        0x8001
> +
> +#define TPM_CC_ReadClock          0x00000181
> +
>  #endif /* TPM_TPM_INT_H */
> diff --git a/hw/tpm/tpm_passthrough.c b/hw/tpm/tpm_passthrough.c
> index dd769a7..2e65703 100644
> --- a/hw/tpm/tpm_passthrough.c
> +++ b/hw/tpm/tpm_passthrough.c
> @@ -33,6 +33,7 @@
>  #include "hw/i386/pc.h"
>  #include "sysemu/tpm_backend_int.h"
>  #include "tpm_tis.h"
> +#include "tpm_util.h"
>  
>  #define DEBUG_TPM 0
>  
> @@ -69,6 +70,8 @@ struct TPMPassthruState {
>      bool tpm_op_canceled;
>      int cancel_fd;
>      bool had_startup_error;
> +
> +    enum TPMVersion tpm_version;

Use a typedef please, without enum.

>  };
>  
>  typedef struct TPMPassthruState TPMPassthruState;
> @@ -333,59 +336,9 @@ static const char *tpm_passthrough_create_desc(void)
>  
>  static enum TPMVersion tpm_passthrough_get_tpm_version(TPMBackend *tb)
>  {
> -    return TPMVersion1_2;
> -}
> -
> -/*
> - * A basic test of a TPM device. We expect a well formatted response header
> - * (error response is fine) within one second.
> - */
> -static int tpm_passthrough_test_tpmdev(int fd)
> -{
> -    struct tpm_req_hdr req = {
> -        .tag = cpu_to_be16(TPM_TAG_RQU_COMMAND),
> -        .len = cpu_to_be32(sizeof(req)),
> -        .ordinal = cpu_to_be32(TPM_ORD_GetTicks),
> -    };
> -    struct tpm_resp_hdr *resp;
> -    fd_set readfds;
> -    int n;
> -    struct timeval tv = {
> -        .tv_sec = 1,
> -        .tv_usec = 0,
> -    };
> -    unsigned char buf[1024];
> -
> -    n = write(fd, &req, sizeof(req));
> -    if (n < 0) {
> -        return errno;
> -    }
> -    if (n != sizeof(req)) {
> -        return EFAULT;
> -    }
> -
> -    FD_ZERO(&readfds);
> -    FD_SET(fd, &readfds);
> -
> -    /* wait for a second */
> -    n = select(fd + 1, &readfds, NULL, NULL, &tv);
> -    if (n != 1) {
> -        return errno;
> -    }
> -
> -    n = read(fd, &buf, sizeof(buf));
> -    if (n < sizeof(struct tpm_resp_hdr)) {
> -        return EFAULT;
> -    }
> -
> -    resp = (struct tpm_resp_hdr *)buf;
> -    /* check the header */
> -    if (be16_to_cpu(resp->tag) != TPM_TAG_RSP_COMMAND ||
> -        be32_to_cpu(resp->len) != n) {
> -        return EBADMSG;
> -    }
> +    TPMPassthruState *tpm_pt = TPM_PASSTHROUGH(tb);
>  
> -    return 0;
> +    return tpm_pt->tpm_version;
>  }
>  
>  /*
> @@ -455,7 +408,7 @@ static int tpm_passthrough_handle_device_opts(QemuOpts *opts, TPMBackend *tb)
>          goto err_free_parameters;
>      }
>  
> -    if (tpm_passthrough_test_tpmdev(tpm_pt->tpm_fd)) {
> +    if (tpm_util_test_tpmdev(tpm_pt->tpm_fd, &tpm_pt->tpm_version)) {
>          error_report("'%s' is not a TPM device.",
>                       tpm_pt->tpm_dev);
>          goto err_close_tpmdev;
> diff --git a/hw/tpm/tpm_util.c b/hw/tpm/tpm_util.c
> new file mode 100644
> index 0000000..f9fb9c1
> --- /dev/null
> +++ b/hw/tpm/tpm_util.c
> @@ -0,0 +1,126 @@
> +/*
> + * TPM utility functions
> + *
> + *  Copyright (c) 2010 - 2015 IBM Corporation
> + *  Authors:
> + *    Stefan Berger <stefanb@us.ibm.com>
> + *
> + * This library is free software; you can redistribute it and/or
> + * modify it under the terms of the GNU Lesser General Public
> + * License as published by the Free Software Foundation; either
> + * version 2 of the License, or (at your option) any later version.
> + *
> + * This library is distributed in the hope that it will be useful,
> + * but WITHOUT ANY WARRANTY; without even the implied warranty of
> + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
> + * Lesser General Public License for more details.
> + *
> + * You should have received a copy of the GNU Lesser General Public
> + * License along with this library; if not, see <http://www.gnu.org/licenses/>
> + */
> +
> +#include "tpm_util.h"
> +#include "tpm_int.h"
> +
> +/*
> + * A basic test of a TPM device. We expect a well formatted response header
> + * (error response is fine) within one second.
> + */
> +static int tpm_util_test(int fd,
> +                         unsigned char *request,
> +                         size_t requestlen,
> +                         uint16_t *returnTag)
> +{
> +    struct tpm_resp_hdr *resp;
> +    fd_set readfds;
> +    int n;
> +    struct timeval tv = {
> +        .tv_sec = 1,
> +        .tv_usec = 0,
> +    };
> +    unsigned char buf[1024];
> +
> +    n = write(fd, request, requestlen);
> +    if (n < 0) {
> +        return errno;
> +    }
> +    if (n != requestlen) {
> +        return EFAULT;
> +    }
> +
> +    FD_ZERO(&readfds);
> +    FD_SET(fd, &readfds);
> +
> +    /* wait for a second */
> +    n = select(fd + 1, &readfds, NULL, NULL, &tv);
> +    if (n != 1) {
> +        return errno;
> +    }
> +
> +    n = read(fd, &buf, sizeof(buf));
> +    if (n < sizeof(struct tpm_resp_hdr)) {
> +        return EFAULT;
> +    }
> +
> +    resp = (struct tpm_resp_hdr *)buf;
> +    /* check the header */
> +    if (be32_to_cpu(resp->len) != n) {
> +        return EBADMSG;
> +    }
> +
> +    *returnTag = be16_to_cpu(resp->tag);
> +
> +    return 0;
> +}
> +
> +/*
> + * Probe for the TPM device in the back
> + * Returns 0 on success with the version of the probed TPM set, 1 on failure.
> + */
> +int tpm_util_test_tpmdev(int tpm_fd, enum TPMVersion *tpm_version)
> +{
> +    /*
> +     * Sending a TPM1.2 command to a TPM2 should return a TPM1.2
> +     * header (tag = 0xc4) and error code (TPM_BADTAG = 0x1e)
> +     *
> +     * Sending a TPM2 command to a TPM 2 will give a TPM 2 tag in the
> +     * header.
> +     * Sending a TPM2 command to a TPM 1.2 will give a TPM 1.2 tag
> +     * in the header and an error code.
> +     */
> +    const struct tpm_req_hdr test_req = {
> +        .tag = cpu_to_be16(TPM_TAG_RQU_COMMAND),
> +        .len = cpu_to_be32(sizeof(test_req)),
> +        .ordinal = cpu_to_be32(TPM_ORD_GetTicks),
> +    };
> +
> +    const struct tpm_req_hdr test_req_tpm2 = {
> +        .tag = cpu_to_be16(TPM_ST_NO_SESSIONS),
> +        .len = cpu_to_be32(sizeof(test_req_tpm2)),
> +        .ordinal = cpu_to_be32(TPM_CC_ReadClock),
> +    };
> +    uint16_t returnTag;

use lower case for vars pls


> +    int ret;
> +
> +    /* Send TPM 2 command */
> +    ret = tpm_util_test(tpm_fd, (unsigned char *)&test_req_tpm2,
> +                        sizeof(test_req_tpm2), &returnTag);
> +    /* TPM 2 would respond with a tag of TPM_ST_NO_SESSIONS */
> +    if (!ret && returnTag == TPM_ST_NO_SESSIONS) {
> +        *tpm_version = TPMVersion2_0;
> +        return 0;
> +    }
> +
> +    /* Send TPM 1.2 command */
> +    ret = tpm_util_test(tpm_fd, (unsigned char *)&test_req,
> +                        sizeof(test_req), &returnTag);
> +    if (!ret && returnTag == TPM_TAG_RSP_COMMAND) {
> +        *tpm_version = TPMVersion1_2;
> +        /* this is a TPM 1.2 */
> +        return 0;
> +    }
> +
> +    *tpm_version = TPMVersion_Unspec;
> +
> +    return 1;
> +}
> diff --git a/hw/tpm/tpm_util.h b/hw/tpm/tpm_util.h
> new file mode 100644
> index 0000000..3ce25c8
> --- /dev/null
> +++ b/hw/tpm/tpm_util.h
> @@ -0,0 +1,28 @@
> +/*
> + * TPM utility functions
> + *
> + *  Copyright (c) 2010 - 2015 IBM Corporation
> + *  Authors:
> + *    Stefan Berger <stefanb@us.ibm.com>
> + *
> + * This library is free software; you can redistribute it and/or
> + * modify it under the terms of the GNU Lesser General Public
> + * License as published by the Free Software Foundation; either
> + * version 2 of the License, or (at your option) any later version.
> + *
> + * This library is distributed in the hope that it will be useful,
> + * but WITHOUT ANY WARRANTY; without even the implied warranty of
> + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
> + * Lesser General Public License for more details.
> + *
> + * You should have received a copy of the GNU Lesser General Public
> + * License along with this library; if not, see <http://www.gnu.org/licenses/>
> + */
> +#ifndef TPM_TPM_UTILS_H
> +#define TPM_TPM_UTILS_H
> +
> +#include "sysemu/tpm_backend.h"
> +
> +int tpm_util_test_tpmdev(int tpm_fd, enum TPMVersion *tpm_version);
> +
> +#endif /* TPM_TPM_UTILS_H */
> -- 
> 1.9.3

  parent reply	other threads:[~2015-04-14  5:48 UTC|newest]

Thread overview: 14+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2015-03-31 19:40 [Qemu-devel] [PATCH 0/3] tpm: Upgrade TPM TIS for support of a TPM 2 Stefan Berger
2015-03-31 19:40 ` [Qemu-devel] [PATCH 1/3] Extend TPM TIS interface to version 2.0 Stefan Berger
2015-04-14  5:50   ` Michael S. Tsirkin
2015-03-31 19:40 ` [Qemu-devel] [PATCH 2/3] tpm: Probe for connected TPM 1.2 or TPM 2 Stefan Berger
2015-04-07  8:54   ` Xu, Quan
2015-04-12 20:59     ` Stefan Berger
2015-04-13 14:43       ` Eric Blake
2015-04-13 14:58         ` Stefan Berger
2015-04-14  5:48   ` Michael S. Tsirkin [this message]
2015-03-31 19:40 ` [Qemu-devel] [PATCH 3/3] TPM2 ACPI table support Stefan Berger
2015-04-07  8:58   ` Xu, Quan
2015-04-13  6:27   ` Michael S. Tsirkin
2015-04-14  2:29     ` Stefan Berger
2015-04-14  5:51       ` Michael S. Tsirkin

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20150414074646-mutt-send-email-mst@redhat.com \
    --to=mst@redhat.com \
    --cc=qemu-devel@nongnu.org \
    --cc=quan.xu@intel.com \
    --cc=stefanb@linux.vnet.ibm.com \
    --cc=stefanb@us.ibm.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.