From patchwork Thu Aug 31 17:18:58 2017 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Alexander Steffen X-Patchwork-Id: 9932585 Return-Path: Received: from mail.wl.linuxfoundation.org (pdx-wl-mail.web.codeaurora.org [172.30.200.125]) by pdx-korg-patchwork.web.codeaurora.org (Postfix) with ESMTP id AE686602F0 for ; Thu, 31 Aug 2017 17:19:42 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 91F5E289FC for ; Thu, 31 Aug 2017 17:19:42 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id 86DC828A1B; Thu, 31 Aug 2017 17:19:42 +0000 (UTC) X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on pdx-wl-mail.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-6.8 required=2.0 tests=BAYES_00,DKIM_SIGNED, RCVD_IN_DNSWL_HI,T_DKIM_INVALID autolearn=unavailable version=3.3.1 Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 012C2289FC for ; Thu, 31 Aug 2017 17:19:42 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1751872AbdHaRTN (ORCPT ); Thu, 31 Aug 2017 13:19:13 -0400 Received: from smtp11.infineon.com ([217.10.52.105]:31730 "EHLO smtp11.infineon.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1751881AbdHaRTK (ORCPT ); Thu, 31 Aug 2017 13:19:10 -0400 DKIM-Signature: v=1; a=rsa-sha256; c=simple/simple; d=infineon.com; i=@infineon.com; q=dns/txt; s=IFXMAIL; t=1504199949; x=1535735949; h=from:to:cc:subject:date:message-id:in-reply-to: references:mime-version; bh=TnKLVRmBDATGJ+71lsAAujMZiln+E+LKSK6/WiMA/6E=; b=H8XhBvhauk454/67JZcSysDC9rfGts39O5fj5om4W71kyCXIC/hYfzkn jbmH40Aef+u/kkHqkI1oWX02t8ijmisRog6IE2VEq5UUcM48/z+Fr8uHa +112RIsEyFPZ4QySF+vYytbgJ2uphpTLkzsq4SopMsCCpoUV7RByp1oIv k=; X-SBRS: None Received: from unknown (HELO mucxv003.muc.infineon.com) ([172.23.11.20]) by smtp11.infineon.com with ESMTP/TLS/AES256-GCM-SHA384; 31 Aug 2017 19:19:07 +0200 Received: from MUCSE606.infineon.com (mucse606.infineon.com [172.23.7.107]) by mucxv003.muc.infineon.com (Postfix) with ESMTPS; Thu, 31 Aug 2017 19:19:07 +0200 (CEST) Received: from MUCSE603.infineon.com (172.23.7.104) by MUCSE606.infineon.com (172.23.7.107) with Microsoft SMTP Server (TLS) id 15.0.1263.5; Thu, 31 Aug 2017 19:19:06 +0200 Received: from ABGN5CG4522MQD.eu.infineon.com (172.29.170.103) by MUCSE603.infineon.com (172.23.7.104) with Microsoft SMTP Server (TLS) id 15.0.1263.5; Thu, 31 Aug 2017 19:19:07 +0200 From: Alexander Steffen To: , CC: , , Alexander Steffen Subject: [PATCH RESEND v2 3/3] tpm2-cmd: React correctly to RC_TESTING from self tests Date: Thu, 31 Aug 2017 19:18:58 +0200 Message-ID: <20170831171858.13252-4-Alexander.Steffen@infineon.com> X-Mailer: git-send-email 2.11.1.windows.1 In-Reply-To: <20170831171858.13252-1-Alexander.Steffen@infineon.com> References: <20170831171858.13252-1-Alexander.Steffen@infineon.com> MIME-Version: 1.0 X-Originating-IP: [172.29.170.103] X-ClientProxiedBy: MUCSE601.infineon.com (172.23.7.102) To MUCSE603.infineon.com (172.23.7.104) Sender: owner-linux-security-module@vger.kernel.org Precedence: bulk List-ID: X-Virus-Scanned: ClamAV using ClamSMTP The TPM can choose one of two ways to react to the TPM2_SelfTest command. It can either run all self tests synchronously and then return RC_SUCCESS once all tests were successful. Or it can choose to run the tests asynchronously and return RC_TESTING immediately while the self tests still execute in the background. The previous implementation apparently was not aware of those possibilities and attributed RC_TESTING to some prototype chips instead. With this change the return code of TPM2_SelfTest is interpreted correctly, i.e. the self test result is polled if and only if RC_TESTING is received. Unfortunately, the polling cannot be done in the most straightforward way. If RC_TESTING is received, ideally the code should now poll the selfTestDone bit in the STS register, as this avoids sending more commands, that might interrupt self tests executing in the background and thus prevent them from ever completing. But it cannot be guaranteed that this bit is correctly implemented for all devices, so the next best thing would be to use TPM2_GetTestResult to query the test result. But the response to that command can be very long, and the code currently lacks the capabilities for efficient unmarshalling, so it is difficult to execute this command. Therefore, we simply run the TPM2_SelfTest command in a loop, which should complete eventually, since we only request the execution of self tests that have not yet been done. Signed-off-by: Alexander Steffen Reviewed-by: Jarkko Sakkinen --- drivers/char/tpm/tpm2-cmd.c | 52 ++++++++++----------------------------------- 1 file changed, 11 insertions(+), 41 deletions(-) diff --git a/drivers/char/tpm/tpm2-cmd.c b/drivers/char/tpm/tpm2-cmd.c index 2178437..70ee328 100644 --- a/drivers/char/tpm/tpm2-cmd.c +++ b/drivers/char/tpm/tpm2-cmd.c @@ -834,64 +834,34 @@ static const struct tpm_input_header tpm2_selftest_header = { }; /** - * tpm2_continue_selftest() - start a self test - * - * @chip: TPM chip to use - * @full: test all commands instead of testing only those that were not - * previously tested. - * - * Return: Same as with tpm_transmit_cmd with exception of RC_TESTING. - */ -static int tpm2_start_selftest(struct tpm_chip *chip, bool full) -{ - int rc; - struct tpm2_cmd cmd; - - cmd.header.in = tpm2_selftest_header; - cmd.params.selftest_in.full_test = full; - - rc = tpm_transmit_cmd(chip, NULL, &cmd, TPM2_SELF_TEST_IN_SIZE, 0, 0, - "continue selftest"); - - /* At least some prototype chips seem to give RC_TESTING error - * immediately. This is a workaround for that. - */ - if (rc == TPM2_RC_TESTING) { - dev_warn(&chip->dev, "Got RC_TESTING, ignoring\n"); - rc = 0; - } - - return rc; -} - -/** * tpm2_do_selftest() - ensure that all self tests have passed * * @chip: TPM chip to use * * Return: Same as with tpm_transmit_cmd. * - * During the self test TPM2 commands return with the error code RC_TESTING. - * Waiting is done by issuing PCR read until it executes successfully. + * The TPM can either run all self tests synchronously and then return + * RC_SUCCESS once all tests were successful. Or it can choose to run the tests + * asynchronously and return RC_TESTING immediately while the self tests still + * execute in the background. This function handles both cases and waits until + * all tests have completed. */ static int tpm2_do_selftest(struct tpm_chip *chip) { int rc; unsigned int delay_msec = 20; long duration; + struct tpm2_cmd cmd; duration = jiffies_to_msecs( tpm2_calc_ordinal_duration(chip, TPM2_CC_SELF_TEST)); - rc = tpm2_start_selftest(chip, false); - if (rc) - return rc; - while (duration > 0) { - /* Attempt to read a PCR value */ - rc = tpm2_pcr_read(chip, 0, NULL); - if (rc < 0) - break; + cmd.header.in = tpm2_selftest_header; + cmd.params.selftest_in.full_test = 0; + + rc = tpm_transmit_cmd(chip, NULL, &cmd, TPM2_SELF_TEST_IN_SIZE, + 0, 0, "continue selftest"); if (rc != TPM2_RC_TESTING) break;