[v2,12/14] libstb: check container version before using it

Message ID 1504164285-15095-13-git-send-email-cclaudio@linux.vnet.ibm.com
State Superseded
Headers show
Series
  • libstb: simplify the initialization of cvc drivers
Related show

Commit Message

Claudio Carvalho Aug. 31, 2017, 7:24 a.m.
Secureboot containers can be built for any cvc version, including one
that is not supported by skiboot. The version is stored in the
container.

This checks the container version before using it.

Signed-off-by: Claudio Carvalho <cclaudio@linux.vnet.ibm.com>
---
 libstb/container.c | 47 +++++++++++++++++++++++++++++++++++++----------
 libstb/container.h |  9 +++++++--
 libstb/stb.c       | 32 +++++++++++++++++++++++---------
 3 files changed, 67 insertions(+), 21 deletions(-)

Patch

diff --git a/libstb/container.c b/libstb/container.c
index a720fbb..d421bd7 100644
--- a/libstb/container.c
+++ b/libstb/container.c
@@ -17,6 +17,17 @@ 
 #include <skiboot.h>
 #include "container.h"
 
+uint16_t stb_container_version(const void *buf, size_t size)
+{
+	ROM_container_raw *c;
+
+	if (!stb_is_container(buf, size))
+		return 0;
+	c = (ROM_container_raw*) buf;
+
+	return be16_to_cpu(c->version);
+}
+
 bool stb_is_container(const void *buf, size_t size)
 {
 	ROM_container_raw *c;
@@ -29,6 +40,15 @@  bool stb_is_container(const void *buf, size_t size)
 	return true;
 }
 
+uint32_t stb_container_magic(const void *buf, size_t size)
+{
+	ROM_container_raw *c;
+	if (!stb_is_container(buf, size))
+		return 0;
+	c = (ROM_container_raw*) buf;
+	return be32_to_cpu(c->magic_number);
+}
+
 uint32_t stb_payload_magic(const void *buf, size_t size)
 {
 	uint8_t *p;
@@ -40,15 +60,19 @@  uint32_t stb_payload_magic(const void *buf, size_t size)
 
 uint64_t stb_sw_payload_size(const void *buf, size_t size)
 {
-	struct parsed_stb_container c;
+	struct parsed_stb_container_v1 c;
 	if (!stb_is_container(buf, size))
 		return 0;
-	if (parse_stb_container(buf, size, &c) != 0)
-		return 0;
-	return be64_to_cpu(c.sh->payload_size);
+	/* Container v1 */
+	if (stb_container_version(buf, size) == 1) {
+		if (parse_stb_container_v1(buf, size, &c) != 0)
+			return 0;
+		return be64_to_cpu(c.sh->payload_size);
+	}
+	return 0;
 }
 
-int parse_stb_container(const void* data, size_t len, struct parsed_stb_container *c)
+int parse_stb_container_v1(const void* data, size_t len, struct parsed_stb_container_v1 *c)
 {
 	const size_t prefix_data_min_size = 3 * (EC_COORDBYTES * 2);
 	c->buf = data;
@@ -65,14 +89,17 @@  int parse_stb_container(const void* data, size_t len, struct parsed_stb_containe
 
 const uint8_t* stb_sw_payload_hash(const void *buf, size_t size)
 {
-	struct parsed_stb_container c;
+	struct parsed_stb_container_v1 c;
 
 	if (!stb_is_container(buf, size))
 		return NULL;
-	if (parse_stb_container(buf, size, &c) != 0)
-		return NULL;
-
-	return c.sh->payload_hash;
+	/* Container v1 */
+	if (stb_container_version(buf, size) == 1) {
+		if (parse_stb_container_v1(buf, size, &c) != 0)
+			return NULL;
+		return c.sh->payload_hash;
+	}
+	return NULL;
 }
 
 
diff --git a/libstb/container.h b/libstb/container.h
index 1233e7e..b55508e 100644
--- a/libstb/container.h
+++ b/libstb/container.h
@@ -123,7 +123,7 @@  typedef struct {
 	be64 log;
 }__attribute__((packed)) ROM_hw_params;
 
-struct parsed_stb_container {
+struct parsed_stb_container_v1 {
 	const void *buf;
 	size_t bufsz;
 	const ROM_container_raw *c;
@@ -147,7 +147,12 @@  bool stb_is_container(const void* buf, size_t size);
 const uint8_t* stb_sw_payload_hash(const void* buf, size_t size);
 uint64_t       stb_sw_payload_size(const void *buf, size_t size);
 
-int parse_stb_container(const void* data, size_t len, struct parsed_stb_container *c);
+int parse_stb_container_v1(const void* data, size_t len,
+			   struct parsed_stb_container_v1 *c);
+
+uint16_t stb_container_version(const void* buf, size_t size);
+
+uint32_t stb_container_magic(const void* buf, size_t size);
 
 void stb_print_data(const void *data, size_t len);
 
diff --git a/libstb/stb.c b/libstb/stb.c
index 3bc41c6..f0eb108 100644
--- a/libstb/stb.c
+++ b/libstb/stb.c
@@ -405,6 +405,7 @@  int tb_measure(enum resource_id id, void *buf, size_t len)
 int sb_verify(enum resource_id id, void *buf, size_t len)
 {
 	const char *name;
+	int rc = -1;
 
 	if (!secure_mode) {
 		prlog(PR_INFO, "STB: %s skipped resource %d, "
@@ -418,22 +419,35 @@  int sb_verify(enum resource_id id, void *buf, size_t len)
 		      "resource_id=%d unknown\n", id);
 		sb_enforce();
 	}
-	if (!c1vc || !c1vc->verify) {
-		prlog(PR_EMERG, "STB: secure boot not initialized\n");
-		sb_enforce();
-	}
 	if (!buf || len < SECURE_BOOT_HEADERS_SIZE) {
 		prlog(PR_EMERG, "STB: %s arg error: id %d, buf %p, len %zd\n",
 		      __func__, id, buf, len);
 		sb_enforce();
 	}
-	if (c1vc->verify((void*) c1vc->verify_addr, name, buf,
-			 hw_key_hash, hw_key_hash_size)) {
-		prlog(PR_EMERG, "STB: %s failed: resource %s, "
-		      "eyecatcher 0x%016llx\n", __func__, name,
-		      *((uint64_t*)buf));
+	if (!stb_is_container(buf, len)) {
+		prlog(PR_EMERG, "STB: %s NOT VERIFIED, magic_number=%x "
+		      "not supported\n", name, stb_container_magic(buf, len));
 		sb_enforce();
 	}
+
+	/* Handle container version 1 */
+	if (stb_container_version(buf, len) == 1) {
+
+		if (c1vc && c1vc->verify)
+			rc = c1vc->verify((void*) c1vc->verify_addr, name, buf,
+					  hw_key_hash, hw_key_hash_size);
+		else
+			prlog(PR_EMERG, "STB: %s NOT VERIFIED, secureboot not "
+			      "initialized\n", name);
+
+	} else {
+		prlog(PR_EMERG, "STB: %s NOT VERIFIED, version=%d not supported\n",
+		      name, stb_container_version(buf, len));
+	}
+
+	if (rc)
+		sb_enforce();
+
 	prlog(PR_NOTICE, "STB: %s verified\n", name);
 	return 0;
 }