[Skiboot] [PATCH v2 06/20] libstb/trustedboot.c: import tb_measure() from stb.c

Claudio Carvalho cclaudio at linux.vnet.ibm.com
Sat Dec 9 15:52:20 AEDT 2017


This imports tb_measure() from stb.c, but now it calls the CVC sha512
wrapper to calculate the sha512 hash of the firmware image provided.

In trustedboot.c, the tb_measure() is renamed to trustedboot_measure().

The new function, trustedboot_measure(), no longer checks if the
container payload hash calculated at boot time matches with the hash
found in the container header. A few reasons:
	- If the system admin wants the container header to be
	  checked/validated, the secure boot jumper must be set. Otherwise,
	  the container header information may not be reliable.
	- The container layout is expected to change over time. Skiboot
	  would need to maintain a parser for each container layout
	  change.
	- Skiboot could be checking the hash against a container version that
	  is not supported by the Container-Verification-Code (CVC).

The tb_measure() calls are updated to trustedboot_measure() in a
subsequent patch.

Signed-off-by: Claudio Carvalho <cclaudio at linux.vnet.ibm.com>
---
 asm/cvc_entry.S          |   4 +-
 libstb/cvc.c             |  28 ++++++++++++
 libstb/cvc.h             |  13 ++++++
 libstb/drivers/romcode.c |   4 +-
 libstb/trustedboot.c     | 112 +++++++++++++++++++++++++++++++++++++++++++++++
 libstb/trustedboot.h     |  18 ++++++++
 6 files changed, 175 insertions(+), 4 deletions(-)

diff --git a/asm/cvc_entry.S b/asm/cvc_entry.S
index ccca006..069ed09 100644
--- a/asm/cvc_entry.S
+++ b/asm/cvc_entry.S
@@ -26,10 +26,10 @@
 .section .text
 
 .global __cvc_verify_v1
-.global call_rom_SHA512
+.global __cvc_sha512_v1
 
 __cvc_verify_v1:
-call_rom_SHA512:
+__cvc_sha512_v1:
 
 call_rom_entry:
     std %r2, 40(%r1)
diff --git a/libstb/cvc.c b/libstb/cvc.c
index 96c48f4..b0f5cd3 100644
--- a/libstb/cvc.c
+++ b/libstb/cvc.c
@@ -33,6 +33,8 @@
  */
 ROM_response __cvc_verify_v1(void *func_ptr, ROM_container_raw *container,
 			     ROM_hw_params *params);
+void __cvc_sha512_v1(void *func_ptr, const uint8_t *data, size_t len,
+		     uint8_t *digest);
 
 struct container_verification_code {
 	uint64_t start_addr;
@@ -200,6 +202,32 @@ int cvc_init(void)
 	return rc;
 }
 
+int call_cvc_sha512(const uint8_t *data, size_t data_len, uint8_t *digest,
+		   size_t digest_size)
+{
+	struct cvc_service *service;
+
+	if (!data || !digest || digest_size < SHA512_DIGEST_LENGTH)
+		return OPAL_PARAMETER;
+
+	if (data_len <= 0)
+		return OPAL_SUCCESS;
+
+	memset(digest, 0, SHA512_DIGEST_LENGTH);
+
+	service = cvc_find_service(CVC_SHA512_SERVICE);
+
+	if (!service)
+		return OPAL_UNSUPPORTED;
+
+	if (service->version == 1)
+		__cvc_sha512_v1((void*) service->addr, data, data_len, digest);
+	else
+		return OPAL_UNSUPPORTED;
+
+	return OPAL_SUCCESS;
+}
+
 int call_cvc_verify(void *container, size_t len, const void *hw_key_hash,
 		    size_t hw_key_hash_size, uint64_t *log)
 {
diff --git a/libstb/cvc.h b/libstb/cvc.h
index 14e8cd2..13c1b33 100644
--- a/libstb/cvc.h
+++ b/libstb/cvc.h
@@ -44,4 +44,17 @@ int cvc_init(void);
 int call_cvc_verify(void *buf, size_t size, const void *hw_key_hash,
 		    size_t hw_key_hash_size, uint64_t *log);
 
+/*
+ * call_cvc_sha512 - Call the CVC-sha512 service to calculate a sha512 hash.
+ *
+ * @data - buffer that has data to be hashed
+ * @data_len - number of bytes from @data to be considered in the hash
+ * calculation
+ * @digest - buffer to store the calculated hash
+ * @digest_size - number of bytes allocated for @digest
+ *
+ */
+int call_cvc_sha512(const uint8_t *data, size_t data_len, uint8_t *digest,
+		    size_t digest_size);
+
 #endif /* __CVC_H */
diff --git a/libstb/drivers/romcode.c b/libstb/drivers/romcode.c
index d914ba1..ab5f1aa 100644
--- a/libstb/drivers/romcode.c
+++ b/libstb/drivers/romcode.c
@@ -44,7 +44,7 @@ static sha2_hash_t *hw_key_hash = NULL;
  */
 ROM_response __cvc_verify_v1(void *func_ptr, ROM_container_raw *container,
 			     ROM_hw_params *params);
-void call_rom_SHA512(void *func_ptr, const uint8_t *data, size_t len,
+void __cvc_sha512_v1(void *func_ptr, const uint8_t *data, size_t len,
 		     uint8_t *digest);
 
 static int romcode_verify(void *container)
@@ -71,7 +71,7 @@ static int romcode_verify(void *container)
 static void romcode_sha512(const uint8_t *data, size_t len, uint8_t *digest)
 {
 	memset(digest, 0, sizeof(sha2_hash_t));
-	call_rom_SHA512(romcode_base_addr + ROMCODE_SHA512_OFFSET,
+	__cvc_sha512_v1(romcode_base_addr + ROMCODE_SHA512_OFFSET,
 			data, len, digest);
 }
 
diff --git a/libstb/trustedboot.c b/libstb/trustedboot.c
index 9644d1a..f829c0b 100644
--- a/libstb/trustedboot.c
+++ b/libstb/trustedboot.c
@@ -21,12 +21,41 @@
 #include <skiboot.h>
 #include <device.h>
 #include <nvram.h>
+#include <opal-api.h>
 #include "secureboot.h"
 #include "trustedboot.h"
 #include "tpm_chip.h"
 
+/* For debugging only */
+//#define STB_DEBUG
+
 static bool trusted_mode = false;
 
+/*
+ * This maps a PCR for each resource we can measure. The PCR number is
+ * mapped according to the TCG PC Client Platform Firmware Profile
+ * specification, Revision 00.21
+ * Only resources included in this whitelist can be measured.
+ */
+static struct {
+	enum resource_id id;
+	TPM_Pcr pcr;
+} resources[] = {
+	{ RESOURCE_ID_IMA_CATALOG, PCR_2 },
+	{ RESOURCE_ID_KERNEL, PCR_4 },
+	{ RESOURCE_ID_CAPP,   PCR_2 },
+};
+
+static TPM_Pcr map_pcr(enum resource_id id)
+{
+	int i;
+	for (i = 0; i < ARRAY_SIZE(resources); i++) {
+		if (resources[i].id == id)
+			return resources[i].pcr;
+	}
+	return -1;
+}
+
 void trustedboot_init(void)
 {
 	struct dt_node *node;
@@ -61,6 +90,89 @@ void trustedboot_init(void)
 
 	if (!trusted_mode)
 		return;
+
 	cvc_init();
 	tpm_init();
 }
+
+int trustedboot_measure(enum resource_id id, void *buf, size_t len)
+{
+	uint8_t digest[SHA512_DIGEST_LENGTH];
+	void *buf_aux;
+	size_t len_aux;
+	const char *name;
+	TPM_Pcr pcr;
+	int rc = -1;
+
+	if (!trusted_mode)
+		return 1;
+
+	name = flash_map_resource_name(id);
+	if (!name) {
+		/**
+		 * @fwts-label ResourceNotMeasuredUnknown
+		 * @fwts-advice This is a bug in the trustedboot_measure()
+		 * caller, which is passing an unknown resource_id.
+		 */
+		prlog(PR_ERR, "resource NOT MEASURED, resource_id=%d unknown\n", id);
+		return -1;
+	}
+	pcr = map_pcr(id);
+	if (pcr == -1) {
+		/**
+		 * @fwts-label ResourceNotMappedToPCR
+		 * @fwts-advice This is a bug. The resource cannot be measured
+		 * because it is not mapped to a PCR in the resources[] array.
+		 */
+		prlog(PR_ERR, "%s NOT MEASURED, it's not mapped to a PCR\n", name);
+		return -1;
+	}
+	if (!buf) {
+		/**
+		 * @fwts-label ResourceNotMeasuredNull
+		 * @fwts-advice This is a bug. The trustedboot_measure() caller
+		 * provided a NULL container.
+		 */
+		prlog(PR_ERR, "%s NOT MEASURED, it's null\n", name);
+		return -1;
+	}
+	if (stb_is_container(buf, len)) {
+		buf_aux = buf + SECURE_BOOT_HEADERS_SIZE;
+		len_aux = len - SECURE_BOOT_HEADERS_SIZE;
+	} else {
+		buf_aux = buf;
+		len_aux = len;
+	}
+
+	rc = call_cvc_sha512(buf_aux, len_aux, digest, SHA512_DIGEST_LENGTH);
+
+	if (rc == OPAL_SUCCESS) {
+		prlog(PR_INFO, "%s hash calculated\n", name);
+	} else if (rc == OPAL_PARAMETER) {
+		prlog(PR_ERR, "%s NOT MEASURED, invalid param. buf=%p, "
+		      "len=%zd, digest=%p\n", name, buf_aux,
+		      len_aux, digest);
+		return -1;
+	} else if (rc == OPAL_UNSUPPORTED) {
+		prlog(PR_ERR, "%s NOT MEASURED, CVC-sha512 service not "
+		      "supported\n", name);
+		return -1;
+	} else {
+		prlog(PR_ERR, "%s NOT MEASURED, unknown CVC-sha512 error. "
+		      "rc=%d\n", name, rc);
+		return -1;
+	}
+
+#ifdef STB_DEBUG
+	stb_print_data(digest, TPM_ALG_SHA256_SIZE);
+#endif
+	/*
+	 * Extend the given PCR number in both sha256 and sha1 banks with the
+	 * sha512 hash calculated. The hash is truncated accordingly to fit the
+	 * PCR.
+	 */
+	return tpm_extendl(pcr,
+			   TPM_ALG_SHA256, digest, TPM_ALG_SHA256_SIZE,
+			   TPM_ALG_SHA1,   digest, TPM_ALG_SHA1_SIZE,
+			   EV_ACTION, name);
+}
diff --git a/libstb/trustedboot.h b/libstb/trustedboot.h
index 4597514..bd5ac91 100644
--- a/libstb/trustedboot.h
+++ b/libstb/trustedboot.h
@@ -17,6 +17,24 @@
 #ifndef __TRUSTEDBOOT_H
 #define __TRUSTEDBOOT_H
 
+#include <platform.h>
+
 void trustedboot_init(void);
 
+/**
+ * trustedboot_measure - measure a resource
+ * @id    : resource id
+ * @buf   : data to be measured
+ * @len   : buf length
+ *
+ * This measures a resource downloaded from PNOR if trusted mode is on. That is,
+ * an EV_ACTION event is recorded in the event log for the mapped PCR, and the
+ * the sha1 and sha256 measurements are extended in the mapped PCR.
+ *
+ * For more information please refer to 'doc/stb.rst'
+ *
+ * returns: 0 or an error as defined in status_codes.h
+ */
+int trustedboot_measure(enum resource_id id, void *buf, size_t len);
+
 #endif /* __TRUSTEDBOOT_H */
-- 
2.7.4



More information about the Skiboot mailing list