From patchwork Sat Nov 11 17:28:27 2017 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Claudio Carvalho X-Patchwork-Id: 837052 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Received: from lists.ozlabs.org (lists.ozlabs.org [IPv6:2401:3900:2:1::3]) (using TLSv1.2 with cipher ADH-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by ozlabs.org (Postfix) with ESMTPS id 3yZ3pW6BXKz9sNd for ; Sun, 12 Nov 2017 04:30:59 +1100 (AEDT) Received: from lists.ozlabs.org (lists.ozlabs.org [IPv6:2401:3900:2:1::3]) by lists.ozlabs.org (Postfix) with ESMTP id 3yZ3pW51hZzDrLh for ; Sun, 12 Nov 2017 04:30:59 +1100 (AEDT) X-Original-To: skiboot@lists.ozlabs.org Delivered-To: skiboot@lists.ozlabs.org Authentication-Results: ozlabs.org; spf=none (mailfrom) smtp.mailfrom=linux.vnet.ibm.com (client-ip=148.163.156.1; helo=mx0a-001b2d01.pphosted.com; envelope-from=cclaudio@linux.vnet.ibm.com; receiver=) Received: from mx0a-001b2d01.pphosted.com (mx0a-001b2d01.pphosted.com [148.163.156.1]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by lists.ozlabs.org (Postfix) with ESMTPS id 3yZ3mD0KVbzDrLT for ; Sun, 12 Nov 2017 04:28:59 +1100 (AEDT) Received: from pps.filterd (m0098404.ppops.net [127.0.0.1]) by mx0a-001b2d01.pphosted.com (8.16.0.21/8.16.0.21) with SMTP id vABHRnv7064825 for ; Sat, 11 Nov 2017 12:28:57 -0500 Received: from e38.co.us.ibm.com (e38.co.us.ibm.com [32.97.110.159]) by mx0a-001b2d01.pphosted.com with ESMTP id 2e5x60w01f-1 (version=TLSv1.2 cipher=AES256-SHA bits=256 verify=NOT) for ; Sat, 11 Nov 2017 12:28:57 -0500 Received: from localhost by e38.co.us.ibm.com with IBM ESMTP SMTP Gateway: Authorized Use Only! Violators will be prosecuted for from ; Sat, 11 Nov 2017 10:28:56 -0700 Received: from b03cxnp08027.gho.boulder.ibm.com (9.17.130.19) by e38.co.us.ibm.com (192.168.1.138) with IBM ESMTP SMTP Gateway: Authorized Use Only! Violators will be prosecuted; Sat, 11 Nov 2017 10:28:55 -0700 Received: from b03ledav006.gho.boulder.ibm.com (b03ledav006.gho.boulder.ibm.com [9.17.130.237]) by b03cxnp08027.gho.boulder.ibm.com (8.14.9/8.14.9/NCO v10.0) with ESMTP id vABHSthw64749658; Sat, 11 Nov 2017 10:28:55 -0700 Received: from b03ledav006.gho.boulder.ibm.com (unknown [127.0.0.1]) by IMSVA (Postfix) with ESMTP id E38EAC6037; Sat, 11 Nov 2017 10:28:54 -0700 (MST) Received: from legolas.ibm.com (unknown [9.85.175.178]) by b03ledav006.gho.boulder.ibm.com (Postfix) with ESMTP id EC82EC603E; Sat, 11 Nov 2017 10:28:53 -0700 (MST) From: Claudio Carvalho To: skiboot@lists.ozlabs.org Date: Sat, 11 Nov 2017 15:28:27 -0200 X-Mailer: git-send-email 2.7.4 In-Reply-To: <1510421322-27237-1-git-send-email-cclaudio@linux.vnet.ibm.com> References: <1510421322-27237-1-git-send-email-cclaudio@linux.vnet.ibm.com> X-TM-AS-GCONF: 00 x-cbid: 17111117-0028-0000-0000-000008A2924E X-IBM-SpamModules-Scores: X-IBM-SpamModules-Versions: BY=3.00008052; HX=3.00000241; KW=3.00000007; PH=3.00000004; SC=3.00000239; SDB=6.00944424; UDB=6.00476526; IPR=6.00724686; BA=6.00005688; NDR=6.00000001; ZLA=6.00000005; ZF=6.00000009; ZB=6.00000000; ZP=6.00000000; ZH=6.00000000; ZU=6.00000002; MB=3.00017969; XFM=3.00000015; UTC=2017-11-11 17:28:56 X-IBM-AV-DETECTION: SAVI=unused REMOTE=unused XFE=unused x-cbparentid: 17111117-0029-0000-0000-0000384ADE44 Message-Id: <1510421322-27237-5-git-send-email-cclaudio@linux.vnet.ibm.com> X-Proofpoint-Virus-Version: vendor=fsecure engine=2.50.10432:, , definitions=2017-11-11_05:, , signatures=0 X-Proofpoint-Spam-Details: rule=outbound_notspam policy=outbound score=0 priorityscore=1501 malwarescore=0 suspectscore=1 phishscore=0 bulkscore=0 spamscore=0 clxscore=1015 lowpriorityscore=0 impostorscore=0 adultscore=0 classifier=spam adjust=0 reason=mlx scancount=1 engine=8.0.1-1707230000 definitions=main-1711110250 Subject: [Skiboot] [PATCH 04/19] hdata/tpmrel.c: register CVC services during HDAT parsing X-BeenThere: skiboot@lists.ozlabs.org X-Mailman-Version: 2.1.24 Precedence: list List-Id: Mailing list for skiboot development List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , MIME-Version: 1.0 Errors-To: skiboot-bounces+incoming=patchwork.ozlabs.org@lists.ozlabs.org Sender: "Skiboot" 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 --- 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 #include +#include +#include #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); + cvc_register(start_addr, end_addr); + /* + * 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 +#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 */