From mboxrd@z Thu Jan 1 00:00:00 1970 Received: from list by lists.gnu.org with archive (Exim 4.90_1) id 1nWXLt-0002ma-Gv for mharc-grub-devel@gnu.org; Tue, 22 Mar 2022 01:46:42 -0400 Received: from eggs.gnu.org ([209.51.188.92]:46284) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1nWXLp-0002mI-KQ for grub-devel@gnu.org; Tue, 22 Mar 2022 01:46:38 -0400 Received: from de-smtp-delivery-102.mimecast.com ([194.104.109.102]:37632) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1nWXLm-0006Se-9H for grub-devel@gnu.org; Tue, 22 Mar 2022 01:46:36 -0400 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=suse.com; s=mimecast20200619; t=1647927991; 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=/isl+Ok4rJW53Qu2zElgMv7hhcYXhrHBY79Ukd/8eJw=; b=AwfRtb73/3p6dm6Ll8MuAg9JXmcNnggOh4Lvh13siZV4PuFKqHkyx3Gh7v5TFe5uYFelec bE55fjM7Fnzdm3J/IE3aSKnfGk0+4CV3naR1Gjqtoh+7lBWhI8fsVSck+FelpO/+QNFU3x nTbhkSNmK05KlU3eSAgt6gbtE9GB0r4= Received: from EUR05-DB8-obe.outbound.protection.outlook.com (mail-db8eur05lp2106.outbound.protection.outlook.com [104.47.17.106]) by relay.mimecast.com with ESMTP with STARTTLS (version=TLSv1.2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id de-mta-29-EeVLTA1HNxqD5WEq_0EC8A-1; Tue, 22 Mar 2022 06:46:29 +0100 X-MC-Unique: EeVLTA1HNxqD5WEq_0EC8A-1 ARC-Seal: i=1; a=rsa-sha256; s=arcselector9901; d=microsoft.com; cv=none; b=oXBncJFGi3EBPPt2sFlclxl10422Q7I2XP1xahcL7UAlRNqeJZykHL8BDoiMY1mIZ/RjKKHmUgM+O+Kv+1po0L+NMLDMTzcHyhpMKzond/v8OYXp4cqdhHSdGwGttmDxd+tkzo5aC4LkWdLtHW2jYYVwf1I0ZFt+aTqtfRE5C22KVczWY44xMAAjJ9LAzDmgUryvrSp6X8uaSM/jLJGqJ5hkl2WE4xZYhlPzHES8b1YqVfDdlg+WtcJ88N/5/NdxtQ7n+6sFZGyVhha9kK7c8law55ECO/70cwCj3TturVSZpgwDwAhAQ82thktK96XukMgyq72divgOM5ChpcBoaA== 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=/isl+Ok4rJW53Qu2zElgMv7hhcYXhrHBY79Ukd/8eJw=; b=e/bytq8KY3vlfcW6FnWASDcxPN/+2qdU1/VCsws7IUCObmHmcIVT3661FlZQBeWgO3HJDLEI5+KEfFWbppsw6faT4wRqj1Vr1y2s6LKumvOnXD8cWTC+BZRquIEJ7IynplhVQ2IaMVXpgl7xTHNNxvVP3jT1CZC+uk3PdhNp6y6AtmHjY0AbdhFC483qSI4YEGoChu0GPB0vJY3CWKwiITPyisqF/C60YkQzJdQ2jWA5qDVVko9N4CmwQuWA4o+Gzh3PSmeKBrC/J03EYz+Ms2K4YWgUIQUjGUuEKI40qiyHHx/SoWVqvmmaisHbowVR3Lg0dv7YDOOPT7z5mJzwtg== 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 AM6PR04MB6504.eurprd04.prod.outlook.com (2603:10a6:20b:f9::21) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.20.5081.23; Tue, 22 Mar 2022 05:46: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 05:46:26 +0000 Date: Tue, 22 Mar 2022 13:46: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: <20220322054620.GB10510@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: HKAPR04CA0015.apcprd04.prod.outlook.com (2603:1096:203:d0::25) 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: 2781829b-7afe-497b-e10b-08da0bc74e3c X-MS-TrafficTypeDiagnostic: AM6PR04MB6504: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: pxQ63SJse0dpqrxnYBOt+qBuiTORMqX7x7ZOPa9H6kG6Jn+HgYM9HDplFz7WBTPjN4BV1oEnQDcOWn5MUtFDiirmoo5yaDLK5l0JJOPkyavucii3cE/YJgXswys9FlxM2c0rtjYv6Tp/uFtG5QyQ/U0ydvevNjRh0fgHqb6Fn/Q5qaXanOxmxKZ2CVK+h999tg1+edLSo1BpswyVJJhTbqtRbezTbv2T0NBkfIg6rBJnKX7YWSxWowdykyaeMP5v8vkKMAsqWhlC6XfuyjG4S8z0qO/RdoLM/2NMoL3Ws7QoEeZGuJScF4gcg/Vxf4H3zJCcrP+YVOiIqVMEpAa7fQ1KPmdSEmLHyaRKu2RWZqnXQyo8PVFHfO6K8fZCR6GZ++sWNuoDNIyigFsyf8Klb09RXsJoLtMeHsAsIVxW1aiE9i5uZyMbf3YtcBvBVt81joiAeLoNoejk/bcsWrBHfp1RDdRq/jhBRhpTIU0kKsi1zsc8Bbs05S7zd8kDVQ9X/D5t4HrqqXEat/6rm4680+a2qBn1lVRbVLWrhQKMEFooupR2ibCB10aGic+b4ACDZ63RoymxbhOAn3xlILlugyhwbjh32CXK/HmdLxkxdMH2tLaBMcwAW31uNzUQArJrPGITJBBoupZcTapEBKFfVBW/grVQbNOqSuRUqB6zRdPIAM3IoOhnwtWZQ8NhMwb1sdnMzhF2j0lgn3+697oIvkxbyCAFQVF2cjEZATwZCfj193mmHyi3sOk6itBwg9HBA4hbk53lykG7yTh56K58jRqBeB/cX5uil18xslDfudHPJQr6knYG50RdFylHzV2g 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)(86362001)(38100700002)(6486002)(2906002)(508600001)(66946007)(33656002)(966005)(83380400001)(45080400002)(66556008)(8676002)(66476007)(4326008)(19627235002)(1076003)(5660300002)(316002)(8936002)(33716001)(186003)(30864003)(6916009)(6506007)(6666004)(9686003)(6512007)(2004002); DIR:OUT; SFP:1101; X-MS-Exchange-AntiSpam-MessageData-ChunkCount: 1 X-MS-Exchange-AntiSpam-MessageData-0: =?us-ascii?Q?16oNfcbO/tIyBvkfjH+Gl2ZwME9Z1nnPpwEjkst3efWV2iUWY/0qBMD770Lw?= =?us-ascii?Q?h0em89862Su+PDdf73yMqYWmY8/orChL7IO+TzlCQjXZJL19zn64Trreh7e7?= =?us-ascii?Q?uYX7SrCV2fRVeP5tWOBa9XBqz/4Tot4vbYrMTGjDnG/XU/PHt3TQh1xsHbpM?= =?us-ascii?Q?ERVRcszmHZZ3G6BLxFHLHdgLcwwjeffqHbDCJvpO9Z/nlxFsohezdl4VmkSr?= =?us-ascii?Q?rN8YK52z9+iPJcqNqlRx8Es7oetMHg6g7dil2kNHqMI3BjF+H893PSjaDQKM?= =?us-ascii?Q?GprRcA8vxd2hJfLv33134+592CiDsBebxpAqtMvpRL3KCy7nmDgqSWQDufIy?= =?us-ascii?Q?Tk806iedheh/XuojXt42eoxnPc/gst2/6C5l/H6bpU7Exh5ydvbw9mF+EALs?= =?us-ascii?Q?r0Y3PGBDx38tA/S4BjWvLw1lZwKysZebWKX4iZHFNCjSUVzKhT9FElOypA0L?= =?us-ascii?Q?qWK2bWmk88rFUFmUMSY7DmVem7OYlAJYlak8t5D/N7HMfd5mWyN6+ThMxZg1?= =?us-ascii?Q?UI3X6ee7OildK3z+XjDvsalrZynkOnMDdovGcLr13cEbT2vPoErHDlS5sfZr?= =?us-ascii?Q?pbwrfqE4Gljl31jU6xRyR19EcQIgQz6q4sRobfWgfZ0gMzgk4/UlFrrRSV2H?= =?us-ascii?Q?31lEJHhL5XUQwpaKspBcwxLAfiQOpak28mgNxS6fg3/h2lMOgJ7pBMcqUDA3?= =?us-ascii?Q?FtFzZ9zW12lYJATEYi/Jyuc1XZiE6W7SvxbNLP8QrBOXmk5wOOwMncSpwF7u?= =?us-ascii?Q?IbLs1Uo+/FVRfVdGGyslAQhIPTPF99D67aBqRST1NPTdw6MP3FGp8B5EJtEm?= =?us-ascii?Q?nBO8MH/SzOqBCKinE7yGwfY1yjXzNH0cU219N7DHAMXka7MMngBnl+jFbukq?= =?us-ascii?Q?ZQMVJ9pHtk+unfpzYNNqzEuRpUR/XKM/sZ23Nxl09cMXB09RIXa8y+PPw9RU?= =?us-ascii?Q?V0t3Ks6Tz7I2ATiFf+sq5rvaSTqyPMAP1JSkSEV2rBJZl6LRLt4nUeA4Ih51?= =?us-ascii?Q?FFzkZBpGx+nyB1iAqqD2ok9yMWuHJVWGSjR+B7+I69fM+Ox2Zxw6ZI7rgAIo?= =?us-ascii?Q?pgiYOTf51Auw+rx9XnCHsDl1Gj1VTw4MXPyYboJwtKTHyPd1uQHDrbh7Bxb8?= =?us-ascii?Q?TY43bCcJX+lB8CVAWXYKtwYqhSeyPAxWg2UxYU14+tZk6RXDWnYtNyfEWkGV?= =?us-ascii?Q?2gdimm18zHYisFXF9QdXWjJYfGlzIT0F2yYg0FyvOFntX5HXgj/jNrZe7uo4?= =?us-ascii?Q?3gSBWtx1hg3ggrmUqdXgJuoT+t5UbrUKPOQpSXWZRRTNziY3xOm2m8/yls3r?= =?us-ascii?Q?m6TzJSt6+gDaTHWPfMAlCm5W9VH5Wb2woAy2DkBdV4Mgw6Qy1tyR+JWgIR5p?= =?us-ascii?Q?ki5n+AcRHZi7zoOoBITzkYbLYpfcLIPcMxv8PtHywTX4RHVjVHjuqKeAZn+U?= =?us-ascii?Q?Zz5zNRYOO9QrkDcDfeVXD0Acvdg5uv1/iSDIG643x8BW9HBNH1i/Z0laOg/S?= =?us-ascii?Q?QqlLwDRFjL/zQWG0HO8pg8Y9lpaiA2h5/tyf?= X-OriginatorOrg: suse.com X-MS-Exchange-CrossTenant-Network-Message-Id: 2781829b-7afe-497b-e10b-08da0bc74e3c X-MS-Exchange-CrossTenant-AuthSource: DU2PR04MB9081.eurprd04.prod.outlook.com X-MS-Exchange-CrossTenant-AuthAs: Internal X-MS-Exchange-CrossTenant-OriginalArrivalTime: 22 Mar 2022 05:46:26.8480 (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: +/KhwjwbCWY3+2hXEnT/u7jA1QbWcZEaDsvRaBALqkvfrLH0MTdz41FQ5sV4/h8T X-MS-Exchange-Transport-CrossTenantHeadersStamped: AM6PR04MB6504 Received-SPF: pass client-ip=194.104.109.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_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: Tue, 22 Mar 2022 05:46:39 -0000 On Tue, Feb 01, 2022 at 05:02:55AM -0800, Hernan Gatta wrote: Sorry forgot to mention another build related issue in previous reply. > +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); This fails in i386-efi build with: ../../grub-core/tpm2/module.c: In function 'grub_tpm2_protector_srk_unmarshal_keyfile': ../../grub-core/tpm2/module.c:197:29: error: format '%lu' expects argument of type 'long unsigned int', but argument 5 has type 'grub_size_t' {aka 'unsigned int'} [-Werror=format=] 197 | grub_dprintf ("tpm2", "Sealed key file is larger than decode buffer " | ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 198 | "(%lu vs %lu bytes).\n", sealed_key_size, buf.cap); | ~~~~~~~~~~~~~~~ | | | grub_size_t {aka unsigned int} Maybe it's better to use generalized PRI[uxd]GRUB_.* macro defined in grub/types.h than lu to deal with platform dependent conversion specifiers. Thanks, Michael > + 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