From patchwork Wed Aug 1 22:53:44 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Eric Richter X-Patchwork-Id: 952541 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Received: from lists.ozlabs.org (lists.ozlabs.org [IPv6:2401:3900:2:1::3]) (using TLSv1.2 with cipher ADH-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by ozlabs.org (Postfix) with ESMTPS id 41gwbW36znz9s2g for ; Thu, 2 Aug 2018 13:27:35 +1000 (AEST) Authentication-Results: ozlabs.org; dmarc=none (p=none dis=none) header.from=linux.ibm.com Received: from lists.ozlabs.org (lists.ozlabs.org [IPv6:2401:3900:2:1::3]) by lists.ozlabs.org (Postfix) with ESMTP id 41gwbV5mCRzF1jP for ; Thu, 2 Aug 2018 13:27:34 +1000 (AEST) Authentication-Results: lists.ozlabs.org; dmarc=none (p=none dis=none) header.from=linux.ibm.com X-Original-To: skiboot@lists.ozlabs.org Delivered-To: skiboot@lists.ozlabs.org Authentication-Results: lists.ozlabs.org; spf=pass (mailfrom) smtp.mailfrom=linux.ibm.com (client-ip=148.163.158.5; helo=mx0a-001b2d01.pphosted.com; envelope-from=erichte@linux.ibm.com; receiver=) Authentication-Results: lists.ozlabs.org; dmarc=none (p=none dis=none) header.from=linux.ibm.com Received: from mx0a-001b2d01.pphosted.com (mx0b-001b2d01.pphosted.com [148.163.158.5]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by lists.ozlabs.org (Postfix) with ESMTPS id 41gpX13pX9zF1R6 for ; Thu, 2 Aug 2018 08:54:09 +1000 (AEST) Received: from pps.filterd (m0098421.ppops.net [127.0.0.1]) by mx0a-001b2d01.pphosted.com (8.16.0.22/8.16.0.22) with SMTP id w71Mn7Eq060246 for ; Wed, 1 Aug 2018 18:54:07 -0400 Received: from e06smtp03.uk.ibm.com (e06smtp03.uk.ibm.com [195.75.94.99]) by mx0a-001b2d01.pphosted.com with ESMTP id 2kkms2agwn-1 (version=TLSv1.2 cipher=AES256-GCM-SHA384 bits=256 verify=NOT) for ; Wed, 01 Aug 2018 18:54:07 -0400 Received: from localhost by e06smtp03.uk.ibm.com with IBM ESMTP SMTP Gateway: Authorized Use Only! Violators will be prosecuted for from ; Wed, 1 Aug 2018 23:54:05 +0100 Received: from b06cxnps3074.portsmouth.uk.ibm.com (9.149.109.194) by e06smtp03.uk.ibm.com (192.168.101.133) with IBM ESMTP SMTP Gateway: Authorized Use Only! Violators will be prosecuted; (version=TLSv1/SSLv3 cipher=AES256-GCM-SHA384 bits=256/256) Wed, 1 Aug 2018 23:54:04 +0100 Received: from d06av22.portsmouth.uk.ibm.com (d06av22.portsmouth.uk.ibm.com [9.149.105.58]) by b06cxnps3074.portsmouth.uk.ibm.com (8.14.9/8.14.9/NCO v10.0) with ESMTP id w71Ms29N42795260 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-GCM-SHA384 bits=256 verify=FAIL); Wed, 1 Aug 2018 22:54:03 GMT Received: from d06av22.portsmouth.uk.ibm.com (unknown [127.0.0.1]) by IMSVA (Postfix) with ESMTP id 803194C046; Thu, 2 Aug 2018 01:54:14 +0100 (BST) Received: from d06av22.portsmouth.uk.ibm.com (unknown [127.0.0.1]) by IMSVA (Postfix) with ESMTP id F2C2E4C040; Thu, 2 Aug 2018 01:54:13 +0100 (BST) Received: from boston-1.rtp.stglabs.ibm.com (unknown [9.27.30.60]) by d06av22.portsmouth.uk.ibm.com (Postfix) with ESMTP; Thu, 2 Aug 2018 01:54:13 +0100 (BST) From: Eric Richter To: skiboot@lists.ozlabs.org Date: Wed, 1 Aug 2018 18:53:44 -0400 X-Mailer: git-send-email 2.14.4 In-Reply-To: <20180801225349.6535-1-erichte@linux.ibm.com> References: <20180801225349.6535-1-erichte@linux.ibm.com> X-TM-AS-GCONF: 00 x-cbid: 18080122-0012-0000-0000-000002926C02 X-IBM-AV-DETECTION: SAVI=unused REMOTE=unused XFE=unused x-cbparentid: 18080122-0013-0000-0000-000020C475E5 Message-Id: <20180801225349.6535-6-erichte@linux.ibm.com> X-Proofpoint-Virus-Version: vendor=fsecure engine=2.50.10434:, , definitions=2018-08-01_08:, , signatures=0 X-Proofpoint-Spam-Details: rule=outbound_notspam policy=outbound score=0 priorityscore=1501 malwarescore=0 suspectscore=4 phishscore=0 bulkscore=0 spamscore=0 clxscore=1015 lowpriorityscore=0 mlxscore=0 impostorscore=0 mlxlogscore=999 adultscore=0 classifier=spam adjust=0 reason=mlx scancount=1 engine=8.0.1-1806210000 definitions=main-1808010231 X-Mailman-Approved-At: Thu, 02 Aug 2018 13:26:15 +1000 Subject: [Skiboot] [RFC PATCH 05/10] keystore: initialize the base keystore structure X-BeenThere: skiboot@lists.ozlabs.org X-Mailman-Version: 2.1.27 Precedence: list List-Id: Mailing list for skiboot development List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: Claudio Carvalho MIME-Version: 1.0 Errors-To: skiboot-bounces+incoming=patchwork.ozlabs.org@lists.ozlabs.org Sender: "Skiboot" This patch introduces and initializes the structures for representing the keystore in memory. Also included is the logic for parsing the secboot partition data into the in-memory keystore. The keystore is kept in-memory for a few reasons. First, we don't want to be reloading from PNOR whenever we want to retrieve a key, as the underlying PNOR section may have been overwritten without validation. The second point is a matter of performance -- by keeping things in memory it reduces the amount of slow I/O operations on the chip, as well as reducing the amount of wear. Finally, it is much simpler from a programming perspective to manipulate a list in-memory than to be constantly operating on a blob of binary data that would need to be reparsed each time, although this does consume more memory. There are two parts to the in-memory keystore: the Active Bank, and the Update Queue. The Active Bank is the list of keys to be operated on. As the name implies, the Update Queue is a queue of updates to be applied to the Active Bank (though the actual processing of this is left to the kernel[1]). For simplicity and sake of code reuse, the Active Bank and the Update Queue use the exact same format, and therefore can be loaded in the exact same manner -- the only difference is the offset that they are loaded from in the secboot partition. [1] Implementations of the update queue processing code in the kernel are forthcoming, we have an internal version that is not quite ready for upstream. Signed-off-by: Eric Richter --- libstb/Makefile.inc | 2 +- libstb/keystore.c | 71 +++++++++++++++++++++++++++++++++++++++++++++++++++ libstb/keystore.h | 38 +++++++++++++++++++++++++++ libstb/secboot_part.c | 67 ++++++++++++++++++++++++++++++++++++++++++++++++ libstb/secboot_part.h | 1 + libstb/secureboot.c | 4 +++ 6 files changed, 182 insertions(+), 1 deletion(-) create mode 100644 libstb/keystore.c create mode 100644 libstb/keystore.h diff --git a/libstb/Makefile.inc b/libstb/Makefile.inc index 5cd6c2ee..6cc30134 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 secboot_part.c +LIBSTB_SRCS = container.c tpm_chip.c cvc.c secureboot.c trustedboot.c secboot_part.c keystore.c LIBSTB_OBJS = $(LIBSTB_SRCS:%.c=%.o) LIBSTB = $(LIBSTB_DIR)/built-in.a diff --git a/libstb/keystore.c b/libstb/keystore.c new file mode 100644 index 00000000..7d6027ef --- /dev/null +++ b/libstb/keystore.c @@ -0,0 +1,71 @@ +/* Copyright 2013-2017 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) "KEYSTORE: " fmt +#endif + +#include +#include +#include +#include "container.h" +#include "cvc.h" +#include "keystore.h" +#include "secboot_part.h" + +static struct list_head active_bank_list = LIST_HEAD_INIT(active_bank_list); +static struct list_head update_queue_list = LIST_HEAD_INIT(update_queue_list); + +static bool keystore_ready = false; /* has the keystore been loaded? */ + +// TODO: OPAL_UNSUPPORTED? +#define CHECK_KEYSTORE_READY if(!keystore_ready) {prlog(PR_ERR, "Ignoring call, keystore not ready\n"); return OPAL_RESOURCE; } + + + +int keystore_init(void) +{ + int rc; + + /* software secure boot supported only on p9 and above */ + if (proc_gen != proc_gen_p9) { + prlog(PR_INFO, "Secureboot is not supported on this platform\n"); + return 0; + } + + /* API init */ + list_head_init(&active_bank_list); + list_head_init(&update_queue_list); + + rc = secboot_part_init(); + if (rc) { + prlog(PR_ERR, "Failed to initialize the secboot partition\n"); + return -1; + } + + /* add variables we have in pnor secboot */ + rc = secboot_part_build_keystore(&active_bank_list, &update_queue_list); + if (rc) { + prlog(PR_ERR, "Failed to build the keystore\n"); + return -1; + } + + keystore_ready = true; + + prlog(PR_INFO, "Keystore initialized successfully\n"); + + return 0; +} diff --git a/libstb/keystore.h b/libstb/keystore.h new file mode 100644 index 00000000..e2eb296c --- /dev/null +++ b/libstb/keystore.h @@ -0,0 +1,38 @@ +/* Copyright 2013-2014 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 __KEYSTORE_H +#define __KEYSTORE_H + +// TODO: Assign these constants more intelligently +#define ACTIVE_BANK 0x1 +#define UPDATE_QUEUE 0x2 +#define CLEAR_QUEUE 0x4 +#define START_OVER 0x8 + +int keystore_init(void); + +// TODO: figure out how this differs from secboot_section_item +// Struct for bank lists +struct keystore_variable { + struct list_node link; + uint64_t name_size; + uint64_t data_size; + char *name; + char *data; +}; + +#endif /* __KEYSTORE_H */ diff --git a/libstb/secboot_part.c b/libstb/secboot_part.c index e6558166..9a2c8ac0 100644 --- a/libstb/secboot_part.c +++ b/libstb/secboot_part.c @@ -20,6 +20,7 @@ #include #include "secboot_part.h" +#include "keystore.h" struct secboot_section_item { const char *name; /* null terminated string */ @@ -164,6 +165,72 @@ static int secboot_part_validate(void) } +static int read_section(struct list_head *bank, char *cur, char *end) +{ + struct keystore_variable *var; + + while (cur < end) { + // Bail if variable name size is empty -- end of list + if (*((uint64_t*) cur) == 0llu) { + prlog(PR_INFO, "variable name size is empty, bailing\n"); + break; + } + + var = (struct keystore_variable*) malloc(sizeof(struct keystore_variable)); + if (!var) { + return -1; + } + + var->name_size = *((uint64_t*) cur); cur += sizeof(uint64_t); + var->data_size = *((uint64_t*) cur); cur += sizeof(uint64_t); + var->name = malloc(var->name_size); + if (!var->name) { + free(var); + return -2; + } + var->data = malloc(var->data_size); + if (!var->data) { + free(var->name); + free(var); + return -3; + } + + memcpy(var->name, cur, var->name_size); + cur += var->name_size; + memcpy(var->data, cur, var->data_size); + cur += var->data_size; + + prlog(PR_INFO, "loaded: '%s'\n", var->name); + + list_add_tail(bank, &var->link); + } + + return 0; +} + + +int secboot_part_build_keystore(struct list_head *active, struct list_head *uqueue) +{ + int ret = -1; + + if (!secboot_valid) + return -1; + + ret = read_section(active, (char*) active_bank->item, ((char*) active_bank) + SECBOOT_BANK_SIZE); + if (ret) { + prlog(PR_ERR, "Error loading Active Bank: %d\n", ret); + } + + ret = read_section(uqueue, (char*) update_queue->item, ((char*) update_queue) + SECBOOT_QUEUE_SIZE); + if (ret) { + prlog(PR_ERR, "Error loading update queue: %d\n", ret); + } + + return ret; + +} + + int secboot_part_init() { int rc; diff --git a/libstb/secboot_part.h b/libstb/secboot_part.h index 7f29183b..66e71561 100644 --- a/libstb/secboot_part.h +++ b/libstb/secboot_part.h @@ -18,5 +18,6 @@ #define __SECBOOT_PART_H int secboot_part_init(void); +int secboot_part_build_keystore(struct list_head* active, struct list_head* uqueue); #endif /* __SECBOOT_PART_H */ diff --git a/libstb/secureboot.c b/libstb/secureboot.c index 4f6a301d..c6b72b5d 100644 --- a/libstb/secureboot.c +++ b/libstb/secureboot.c @@ -24,6 +24,7 @@ #include #include #include "secureboot.h" +#include "keystore.h" static const void* hw_key_hash = NULL; static size_t hw_key_hash_size; @@ -171,6 +172,9 @@ void secureboot_init(void) secureboot_enforce(); secure_init = true; + + keystore_init(); + } int secureboot_verify(enum resource_id id, void *buf, size_t len)