diff mbox series

[RFC,v2,4/8] libstb: add secure variable internal abstraction

Message ID 20190411224551.29401-5-erichte@linux.ibm.com
State RFC
Headers show
Series Initial Skiboot Secure Variable Support | expand

Checks

Context Check Description
snowpatch_ozlabs/snowpatch_job_snowpatch-skiboot-dco success Signed-off-by present
snowpatch_ozlabs/snowpatch_job_snowpatch-skiboot success Test snowpatch/job/snowpatch-skiboot on branch master
snowpatch_ozlabs/apply_patch success Successfully applied on branch master (ff79070d1c4cdc38f2ecb42e45b8322cb1efb819)

Commit Message

Eric Richter April 11, 2019, 10:45 p.m. UTC
This patch implements a platform-independent abstraction for storing and
retrieving secure variables, as required for host OS secure boot. This
serves as the main entry point for initializing the in-memory cache of the
secure variables, which also kicks off any platform-specific logic that may
be needed. This patch also provides core functions for the subsequent
patches in this series to utilize.

This abstraction utilizes two linked lists ("banks") for storing the
variables in memory for other components (such as the runtime service API)
to access.

v2:
 - secvar_init() returns opal return codes
 - changed guid_t to be a single-element struct instead of array
 - secvar_init() now calls platform hooks, rather than expecting
   function pointers to be set
 - secure variable support is determined by presence of platform hooks

Signed-off-by: Eric Richter <erichte@linux.ibm.com>
---
 libstb/Makefile.inc |   2 +-
 libstb/secvar.c     | 138 ++++++++++++++++++++++++++++++++++++++++++++
 libstb/secvar.h     |  64 ++++++++++++++++++++
 3 files changed, 203 insertions(+), 1 deletion(-)
 create mode 100644 libstb/secvar.c
 create mode 100644 libstb/secvar.h
diff mbox series

Patch

diff --git a/libstb/Makefile.inc b/libstb/Makefile.inc
index 6d54c5cd..2bc9e91b 100644
--- a/libstb/Makefile.inc
+++ b/libstb/Makefile.inc
@@ -4,7 +4,7 @@  LIBSTB_DIR = libstb
 
 SUBDIRS += $(LIBSTB_DIR)
 
-LIBSTB_SRCS = container.c tpm_chip.c cvc.c secureboot.c trustedboot.c
+LIBSTB_SRCS = container.c tpm_chip.c cvc.c secureboot.c trustedboot.c secvar.c
 LIBSTB_OBJS = $(LIBSTB_SRCS:%.c=%.o)
 LIBSTB = $(LIBSTB_DIR)/built-in.a
 
diff --git a/libstb/secvar.c b/libstb/secvar.c
new file mode 100644
index 00000000..6ed6a7e8
--- /dev/null
+++ b/libstb/secvar.c
@@ -0,0 +1,138 @@ 
+/* Copyright 2019 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) "SECVAR: " fmt
+#endif
+
+#include <stdlib.h>
+#include <string.h>
+#include <skiboot.h>
+#include <opal.h>
+#include "secvar.h"
+
+struct list_head variable_bank;
+struct list_head update_bank;
+int secvar_enabled = 0;
+
+// Calculate length of a char16_t, with a max possible bytes
+//  if end of string is not found before max bytes, returns -1
+//  otherwise, returns length
+int str16nlen(char16_t *str, size_t maxbytes)
+{
+	int ret = 0;
+	char16_t *c = str;
+
+	while ((c - str) < maxbytes) {
+		if (*c == 0)
+			return ret;
+		ret++;
+		c++;
+	}
+
+	return -1;
+}
+
+
+void clear_bank_list(struct list_head *bank)
+{
+	struct secvar *node, *next;
+
+	if (!bank)
+		return;
+
+	list_for_each_safe(bank, node, next, link) {
+		if (node->data)
+			free(node->data);
+		list_del(&node->link);
+		free(node);
+	}
+}
+
+struct secvar *find_secvar_by_name_vendor(char16_t *name, guid_t *vendor, struct list_head *bank)
+{
+	struct secvar *var = NULL;
+	int len;
+
+	len = str16nlen(name, SECVAR_MAX_NAME_SIZE);
+	if (len <= 0) {
+		return NULL;
+	}
+
+	list_for_each(bank, var, link) {
+		if (!memcmp(name, var->name, len*2) &&
+		    !memcmp(vendor, &var->vendor, sizeof(guid_t))) {
+			return var;
+		}
+	}
+
+	return NULL;
+}
+
+
+// Returns the packed physical size of a variable
+size_t sizeof_secvar(struct secvar *var)
+{
+	return sizeof(var->name) +
+		sizeof(var->vendor) +
+		sizeof(var->attributes) +
+		sizeof(var->data_size) +
+		var->data_size;
+
+}
+
+
+int secvar_init(void)
+{
+	int ret = OPAL_UNSUPPORTED;
+
+	if ((!platform.secvar_platform_init)
+		|| (!platform.secvar_load_bank)
+		|| (!platform.secvar_write_bank)) {
+		prlog(PR_DEBUG, "Secure variable support not enabled for platform\n");
+		return ret;
+	}
+
+	prlog(PR_DEBUG, "Initializing secure variables\n");
+
+	ret = platform.secvar_platform_init();
+	if (ret)
+		return ret;
+
+	list_head_init(&variable_bank);
+	list_head_init(&update_bank);
+
+	ret = platform.secvar_load_bank(&variable_bank, SECVAR_VARIABLE_BANK);
+	if (ret)
+		return ret;
+	prlog(PR_DEBUG, "Loaded variable bank\n");
+
+	ret = platform.secvar_load_bank(&update_bank, SECVAR_UPDATE_BANK);
+	if (ret)
+		return ret;
+	prlog(PR_DEBUG, "Loaded updates, ");
+	if (list_empty(&update_bank))
+		prlog(PR_DEBUG, "none to apply.\n");
+	else
+		prlog(PR_DEBUG, "found updates to apply\n");
+
+	// TODO: Process update queue here
+	// TODO: Derive SecureMode, etc variables here
+
+	secvar_enabled = 1;
+
+	return OPAL_SUCCESS;
+}
diff --git a/libstb/secvar.h b/libstb/secvar.h
new file mode 100644
index 00000000..f686ce20
--- /dev/null
+++ b/libstb/secvar.h
@@ -0,0 +1,64 @@ 
+/* Copyright 2019 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 _SECVAR_H_
+#define _SECVAR_H_
+
+#include <ccan/list/list.h>
+#include <stdint.h>
+
+typedef uint16_t char16_t;
+
+#define SECVAR_MAX_NAME_SIZE	1024
+#define SECVAR_MAX_NAME_LEN	(SECVAR_MAX_NAME_SIZE/sizeof(char16_t))
+#define SECVAR_MAX_DATA_SIZE	2048
+#define SECVAR_VENDOR_SIZE	16
+
+
+enum {
+	SECVAR_VARIABLE_BANK,
+	SECVAR_UPDATE_BANK,
+};
+
+
+//typedef unsigned char guid_t[SECVAR_VENDOR_SIZE];
+typedef struct {
+	uint8_t b[16];
+} guid_t;
+
+struct secvar {
+	struct list_node link;
+	char16_t name[SECVAR_MAX_NAME_LEN];
+	guid_t vendor;
+	uint32_t attributes;
+	uint32_t data_size;
+	char *data;
+};
+
+extern struct list_head variable_bank;
+extern struct list_head update_bank;
+extern int secvar_enabled;
+
+// Helper functions
+int str16nlen(char16_t *str, size_t max);
+void clear_bank_list(struct list_head *bank);
+struct secvar *find_secvar_by_name_vendor(char16_t *name, guid_t *vendor, struct list_head *bank);
+size_t sizeof_secvar(struct secvar *var);
+
+
+int secvar_init(void);
+
+#endif