[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