[Skiboot] [PATCH 04/19] hdata/tpmrel.c: register CVC services during HDAT parsing
Oliver
oohall at gmail.com
Tue Nov 21 15:59:39 AEDT 2017
On Sun, Nov 12, 2017 at 4:28 AM, Claudio Carvalho
<cclaudio at linux.vnet.ibm.com> wrote:
> This registers the address range of the Container-Verification-Code
> (CVC) and then registers each CVC service provided. The offset of
> each service is checked to make sure that it is not out of the CVC
> address range.
>
> The hostboot reserved memory that stores the CVC is identified by
> parsing the msvpd_hb_reserved_mem HDAT structure. In order to register
> its address range, we call the cvc_register() libstb function.
>
> The CVC services provided are identified by parsing the hash_and_verify
> HDAT structure. In order to register them, we call the
> cvc_service_register() libstb function.
>
> This also updates the hdat_to_dt unit test adding one stub for each
> libstb function called.
>
> Since skiboot is the only consumer for the CVC services, this patch
> doesn't add them to the device tree.
>
> Signed-off-by: Claudio Carvalho <cclaudio at linux.vnet.ibm.com>
> ---
> hdata/spira.h | 12 ++++++
> hdata/test/stubs.c | 2 +
> hdata/tpmrel.c | 90 +++++++++++++++++++++++++++++++++++++++++
> libstb/Makefile.inc | 2 +-
> libstb/cvc.c | 114 ++++++++++++++++++++++++++++++++++++++++++++++++++++
> libstb/cvc.h | 29 +++++++++++++
> 6 files changed, 248 insertions(+), 1 deletion(-)
> create mode 100644 libstb/cvc.c
> create mode 100644 libstb/cvc.h
>
> diff --git a/hdata/spira.h b/hdata/spira.h
> index 88fd2bf..328fb8d 100644
> --- a/hdata/spira.h
> +++ b/hdata/spira.h
> @@ -528,6 +528,8 @@ struct msvpd_trace {
> /* Idata index 5: Hostboot reserved memory address range */
> #define MSVPD_IDATA_HB_RESERVED_MEM 5
> struct msvpd_hb_reserved_mem {
> +#define MSVPD_HBRMEM_RANGE_TYPE PPC_BITMASK32(0,7)
> +#define HBRMEM_CONTAINER_VERIFICATION_CODE 0x3
> __be32 type_instance;
> __be64 start_addr;
> __be64 end_addr;
> @@ -1258,6 +1260,16 @@ struct secureboot_tpm_info {
> __be32 drtm_log_size;
> } __packed;
>
> +/* Idata index 2: Hash and Verification Function Offsets Array */
> +#define TPMREL_IDATA_HASH_VERIF_OFFSETS 2
> +
> +struct hash_and_verification {
> + __be32 type;
> + __be32 version;
> + __be32 dbob_id;
> + __be32 offset;
> +} __packed;
> +
> static inline const char *cpu_state(u32 flags)
> {
> switch ((flags & CPU_ID_VERIFY_MASK) >> CPU_ID_VERIFY_SHIFT) {
> diff --git a/hdata/test/stubs.c b/hdata/test/stubs.c
> index abeb832..ce1384d 100644
> --- a/hdata/test/stubs.c
> +++ b/hdata/test/stubs.c
> @@ -117,4 +117,6 @@ NOOP_STUB(mem_reserve_hwbuf);
> NOOP_STUB(add_chip_dev_associativity);
> NOOP_STUB(enable_mambo_console);
> NOOP_STUB(backtrace);
> +NOOP_STUB(cvc_register);
> +NOOP_STUB(cvc_service_register);
>
> diff --git a/hdata/tpmrel.c b/hdata/tpmrel.c
> index 0aaa70b..11ed3ce 100644
> --- a/hdata/tpmrel.c
> +++ b/hdata/tpmrel.c
> @@ -20,6 +20,8 @@
>
> #include <skiboot.h>
> #include <device.h>
> +#include <inttypes.h>
> +#include <libstb/cvc.h>
>
> #include "spira.h"
> #include "hdata.h"
> @@ -72,6 +74,93 @@ static void tpmrel_add_firmware_event_log(const struct HDIF_common_hdr *hdif_hdr
> }
> }
>
> +static const struct msvpd_hb_reserved_mem *get_cvc_reserved_memory(void)
> +{
> +
> + const struct msvpd_hb_reserved_mem *hb_resv_mem;
> + const struct HDIF_common_hdr *ms_vpd;
> + uint32_t type;
> + int count, i;
> +
> + ms_vpd = get_hdif(&spira.ntuples.ms_vpd, MSVPD_HDIF_SIG);
> +
> + if (!ms_vpd) {
> + prlog(PR_ERR, "MS VPD invalid\n");
> + return NULL;
> + }
> +
> + count = HDIF_get_iarray_size(ms_vpd, MSVPD_IDATA_HB_RESERVED_MEM);
> + if (count <= 0) {
> + prlog(PR_ERR, "no hostboot reserved memory found\n");
> + return NULL;
> + }
> +
> + for (i = 0; i < count; i++) {
> + hb_resv_mem = HDIF_get_iarray_item(ms_vpd,
> + MSVPD_IDATA_HB_RESERVED_MEM,
> + i, NULL);
> + if (!CHECK_SPPTR(hb_resv_mem))
> + continue;
> +
> + type = be32_to_cpu(hb_resv_mem->type_instance);
> + type = GETFIELD(MSVPD_HBRMEM_RANGE_TYPE, type);
> +
> + /* Reserved memory for the Container Verification Code? */
> + if (type == HBRMEM_CONTAINER_VERIFICATION_CODE)
> + return hb_resv_mem;
> + }
> +
> + return NULL;
> +}
> +
> +#define HRMOR_BIT (1ul << 63)
> +
> +static void tpmrel_cvc_init(struct HDIF_common_hdr *hdif_hdr)
> +{
> + const struct hash_and_verification *hv;
> + const struct msvpd_hb_reserved_mem *cvc_resv_mem;
> + uint32_t type, version, offset;
> + uint64_t start_addr, end_addr;
> + int count, i;
> +
> + cvc_resv_mem = get_cvc_reserved_memory();
> +
> + if (!cvc_resv_mem) {
> + prlog(PR_ERR, "CVC reserved memory not found\n");
> + return;
> + }
> +
> + start_addr = be64_to_cpu(cvc_resv_mem->start_addr);
> + start_addr &= ~HRMOR_BIT;
> + end_addr = be64_to_cpu(cvc_resv_mem->end_addr);
> + end_addr &= ~HRMOR_BIT;
> + prlog(PR_DEBUG, "Found CVC at 0x%"PRIx64"...0x%"PRIx64"\n",
> + start_addr, end_addr);
The parsing here seems to be a duplicate of what's in memory.c. At
this point it should have already been parsed into
/ibm,hostboot/reserved-memory/ in the device-tree, so why not look it
up there?
> + cvc_register(start_addr, end_addr);
As an aside we try to keep this sort of thing out of the HDAT parser.
In theory we should be able to boot off just a device-tree and have
everything work. The main application of that is allowing cronus
booting. Granted secure cronus booting doesn't make a whole lot of
sense it's not really a problem here, but it's something to keep in
mind.
> + /*
> + * Initialize each service provided by the container verification code
> + */
> + count = HDIF_get_iarray_size(hdif_hdr, TPMREL_IDATA_HASH_VERIF_OFFSETS);
> + if (count <= 0 ) {
> + prlog(PR_ERR, "no CVC service found\n");
> + return;
> + }
> +
> + for (i = 0; i < count; i++) {
> +
> + hv = HDIF_get_iarray_item(hdif_hdr,
> + TPMREL_IDATA_HASH_VERIF_OFFSETS,
> + i, NULL);
> + type = be32_to_cpu(hv->type);
> + version = be32_to_cpu(hv->version);
> + offset = be32_to_cpu(hv->offset);
> +
> + prlog(PR_DEBUG, "Found CVC service. type=0x%x version=%d "
> + "offset=0x%x\n", type, version, offset);
> + cvc_service_register(type, version, offset);
> + }
> +}
> +
> void node_stb_parse(void)
> {
> struct HDIF_common_hdr *hdif_hdr;
> @@ -87,4 +176,5 @@ void node_stb_parse(void)
> }
>
> tpmrel_add_firmware_event_log(hdif_hdr);
> + tpmrel_cvc_init(hdif_hdr);
> }
> diff --git a/libstb/Makefile.inc b/libstb/Makefile.inc
> index 64be4d6..010e4b1 100644
> --- a/libstb/Makefile.inc
> +++ b/libstb/Makefile.inc
> @@ -4,7 +4,7 @@ LIBSTB_DIR = libstb
>
> SUBDIRS += $(LIBSTB_DIR)
>
> -LIBSTB_SRCS = container.c rom.c tpm_chip.c stb.c
> +LIBSTB_SRCS = container.c rom.c tpm_chip.c stb.c cvc.c
> LIBSTB_OBJS = $(LIBSTB_SRCS:%.c=%.o)
> LIBSTB = $(LIBSTB_DIR)/built-in.o
>
> diff --git a/libstb/cvc.c b/libstb/cvc.c
> new file mode 100644
> index 0000000..ebf0ecf
> --- /dev/null
> +++ b/libstb/cvc.c
> @@ -0,0 +1,114 @@
> +/* Copyright 2013-2017 IBM Corp.
> + *
> + * Licensed under the Apache License, Version 2.0 (the "License");
> + * you may not use this file except in compliance with the License.
> + * You may obtain a copy of the License at
> + *
> + * http://www.apache.org/licenses/LICENSE-2.0
> + *
> + * Unless required by applicable law or agreed to in writing, software
> + * distributed under the License is distributed on an "AS IS" BASIS,
> + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
> + * implied.
> + * See the License for the specific language governing permissions and
> + * limitations under the License.
> + */
> +
> +#ifndef pr_fmt
> +#define pr_fmt(fmt) "STB: " fmt
> +#endif
> +
> +#include <skiboot.h>
> +#include "cvc.h"
> +
> +struct cvc_service {
> + int id;
> + uint64_t addr; /* base_addr + offset */
> + uint32_t version;
> + struct list_node link;
> +};
> +
> +struct container_verification_code {
> + uint64_t start_addr;
> + uint64_t end_addr;
> + struct list_head service_list;
> +};
> +
> +static struct {
> + enum cvc_service_id id;
> + const char *name;
> +} cvc_sevice_map[] = {
> + { CVC_SHA512_SERVICE, "sha512" },
> + { CVC_VERIFY_SERVICE, "verify" },
> +};
> +
> +static struct container_verification_code *cvc = NULL;
> +
> +static struct cvc_service *cvc_find_service(enum cvc_service_id id)
> +{
> + struct cvc_service *service;
> + if (!cvc)
> + return NULL;
> +
> + list_for_each(&cvc->service_list, service, link) {
> + if (service->id == id)
> + return service;
> + }
> + return NULL;
> +}
> +
> +static const char *cvc_get_service_name(enum cvc_service_id id)
> +{
> + int i;
> +
> + for (i = 0; i < ARRAY_SIZE(cvc_sevice_map); i++) {
> + if (cvc_sevice_map[i].id == id)
> + return cvc_sevice_map[i].name;
> + }
> + return NULL;
> +}
> +
> +void cvc_register(uint64_t start_addr, uint64_t end_addr)
> +{
> + if (cvc)
> + return;
> +
> + cvc = malloc(sizeof(struct container_verification_code));
> + assert(cvc);
> + cvc->start_addr = start_addr;
> + cvc->end_addr = end_addr;
> + list_head_init(&cvc->service_list);
> +}
> +
> +void cvc_service_register(uint32_t id, uint32_t version, uint32_t offset)
> +{
> + struct cvc_service *service;
> + const char *name;
> +
> + if (!cvc)
> + return;
> +
> + /* Service already registered? */
> + if (cvc_find_service(id))
> + return;
> +
> + if (cvc->start_addr + offset > cvc->end_addr) {
> + prlog(PR_WARNING, "CVC offset %x out of range, "
> + "id=0x%x\n", offset, id);
> + return;
> + }
> +
> + name = cvc_get_service_name(id);
> + if (!name) {
> + prlog(PR_ERR, "CVC service 0x%x not supported\n", id);
> + return;
> + }
> +
> + service = malloc(sizeof(struct cvc_service));
> + assert(service);
> + service->id = id;
> + service->version = version;
> + service->addr = cvc->start_addr + offset;
> + list_add_tail(&cvc->service_list, &service->link);
> + prlog(PR_INFO, "CVC-%s service found @0x%llx\n", name, service->addr);
> +}
> diff --git a/libstb/cvc.h b/libstb/cvc.h
> new file mode 100644
> index 0000000..8b5700c
> --- /dev/null
> +++ b/libstb/cvc.h
> @@ -0,0 +1,29 @@
> +/* Copyright 2013-2017 IBM Corp.
> + *
> + * Licensed under the Apache License, Version 2.0 (the "License");
> + * you may not use this file except in compliance with the License.
> + * You may obtain a copy of the License at
> + *
> + * http://www.apache.org/licenses/LICENSE-2.0
> + *
> + * Unless required by applicable law or agreed to in writing, software
> + * distributed under the License is distributed on an "AS IS" BASIS,
> + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
> + * implied.
> + * See the License for the specific language governing permissions and
> + * limitations under the License.
> + */
> +
> +#ifndef __CVC_H
> +#define __CVC_H
> +
> +/* As defined in the HDAT spec version 10.5e */
> +enum cvc_service_id {
> + CVC_SHA512_SERVICE = 0x00,
> + CVC_VERIFY_SERVICE = 0x01,
> +};
> +
> +void cvc_register(uint64_t start_addr, uint64_t end_addr);
> +void cvc_service_register(uint32_t type, uint32_t version, uint32_t offset);
> +
> +#endif /* __CVC_H */
> --
> 2.7.4
>
More information about the Skiboot
mailing list