From mboxrd@z Thu Jan 1 00:00:00 1970 Received: from list by lists.gnu.org with archive (Exim 4.90_1) id 1nH60S-0000ro-Gx for mharc-grub-devel@gnu.org; Mon, 07 Feb 2022 10:32:44 -0500 Received: from eggs.gnu.org ([209.51.188.92]:49724) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1nH60Q-0000nz-Lg for grub-devel@gnu.org; Mon, 07 Feb 2022 10:32:42 -0500 Received: from mx0b-001b2d01.pphosted.com ([148.163.158.5]:6514) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1nH60O-0001LM-5H for grub-devel@gnu.org; Mon, 07 Feb 2022 10:32:41 -0500 Received: from pps.filterd (m0098417.ppops.net [127.0.0.1]) by mx0a-001b2d01.pphosted.com (8.16.1.2/8.16.1.2) with SMTP id 217Ew390008803; Mon, 7 Feb 2022 15:32:33 GMT DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=ibm.com; h=from : to : cc : subject : date : message-id : in-reply-to : references : mime-version : content-transfer-encoding; s=pp1; bh=TxyJoXf4gRieDhjt3wea/wZyASO0zx6S6Xo7sIvblWI=; b=EZvja7FtgMdxZOjaTkh8wRivvr0JnOWWPfzI6F6AnllhnHnlOaDb8t+R5Ysc0b9IwCXi BzNtFjMT+BVCJXgvgxCRZ8WWK/GR+u1BRVD0OLDjM3kDhcOJf3k78d15uhMXzL0tkxqL cBRfuQL9pYegHIodLPkhaPAMW+xb5Cwi+7vLw1GJ6Rh7KEcuMDKEhjKOhSKVsIn6gOG/ vFzu9JwPH4BFTop32QXJeTup9BLOg0drZcPpDaSctLRybCMHbAlhqtdvRz2+FdmKwTOi FYIFVGHHvq1dKkw454B14n89zvhWlJxGMQI5hupDUFJStuzBana5GvQK4nfWZlAcDM2k AA== Received: from pps.reinject (localhost [127.0.0.1]) by mx0a-001b2d01.pphosted.com with ESMTP id 3e22vkqha1-1 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NOT); Mon, 07 Feb 2022 15:32:33 +0000 Received: from m0098417.ppops.net (m0098417.ppops.net [127.0.0.1]) by pps.reinject (8.16.0.43/8.16.0.43) with SMTP id 217FRp0v022110; Mon, 7 Feb 2022 15:32:32 GMT Received: from ppma01wdc.us.ibm.com (fd.55.37a9.ip4.static.sl-reverse.com [169.55.85.253]) by mx0a-001b2d01.pphosted.com with ESMTP id 3e22vkqh62-1 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NOT); Mon, 07 Feb 2022 15:32:32 +0000 Received: from pps.filterd (ppma01wdc.us.ibm.com [127.0.0.1]) by ppma01wdc.us.ibm.com (8.16.1.2/8.16.1.2) with SMTP id 217FDfYT025124; Mon, 7 Feb 2022 15:32:22 GMT Received: from b03cxnp07029.gho.boulder.ibm.com (b03cxnp07029.gho.boulder.ibm.com [9.17.130.16]) by ppma01wdc.us.ibm.com with ESMTP id 3e1gv9qxgd-1 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NOT); Mon, 07 Feb 2022 15:32:22 +0000 Received: from b03ledav001.gho.boulder.ibm.com (b03ledav001.gho.boulder.ibm.com [9.17.130.232]) by b03cxnp07029.gho.boulder.ibm.com (8.14.9/8.14.9/NCO v10.0) with ESMTP id 217FWI4M35193206 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-GCM-SHA384 bits=256 verify=OK); Mon, 7 Feb 2022 15:32:18 GMT Received: from b03ledav001.gho.boulder.ibm.com (unknown [127.0.0.1]) by IMSVA (Postfix) with ESMTP id EF0D56E050; Mon, 7 Feb 2022 15:32:17 +0000 (GMT) Received: from b03ledav001.gho.boulder.ibm.com (unknown [127.0.0.1]) by IMSVA (Postfix) with ESMTP id AD42E6E060; Mon, 7 Feb 2022 15:32:15 +0000 (GMT) Received: from jarvis.int.hansenpartnership.com (unknown [9.211.78.81]) by b03ledav001.gho.boulder.ibm.com (Postfix) with ESMTP; Mon, 7 Feb 2022 15:32:15 +0000 (GMT) From: James Bottomley To: grub-devel@gnu.org Cc: thomas.lendacky@amd.com, ashish.kalra@amd.com, brijesh.singh@amd.com, david.kaplan@amd.com, jon.grimm@amd.com, tobin@ibm.com, frankeh@us.ibm.com, Dr David Alan Gilbert , dovmurik@linux.vnet.ibm.com, Dov.Murik1@il.ibm.com, Javier Martinez Canillas , GNUtoo@cyberdimension.org, ps@pks.im, development@efficientek.com, Daniel Kiper Subject: [PATCH v4 2/2] efi: Add API for retrieving the EFI secret for cryptodisk Date: Mon, 7 Feb 2022 10:29:44 -0500 Message-Id: <20220207152944.27183-3-jejb@linux.ibm.com> X-Mailer: git-send-email 2.34.1 In-Reply-To: <20220207152944.27183-1-jejb@linux.ibm.com> References: <20220207152944.27183-1-jejb@linux.ibm.com> MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-TM-AS-GCONF: 00 X-Proofpoint-GUID: O43TwAC2jOu4Tz02FhfJLnEl8-1HqOz6 X-Proofpoint-ORIG-GUID: FJYKSWa5dUybxFxSZZ2l07SKz16Nc3IW X-Proofpoint-Virus-Version: vendor=baseguard engine=ICAP:2.0.205,Aquarius:18.0.816,Hydra:6.0.425,FMLib:17.11.62.513 definitions=2022-02-07_06,2022-02-07_02,2021-12-02_01 X-Proofpoint-Spam-Details: rule=outbound_notspam policy=outbound score=0 clxscore=1015 bulkscore=0 lowpriorityscore=0 mlxscore=0 impostorscore=0 phishscore=0 suspectscore=0 priorityscore=1501 adultscore=0 malwarescore=0 spamscore=0 mlxlogscore=999 classifier=spam adjust=0 reason=mlx scancount=1 engine=8.12.0-2201110000 definitions=main-2202070097 Received-SPF: pass client-ip=148.163.158.5; envelope-from=jejb@linux.ibm.com; helo=mx0b-001b2d01.pphosted.com X-Spam_score_int: -19 X-Spam_score: -2.0 X-Spam_bar: -- X-Spam_report: (-2.0 / 5.0 requ) BAYES_00=-1.9, DKIM_SIGNED=0.1, DKIM_VALID=-0.1, DKIM_VALID_EF=-0.1, RCVD_IN_MSPIKE_H5=0.001, RCVD_IN_MSPIKE_WL=0.001, SPF_HELO_NONE=0.001, SPF_PASS=-0.001, T_SCC_BODY_TEXT_LINE=-0.01 autolearn=ham autolearn_force=no X-Spam_action: no action X-BeenThere: grub-devel@gnu.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: The development of GNU GRUB List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Mon, 07 Feb 2022 15:32:42 -0000 This module is designed to provide an efisecret provider which interrogates the EFI configuration table to find the location of the confidential computing secret and tries to register the secret with the cryptodisk. The secret is stored in a boot allocated area, usually a page in size. The layout of the secret injection area is a header |GRUB_EFI_SECRET_TABLE_HEADER_GUID|len| with entries of the form |guid|len|data| the guid corresponding to the disk encryption passphrase is GRUB_EFI_DISKPASSWD_GUID and data must be a zero terminated string. To get a high entropy string that doesn't need large numbers of iterations, use a base64 encoding of 33 bytes of random data. Signed-off-by: James Bottomley --- v2: use callback to print failure message and destroy secret v3: change to generic naming to use for TDX and SEV and use new mechanism v4: review fixes --- grub-core/Makefile.core.def | 8 ++ grub-core/disk/efi/efisecret.c | 129 +++++++++++++++++++++++++++++++++ include/grub/efi/api.h | 15 ++++ 3 files changed, 152 insertions(+) create mode 100644 grub-core/disk/efi/efisecret.c diff --git a/grub-core/Makefile.core.def b/grub-core/Makefile.core.def index 8022e1c0a..6293ddaa5 100644 --- a/grub-core/Makefile.core.def +++ b/grub-core/Makefile.core.def @@ -788,6 +788,14 @@ module = { enable = efi; }; +module = { + name = efisecret; + + common = disk/efi/efisecret.c; + + enable = efi; +}; + module = { name = lsefimmap; diff --git a/grub-core/disk/efi/efisecret.c b/grub-core/disk/efi/efisecret.c new file mode 100644 index 000000000..4cecebbdc --- /dev/null +++ b/grub-core/disk/efi/efisecret.c @@ -0,0 +1,129 @@ +#include +#include +#include +#include +#include +#include + +GRUB_MOD_LICENSE ("GPLv3+"); + +static grub_efi_packed_guid_t secret_guid = GRUB_EFI_SECRET_TABLE_GUID; +static grub_efi_packed_guid_t tableheader_guid = GRUB_EFI_SECRET_TABLE_HEADER_GUID; +static grub_efi_packed_guid_t diskpasswd_guid = GRUB_EFI_DISKPASSWD_GUID; + +struct efi_secret { + grub_uint64_t base; + grub_uint64_t size; +}; + +struct secret_header { + grub_efi_packed_guid_t guid; + grub_uint32_t len; +}; + +struct secret_entry { + grub_efi_packed_guid_t guid; + grub_uint32_t len; + grub_uint8_t data[0]; +}; + +static grub_err_t +grub_efi_secret_put (const char *arg __attribute__((unused)), int have_it, + grub_uint8_t **ptr) +{ + struct secret_entry *e = (struct secret_entry *)(*ptr - (long)&((struct secret_entry *)0)->data); + int len = e->len; + + /* destroy the secret */ + grub_memset (e, 0, len); + /* put back the length to make sure the table is still traversable */ + e->len = len; + + *ptr = NULL; + + if (have_it) + return GRUB_ERR_NONE; + + return grub_error (GRUB_ERR_ACCESS_DENIED, "EFI secret failed to unlock any volumes"); +} + +static grub_err_t +grub_efi_secret_find (struct efi_secret *s, grub_uint8_t **secret_ptr) +{ + int len; + struct secret_header *h; + struct secret_entry *e; + unsigned char *ptr = (unsigned char *)(unsigned long)s->base; + + /* the area must be big enough for a guid and a u32 length */ + if (s->size < sizeof (*h)) + return grub_error (GRUB_ERR_BAD_ARGUMENT, "EFI secret area is too small"); + + h = (struct secret_header *)ptr; + if (grub_memcmp(&h->guid, &tableheader_guid, sizeof (h->guid))) + return grub_error (GRUB_ERR_BAD_ARGUMENT, "EFI secret area does not start with correct guid\n"); + if (h->len < sizeof (*h)) + return grub_error (GRUB_ERR_BAD_ARGUMENT, "EFI secret area is too small\n"); + + len = h->len - sizeof (*h); + ptr += sizeof (*h); + + while (len >= (int)sizeof (*e)) { + e = (struct secret_entry *)ptr; + if (e->len < sizeof(*e) || e->len > (unsigned int)len) + return grub_error (GRUB_ERR_BAD_ARGUMENT, "EFI secret area is corrupt\n"); + + if (! grub_memcmp (&e->guid, &diskpasswd_guid, sizeof (e->guid))) { + int end = e->len - sizeof(*e); + + /* + * the passphrase must be a zero terminated string because the + * password routines call grub_strlen () to find its size + */ + if (end < 2 || e->data[end - 1] != '\0') + return grub_error (GRUB_ERR_BAD_ARGUMENT, "EFI secret area disk encryption password is corrupt\n"); + + *secret_ptr = e->data; + return GRUB_ERR_NONE; + } + ptr += e->len; + len -= e->len; + } + return grub_error (GRUB_ERR_BAD_ARGUMENT, "EFI secret area does not contain disk decryption password\n"); +} + +static grub_err_t +grub_efi_secret_get (const char *arg __attribute__((unused)), grub_uint8_t **ptr) +{ + unsigned int i; + + for (i = 0; i < grub_efi_system_table->num_table_entries; i++) + { + grub_efi_packed_guid_t *guid = + &grub_efi_system_table->configuration_table[i].vendor_guid; + + if (! grub_memcmp (guid, &secret_guid, sizeof (grub_efi_packed_guid_t))) { + struct efi_secret *s = + grub_efi_system_table->configuration_table[i].vendor_table; + + return grub_efi_secret_find(s, ptr); + } + } + return grub_error (GRUB_ERR_BAD_ARGUMENT, "No secret found in the EFI configuration table"); +} + +static struct grub_secret_entry secret = { + .name = "efisecret", + .get = grub_efi_secret_get, + .put = grub_efi_secret_put, +}; + +GRUB_MOD_INIT(efisecret) +{ + grub_cryptodisk_add_secret_provider (&secret); +} + +GRUB_MOD_FINI(efisecret) +{ + grub_cryptodisk_remove_secret_provider (&secret); +} diff --git a/include/grub/efi/api.h b/include/grub/efi/api.h index f1a52210c..f33a8f2ab 100644 --- a/include/grub/efi/api.h +++ b/include/grub/efi/api.h @@ -299,6 +299,21 @@ { 0x9a, 0x16, 0x00, 0x90, 0x27, 0x3f, 0xc1, 0x4d } \ } +#define GRUB_EFI_SECRET_TABLE_GUID \ + { 0xadf956ad, 0xe98c, 0x484c, \ + { 0xae, 0x11, 0xb5, 0x1c, 0x7d, 0x33, 0x64, 0x47} \ + } + +#define GRUB_EFI_SECRET_TABLE_HEADER_GUID \ + { 0x1e74f542, 0x71dd, 0x4d66, \ + { 0x96, 0x3e, 0xef, 0x42, 0x87, 0xff, 0x17, 0x3b } \ + } + +#define GRUB_EFI_DISKPASSWD_GUID \ + { 0x736869e5, 0x84f0, 0x4973, \ + { 0x92, 0xec, 0x06, 0x87, 0x9c, 0xe3, 0xda, 0x0b } \ + } + #define GRUB_EFI_ACPI_TABLE_GUID \ { 0xeb9d2d30, 0x2d88, 0x11d3, \ { 0x9a, 0x16, 0x0, 0x90, 0x27, 0x3f, 0xc1, 0x4d } \ -- 2.34.1