From mboxrd@z Thu Jan 1 00:00:00 1970 Received: from list by lists.gnu.org with archive (Exim 4.90_1) id 1nWVUj-0002yG-EQ for mharc-grub-devel@gnu.org; Mon, 21 Mar 2022 23:47:41 -0400 Received: from eggs.gnu.org ([209.51.188.92]:54412) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1nWVUh-0002xq-6s for grub-devel@gnu.org; Mon, 21 Mar 2022 23:47:39 -0400 Received: from de-smtp-delivery-102.mimecast.com ([194.104.111.102]:26124) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1nWVUc-0002ja-1b for grub-devel@gnu.org; Mon, 21 Mar 2022 23:47:37 -0400 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=suse.com; s=mimecast20200619; t=1647920850; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version:content-type:content-type: in-reply-to:in-reply-to:references:references; bh=05znQgSuYWars9CvUoBSCPR0OnfzqGCwGBrGS9hgASc=; b=EVexL+y8T8WPbSEE+XvZjsWwvREMNUZwfZfW5eJzQgHb8tYm9gYkDn5Cw46anaLZChdCy1 unMe2g3pphm3GLIy+OSNt2C3WYtbvOh0a45vf0axxTZ+FqVwfW7BnvLDo2Ft2nRWor/Cso hroppNkVwhzAceFuX3UY5/mfwg4jkbY= Received: from EUR04-VI1-obe.outbound.protection.outlook.com (mail-vi1eur04lp2055.outbound.protection.outlook.com [104.47.14.55]) by relay.mimecast.com with ESMTP with STARTTLS (version=TLSv1.2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id de-mta-26-hG7W02_5Pxy-FZTbom2Kcw-1; Tue, 22 Mar 2022 04:47:28 +0100 X-MC-Unique: hG7W02_5Pxy-FZTbom2Kcw-1 ARC-Seal: i=1; a=rsa-sha256; s=arcselector9901; d=microsoft.com; cv=none; b=UxYG9nM1hiHd/lNExVkKfYBwjzxkKu3vn1zanQ4LG+kxMvVjs8hbR37cyAwt0ThW4V2bREgirPd0+wGwMaCcVd4qfeoxek2LeBshJNw0W3teVVHjAdFkKv5yMGVS2phf/R620rJDL17IoJLm9F2LsN2SAJD7ZAlbCmhKQMXIqP7O9AtAmRtHa7RqLpBC0cM110ekQIl7cP3vFGmS6thzuh4c2KN6Wza4UrpC94LRm8W+RMde5xgYk/h7zaPlc37NtuVP/0yssAOOBf8xqtaYM6xdY6i2PteRdLp6Wr7MwpFPXe/8saRAP0bNxY63wSRvJpukgLLJo1FdsohH5Mf58A== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=microsoft.com; s=arcselector9901; h=From:Date:Subject:Message-ID:Content-Type:MIME-Version:X-MS-Exchange-AntiSpam-MessageData-ChunkCount:X-MS-Exchange-AntiSpam-MessageData-0:X-MS-Exchange-AntiSpam-MessageData-1; bh=05znQgSuYWars9CvUoBSCPR0OnfzqGCwGBrGS9hgASc=; b=Od7Jipin40YWsAwEyStjLzz3eAGCFv6UEl088aNwM0RA0vzeIN2LBD4bLesrwT8G4Pp92Yb+qgsQcImsRXEQSjtSOJFGjQwMjwFGgzsRm0kfDevhXCCePmOS1gvvjYKrGVLXgLux/YZdME/AVAN3nseS7Z5E4zz6dNmv5Xe3f7cRuXIPBhTa6cRUb5AZjLj3KTfSDp7NVP1+iESWANmN0zCtq+B6R2s+FVl1KASmzcBpFjqNbVPve8i5FAfMOUC47UAnkg55sxkK1xOgKgnCSEWC9yAH5+bfEfkaNAca88fYp+iF+yKkxhvEms40AQKnOl/ChR3R2TbdLTc4sEv4ew== ARC-Authentication-Results: i=1; mx.microsoft.com 1; spf=pass smtp.mailfrom=suse.com; dmarc=pass action=none header.from=suse.com; dkim=pass header.d=suse.com; arc=none Authentication-Results: dkim=none (message not signed) header.d=none;dmarc=none action=none header.from=suse.com; Received: from DU2PR04MB9081.eurprd04.prod.outlook.com (2603:10a6:10:2f0::13) by PA4PR04MB7854.eurprd04.prod.outlook.com (2603:10a6:102:c2::20) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.20.5102.16; Tue, 22 Mar 2022 03:47:26 +0000 Received: from DU2PR04MB9081.eurprd04.prod.outlook.com ([fe80::2d29:445:cc37:a97f]) by DU2PR04MB9081.eurprd04.prod.outlook.com ([fe80::2d29:445:cc37:a97f%4]) with mapi id 15.20.5081.022; Tue, 22 Mar 2022 03:47:26 +0000 Date: Tue, 22 Mar 2022 11:47:20 +0800 From: Michael Chang To: The development of GNU GRUB Cc: shkhisti@microsoft.com, jaskaran.khurana@microsoft.com, christopher.co@microsoft.com, daniel.mihai@microsoft.com, rharwood@redhat.com, jaredz@redhat.com, development@efficientek.com, jejb@linux.ibm.com Subject: Re: [PATCH v2 3/5] protectors: Add TPM2 Key Protector Message-ID: <20220322034720.GA10510@mazu> References: <1643720577-22911-1-git-send-email-hegatta@linux.microsoft.com> <1643720577-22911-4-git-send-email-hegatta@linux.microsoft.com> Content-Type: text/plain; charset=us-ascii Content-Disposition: inline In-Reply-To: <1643720577-22911-4-git-send-email-hegatta@linux.microsoft.com> User-Agent: Mutt/1.10.1 (2018-07-13) X-ClientProxiedBy: HK0PR03CA0111.apcprd03.prod.outlook.com (2603:1096:203:b0::27) To DU2PR04MB9081.eurprd04.prod.outlook.com (2603:10a6:10:2f0::13) MIME-Version: 1.0 X-MS-PublicTrafficType: Email X-MS-Office365-Filtering-Correlation-Id: 21ea5d9e-5586-41f1-8968-08da0bb6adf9 X-MS-TrafficTypeDiagnostic: PA4PR04MB7854:EE_ X-Microsoft-Antispam-PRVS: X-MS-Exchange-SenderADCheck: 1 X-MS-Exchange-AntiSpam-Relay: 0 X-Microsoft-Antispam: BCL:0; X-Microsoft-Antispam-Message-Info: COLEvOyJdtxRTx6fdFjCNQmqFbmpOIo7LrliyT/c9BthcRUd1pLKN/Ffv4TJVczkaOWcoLOvFbm8wU6dsqiFQbe/XOTQ88T1EmBklHUiXHGGDbZcNfiUb8/4xN5Sulykls3mAprg8mxvTsMQdyz+csvIdEifP35WRRg8UpY5j82rGZkYnWF4Nl6AzRpIwxLwprRbcveOmnyHjVeQrFdvOi1xR0NuGUscCcXyuJNvHaC4IV/HEVICEtjAfjCp51gcsq70uRQfcdqqGLMouYBvjPxtxcMjEGd8MzJkGz/87WHuIorhXMbLfAGAwQWF8yXklmttNPpGHvif5E3gN0+EAelxvCMJ0MKJImEw6tWZJ0+dFaeIWAYjilkWuaMy2pDHUx3jlldrhYmZx1bHPGYLeaD3xiq/lRfW7WgZg2Ldjx7146FgXdEHi/LsaoTM9ESqE0NXieraeDy97LACfOD418/6ieHwaHiIzCDS9lL8xTE2vZbPIBzaGLjVeUxNR8yQeIR4fCW5/Z/PIVDOXC0Ahpue32Iqd23VH8vFYRBXhzG+WyKh+W4TOsoI8T8N8Nt9uyNszkOuehsfWmdGH4mA96EjZAg4Pfh/b0+Vvb+1SgKWIeQw71u8cu+6Rw5DyX9RfPJ9KxLd2ms7Fvlz/lUbv8GSf8pGKiRQzYfb3rhtqzwKBzpmUn5iNF7+WuzWhJK75taxt6v0G3qNpkyFuLWooc6r9njKeHhHSIkzXVJHmSZiLHzGsBzSoWDCpMpplSdXT6ThmWYYM2cphFzChH/P3t+Ig8vyO+05fzA+2gVoyPHqP7hJUhtU9Hxwg9viDiuk X-Forefront-Antispam-Report: CIP:255.255.255.255; CTRY:; LANG:en; SCL:1; SRV:; IPV:NLI; SFV:NSPM; H:DU2PR04MB9081.eurprd04.prod.outlook.com; PTR:; CAT:NONE; SFS:(13230001)(7916004)(366004)(33656002)(66556008)(66476007)(66946007)(83380400001)(19627235002)(316002)(86362001)(6916009)(6666004)(9686003)(6512007)(6506007)(186003)(33716001)(1076003)(6486002)(966005)(508600001)(38100700002)(45080400002)(8676002)(8936002)(4326008)(30864003)(5660300002)(2906002)(2004002); DIR:OUT; SFP:1101; X-MS-Exchange-AntiSpam-MessageData-ChunkCount: 1 X-MS-Exchange-AntiSpam-MessageData-0: =?us-ascii?Q?4wa+Wn4c81zn5aTalty90uhxFKfpv1C+XH4yHDmeMAej/qvSJSwMKQHo0inL?= =?us-ascii?Q?E/lFYey0OEn2htdRzg6Gl9n2x4JoM+1ycrv7wL2N7gW34QWQXcAdLPjzKler?= =?us-ascii?Q?Pd4fL+n7DAARZkD02LX7LsZ1rcHnVCtK6Psbq6+PH8ZfluGOuvleHFBnSm+x?= =?us-ascii?Q?G3W1OlymLRYlTvZbqPVvKT7PqV7O3jAJbwfVyqVleA0jv7z5OOTVqTfHADjd?= =?us-ascii?Q?u+Pa7yTMwUPAmbDW+l2QFxnYj0QGRH0YfTvrHdlXmxU5DRbdMOhGr8ww4/fb?= =?us-ascii?Q?Wo0GCcnyovTV6QVQyIfr+D4qcILGk2KG8hxw+7aMpjsI9/q/3/qjPksfgdna?= =?us-ascii?Q?FVdUPilREvp4f3oInDxWbi8gkk98Zb0pPaSiPrEpG2wsdleIxeXDs29BrbXh?= =?us-ascii?Q?2poqBVHAGWRVDwutsgBDW/taXVS0DaXoiTkWoGVxCbudq+NHDzr5brmJDVsi?= =?us-ascii?Q?OfYYVWZKr0cQJ5SsU85sh/w9uYlq6C2LYsi0wZZDVJfPI1rM1LuE4RWuFYs1?= =?us-ascii?Q?ZybJbLRbIRngNZVyO9Y3+QtcnhL9PSK0NgVnUi43HScSYzg6RDmSS747Ub3V?= =?us-ascii?Q?Dk1CNZS02CjOxktNSaqaCGR7n60HPNcpR4oxfmNstlf+SnLu0KMVBOrYyKgY?= =?us-ascii?Q?E6qZ8TZ34QRziXaMg3AzR1gwld61I6W3BzVqaMFoVGDHd6OAnRrozKKGebeR?= =?us-ascii?Q?tHlr/+F1JBkXtxs1Dl0BR/TCe5BSUGD8bAPasXbkfJXZJs2yLaoiIt2OQDuC?= =?us-ascii?Q?hGDfhlLuji4r1lrhJkeTT7Gl5jt4YUq/V6eLiTJkW6zpNPOFIAdoJID8wUkx?= =?us-ascii?Q?qlwuqK12ukzU57P7w1PncPQMi3AjumVCovwPM5MyiPQW79I3O6zM9c4rw6Wu?= =?us-ascii?Q?lTuM3NIpP6dC4lpOAw5VGTCAewt5AKQ+Ir7EIahuLdKJklUOx/KzpOXL63oJ?= =?us-ascii?Q?fEladQidJ0uyh22PBACjnSjfkrVBXV+5KdR72JTnA+MRhQYTgIjHmC4QFXQl?= =?us-ascii?Q?pxSvRLSis8XwHfQfaMS3kyRQ+UWuohT01Y4YZqGPLGsptnv6dviEzHNYJV2z?= =?us-ascii?Q?diprQbiJgq1BccDBJXxxjKV0bGvwBOqtl1yoiGG/t6WLdWXo4dmBQH8iR9tt?= =?us-ascii?Q?8hcOWa5poQ/TF9Z2mmpstOia1r+BAaFwgCfvvBMlSqSVJl70FybcdBMBcOSP?= =?us-ascii?Q?X72IS8U8HCTC9baKC5fLzZntYFhj2K0XjuTxZYpfX7RaGtuGc7gaiI8aBmVv?= =?us-ascii?Q?99lL9/4Juns+CoAZsXW9y33zDw0lqANth3SOWMR9w84WXvWcvXWizFTtk2ZI?= =?us-ascii?Q?d7HypAhidxnVGSnAQYcCQW3Or/c0e2k3GmQDL8zcnh/NqqUfxd6JfayEeUqu?= =?us-ascii?Q?YZzlX6c/acRectRZQ8E0uCvdQQRl+dctfmgcDGC9G8XAbq54sJ3BjYPsNaGo?= =?us-ascii?Q?kcHww5VUWepPhqTvmUbtKS7tFGaSjhP9kQ2yCqge8OZbzNPNQTx53+qkW4/n?= =?us-ascii?Q?gsFseMntFdyDTCR8pBKJO4pnQW+Moeb3xX0h?= X-OriginatorOrg: suse.com X-MS-Exchange-CrossTenant-Network-Message-Id: 21ea5d9e-5586-41f1-8968-08da0bb6adf9 X-MS-Exchange-CrossTenant-AuthSource: DU2PR04MB9081.eurprd04.prod.outlook.com X-MS-Exchange-CrossTenant-AuthAs: Internal X-MS-Exchange-CrossTenant-OriginalArrivalTime: 22 Mar 2022 03:47:26.1173 (UTC) X-MS-Exchange-CrossTenant-FromEntityHeader: Hosted X-MS-Exchange-CrossTenant-Id: f7a17af6-1c5c-4a36-aa8b-f5be247aa4ba X-MS-Exchange-CrossTenant-MailboxType: HOSTED X-MS-Exchange-CrossTenant-UserPrincipalName: YZTCdEECHVY85Rzjo8jyW0h+ZoJ/Ggi7lNQzcANvOy1NSUibhzyY1IoTAADRrC63 X-MS-Exchange-Transport-CrossTenantHeadersStamped: PA4PR04MB7854 Received-SPF: pass client-ip=194.104.111.102; envelope-from=mchang@suse.com; helo=de-smtp-delivery-102.mimecast.com X-Spam_score_int: -27 X-Spam_score: -2.8 X-Spam_bar: -- X-Spam_report: (-2.8 / 5.0 requ) BAYES_00=-1.9, DKIM_SIGNED=0.1, DKIM_VALID=-0.1, DKIM_VALID_AU=-0.1, DKIM_VALID_EF=-0.1, RCVD_IN_DNSWL_LOW=-0.7, RCVD_IN_MSPIKE_H4=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: Tue, 22 Mar 2022 03:47:39 -0000 On Tue, Feb 01, 2022 at 05:02:55AM -0800, Hernan Gatta wrote: > The TPM2 key protector is a module that enables the automatic retrieval of a > fully-encrypted disk's unlocking key from a TPM 2.0. > > The theory of operation is such that the module accepts various arguments, most > of which are optional and therefore possess reasonable defaults. One of these > arguments is the keyfile parameter, which is mandatory. > > The value of this parameter must be a path to a sealed key file (e.g., > (hd0,gpt1)/boot/grub2/sealed_key). This sealed key file is created via the > grub-protect tool. The tool utilizes the TPM's sealing functionality to seal > (i.e., encrypt) an unlocking key using a Storage Root Key (SRK) to the values of > various Platform Configuration Registers (PCRs). These PCRs reflect the state of > the system as it boots. If the values are as expected, the system may be > considered trustworthy, at which point the TPM allows for a caller to utilize > the private component of the SRK to unseal (i.e., decrypt) the sealed key file. > The caller, in this case, is this key protector. > > The TPM2 key protector registers two commands: > > - tpm2_key_protector_init: Initializes the state of the TPM2 key protector for > later usage, clearing any previous state, too, if > any. > > - tpm2_key_protector_clear: Clears any state set by tpm2_key_protector_init. > > The way this is expected to be used requires the user to, either interactively > or, normally, via a boot script, initialize (i.e., configure) the key protector > and then specify that it be used by the cryptomount command (modifications to > this command are in a different patch). > > For instance: > > tpm2_key_protector_init --keyfile=KEYFILE1 > cryptomount DISK1 -k tpm2 > > tpm2_key_protector_init --keyfile=KEYFILE2 --pcrs=7,11 > cryptomount DISK2 -k tpm2 > > If a user does not initialize the key protector and attempts to use it anyway, > the protector returns an error. > > Signed-off-by: Hernan Gatta > --- > grub-core/Makefile.core.def | 10 + > grub-core/tpm2/args.c | 129 +++++++ > grub-core/tpm2/module.c | 710 ++++++++++++++++++++++++++++++++++++++ > include/grub/tpm2/internal/args.h | 39 +++ > 4 files changed, 888 insertions(+) > create mode 100644 grub-core/tpm2/args.c > create mode 100644 grub-core/tpm2/module.c > create mode 100644 include/grub/tpm2/internal/args.h > > diff --git a/grub-core/Makefile.core.def b/grub-core/Makefile.core.def > index e4ae78b..78d09d9 100644 > --- a/grub-core/Makefile.core.def > +++ b/grub-core/Makefile.core.def > @@ -2498,6 +2498,16 @@ module = { > }; > > module = { > + name = tpm2; > + common = tpm2/args.c; > + common = tpm2/buffer.c; > + common = tpm2/module.c; > + common = tpm2/mu.c; > + common = tpm2/tpm2.c; > + efi = tpm2/tcg2.c; The tpm2 module fails to build on non-efi platforms because of undefined symbols from tpm2/tcg2.c. Maybe adding enable = efi is required here as long as supporting other platform seems not to be intended. Thanks, Michael > +}; > + > +module = { > name = tr; > common = commands/tr.c; > }; > diff --git a/grub-core/tpm2/args.c b/grub-core/tpm2/args.c > new file mode 100644 > index 0000000..90c7cd8 > --- /dev/null > +++ b/grub-core/tpm2/args.c > @@ -0,0 +1,129 @@ > +/* > + * GRUB -- GRand Unified Bootloader > + * Copyright (C) 2022 Microsoft Corporation > + * > + * GRUB is free software: you can redistribute it and/or modify > + * it under the terms of the GNU General Public License as published by > + * the Free Software Foundation, either version 3 of the License, or > + * (at your option) any later version. > + * > + * GRUB is distributed in the hope that it will be useful, > + * but WITHOUT ANY WARRANTY; without even the implied warranty of > + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the > + * GNU General Public License for more details. > + * > + * You should have received a copy of the GNU General Public License > + * along with GRUB. If not, see . > + */ > + > +#include > +#include > +#include > +#include > + > +grub_err_t > +grub_tpm2_protector_parse_pcrs (char *value, grub_uint8_t *pcrs, > + grub_uint8_t *pcr_count) > +{ > + char *current_pcr = value; > + char *next_pcr; > + unsigned long pcr; > + grub_uint8_t i; > + > + if (grub_strlen (value) == 0) > + return GRUB_ERR_BAD_ARGUMENT; > + > + *pcr_count = 0; > + for (i = 0; i < TPM_MAX_PCRS; i++) > + { > + next_pcr = grub_strchr (current_pcr, ','); > + if (next_pcr == current_pcr) > + return grub_error (GRUB_ERR_BAD_ARGUMENT, > + N_("Empty entry in PCR list")); > + if (next_pcr) > + *next_pcr = '\0'; > + > + grub_errno = GRUB_ERR_NONE; > + pcr = grub_strtoul (current_pcr, NULL, 10); > + if (grub_errno != GRUB_ERR_NONE) > + return grub_error (grub_errno, > + N_("Entry '%s' in PCR list is not a number"), > + current_pcr); > + > + if (pcr > TPM_MAX_PCRS) > + return grub_error (GRUB_ERR_OUT_OF_RANGE, > + N_("Entry %lu in PCR list is too large to be a PCR " > + "number, PCR numbers range from 0 to %u"), > + pcr, TPM_MAX_PCRS); > + > + pcrs[i] = (grub_uint8_t)pcr; > + *pcr_count += 1; > + > + if (!next_pcr) > + break; > + > + current_pcr = next_pcr + 1; > + if (*current_pcr == '\0') > + return grub_error (GRUB_ERR_BAD_ARGUMENT, > + N_("Trailing comma at the end of PCR list")); > + } > + > + if (i == TPM_MAX_PCRS) > + return grub_error (GRUB_ERR_OUT_OF_RANGE, > + N_("Too many PCRs in PCR list, the maximum number of " > + "PCRs is %u"), TPM_MAX_PCRS); > + > + return GRUB_ERR_NONE; > +} > + > +grub_err_t > +grub_tpm2_protector_parse_asymmetric (const char *value, TPM_ALG_ID *asymmetric) > +{ > + if (grub_strcasecmp (value, "ECC") == 0) > + *asymmetric = TPM_ALG_ECC; > + else if (grub_strcasecmp (value, "RSA") == 0) > + *asymmetric = TPM_ALG_RSA; > + else > + return grub_error (GRUB_ERR_OUT_OF_RANGE, > + N_("Value '%s' is not a valid asymmetric key type"), > + value); > + > + return GRUB_ERR_NONE; > +} > + > +grub_err_t > +grub_tpm2_protector_parse_bank (const char *value, TPM_ALG_ID *bank) > +{ > + if (grub_strcasecmp (value, "SHA1") == 0) > + *bank = TPM_ALG_SHA1; > + else if (grub_strcasecmp (value, "SHA256") == 0) > + *bank = TPM_ALG_SHA256; > + else if (grub_strcasecmp (value, "SHA384") == 0) > + *bank = TPM_ALG_SHA384; > + else > + return grub_error (GRUB_ERR_OUT_OF_RANGE, > + N_("Value '%s' is not a valid PCR bank"), value); > + > + return GRUB_ERR_NONE; > +} > + > +grub_err_t > +grub_tpm2_protector_parse_tpm_handle (const char *value, TPM_HANDLE *handle) > +{ > + unsigned long num; > + > + grub_errno = GRUB_ERR_NONE; > + num = grub_strtoul (value, NULL, 0); > + if (grub_errno != GRUB_ERR_NONE) > + return grub_error (grub_errno, N_("TPM handle value '%s' is not a number"), > + value); > + > + if (num > GRUB_UINT_MAX) > + return grub_error (GRUB_ERR_OUT_OF_RANGE, > + N_("Value %lu is too large to be a TPM handle, TPM " > + "handles are unsigned 32-bit integers"), num); > + > + *handle = (TPM_HANDLE)num; > + > + return GRUB_ERR_NONE; > +} > diff --git a/grub-core/tpm2/module.c b/grub-core/tpm2/module.c > new file mode 100644 > index 0000000..3f2f386 > --- /dev/null > +++ b/grub-core/tpm2/module.c > @@ -0,0 +1,710 @@ > +/* > + * GRUB -- GRand Unified Bootloader > + * Copyright (C) 2022 Microsoft Corporation > + * > + * GRUB is free software: you can redistribute it and/or modify > + * it under the terms of the GNU General Public License as published by > + * the Free Software Foundation, either version 3 of the License, or > + * (at your option) any later version. > + * > + * GRUB is distributed in the hope that it will be useful, > + * but WITHOUT ANY WARRANTY; without even the implied warranty of > + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the > + * GNU General Public License for more details. > + * > + * You should have received a copy of the GNU General Public License > + * along with GRUB. If not, see . > + */ > + > +#include > +#include > +#include > +#include > +#include > +#include > +#include > +#include > +#include > +#include > + > +GRUB_MOD_LICENSE ("GPLv3+"); > + > +typedef enum grub_tpm2_protector_mode > +{ > + GRUB_TPM2_PROTECTOR_MODE_UNSET, > + GRUB_TPM2_PROTECTOR_MODE_SRK, > + GRUB_TPM2_PROTECTOR_MODE_NV > +} grub_tpm2_protector_mode_t; > + > +struct grub_tpm2_protector_context > +{ > + grub_tpm2_protector_mode_t mode; > + grub_uint8_t pcrs[TPM_MAX_PCRS]; > + grub_uint8_t pcr_count; > + TPM_ALG_ID asymmetric; > + TPM_ALG_ID bank; > + const char *keyfile; > + TPM_HANDLE srk; > + TPM_HANDLE nv; > +}; > + > +static const struct grub_arg_option grub_tpm2_protector_init_cmd_options[] = > + { > + /* Options for all modes */ > + { > + .longarg = "mode", > + .shortarg = 'm', > + .flags = 0, > + .arg = NULL, > + .type = ARG_TYPE_STRING, > + .doc = > + N_("Unseal key using SRK ('srk') (default) or retrieve it from an NV " > + "Index ('nv')."), > + }, > + { > + .longarg = "pcrs", > + .shortarg = 'p', > + .flags = 0, > + .arg = NULL, > + .type = ARG_TYPE_STRING, > + .doc = > + N_("Comma-separated list of PCRs used to authorize key release " > + "(e.g., '7,11', default is 7."), > + }, > + { > + .longarg = "bank", > + .shortarg = 'b', > + .flags = 0, > + .arg = NULL, > + .type = ARG_TYPE_STRING, > + .doc = > + N_("Bank of PCRs used to authorize key release: " > + "SHA1, SHA256 (default), or SHA384."), > + }, > + /* SRK-mode options */ > + { > + .longarg = "keyfile", > + .shortarg = 'k', > + .flags = 0, > + .arg = NULL, > + .type = ARG_TYPE_STRING, > + .doc = > + N_("Required in SRK mode, path to the sealed key file to unseal using " > + "the TPM (e.g., (hd0,gpt1)/boot/grub2/sealed_key)."), > + }, > + { > + .longarg = "srk", > + .shortarg = 's', > + .flags = 0, > + .arg = NULL, > + .type = ARG_TYPE_STRING, > + .doc = > + N_("In SRK mode, the SRK handle if the SRK is persistent " > + "(default is 0x81000001)."), > + }, > + { > + .longarg = "asymmetric", > + .shortarg = 'a', > + .flags = 0, > + .arg = NULL, > + .type = ARG_TYPE_STRING, > + .doc = > + N_("In SRK mode, the type of SRK: RSA (default) or ECC."), > + }, > + /* NV Index-mode options */ > + { > + .longarg = "nvindex", > + .shortarg = 'n', > + .flags = 0, > + .arg = NULL, > + .type = ARG_TYPE_STRING, > + .doc = > + N_("Required in NV Index mode, the NV handle to read which must " > + "readily exist on the TPM and which contains the key."), > + }, > + /* End of list */ > + {0, 0, 0, 0, 0, 0} > + }; > + > +static grub_extcmd_t grub_tpm2_protector_init_cmd; > +static grub_extcmd_t grub_tpm2_protector_clear_cmd; > +static struct grub_tpm2_protector_context grub_tpm2_protector_ctx = { 0 }; > + > +static grub_err_t > +grub_tpm2_protector_srk_read_keyfile (const char *filepath, void **buffer, > + grub_size_t *buffer_size) > +{ > + grub_file_t sealed_key_file; > + grub_off_t sealed_key_size; > + void *sealed_key_buffer; > + grub_off_t sealed_key_read; > + > + sealed_key_file = grub_file_open (filepath, GRUB_FILE_TYPE_NONE); > + if (!sealed_key_file) > + { > + grub_dprintf ("tpm2", "Could not open sealed key file.\n"); > + /* grub_file_open sets grub_errno on error, and if we do no unset it, > + * future calls to grub_file_open will fail (and so will anybody up the > + * stack who checks the value, if any). */ > + grub_errno = GRUB_ERR_NONE; > + return GRUB_ERR_FILE_NOT_FOUND; > + } > + > + sealed_key_size = grub_file_size (sealed_key_file); > + if (!sealed_key_size) > + { > + grub_dprintf ("tpm2", "Could not read sealed key file size.\n"); > + grub_file_close (sealed_key_file); > + return GRUB_ERR_OUT_OF_RANGE; > + } > + > + sealed_key_buffer = grub_malloc (sealed_key_size); > + if (!sealed_key_buffer) > + { > + grub_dprintf ("tpm2", "Could not allocate buffer for sealed key.\n"); > + grub_file_close (sealed_key_file); > + return GRUB_ERR_OUT_OF_MEMORY; > + } > + > + sealed_key_read = grub_file_read (sealed_key_file, sealed_key_buffer, > + sealed_key_size); > + if (sealed_key_read != sealed_key_size) > + { > + grub_dprintf ("tpm2", "Could not retrieve sealed key file contents.\n"); > + grub_free (sealed_key_buffer); > + grub_file_close (sealed_key_file); > + return GRUB_ERR_FILE_READ_ERROR; > + } > + > + grub_file_close (sealed_key_file); > + > + *buffer = sealed_key_buffer; > + *buffer_size = sealed_key_size; > + > + return GRUB_ERR_NONE; > +} > + > +static grub_err_t > +grub_tpm2_protector_srk_unmarshal_keyfile (void *sealed_key, > + grub_size_t sealed_key_size, > + TPM2_SEALED_KEY *sk) > +{ > + struct grub_tpm2_buffer buf; > + > + grub_tpm2_buffer_init (&buf); > + if (sealed_key_size > buf.cap) > + { > + grub_dprintf ("tpm2", "Sealed key file is larger than decode buffer " > + "(%lu vs %lu bytes).\n", sealed_key_size, buf.cap); > + return GRUB_ERR_BAD_ARGUMENT; > + } > + > + grub_memcpy (buf.data, sealed_key, sealed_key_size); > + buf.size = sealed_key_size; > + > + grub_tpm2_mu_TPM2B_PUBLIC_Unmarshal (&buf, &sk->public); > + grub_tpm2_mu_TPM2B_Unmarshal (&buf, (TPM2B *)&sk->private); > + > + if (buf.error) > + { > + grub_dprintf ("tpm2", "Could not unmarshal sealed key file, it is likely " > + "malformed.\n"); > + return GRUB_ERR_BAD_ARGUMENT; > + } > + > + return GRUB_ERR_NONE; > +} > + > +static grub_err_t > +grub_tpm2_protector_srk_get (const struct grub_tpm2_protector_context *ctx, > + TPM_HANDLE *srk) > +{ > + TPM_RC rc; > + TPM2B_PUBLIC public; > + TPMS_AUTH_COMMAND authCommand = { 0 }; > + TPM2B_SENSITIVE_CREATE inSensitive = { 0 }; > + TPM2B_PUBLIC inPublic = { 0 }; > + TPM2B_DATA outsideInfo = { 0 }; > + TPML_PCR_SELECTION creationPcr = { 0 }; > + TPM2B_PUBLIC outPublic = { 0 }; > + TPM2B_CREATION_DATA creationData = { 0 }; > + TPM2B_DIGEST creationHash = { 0 }; > + TPMT_TK_CREATION creationTicket = { 0 }; > + TPM2B_NAME srkName = { 0 }; > + TPM_HANDLE srkHandle; > + > + /* Find SRK */ > + rc = TPM2_ReadPublic (ctx->srk, NULL, &public); > + if (rc == TPM_RC_SUCCESS) > + { > + *srk = ctx->srk; > + return GRUB_ERR_NONE; > + } > + > + /* The handle exists but its public area could not be read. */ > + if ((rc & ~TPM_RC_N_MASK) != TPM_RC_HANDLE) > + { > + grub_dprintf ("tpm2", "The SRK handle (0x%x) exists on the TPM but its " > + "public area could not be read (TPM2_ReadPublic " > + "failed with TSS/TPM error %u).\n", ctx->srk, rc); > + return GRUB_ERR_BAD_DEVICE; > + } > + > + /* Create SRK */ > + authCommand.sessionHandle = TPM_RS_PW; > + inPublic.publicArea.type = ctx->asymmetric; > + inPublic.publicArea.nameAlg = TPM_ALG_SHA256; > + inPublic.publicArea.objectAttributes.restricted = 1; > + inPublic.publicArea.objectAttributes.userWithAuth = 1; > + inPublic.publicArea.objectAttributes.decrypt = 1; > + inPublic.publicArea.objectAttributes.fixedTPM = 1; > + inPublic.publicArea.objectAttributes.fixedParent = 1; > + inPublic.publicArea.objectAttributes.sensitiveDataOrigin = 1; > + inPublic.publicArea.objectAttributes.noDA = 1; > + > + if (ctx->asymmetric == TPM_ALG_RSA) > + { > + inPublic.publicArea.parameters.rsaDetail.symmetric.algorithm = TPM_ALG_AES; > + inPublic.publicArea.parameters.rsaDetail.symmetric.keyBits.aes = 128; > + inPublic.publicArea.parameters.rsaDetail.symmetric.mode.aes = TPM_ALG_CFB; > + inPublic.publicArea.parameters.rsaDetail.scheme.scheme = TPM_ALG_NULL; > + inPublic.publicArea.parameters.rsaDetail.keyBits = 2048; > + inPublic.publicArea.parameters.rsaDetail.exponent = 0; > + } > + else if (ctx->asymmetric == TPM_ALG_ECC) > + { > + inPublic.publicArea.parameters.eccDetail.symmetric.algorithm = TPM_ALG_AES; > + inPublic.publicArea.parameters.eccDetail.symmetric.keyBits.aes = 128; > + inPublic.publicArea.parameters.eccDetail.symmetric.mode.aes = TPM_ALG_CFB; > + inPublic.publicArea.parameters.eccDetail.scheme.scheme = TPM_ALG_NULL; > + inPublic.publicArea.parameters.eccDetail.curveID = TPM_ECC_NIST_P256; > + inPublic.publicArea.parameters.eccDetail.kdf.scheme = TPM_ALG_NULL; > + } > + else > + return GRUB_ERR_BAD_ARGUMENT; > + > + rc = TPM2_CreatePrimary (TPM_RH_OWNER, &authCommand, &inSensitive, &inPublic, > + &outsideInfo, &creationPcr, &srkHandle, &outPublic, > + &creationData, &creationHash, &creationTicket, > + &srkName, NULL); > + if (rc != TPM_RC_SUCCESS) > + { > + grub_dprintf ("tpm2", "Could not create SRK (TPM2_CreatePrimary failed " > + "with TSS/TPM error %u).\n", rc); > + return GRUB_ERR_BAD_DEVICE; > + } > + > + *srk = srkHandle; > + > + return GRUB_ERR_NONE; > +} > + > +static grub_err_t > +grub_tpm2_protector_srk_recover (const struct grub_tpm2_protector_context *ctx, > + grub_uint8_t **key, grub_size_t *key_size) > +{ > + TPM_RC rc; > + TPM2_SEALED_KEY sealed_key; > + void *sealed_key_bytes; > + grub_size_t sealed_key_size; > + TPM_HANDLE srk_handle; > + TPM2B_NONCE nonceCaller = { 0 }; > + TPM2B_ENCRYPTED_SECRET salt = { 0 }; > + TPMT_SYM_DEF symmetric = { 0 }; > + TPM2B_NONCE nonceTPM = { 0 }; > + TPMI_SH_AUTH_SESSION session; > + TPML_PCR_SELECTION pcrSel = { > + .count = 1, > + .pcrSelections = { > + { > + .hash = ctx->bank, > + .sizeOfSelect = 3, > + .pcrSelect = { 0 } > + }, > + } > + }; > + TPMS_AUTH_COMMAND authCmd = { 0 }; > + TPM_HANDLE sealed_key_handle; > + TPM2B_NAME name; > + TPMS_AUTH_RESPONSE authResponse; > + TPM2B_SENSITIVE_DATA data; > + grub_uint8_t *key_out; > + grub_uint8_t i; > + grub_err_t err; > + > + /* Retrieve Sealed Key */ > + err = grub_tpm2_protector_srk_read_keyfile (ctx->keyfile, &sealed_key_bytes, > + &sealed_key_size); > + if (err) > + return grub_error (err, N_("Failed to read key file %s"), ctx->keyfile); > + > + err = grub_tpm2_protector_srk_unmarshal_keyfile (sealed_key_bytes, > + sealed_key_size, > + &sealed_key); > + if (err) > + { > + grub_error (err, N_("Failed to unmarshal key, ensure the key file is in " > + "TPM wire format")); > + goto exit1; > + } > + > + /* Get SRK */ > + err = grub_tpm2_protector_srk_get (ctx, &srk_handle); > + if (err) > + { > + grub_error (err, N_("Failed to retrieve the SRK")); > + goto exit1; > + } > + > + err = GRUB_ERR_BAD_DEVICE; > + > + /* Start Auth Session */ > + nonceCaller.size = TPM_SHA256_DIGEST_SIZE; > + symmetric.algorithm = TPM_ALG_NULL; > + > + rc = TPM2_StartAuthSession (TPM_RH_NULL, TPM_RH_NULL, 0, &nonceCaller, &salt, > + TPM_SE_POLICY, &symmetric, TPM_ALG_SHA256, > + &session, &nonceTPM, 0); > + if (rc) > + { > + grub_error (err, N_("Failed to start auth session (TPM2_StartAuthSession " > + "failed with TSS/TPM error %u)"), rc); > + goto exit2; > + } > + > + /* Policy PCR */ > + for (i = 0; i < ctx->pcr_count; i++) > + pcrSel > + .pcrSelections[0] > + .pcrSelect[TPM2_PCR_TO_SELECT(ctx->pcrs[i])] > + |= TPM2_PCR_TO_BIT(ctx->pcrs[i]); > + > + rc = TPM2_PolicyPCR (session, NULL, NULL, &pcrSel, NULL); > + if (rc) > + { > + grub_error (err, N_("Failed to submit PCR policy (TPM2_PolicyPCR failed " > + "with TSS/TPM error %u)"), rc); > + goto exit3; > + } > + > + /* Load Sealed Key */ > + authCmd.sessionHandle = TPM_RS_PW; > + rc = TPM2_Load (srk_handle, &authCmd, &sealed_key.private, &sealed_key.public, > + &sealed_key_handle, &name, &authResponse); > + if (rc) > + { > + grub_error (err, N_("Failed to load sealed key (TPM2_Load failed with " > + "TSS/TPM error %u)"), rc); > + goto exit3; > + } > + > + /* Unseal Sealed Key */ > + authCmd.sessionHandle = session; > + grub_memset (&authResponse, 0, sizeof (authResponse)); > + > + rc = TPM2_Unseal (sealed_key_handle, &authCmd, &data, &authResponse); > + if (rc) > + { > + grub_error (err, N_("Failed to unseal sealed key (TPM2_Unseal failed " > + "with TSS/TPM error %u)"), rc); > + goto exit4; > + } > + > + /* Epilogue */ > + key_out = grub_malloc (data.size); > + if (!key_out) > + { > + err = GRUB_ERR_OUT_OF_MEMORY; > + grub_error (err, N_("No memory left to allocate unlock key buffer")); > + goto exit4; > + } > + > + grub_memcpy (key_out, data.buffer, data.size); > + > + *key = key_out; > + *key_size = data.size; > + > + err = GRUB_ERR_NONE; > + > +exit4: > + TPM2_FlushContext (sealed_key_handle); > + > +exit3: > + TPM2_FlushContext (session); > + > +exit2: > + TPM2_FlushContext (srk_handle); > + > +exit1: > + grub_free (sealed_key_bytes); > + return err; > +} > + > +static grub_err_t > +grub_tpm2_protector_nv_recover (const struct grub_tpm2_protector_context *ctx, > + grub_uint8_t **key, grub_size_t *key_size) > +{ > + (void)ctx; > + (void)key; > + (void)key_size; > + > + return grub_error (GRUB_ERR_NOT_IMPLEMENTED_YET, > + N_("NV Index mode is not implemented yet")); > +} > + > +static grub_err_t > +grub_tpm2_protector_recover (const struct grub_tpm2_protector_context *ctx, > + grub_uint8_t **key, grub_size_t *key_size) > +{ > + switch (ctx->mode) > + { > + case GRUB_TPM2_PROTECTOR_MODE_SRK: > + return grub_tpm2_protector_srk_recover (ctx, key, key_size); > + case GRUB_TPM2_PROTECTOR_MODE_NV: > + return grub_tpm2_protector_nv_recover (ctx, key, key_size); > + default: > + return GRUB_ERR_BAD_ARGUMENT; > + } > +} > + > +static grub_err_t > +grub_tpm2_protector_recover_key (grub_uint8_t **key, grub_size_t *key_size) > +{ > + grub_err_t err; > + > + /* Expect a call to tpm2_protector_init before anybody tries to use us */ > + if (grub_tpm2_protector_ctx.mode == GRUB_TPM2_PROTECTOR_MODE_UNSET) > + return grub_error (GRUB_ERR_INVALID_COMMAND, > + N_("Cannot use TPM2 key protector without initializing " > + "it, call tpm2_protector_init first")); > + > + if (!key) > + return GRUB_ERR_BAD_ARGUMENT; > + > + err = grub_tpm2_protector_recover (&grub_tpm2_protector_ctx, key, key_size); > + if (err) > + return err; > + > + return GRUB_ERR_NONE; > +} > + > + > +static grub_err_t > +grub_tpm2_protector_check_args (struct grub_tpm2_protector_context *ctx) > +{ > + if (ctx->mode == GRUB_TPM2_PROTECTOR_MODE_UNSET) > + ctx->mode = GRUB_TPM2_PROTECTOR_MODE_SRK; > + > + /* Checks for SRK mode */ > + if (ctx->mode == GRUB_TPM2_PROTECTOR_MODE_SRK && !ctx->keyfile) > + return grub_error (GRUB_ERR_BAD_ARGUMENT, > + N_("In SRK mode, a key file must be specified: " > + "--keyfile or -k")); > + > + if (ctx->mode == GRUB_TPM2_PROTECTOR_MODE_SRK && ctx->nv) > + return grub_error (GRUB_ERR_BAD_ARGUMENT, > + N_("In SRK mode, an NV Index cannot be specified")); > + > + /* Checks for NV mode */ > + if (ctx->mode == GRUB_TPM2_PROTECTOR_MODE_NV && !ctx->nv) > + return grub_error (GRUB_ERR_BAD_ARGUMENT, > + N_("In NV Index mode, an NV Index must be specified: " > + "--nvindex or -n")); > + > + if (ctx->mode == GRUB_TPM2_PROTECTOR_MODE_NV && ctx->keyfile) > + return grub_error (GRUB_ERR_BAD_ARGUMENT, > + N_("In NV Index mode, a keyfile cannot be specified")); > + > + if (ctx->mode == GRUB_TPM2_PROTECTOR_MODE_NV && ctx->srk) > + return grub_error (GRUB_ERR_BAD_ARGUMENT, > + N_("In NV Index mode, an SRK cannot be specified")); > + > + if (ctx->mode == GRUB_TPM2_PROTECTOR_MODE_NV && ctx->asymmetric) > + return grub_error (GRUB_ERR_BAD_ARGUMENT, > + N_("In NV Index mode, an asymmetric key type cannot be " > + "specified")); > + > + /* Defaults assignment */ > + if (!ctx->bank) > + ctx->bank = TPM_ALG_SHA256; > + > + if (!ctx->pcr_count) > + { > + ctx->pcrs[0] = 7; > + ctx->pcr_count = 1; > + } > + > + if (ctx->mode == GRUB_TPM2_PROTECTOR_MODE_SRK) > + { > + if (!ctx->srk) > + ctx->srk = TPM2_SRK_HANDLE; > + > + if (!ctx->asymmetric) > + ctx->asymmetric = TPM_ALG_RSA; > + } > + > + return GRUB_ERR_NONE; > +} > + > +static grub_err_t > +grub_tpm2_protector_parse_keyfile (const char *value, const char **keyfile) > +{ > + if (grub_strlen (value) == 0) > + return GRUB_ERR_BAD_ARGUMENT; > + > + *keyfile = grub_strdup (value); > + if (!*keyfile) > + return grub_error (GRUB_ERR_OUT_OF_MEMORY, > + N_("No memory to duplicate keyfile path")); > + > + return GRUB_ERR_NONE; > +} > + > +static grub_err_t > +grub_tpm2_protector_parse_mode (const char *value, > + grub_tpm2_protector_mode_t *mode) > +{ > + if (grub_strcmp (value, "srk") == 0) > + *mode = GRUB_TPM2_PROTECTOR_MODE_SRK; > + else if (grub_strcmp (value, "nv") == 0) > + *mode = GRUB_TPM2_PROTECTOR_MODE_NV; > + else > + return grub_error (GRUB_ERR_OUT_OF_RANGE, > + N_("Value '%s' is not a valid TPM2 key protector mode"), > + value); > + > + return GRUB_ERR_NONE; > +} > + > +static grub_err_t > +grub_tpm2_protector_init_cmd_handler (grub_extcmd_context_t ctxt, int argc, > + char **args __attribute__ ((unused))) > +{ > + struct grub_arg_list *state = ctxt->state; > + grub_err_t err; > + > + if (argc) > + return grub_error (GRUB_ERR_BAD_ARGUMENT, > + N_("The TPM2 key protector does not accept any " > + "non-option arguments (i.e., like -o and/or --option " > + "only)")); > + > + grub_free ((void *) grub_tpm2_protector_ctx.keyfile); > + grub_memset (&grub_tpm2_protector_ctx, 0, sizeof (grub_tpm2_protector_ctx)); > + > + if (state[0].set) /* mode */ > + { > + err = grub_tpm2_protector_parse_mode (state[0].arg, > + &grub_tpm2_protector_ctx.mode); > + if (err) > + return err; > + } > + > + if (state[1].set) /* pcrs */ > + { > + err = grub_tpm2_protector_parse_pcrs (state[1].arg, > + grub_tpm2_protector_ctx.pcrs, > + &grub_tpm2_protector_ctx.pcr_count); > + if (err) > + return err; > + } > + > + if (state[2].set) /* bank */ > + { > + err = grub_tpm2_protector_parse_bank (state[2].arg, > + &grub_tpm2_protector_ctx.bank); > + if (err) > + return err; > + } > + > + if (state[3].set) /* keyfile */ > + { > + err = grub_tpm2_protector_parse_keyfile (state[3].arg, > + &grub_tpm2_protector_ctx.keyfile); > + if (err) > + return err; > + } > + > + if (state[4].set) /* srk */ > + { > + err = grub_tpm2_protector_parse_tpm_handle (state[4].arg, > + &grub_tpm2_protector_ctx.srk); > + if (err) > + return err; > + } > + > + if (state[5].set) /* asymmetric */ > + { > + err = grub_tpm2_protector_parse_asymmetric (state[5].arg, > + &grub_tpm2_protector_ctx.asymmetric); > + if (err) > + return err; > + } > + > + if (state[6].set) /* nvindex */ > + { > + err = grub_tpm2_protector_parse_tpm_handle (state[6].arg, > + &grub_tpm2_protector_ctx.nv); > + if (err) > + return err; > + } > + > + err = grub_tpm2_protector_check_args (&grub_tpm2_protector_ctx); > + > + /* This command only initializes the protector, so nothing else to do. */ > + > + return err; > +} > + > +static grub_err_t > +grub_tpm2_protector_clear_cmd_handler (grub_extcmd_context_t ctxt __attribute__ ((unused)), > + int argc, > + char **args __attribute__ ((unused))) > +{ > + if (argc) > + return grub_error (GRUB_ERR_BAD_ARGUMENT, > + N_("tpm2_key_protector_clear accepts no arguments")); > + > + grub_free ((void *) grub_tpm2_protector_ctx.keyfile); > + grub_memset (&grub_tpm2_protector_ctx, 0, sizeof (grub_tpm2_protector_ctx)); > + > + return GRUB_ERR_NONE; > +} > + > +static struct grub_key_protector grub_tpm2_key_protector = > + { > + .name = "tpm2", > + .recover_key = grub_tpm2_protector_recover_key > + }; > + > +GRUB_MOD_INIT (tpm2) > +{ > + grub_tpm2_protector_init_cmd = > + grub_register_extcmd ("tpm2_key_protector_init", > + grub_tpm2_protector_init_cmd_handler, 0, > + N_("[-m mode] " > + "[-p pcr_list] " > + "[-b pcr_bank] " > + "[-k sealed_key_file_path] " > + "[-s srk_handle] " > + "[-a asymmetric_key_type] " > + "[-n nv_index]"), > + N_("Initialize the TPM2 key protector."), > + grub_tpm2_protector_init_cmd_options); > + grub_tpm2_protector_clear_cmd = > + grub_register_extcmd ("tpm2_key_protector_clear", > + grub_tpm2_protector_clear_cmd_handler, 0, NULL, > + N_("Clear the TPM2 key protector if previously initialized."), > + NULL); > + grub_key_protector_register (&grub_tpm2_key_protector); > +} > + > +GRUB_MOD_FINI (tpm2) > +{ > + grub_free ((void *) grub_tpm2_protector_ctx.keyfile); > + grub_memset (&grub_tpm2_protector_ctx, 0, sizeof (grub_tpm2_protector_ctx)); > + > + grub_key_protector_unregister (&grub_tpm2_key_protector); > + grub_unregister_extcmd (grub_tpm2_protector_clear_cmd); > + grub_unregister_extcmd (grub_tpm2_protector_init_cmd); > +} > diff --git a/include/grub/tpm2/internal/args.h b/include/grub/tpm2/internal/args.h > new file mode 100644 > index 0000000..6341fce > --- /dev/null > +++ b/include/grub/tpm2/internal/args.h > @@ -0,0 +1,39 @@ > +/* > + * GRUB -- GRand Unified Bootloader > + * Copyright (C) 2022 Microsoft Corporation > + * > + * GRUB is free software: you can redistribute it and/or modify > + * it under the terms of the GNU General Public License as published by > + * the Free Software Foundation, either version 3 of the License, or > + * (at your option) any later version. > + * > + * GRUB is distributed in the hope that it will be useful, > + * but WITHOUT ANY WARRANTY; without even the implied warranty of > + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the > + * GNU General Public License for more details. > + * > + * You should have received a copy of the GNU General Public License > + * along with GRUB. If not, see . > + */ > + > +#ifndef GRUB_TPM2_INTERNAL_ARGS_HEADER > +#define GRUB_TPM2_INTERNAL_ARGS_HEADER 1 > + > +#include > +#include > + > +grub_err_t > +grub_tpm2_protector_parse_pcrs (char *value, grub_uint8_t *pcrs, > + grub_uint8_t *pcr_count); > + > +grub_err_t > +grub_tpm2_protector_parse_asymmetric (const char *value, > + TPM_ALG_ID *asymmetric); > + > +grub_err_t > +grub_tpm2_protector_parse_bank (const char *value, TPM_ALG_ID *bank); > + > +grub_err_t > +grub_tpm2_protector_parse_tpm_handle (const char *value, TPM_HANDLE *handle); > + > +#endif /* ! GRUB_TPM2_INTERNAL_ARGS_HEADER */ > -- > 1.8.3.1 > > > _______________________________________________ > Grub-devel mailing list > Grub-devel@gnu.org > https://lists.gnu.org/mailman/listinfo/grub-devel