From mboxrd@z Thu Jan 1 00:00:00 1970 Received: from list by lists.gnu.org with archive (Exim 4.90_1) id 1nWXTk-00048W-3z for mharc-grub-devel@gnu.org; Tue, 22 Mar 2022 01:54:48 -0400 Received: from eggs.gnu.org ([209.51.188.92]:47572) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1nWXTi-00048C-JK for grub-devel@gnu.org; Tue, 22 Mar 2022 01:54:46 -0400 Received: from de-smtp-delivery-102.mimecast.com ([194.104.111.102]:28502) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1nWXTe-00053h-RE for grub-devel@gnu.org; Tue, 22 Mar 2022 01:54:45 -0400 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=suse.com; s=mimecast20200619; t=1647928480; 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=1MFxodLZWwgXQxK2GlWu7vJnzLsph6dDn3V3iAVQyRw=; b=MttAMQfJ8WpqH96L5VPyjJTJFHYzhQiu4xFJ8+3WcUDhOy82Ckq+PDEqyn5tVKEN2irQBc fPVWs/XZw/qANHk/E2GRwesXtCqaq30U7ITYVqpk4SsL0wWhJeQrBDc34nr3NeVCsAKsiA EHWVv8AyvS0tplRcs17Z5qnyusrBoPY= Received: from EUR04-DB3-obe.outbound.protection.outlook.com (mail-db3eur04lp2058.outbound.protection.outlook.com [104.47.12.58]) by relay.mimecast.com with ESMTP with STARTTLS (version=TLSv1.2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id de-mta-16-YRmxGuEPMuWdfEsSTAm47Q-1; Tue, 22 Mar 2022 06:54:39 +0100 X-MC-Unique: YRmxGuEPMuWdfEsSTAm47Q-1 ARC-Seal: i=1; a=rsa-sha256; s=arcselector9901; d=microsoft.com; cv=none; b=dPbgQWvW1i1MUDF50mqVDj0o4380n90wbRFIe34q6BpYlgR4oG3TYkEHN6BgHNVgePFmJWtTaOSZImH2Q/MFP1O3arJ5oYAQvft9wDYiKCepNsod52mOkCACgfMhgRIUGStv/5eg108u6MD8CvfHm4yRpXkVlSVAIDJ/wDrUqB6/NftrBLfs3qdEbuBV6ukWvJnyFqfXgMPGqrmcnLyjxkFSmjJdVTFkZk8R7pnMUDPTIydkWYfmvOy13exWGpw98FP7t6ZHMrmGbZhp+zioUilpIZW/XiDspj3oFdTG8DBU5dUMUAjPJJ2PUO7Jmrl+b2RmV1J7SjYfhAPCGapt7g== 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=1MFxodLZWwgXQxK2GlWu7vJnzLsph6dDn3V3iAVQyRw=; b=IOUgFu1G3vpLK/zgBLTTOYCTUCj7qNV3KoshvatTf/Y8pEkm4PFSvcn/rDS+6fZazRHTnnRhiw3z/ottzJDDNe+5+QgYdMx/gto6Z5RdspDMg5YvBC1WX6bwCWLXs2BorsznaoOWzDU82DIYb7EbufeT3/FvLO7cwSFxut26/iZ5L7dwN6wX/INP3I/bBqDLVNBvLzPDJFBe+qtRxRHZ5tEOjy/g5okzP+/NQrzRnMO6MWn/dlUxlOaRNDxLIGt6CB9sOgZOzp/rMUWLO1SWEt+wko52aPVVCt16PY0DIu0Onh8aSkNn3nrim+gD5UfdC7bUgrjIAO+n26iFNjgqBw== 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 VI1PR04MB5453.eurprd04.prod.outlook.com (2603:10a6:803:c9::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:54:37 +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:54:36 +0000 Date: Tue, 22 Mar 2022 13:54:29 +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 5/5] util/grub-protect: Add new tool Message-ID: <20220322055429.GC10510@mazu> References: <1643720577-22911-1-git-send-email-hegatta@linux.microsoft.com> <1643720577-22911-6-git-send-email-hegatta@linux.microsoft.com> Content-Type: text/plain; charset=us-ascii Content-Disposition: inline In-Reply-To: <1643720577-22911-6-git-send-email-hegatta@linux.microsoft.com> User-Agent: Mutt/1.10.1 (2018-07-13) X-ClientProxiedBy: HK2PR02CA0176.apcprd02.prod.outlook.com (2603:1096:201:21::12) 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: f68640fe-c6ae-4d75-7a90-08da0bc87202 X-MS-TrafficTypeDiagnostic: VI1PR04MB5453: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: wEIi+53pmmGzk9TBhpzZF/ml3t3tVnAkd1W/wVhu4dtvIzppvDCTm/Lb8h2BT7klfYEebhHAJwIvckxXS3fDGDGAuqYIXpk1cv3IPWE42gv/2NvptUAfCcXT8Id7KEnbUs+HYmOyOwZSPRhnU0Gw7RhjimWk9qExx9tzseGbWY6Oz1dSm9uqTfJv4TDR3jSxGhldMWe5yeJ0Oh6gUq2UxLysww9s4yZqHzG8ECylrRmf8mLnxZMnaVn2RwAvY8KyiQhZQ0IjBkdR668TkRiPkUQ+d3pyYaLF1uiADosL1mTj7c9ovarsGpvpzQULLFCYovW2Ro4JhssIXVtMBvbgJTJwu0euHQafFlbWOeqrWe+AYpzyHwhCkzAlYXDj85sCnMlJwtsEIrQ9s9EUYVbxRk3XIv+CczRmCQZrsFrbf3TIVuw0r9pv8OOrahVvbIQOOEf9AeY3Qkn1G9RVPqn0/UBc73A8/5OystVGgSIDFsJO/oYBF8CwlChXdjth0MY1ORD3rK5OozK659eKWtsuRgSbhX9JQeDOXFAI9MoLmI/7/sYveWiBRl47BJvSflJEEoabWQUluccFbURLwGAnHxCYp1YpgKiT88l1nnx7gByr+iQhU/GCfRRfJx2fi5DopGNmOHESiohIk35GNWlfyrguPMScn+B766sorE103bOMbuwtn8nU08bIVe4bVI984cPvSrUAI7fqCeC/saTIxYl5RpIVm22gEw2gXBplJZE= 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)(30864003)(5660300002)(508600001)(966005)(6486002)(186003)(2906002)(8936002)(38100700002)(6666004)(1076003)(19627235002)(6916009)(66946007)(4326008)(8676002)(66556008)(316002)(6506007)(83380400001)(86362001)(9686003)(33656002)(6512007)(66476007)(33716001); DIR:OUT; SFP:1101; X-MS-Exchange-AntiSpam-MessageData-ChunkCount: 1 X-MS-Exchange-AntiSpam-MessageData-0: =?us-ascii?Q?GAfa+JUUa0G6G3OTrRSGXgRy2/iTG7XqRTGaVTLi2RtRTBe1003xEsEprl65?= =?us-ascii?Q?pLxHmLox+V0w6k48Z0QqDQzWwhbFJBPovMmYpqYwcXT8mnq3ntNby99g4P+7?= =?us-ascii?Q?2FyOnhcaPU0MCpCT7MmaGEC4Hf7TCmoy7ZdKVRBFEpRbo+IhD44iurs6pF89?= =?us-ascii?Q?g/SyNfJUhIOIzAB+qgQLa1Ht5h8jVwjZJ+hjCQlZWXpkI9qY58VaHvKQKBX3?= =?us-ascii?Q?VusyV0ZZPrLrFLGw3XNR54tWl37hc8ApZCsVbUAHxSh3z+6X4FONXUofLKeP?= =?us-ascii?Q?NyOqWQLnQqMrYfiZHYofn1p/jAbIhlOzhNMEkbVhP84JrJUERQsOu/myWgNr?= =?us-ascii?Q?P0gVlE1RGCBvLHYhf2cU+VGVQgYvZAJY9BoxyyQ+UTwo45oWQiNCOchriY+n?= =?us-ascii?Q?30SHBzg341SROGKp19ZEVyiSx1XnaUrOvavc5UVvN8+lg6vWqyiW15RHlyJn?= =?us-ascii?Q?9oYcZU2Q+TYYfIY+/+AaVn8TCtXyPxVtKCU4y5m2QwvWZdbXfOuTuqnu/Ixc?= =?us-ascii?Q?fPpIovcAnvpNx9uGwzK2nxWlRpP2veIu4Kez0J78B/Eb5qV/RtygCrI/v3xD?= =?us-ascii?Q?o8+GegNspdeVjYFN6O1hvDymQdbHwIrsBliZv/VG43tP29aOCX8kjwuQK0Lw?= =?us-ascii?Q?fIejaJeqs7eMz7hJKNxayaFqsYti9PzEiJbYwMETL0YZxV2ZZPuxiQSu/NYs?= =?us-ascii?Q?RorebvVLYgiWUugMbnyvhUyi6j45vKi0MHEwehKh4QLvEKSVA6X6u5OeX3zn?= =?us-ascii?Q?MhCD3VAN+pfNYDBEPTiYtjY3HEGkdhFeQajOsWDQn/oB7ySLx/eJ5eej5u9x?= =?us-ascii?Q?7P6ZSWu3xfLmA39HOjJDrWQVvO4u1lMaBBDjkYgtJ3Q1pExqLNymGC8B69uK?= =?us-ascii?Q?tnSCgMo/BhZvMtUPso/oOwlJnkKVhSi1teU24kU3bmZHWLMP4e2jZV1UiDbG?= =?us-ascii?Q?EcI7aJXHygCUqz/rWY2DcNKIfLaCDBId/u1DYP75FrO04pI7X6sa5FpcxEGF?= =?us-ascii?Q?fNArB4qzYrJOwgBb8YFMO1wrTFPZ1NLBKJsaNd4lql1GiJiPtuNICN1T8kxm?= =?us-ascii?Q?secIjFXiWDAqdOXZNqNGwYsW5Sgks/nziBw/4vnYVWH308lDTISyk1Nsc6kQ?= =?us-ascii?Q?tHC9gAMajCyhOZTaFMtS98RmJsnGt4Iz9QCCZR1q8xY8ZeC+a/4VWpntwUkq?= =?us-ascii?Q?5OPcL/9HwXfgJEe/GYR2njZoL90fys0amhNQ8A1TofgNRUWAqJv5eV3uceC6?= =?us-ascii?Q?mR/BgBoTsXxJv4XE9SY3iAN5lQjKdHGCfMmBLsuQgNVZgp4U/Katg+d1TJw+?= =?us-ascii?Q?l5VmFa7cp6oMA0sK+0nNYuFQ21FcASUIUmRsQBHxoezCp9mGmNXK809bWaK6?= =?us-ascii?Q?hEL4Xx+Nze0d8L8bTA4r71H1DzWPDw1AfOX3xaSQvV6vHzDGTEy+km0KGGBE?= =?us-ascii?Q?w0u6vx2YquDC2WhqsmStK132bt9XB8EJhbprZQ+m7szrlNLRxaBkytuxWXVM?= =?us-ascii?Q?sI+tAqAaO+FXpVR2L55GBxyN5hiZShTE9SOS?= X-OriginatorOrg: suse.com X-MS-Exchange-CrossTenant-Network-Message-Id: f68640fe-c6ae-4d75-7a90-08da0bc87202 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:54:36.4069 (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: 9F37sIkfKy/XbS+KwHDZn1ZrU3bqAglSckBXHlPHTjale38p62sg5UiJrkWkuj2r X-MS-Exchange-Transport-CrossTenantHeadersStamped: VI1PR04MB5453 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 05:54:46 -0000 On Tue, Feb 01, 2022 at 05:02:57AM -0800, Hernan Gatta wrote: [snip] > +static grub_err_t > +grub_protect_tpm2_get_policy_digest (struct grub_protect_args *args, > + TPM2B_DIGEST *digest) > +{ [snip] > + for (i = 0; i < args->tpm2_pcr_count; i++) > + { > + if (pcr_values.digests[i].size != pcr_digest_len) > + { > + fprintf (stderr, > + _("Bad PCR value size: expected %lu bytes but got %u bytes.\n"), > + pcr_digest_len, pcr_values.digests[i].size); Again please consider to use PRI[uxd]GRUB_.* for the conversion specifier, otherwise i386-efi will not build. Thanks, Michael > + goto exit2; > + } > + > + grub_memcpy (pcr_cursor, pcr_values.digests[i].buffer, pcr_digest_len); > + pcr_cursor += pcr_digest_len; > + } > + > + grub_crypto_hash (hash_spec, pcr_digest, pcr_concat, pcr_concat_len); > + > + /* Start Trial Session */ > + nonce.size = TPM_SHA256_DIGEST_SIZE; > + symmetric.algorithm = TPM_ALG_NULL; > + > + rc = TPM2_StartAuthSession (TPM_RH_NULL, TPM_RH_NULL, 0, &nonce, &salt, > + TPM_SE_TRIAL, &symmetric, TPM_ALG_SHA256, > + &session, NULL, 0); > + if (rc != TPM_RC_SUCCESS) > + { > + fprintf (stderr, > + _("Failed to start trial policy session (TPM error: 0x%x).\n"), > + rc); > + err = GRUB_ERR_BAD_DEVICE; > + goto exit2; > + } > + > + /* PCR Policy */ > + memcpy (pcr_digest_in.buffer, pcr_digest, TPM_SHA256_DIGEST_SIZE); > + > + rc = TPM2_PolicyPCR (session, NULL, &pcr_digest_in, &pcr_sel, NULL); > + if (rc != TPM_RC_SUCCESS) > + { > + fprintf (stderr, _("Failed to submit PCR policy (TPM error: 0x%x).\n"), > + rc); > + err = GRUB_ERR_BAD_DEVICE; > + goto exit3; > + } > + > + /* Retrieve Policy Digest */ > + rc = TPM2_PolicyGetDigest (session, NULL, &policy_digest, NULL); > + if (rc != TPM_RC_SUCCESS) > + { > + fprintf (stderr, _("Failed to get policy digest (TPM error: 0x%x).\n"), > + rc); > + err = GRUB_ERR_BAD_DEVICE; > + goto exit3; > + } > + > + /* Epilogue */ > + *digest = policy_digest; > + err = GRUB_ERR_NONE; > + > +exit3: > + TPM2_FlushContext (session); > + > +exit2: > + grub_free (pcr_concat); > + > +exit1: > + grub_free (pcr_digest); > + > + return err; > +} > + > +static grub_err_t > +grub_protect_tpm2_get_srk (struct grub_protect_args *args, 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 (args->tpm2_srk, NULL, &public); > + if (rc == TPM_RC_SUCCESS) > + { > + if (args->tpm2_persist) > + fprintf (stderr, > + _("Warning: --tpm2-persist was specified but the SRK already " > + "exists on the TPM. Continuing anyway...\n")); > + > + *srk = TPM2_SRK_HANDLE; > + return GRUB_ERR_NONE; > + } > + > + /* The handle exists but its public area could not be read. */ > + if ((rc & ~TPM_RC_N_MASK) != TPM_RC_HANDLE) > + { > + fprintf (stderr, > + _("The SRK exists on the TPM but its public area cannot be read " > + "(TPM error: 0x%x).\n"), rc); > + return GRUB_ERR_BAD_DEVICE; > + } > + > + /* Create SRK */ > + authCommand.sessionHandle = TPM_RS_PW; > + inPublic.publicArea.type = args->tpm2_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; > + > + switch (args->tpm2_asymmetric) > + { > + case 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; > + break; > + > + case 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; > + break; > + > + default: > + 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) > + { > + fprintf (stderr, _("Failed to create SRK (TPM error: 0x%x).\n"), rc); > + return GRUB_ERR_BAD_DEVICE; > + } > + > + /* Persist SRK */ > + if (args->tpm2_persist) > + { > + rc = TPM2_EvictControl (TPM_RH_OWNER, srkHandle, args->tpm2_srk, > + &authCommand, NULL); > + if (rc == TPM_RC_SUCCESS) > + { > + TPM2_FlushContext (srkHandle); > + srkHandle = args->tpm2_srk; > + } > + else > + fprintf (stderr, > + _("Warning: Failed to persist SRK (TPM error: 0x%x\n). " > + "Continuing anyway...\n"), rc); > + } > + > + /* Epilogue */ > + *srk = srkHandle; > + > + return GRUB_ERR_NONE; > +} > + > +static grub_err_t > +grub_protect_tpm2_seal (TPM2B_DIGEST *policyDigest, TPM_HANDLE srk, > + grub_uint8_t *clearText, grub_size_t clearTextLength, > + TPM2_SEALED_KEY *sealed_key) > +{ > + TPM_RC rc; > + TPMS_AUTH_COMMAND authCommand = { 0 }; > + TPM2B_SENSITIVE_CREATE inSensitive = { 0 }; > + TPM2B_PUBLIC inPublic = { 0 }; > + TPM2B_DATA outsideInfo = { 0 }; > + TPML_PCR_SELECTION pcr_sel = { 0 }; > + TPM2B_PRIVATE outPrivate = { 0 }; > + TPM2B_PUBLIC outPublic = { 0 }; > + > + /* Seal Data */ > + authCommand.sessionHandle = TPM_RS_PW; > + > + inSensitive.sensitive.data.size = clearTextLength; > + memcpy(inSensitive.sensitive.data.buffer, clearText, clearTextLength); > + > + inPublic.publicArea.type = TPM_ALG_KEYEDHASH; > + inPublic.publicArea.nameAlg = TPM_ALG_SHA256; > + inPublic.publicArea.parameters.keyedHashDetail.scheme.scheme = TPM_ALG_NULL; > + inPublic.publicArea.authPolicy = *policyDigest; > + > + rc = TPM2_Create (srk, &authCommand, &inSensitive, &inPublic, &outsideInfo, > + &pcr_sel, &outPrivate, &outPublic, NULL, NULL, NULL, NULL); > + if (rc != TPM_RC_SUCCESS) > + { > + fprintf (stderr, _("Failed to seal key (TPM error: 0x%x).\n"), rc); > + return GRUB_ERR_BAD_DEVICE; > + } > + > + /* Epilogue */ > + sealed_key->public = outPublic; > + sealed_key->private = outPrivate; > + > + return GRUB_ERR_NONE; > +} > + > +static grub_err_t > +grub_protect_tpm2_export_sealed_key (const char *filepath, > + TPM2_SEALED_KEY *sealed_key) > +{ > + grub_err_t err; > + struct grub_tpm2_buffer buf; > + > + grub_tpm2_buffer_init (&buf); > + grub_tpm2_mu_TPM2B_PUBLIC_Marshal (&buf, &sealed_key->public); > + grub_tpm2_mu_TPM2B_Marshal (&buf, sealed_key->private.size, > + sealed_key->private.buffer); > + if (buf.error) > + return GRUB_ERR_BAD_ARGUMENT; > + > + err = grub_protect_write_file (filepath, buf.data, buf.size); > + if (err) > + fprintf (stderr, _("Could not write sealed key file (Error: %u).\n"), > + errno); > + > + return err; > +} > + > +static grub_err_t > +grub_protect_tpm2_add (struct grub_protect_args *args) > +{ > + grub_err_t err; > + grub_uint8_t *key; > + grub_size_t key_size; > + TPM_HANDLE srk; > + TPM2B_DIGEST policy_digest; > + TPM2_SEALED_KEY sealed_key; > + char *grub_drive = NULL; > + > + grub_protect_get_grub_drive_for_file (args->tpm2_outfile, &grub_drive); > + > + err = grub_protect_tpm2_open_device (args->tpm2_device); > + if (err) > + return err; > + > + err = grub_protect_read_file (args->tpm2_keyfile, (void **)&key, &key_size); > + if (err) > + goto exit1; > + > + if (key_size > TPM_MAX_SYM_DATA) > + { > + fprintf (stderr, > + _("Input key is too long, maximum allowed size is %u bytes.\n"), > + TPM_MAX_SYM_DATA); > + return GRUB_ERR_OUT_OF_RANGE; > + } > + > + err = grub_protect_tpm2_get_srk (args, &srk); > + if (err) > + goto exit2; > + > + err = grub_protect_tpm2_get_policy_digest (args, &policy_digest); > + if (err) > + goto exit3; > + > + err = grub_protect_tpm2_seal (&policy_digest, srk, key, key_size, > + &sealed_key); > + if (err) > + goto exit3; > + > + err = grub_protect_tpm2_export_sealed_key (args->tpm2_outfile, &sealed_key); > + if (err) > + goto exit3; > + > + if (grub_drive) > + { > + printf (_("GRUB drive for the sealed key file: %s\n"), grub_drive); > + grub_free (grub_drive); > + } > + else > + { > + fprintf (stderr, > + _("Warning: Could not determine GRUB drive for sealed key " > + "file.\n")); > + err = GRUB_ERR_NONE; > + } > + > +exit3: > + TPM2_FlushContext (srk); > + > +exit2: > + grub_free (key); > + > +exit1: > + grub_protect_tpm2_close_device (); > + > + return err; > +} > + > +static grub_err_t > +grub_protect_tpm2_remove (struct grub_protect_args *args) > +{ > + TPM_RC rc; > + TPM2B_PUBLIC public; > + TPMS_AUTH_COMMAND authCommand = { 0 }; > + grub_err_t err; > + > + if (!args->tpm2_evict) > + { > + printf (_("--tpm2-evict not specified, nothing to do.\n")); > + return GRUB_ERR_NONE; > + } > + > + err = grub_protect_tpm2_open_device (args->tpm2_device); > + if (err) > + return err; > + > + /* Find SRK */ > + rc = TPM2_ReadPublic (args->tpm2_srk, NULL, &public); > + if (rc != TPM_RC_SUCCESS) > + { > + fprintf (stderr, _("SRK with handle 0x%x not found.\n"), args->tpm2_srk); > + err = GRUB_ERR_BAD_ARGUMENT; > + goto exit1; > + } > + > + /* Evict SRK */ > + authCommand.sessionHandle = TPM_RS_PW; > + > + rc = TPM2_EvictControl (TPM_RH_OWNER, args->tpm2_srk, args->tpm2_srk, > + &authCommand, NULL); > + if (rc != TPM_RC_SUCCESS) > + { > + fprintf (stderr, > + _("Failed to evict SRK with handle 0x%x (TPM Error: 0x%x).\n"), > + args->tpm2_srk, rc); > + err = GRUB_ERR_BAD_DEVICE; > + goto exit2; > + } > + > + err = GRUB_ERR_NONE; > + > +exit2: > + TPM2_FlushContext (args->tpm2_srk); > + > +exit1: > + grub_protect_tpm2_close_device (); > + > + return GRUB_ERR_NONE; > +} > + > +static grub_err_t > +grub_protect_tpm2_run (struct grub_protect_args *args) > +{ > + switch (args->action) > + { > + case GRUB_PROTECT_ACTION_ADD: > + return grub_protect_tpm2_add (args); > + > + case GRUB_PROTECT_ACTION_REMOVE: > + return grub_protect_tpm2_remove (args); > + > + default: > + return GRUB_ERR_BAD_ARGUMENT; > + } > +} > + > +static grub_err_t > +grub_protect_tpm2_args_verify (struct grub_protect_args *args) > +{ > + switch (args->action) > + { > + case GRUB_PROTECT_ACTION_ADD: > + if (args->args & GRUB_PROTECT_ARG_TPM2_EVICT) > + { > + fprintf (stderr, > + _("--tpm2-evict is invalid when --action is 'add'.\n")); > + return GRUB_ERR_BAD_ARGUMENT; > + } > + > + if (!args->tpm2_keyfile) > + { > + fprintf (stderr, _("--tpm2-keyfile must be specified.\n")); > + return GRUB_ERR_BAD_ARGUMENT; > + } > + > + if (!args->tpm2_outfile) > + { > + fprintf (stderr, _("--tpm2-outfile must be specified.\n")); > + return GRUB_ERR_BAD_ARGUMENT; > + } > + > + if (!args->tpm2_device) > + args->tpm2_device = "/dev/tpm0"; > + > + if (!args->tpm2_pcr_count) > + { > + args->tpm2_pcrs[0] = 7; > + args->tpm2_pcr_count = 1; > + } > + > + if (!args->tpm2_srk) > + args->tpm2_srk = TPM2_SRK_HANDLE; > + > + if (!args->tpm2_asymmetric) > + args->tpm2_asymmetric = TPM_ALG_RSA; > + > + if (!args->tpm2_bank) > + args->tpm2_bank = TPM_ALG_SHA256; > + > + break; > + > + case GRUB_PROTECT_ACTION_REMOVE: > + if (args->args & GRUB_PROTECT_ARG_TPM2_ASYMMETRIC) > + { > + fprintf (stderr, > + _("--tpm2-asymmetric is invalid when --action is 'remove'.\n")); > + return GRUB_ERR_BAD_ARGUMENT; > + } > + > + if (args->args & GRUB_PROTECT_ARG_TPM2_BANK) > + { > + fprintf (stderr, > + _("--tpm2-bank is invalid when --action is 'remove'.\n")); > + return GRUB_ERR_BAD_ARGUMENT; > + } > + > + if (args->args & GRUB_PROTECT_ARG_TPM2_KEYFILE) > + { > + fprintf (stderr, > + _("--tpm2-keyfile is invalid when --action is 'remove'.\n")); > + return GRUB_ERR_BAD_ARGUMENT; > + } > + > + if (args->args & GRUB_PROTECT_ARG_TPM2_OUTFILE) > + { > + fprintf (stderr, > + _("--tpm2-outfile is invalid when --action is 'remove'.\n")); > + return GRUB_ERR_BAD_ARGUMENT; > + } > + > + if (args->args & GRUB_PROTECT_ARG_TPM2_PCRS) > + { > + fprintf (stderr, > + _("--tpm2-pcrs is invalid when --action is 'remove'.\n")); > + return GRUB_ERR_BAD_ARGUMENT; > + } > + > + if (args->args & GRUB_PROTECT_ARG_TPM2_PERSIST) > + { > + fprintf (stderr, > + _("--tpm2-persist is invalid when --action is 'remove'.\n")); > + return GRUB_ERR_BAD_ARGUMENT; > + } > + > + if (!args->tpm2_device) > + args->tpm2_device = "/dev/tpm0"; > + > + if (!args->tpm2_srk) > + args->tpm2_srk = TPM2_SRK_HANDLE; > + > + break; > + > + default: > + fprintf (stderr, > + _("The TPM2 key protector only supports the following actions: " > + "add, remove.\n")); > + return GRUB_ERR_BAD_ARGUMENT; > + } > + > + return GRUB_ERR_NONE; > +} > + > +static error_t > +grub_protect_argp_parser (int key, char *arg, struct argp_state *state) > +{ > + grub_err_t err; > + struct grub_protect_args *args = state->input; > + > + switch (key) > + { > + case GRUB_PROTECT_OPT_ACTION: > + if (args->args & GRUB_PROTECT_ARG_ACTION) > + { > + fprintf (stderr, _("--action|-a can only be specified once.\n")); > + return EINVAL; > + } > + > + if (grub_strcmp (arg, "add") == 0) > + args->action = GRUB_PROTECT_ACTION_ADD; > + else if (grub_strcmp (arg, "remove") == 0) > + args->action = GRUB_PROTECT_ACTION_REMOVE; > + else > + { > + fprintf (stderr, _("'%s' is not a valid action.\n"), arg); > + return EINVAL; > + } > + > + args->args |= GRUB_PROTECT_ARG_ACTION; > + break; > + > + case GRUB_PROTECT_OPT_PROTECTOR: > + if (args->args & GRUB_PROTECT_ARG_PROTECTOR) > + { > + fprintf (stderr, _("--protector|-p can only be specified once.\n")); > + return EINVAL; > + } > + > + if (grub_strcmp (arg, "tpm2") == 0) > + args->protector = GRUB_PROTECT_TYPE_TPM2; > + else > + { > + fprintf (stderr, _("'%s' is not a valid protector.\n"), arg); > + return EINVAL; > + } > + > + args->args |= GRUB_PROTECT_ARG_PROTECTOR; > + break; > + > + case GRUB_PROTECT_OPT_TPM2_DEVICE: > + if (args->args & GRUB_PROTECT_ARG_TPM2_DEVICE) > + { > + fprintf (stderr, _("--tpm2-device can only be specified once.\n")); > + return EINVAL; > + } > + > + args->tpm2_device = xstrdup(arg); > + args->args |= GRUB_PROTECT_ARG_TPM2_DEVICE; > + break; > + > + case GRUB_PROTECT_OPT_TPM2_PCRS: > + if (args->args & GRUB_PROTECT_ARG_TPM2_PCRS) > + { > + fprintf (stderr, _("--tpm2-pcrs can only be specified once.\n")); > + return EINVAL; > + } > + > + err = grub_tpm2_protector_parse_pcrs (arg, args->tpm2_pcrs, > + &args->tpm2_pcr_count); > + if (err) > + { > + if (grub_errno) > + grub_print_error (); > + return EINVAL; > + } > + > + args->args |= GRUB_PROTECT_ARG_TPM2_PCRS; > + break; > + > + case GRUB_PROTECT_OPT_TPM2_SRK: > + if (args->args & GRUB_PROTECT_ARG_TPM2_SRK) > + { > + fprintf (stderr, _("--tpm2-srk can only be specified once.\n")); > + return EINVAL; > + } > + > + err = grub_tpm2_protector_parse_tpm_handle (arg, &args->tpm2_srk); > + if (err) > + { > + if (grub_errno) > + grub_print_error (); > + return EINVAL; > + } > + > + args->args |= GRUB_PROTECT_ARG_TPM2_SRK; > + break; > + > + case GRUB_PROTECT_OPT_TPM2_ASYMMETRIC: > + if (args->args & GRUB_PROTECT_ARG_TPM2_ASYMMETRIC) > + { > + fprintf (stderr, _("--tpm2-asymmetric can only be specified once.\n")); > + return EINVAL; > + } > + > + err = grub_tpm2_protector_parse_asymmetric (arg, &args->tpm2_asymmetric); > + if (err) > + { > + if (grub_errno) > + grub_print_error (); > + return EINVAL; > + } > + > + args->args |= GRUB_PROTECT_ARG_TPM2_ASYMMETRIC; > + break; > + > + case GRUB_PROTECT_OPT_TPM2_BANK: > + if (args->args & GRUB_PROTECT_ARG_TPM2_BANK) > + { > + fprintf (stderr, _("--tpm2-bank can only be specified once.\n")); > + return EINVAL; > + } > + > + err = grub_tpm2_protector_parse_bank (arg, &args->tpm2_bank); > + if (err) > + { > + if (grub_errno) > + grub_print_error (); > + return EINVAL; > + } > + > + args->args |= GRUB_PROTECT_ARG_TPM2_BANK; > + break; > + > + case GRUB_PROTECT_OPT_TPM2_KEYFILE: > + if (args->args & GRUB_PROTECT_ARG_TPM2_KEYFILE) > + { > + fprintf (stderr, _("--tpm2-keyfile can only be specified once.\n")); > + return EINVAL; > + } > + > + args->tpm2_keyfile = xstrdup(arg); > + args->args |= GRUB_PROTECT_ARG_TPM2_KEYFILE; > + break; > + > + case GRUB_PROTECT_OPT_TPM2_OUTFILE: > + if (args->args & GRUB_PROTECT_ARG_TPM2_OUTFILE) > + { > + fprintf (stderr, _("--tpm2-outfile can only be specified once.\n")); > + return EINVAL; > + } > + > + args->tpm2_outfile = xstrdup(arg); > + args->args |= GRUB_PROTECT_ARG_TPM2_OUTFILE; > + break; > + > + case GRUB_PROTECT_OPT_TPM2_PERSIST: > + if (args->args & GRUB_PROTECT_ARG_TPM2_PERSIST) > + { > + fprintf (stderr, _("--tpm2-persist can only be specified once.\n")); > + return EINVAL; > + } > + > + args->tpm2_persist = 1; > + args->args |= GRUB_PROTECT_ARG_TPM2_PERSIST; > + break; > + > + case GRUB_PROTECT_OPT_TPM2_EVICT: > + if (args->args & GRUB_PROTECT_ARG_TPM2_EVICT) > + { > + fprintf (stderr, _("--tpm2-evict can only be specified once.\n")); > + return EINVAL; > + } > + > + args->tpm2_evict = 1; > + args->args |= GRUB_PROTECT_ARG_TPM2_EVICT; > + break; > + > + default: > + return ARGP_ERR_UNKNOWN; > + } > + > + return 0; > +} > + > +static grub_err_t > +grub_protect_args_verify (struct grub_protect_args *args) > +{ > + if (args->action == GRUB_PROTECT_ACTION_ERROR) > + { > + fprintf (stderr, "--action is mandatory.\n"); > + return GRUB_ERR_BAD_ARGUMENT; > + } > + > + /* At the moment, the only configurable key protector is the TPM2 one, so it > + * is the only key protector supported by this tool. */ > + if (args->protector != GRUB_PROTECT_TYPE_TPM2) > + { > + fprintf (stderr, > + _("--protector is mandatory and only 'tpm2' is currently " > + "supported.\n")); > + return GRUB_ERR_BAD_ARGUMENT; > + } > + > + switch (args->protector) > + { > + case GRUB_PROTECT_TYPE_TPM2: > + return grub_protect_tpm2_args_verify (args); > + default: > + return GRUB_ERR_BAD_ARGUMENT; > + } > + > + return GRUB_ERR_NONE; > +} > + > +static grub_err_t > +grub_protect_dispatch (struct grub_protect_args *args) > +{ > + switch (args->protector) > + { > + case GRUB_PROTECT_TYPE_TPM2: > + return grub_protect_tpm2_run (args); > + default: > + return GRUB_ERR_BAD_ARGUMENT; > + } > +} > + > +static void > +grub_protect_init (int *argc, char **argv[]) > +{ > + grub_util_host_init (argc, argv); > + > + grub_util_biosdisk_init (NULL); > + > + grub_init_all (); > + grub_gcry_init_all (); > + > + grub_lvm_fini (); > + grub_mdraid09_fini (); > + grub_mdraid1x_fini (); > + grub_diskfilter_fini (); > + grub_diskfilter_init (); > + grub_mdraid09_init (); > + grub_mdraid1x_init (); > + grub_lvm_init (); > +} > + > +static void > +grub_protect_fini (void) > +{ > + grub_gcry_fini_all (); > + grub_fini_all (); > + grub_util_biosdisk_fini (); > +} > + > +static struct argp grub_protect_argp = > +{ > + .options = grub_protect_options, > + .parser = grub_protect_argp_parser, > + .args_doc = NULL, > + .doc = > + N_("Protect a cleartext key using a GRUB key protector that can retrieve " > + "the key during boot to unlock fully-encrypted disks automatically."), > + .children = NULL, > + .help_filter = NULL, > + .argp_domain = NULL > +}; > + > +int > +main (int argc, char *argv[]) > +{ > + grub_err_t err; > + struct grub_protect_args args = { 0 }; > + > + if (argp_parse (&grub_protect_argp, argc, argv, 0, 0, &args) != 0) > + { > + fprintf (stderr, _("Could not parse arguments.\n")); > + return GRUB_ERR_BAD_ARGUMENT; > + } > + > + grub_protect_init (&argc, &argv); > + > + err = grub_protect_args_verify (&args); > + if (err) > + goto exit; > + > + err = grub_protect_dispatch (&args); > + if (err) > + goto exit; > + > +exit: > + grub_protect_fini (); > + > + return err; > +} > -- > 1.8.3.1 > > > _______________________________________________ > Grub-devel mailing list > Grub-devel@gnu.org > https://lists.gnu.org/mailman/listinfo/grub-devel