[Skiboot] [PATCH v2 17/20] hdata/tpmrel.c: add ibm, cvc device tree node
Claudio Carvalho
cclaudio at linux.vnet.ibm.com
Sat Dec 9 15:52:31 AEDT 2017
In P9, the Container Verification Code is stored in a hostboot reserved
memory and the list of provided CVC services is stored in the
TPMREL_IDATA_HASH_VERIF_OFFSETS idata array. Each CVC service has an
offset and version.
This adds the ibm,cvc device tree node and its documentation.
Signed-off-by: Claudio Carvalho <cclaudio at linux.vnet.ibm.com>
---
doc/device-tree/ibm,cvc.rst | 47 ++++++++++++++++++++
hdata/spira.h | 14 ++++++
hdata/tpmrel.c | 105 ++++++++++++++++++++++++++++++++++++++++++++
3 files changed, 166 insertions(+)
create mode 100644 doc/device-tree/ibm,cvc.rst
diff --git a/doc/device-tree/ibm,cvc.rst b/doc/device-tree/ibm,cvc.rst
new file mode 100644
index 0000000..c53df24
--- /dev/null
+++ b/doc/device-tree/ibm,cvc.rst
@@ -0,0 +1,47 @@
+.. _device-tree/ibm,cvc:
+
+ibm,cvc
+=======
+
+This describes the code (a.k.a container verification code) that skiboot uses
+to verify signed firmware blobs. Each ibm,cvc child node describes CVC service,
+which has a version and offset (reg).
+
+Added in the device tree from ``ibm,secureboot-v2``.
+
+Required properties
+-------------------
+
+.. code-block:: none
+
+ compatible: should be "ibm,container-verification-code"
+
+ memory-region: this points to the reserved memory where the
+ container-verification-code is stored.
+
+Example
+-------
+
+.. code-block:: dts
+
+ ibm,cvc {
+ phandle = <0x10f>;
+ #address-cells = <0x1>;
+ #size-cells = <0x0>;
+ compatible = "ibm,container-verification-code";
+ memory-region = <0xaa>;
+
+ ibm,cvc-service at 40 {
+ phandle = <0x110>;
+ compatible = "ibm,cvc-sha512";
+ reg = <0x40>;
+ version = <0x1>;
+ };
+
+ ibm,cvc-service at 50 {
+ phandle = <0x111>;
+ compatible = "ibm,cvc-verify";
+ reg = <0x50>;
+ version = <0x1>;
+ };
+ };
diff --git a/hdata/spira.h b/hdata/spira.h
index e2d45ab..2ef13f3 100644
--- a/hdata/spira.h
+++ b/hdata/spira.h
@@ -529,6 +529,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;
@@ -1259,6 +1261,18 @@ 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 {
+#define TPMREL_HV_SHA512 0x00
+#define TPMREL_HV_VERIFY 0x01
+ __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/tpmrel.c b/hdata/tpmrel.c
index 5b6731f..9b09765 100644
--- a/hdata/tpmrel.c
+++ b/hdata/tpmrel.c
@@ -102,6 +102,110 @@ static void tpmrel_add_firmware_event_log(const struct HDIF_common_hdr *hdif_hdr
}
}
+static struct dt_node *get_hb_reserved_memory(const char *label)
+{
+ struct dt_node *node, *hb_reserved_mem;
+
+ hb_reserved_mem = dt_find_by_path(dt_root, "/ibm,hostboot/reserved-memory");
+ if (!hb_reserved_mem) {
+ prlog(PR_DEBUG, "/ibm,hostboot/reserved-memory node not found\n");
+ return NULL;
+ }
+
+ dt_for_each_node(hb_reserved_mem, node) {
+ const char *prd_label;
+ if (!dt_find_property(node, "ibm,prd-label"))
+ continue;
+ prd_label = dt_prop_get(node, "ibm,prd-label");
+ if (!strcmp(prd_label, label))
+ return node;
+ }
+ return NULL;
+}
+
+struct {
+ uint32_t type;
+ const char *compat;
+} cvc_services[] = {
+ { TPMREL_HV_SHA512, "ibm,cvc-sha512" },
+ { TPMREL_HV_VERIFY, "ibm,cvc-verify" },
+};
+
+static const char* cvc_service_map_compat(uint32_t type) {
+ int i;
+ for (i = 0; i < ARRAY_SIZE(cvc_services); i++) {
+ if (cvc_services[i].type == type)
+ return cvc_services[i].compat;
+ }
+ return NULL;
+}
+
+static void tpmrel_cvc_init(struct HDIF_common_hdr *hdif_hdr)
+{
+ struct dt_node *cvc_reserved_mem, *node, *parent;
+ int count, i;
+ unsigned int asize;
+
+ /* Are the hdat values populated? */
+ if (!HDIF_get_idata(hdif_hdr, TPMREL_IDATA_HASH_VERIF_OFFSETS, &asize))
+ return;
+ if (asize < sizeof(struct HDIF_array_hdr)) {
+ prlog(PR_ERR, "hash_and_verification idata not populated\n");
+ return;
+ }
+
+ node = dt_find_by_path(dt_root, "/ibm,secureboot");
+ if (!node)
+ return;
+
+ cvc_reserved_mem = get_hb_reserved_memory("ibm,secure-crypt-algo-code");
+ if (!cvc_reserved_mem) {
+ prlog(PR_ERR, "CVC reserved memory not found\n");
+ return;
+ }
+
+ parent = dt_new(node, "ibm,cvc");
+ assert(parent);
+ dt_add_property_cells(parent, "#address-cells", 1);
+ dt_add_property_cells(parent, "#size-cells", 0);
+ dt_add_property_strings(parent, "compatible", "ibm,container-verification-code");
+ dt_add_property_cells(parent, "memory-region", cvc_reserved_mem->phandle);
+
+ /*
+ * 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++) {
+ const struct hash_and_verification *hv;
+ uint32_t type, offset, version;
+ const char *compat;
+
+ hv = HDIF_get_iarray_item(hdif_hdr,
+ TPMREL_IDATA_HASH_VERIF_OFFSETS,
+ i, NULL);
+ type = be32_to_cpu(hv->type);
+ offset = be32_to_cpu(hv->offset);
+ version = be32_to_cpu(hv->version);
+
+ compat = cvc_service_map_compat(type);
+
+ if (!compat) {
+ prlog(PR_WARNING, "CVC service type 0x%x unknown\n", type);
+ continue;
+ }
+
+ node = dt_new_addr(parent, "ibm,cvc-service", offset);
+ dt_add_property_strings(node, "compatible", compat);
+ dt_add_property_cells(node, "reg", offset);
+ dt_add_property_cells(node, "version", version);
+ }
+}
+
void node_stb_parse(void)
{
struct HDIF_common_hdr *hdif_hdr;
@@ -113,4 +217,5 @@ void node_stb_parse(void)
}
tpmrel_add_firmware_event_log(hdif_hdr);
+ tpmrel_cvc_init(hdif_hdr);
}
--
2.7.4
More information about the Skiboot
mailing list