From patchwork Wed Aug 1 22:53:48 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Eric Richter X-Patchwork-Id: 952469 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 41gpfL0Vzjz9s3Z for ; Thu, 2 Aug 2018 08:59:38 +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 41gpfK4bhLzF1wB for ; Thu, 2 Aug 2018 08:59:37 +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 41gpdw6Zh1zF1R6 for ; Thu, 2 Aug 2018 08:59:16 +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 w71Mx5Kc085146 for ; Wed, 1 Aug 2018 18:59:14 -0400 Received: from e06smtp02.uk.ibm.com (e06smtp02.uk.ibm.com [195.75.94.98]) by mx0a-001b2d01.pphosted.com with ESMTP id 2kkms2andm-1 (version=TLSv1.2 cipher=AES256-GCM-SHA384 bits=256 verify=NOT) for ; Wed, 01 Aug 2018 18:59:14 -0400 Received: from localhost by e06smtp02.uk.ibm.com with IBM ESMTP SMTP Gateway: Authorized Use Only! Violators will be prosecuted for from ; Wed, 1 Aug 2018 23:54:12 +0100 Received: from b06cxnps3075.portsmouth.uk.ibm.com (9.149.109.195) by e06smtp02.uk.ibm.com (192.168.101.132) 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:11 +0100 Received: from d06av22.portsmouth.uk.ibm.com (d06av22.portsmouth.uk.ibm.com [9.149.105.58]) by b06cxnps3075.portsmouth.uk.ibm.com (8.14.9/8.14.9/NCO v10.0) with ESMTP id w71Ms9Pg37879946 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-GCM-SHA384 bits=256 verify=FAIL); Wed, 1 Aug 2018 22:54:09 GMT Received: from d06av22.portsmouth.uk.ibm.com (unknown [127.0.0.1]) by IMSVA (Postfix) with ESMTP id 6731A4C040; Thu, 2 Aug 2018 01:54:21 +0100 (BST) Received: from d06av22.portsmouth.uk.ibm.com (unknown [127.0.0.1]) by IMSVA (Postfix) with ESMTP id D9CD24C046; Thu, 2 Aug 2018 01:54:20 +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:20 +0100 (BST) From: Eric Richter To: skiboot@lists.ozlabs.org Date: Wed, 1 Aug 2018 18:53:48 -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-0008-0000-0000-0000025B59A3 X-IBM-AV-DETECTION: SAVI=unused REMOTE=unused XFE=unused x-cbparentid: 18080122-0009-0000-0000-000021C1F5BE Message-Id: <20180801225349.6535-10-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=3 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-1808010233 Subject: [Skiboot] [RFC PATCH 09/10] keystore: add opal_secboot_commit runtime service 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" The opal_secboot_commit runtime service serializes an in-memory keystore bank and writes it out to the appropriate offset in the secboot partition. There are three options for the section flag: the two in-memory keystore banks ACTIVE_BANK and UPDATE_QUEUE, and a third option CLEAR_QUEUE. The first two flags function almost the same, serialize their respective list and write the blob to PNOR. CLEAR_QUEUE is a special case for use after the update queue has been processed by the kernel and no longer needed, therefore flushing the list and zeroing out the region in the secboot partition. This patch also introduces the secboot_serialize_and_write operation, which takes in a keystore bank list and handles the appropriate serialization logic. This function may be tweaked in the future to accomodate platform specific changes. For example, p9 may implement this function to write variables or other bits of data to the TPM, whereas platforms with lockable flash may not need to do this. NOTE: Right now, this is written to allow for a composite flag to allow for multiple operations to be handled by a single Opal call, however the call itself does not intelligently handle multiple operations -- that is, the call will not lump the serialized blobs into a single PNOR write. This is partially due to the nature of the secboot partition, as this may not all be one contiguous blob Signed-off-by: Eric Richter --- libstb/keystore.c | 39 +++++++++++++++++++++++++++++++++++ libstb/secboot_part.c | 57 +++++++++++++++++++++++++++++++++++++++++++++++++++ libstb/secboot_part.h | 1 + 3 files changed, 97 insertions(+) diff --git a/libstb/keystore.c b/libstb/keystore.c index 0ddabf5f..1c853380 100644 --- a/libstb/keystore.c +++ b/libstb/keystore.c @@ -198,6 +198,45 @@ static int64_t opal_get_next_variable(uint64_t k_varname, uint64_t k_size, uint6 opal_call(OPAL_GET_NEXT_VARIABLE, opal_get_next_variable, 3); +// Cleanup function to empty out a bank list +static void clear_bank_list(struct list_head *head) +{ + struct keystore_variable *node, *next; + + list_for_each_safe(head, node, next, link) { + free(node->name); + free(node->data); + list_del(&node->link); + free(node); + } +} + + +static int64_t opal_secboot_commit(uint64_t section) +{ + int ret = OPAL_SUCCESS; + + CHECK_KEYSTORE_READY; + + if (section & ACTIVE_BANK) { + ret = secboot_part_serialize_and_write(&active_bank_list, ACTIVE_BANK); + } + + if (section & UPDATE_QUEUE) { + ret = secboot_part_serialize_and_write(&update_queue_list, UPDATE_QUEUE); + } + + if (section & CLEAR_QUEUE) { + ret = secboot_part_serialize_and_write(NULL, CLEAR_QUEUE); + // Do we want to clear the in-memory queue even if the above fails? + clear_bank_list(&update_queue_list); + } + + return (ret) ? OPAL_RESOURCE : OPAL_SUCCESS; +} +opal_call(OPAL_SECBOOT_COMMIT, opal_secboot_commit, 1); + + int keystore_init(void) { int rc; diff --git a/libstb/secboot_part.c b/libstb/secboot_part.c index 9a2c8ac0..81b359bf 100644 --- a/libstb/secboot_part.c +++ b/libstb/secboot_part.c @@ -231,6 +231,63 @@ int secboot_part_build_keystore(struct list_head *active, struct list_head *uque } +static int write_variable(char *target, struct keystore_variable *var) +{ + char *cur = target; + + prlog(PR_INFO, "Writing variable '%s'\n", var->name); + + *((uint64_t*) cur) = var->name_size; cur += sizeof(uint64_t); + *((uint64_t*) cur) = var->data_size; cur += sizeof(uint64_t); + memcpy(cur, var->name, var->name_size); + cur += var->name_size; + memcpy(cur, var->data, var->data_size); + cur += var->data_size; + + return cur - target; +} + + +int secboot_part_serialize_and_write(struct list_head *head, int section) +{ + struct keystore_variable *var; + char *cur = NULL, *end = NULL; + + switch(section) { + case ACTIVE_BANK: + cur = (char*) active_bank->item; + end = ((char*) active_bank) + SECBOOT_BANK_SIZE; + break; + case UPDATE_QUEUE: + cur = (char*) update_queue->item; + end = ((char*) update_queue) + SECBOOT_QUEUE_SIZE;; + break; + + case CLEAR_QUEUE: + memset(update_queue->item, 0x00, SECBOOT_QUEUE_SIZE - sizeof(struct secboot_section)); // header? + goto out; // Skip the serialization of variables + + default: return -1; + } + + if (!head) return -1; // head should not be NULL with section != CLEAR_QUEUE + + prlog(PR_INFO, "cur = %p\n", cur); + list_for_each(head, var, link) { + cur += write_variable(cur, var); + } + prlog(PR_INFO, "cur = %p\n", cur); + + memset(cur, 0x00, end-cur); // Clear the rest of the bank + +out: + prlog(PR_INFO,"performing write\n"); + platform.secboot_write(0, secboot, secboot_size); + + return 0; +} + + int secboot_part_init() { int rc; diff --git a/libstb/secboot_part.h b/libstb/secboot_part.h index 66e71561..a853f8c6 100644 --- a/libstb/secboot_part.h +++ b/libstb/secboot_part.h @@ -19,5 +19,6 @@ int secboot_part_init(void); int secboot_part_build_keystore(struct list_head* active, struct list_head* uqueue); +int secboot_part_serialize_and_write(struct list_head *head, int section); #endif /* __SECBOOT_PART_H */