From patchwork Fri Aug 2 20:25:59 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: James Bottomley X-Patchwork-Id: 13751962 Received: from bedivere.hansenpartnership.com (bedivere.hansenpartnership.com [96.44.175.130]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id EA00F4D8A1 for ; Fri, 2 Aug 2024 20:26:35 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=96.44.175.130 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1722630401; cv=none; b=VtADGZDrub8TcvoIvtC1CVzjpsNrQyyO9rRkZK0CnRvME+lqIbRJfUf2r9AhnaS53J4ZIv7Vbpu3dQdUbgO1HU9zMugZ/oWYlwN/UYODadtQBkj2uHdTSVnf2rAXyFVZcDPa4OBnqpRuev5crx/cvBUHLHzyEIZENcMA9GgwH78= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1722630401; c=relaxed/simple; bh=tlYMTE9qUYrL1KkFicy/RFTs+B9cajYqQ8pFQYhQd+c=; h=From:To:Cc:Subject:Date:Message-Id:In-Reply-To:References: MIME-Version; b=eov5cpnH6YdRFvnJ9DK53fbMTjSCcXssimzK0to5iohlac9Xj4pysYUcDQ7n0qEKFzC1QFdpi5rj49FX5dJ67jNpDlHxeHu8C6XKptVcUI5MaaHJGFZRcSNWpRcBvLf/q9exZqJYHYXf5bcS5Uhee/iRqy0sP9Jmzwg38zMM5ZA= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=HansenPartnership.com; spf=pass smtp.mailfrom=HansenPartnership.com; dkim=pass (1024-bit key) header.d=hansenpartnership.com header.i=@hansenpartnership.com header.b=ebCGbhrs; arc=none smtp.client-ip=96.44.175.130 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=HansenPartnership.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=HansenPartnership.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (1024-bit key) header.d=hansenpartnership.com header.i=@hansenpartnership.com header.b="ebCGbhrs" DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=hansenpartnership.com; s=20151216; t=1722630395; bh=tlYMTE9qUYrL1KkFicy/RFTs+B9cajYqQ8pFQYhQd+c=; h=From:To:Subject:Date:Message-Id:In-Reply-To:References:From; b=ebCGbhrsDY+GLCrkOAVkaJ2ppK46cIrMdzvNmZ8syHW8AduMYlByfQ+OP/CUUdsRA MoEh/OkxcgjXOOT/HGVouV3LlDRa3oMTEPdD8govlzUD9F3Zp5B67P1zc1bJQMNoYx VbCV+UlN9B/lSpc9W0pKvfLc2jdlwMvR2lO8xxuI= Received: from localhost (localhost [127.0.0.1]) by bedivere.hansenpartnership.com (Postfix) with ESMTP id 3CA1E1286A6B; Fri, 02 Aug 2024 16:26:35 -0400 (EDT) Received: from bedivere.hansenpartnership.com ([127.0.0.1]) by localhost (bedivere.hansenpartnership.com [127.0.0.1]) (amavis, port 10024) with ESMTP id EmW6V8rWYiMo; Fri, 2 Aug 2024 16:26:35 -0400 (EDT) Received: from lingrow.int.hansenpartnership.com (unknown [153.66.160.227]) by bedivere.hansenpartnership.com (Postfix) with ESMTP id B60C4128690C; Fri, 02 Aug 2024 16:26:34 -0400 (EDT) From: James Bottomley To: openssl-tpm2-engine@groups.io Cc: linux-integrity@vger.kernel.org, Jarkko Sakkinen Subject: [PATCH 1/8] tss: Fix handling of TPM_RH_NULL in intel-tss Date: Fri, 2 Aug 2024 16:25:59 -0400 Message-Id: <20240802202606.12767-2-James.Bottomley@HansenPartnership.com> X-Mailer: git-send-email 2.35.3 In-Reply-To: <20240802202606.12767-1-James.Bottomley@HansenPartnership.com> References: <20240802202606.12767-1-James.Bottomley@HansenPartnership.com> Precedence: bulk X-Mailing-List: linux-integrity@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Now that we're going to be using the NULL primary to salt sessions, the Intel TSS shim needs fixing to cope with this. In the Intel TSS, there are two internal handles representing NULL: ESYS_TR_NONE and ESYS_TR_RH_NULL. We translate TPM_RH_NULL to ESYS_TR_NONE because most of the time it does mean no value. However, for the NULL primary handle we must use ESYS_TR_RH_NULL, so check for that specific case and fix it. Additionally remove the intel_handle() code which was supposed to do this: it's unused because 0 is never passed in as a handle number. Signed-off-by: James Bottomley --- src/include/intel-tss.h | 18 +++++------------- 1 file changed, 5 insertions(+), 13 deletions(-) diff --git a/src/include/intel-tss.h b/src/include/intel-tss.h index 1870b4e..5b8db20 100644 --- a/src/include/intel-tss.h +++ b/src/include/intel-tss.h @@ -251,14 +251,6 @@ intel_sess_helper(TSS_CONTEXT *tssContext, TPM_HANDLE auth, TPMA_SESSION flags) TPMA_SESSION_CONTINUESESSION | flags); } -static inline TPM_HANDLE -intel_handle(TPM_HANDLE h) -{ - if (h == 0) - return ESYS_TR_NONE; - return h; -} - static inline void TSS_Delete(TSS_CONTEXT *tssContext) { @@ -937,8 +929,10 @@ tpm2_CreatePrimary(TSS_CONTEXT *tssContext, TPM_HANDLE primaryHandle, TPM2B_PUBLIC *opub; TPM_RC rc; - /* FIXME will generate wrong value for NULL hierarchy */ - primaryHandle = intel_handle(primaryHandle); + + /* TPM_RH_NULL is mapped to ESYS_TR_NONE, which won't work here */ + if (primaryHandle == TPM_RH_NULL) + primaryHandle = INT_TPM_RH_NULL; outsideInfo.size = 0; creationPcr.count = 0; @@ -993,9 +987,7 @@ tpm2_StartAuthSession(TSS_CONTEXT *tssContext, TPM_HANDLE tpmKey, TPM_HANDLE *sessionHandle, const char *bindPassword) { - bind = intel_handle(bind); - tpmKey = intel_handle(tpmKey); - if (bind != ESYS_TR_NONE) + if (bind != TPM_RH_NULL) intel_auth_helper(tssContext, bind, bindPassword); return Esys_StartAuthSession(tssContext, tpmKey, bind, ESYS_TR_NONE, From patchwork Fri Aug 2 20:26:00 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: James Bottomley X-Patchwork-Id: 13751963 Received: from bedivere.hansenpartnership.com (bedivere.hansenpartnership.com [96.44.175.130]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id AB92933DF for ; Fri, 2 Aug 2024 20:26:45 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=96.44.175.130 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1722630407; cv=none; b=Y+8ORahTKvq8BTqp6IHaBdiYI/9qoHsnp6sgbBaP8ZFyrx3CyxwbCM03S+6xPbgC3zVVQdAUQx2/rFc+FxLUdzr4Kzt7qzLXXJGj6QFhrPJ1dUB/kckJk4MOBnWlrBFTBWLgWOTpWSB4bconhefoSpPct3YY/coHkLy38enroVk= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1722630407; c=relaxed/simple; bh=XU+dvLQYWHnHVWOM2RRqf/WI1AWPHF27cSZcHp3fJRE=; h=From:To:Cc:Subject:Date:Message-Id:In-Reply-To:References: MIME-Version; b=rwy8PTeiqjoXe24M+q/A6j1LNEKvyBY+HAh/k8mx1R7MEj4xwirPG4DSh2iu+M3axTab47KXzrQgGBtEmntiwBkqX9wq465h6KlYd1g/rg2yikdAPlRd0ZUMp5zhccql043Z8w7Eadlu0slWvJgDhTud05uWwnlel6A/wOHg9/c= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=HansenPartnership.com; spf=pass smtp.mailfrom=HansenPartnership.com; dkim=pass (1024-bit key) header.d=hansenpartnership.com header.i=@hansenpartnership.com header.b=R789jnk4; arc=none smtp.client-ip=96.44.175.130 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=HansenPartnership.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=HansenPartnership.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (1024-bit key) header.d=hansenpartnership.com header.i=@hansenpartnership.com header.b="R789jnk4" DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=hansenpartnership.com; s=20151216; t=1722630404; bh=XU+dvLQYWHnHVWOM2RRqf/WI1AWPHF27cSZcHp3fJRE=; h=From:To:Subject:Date:Message-Id:In-Reply-To:References:From; b=R789jnk4xNug0NYkE18ZxHl1EuraccXkosrYLQbfWgG2l2mcgzNwmYd3oKZeItLp6 Kg/ehLnNGuKunZncpAu4aTXWBCeNbKcFvnliXbcP4MawMv9bJugCHL/nlxbisEUmD2 40azjqK1kMGPZ5Km/Vpwv0qGzTX7OOxjww/Xmz2Y= Received: from localhost (localhost [127.0.0.1]) by bedivere.hansenpartnership.com (Postfix) with ESMTP id D78A51286A6B; Fri, 02 Aug 2024 16:26:44 -0400 (EDT) Received: from bedivere.hansenpartnership.com ([127.0.0.1]) by localhost (bedivere.hansenpartnership.com [127.0.0.1]) (amavis, port 10024) with ESMTP id dExUoxIiLZ06; Fri, 2 Aug 2024 16:26:44 -0400 (EDT) Received: from lingrow.int.hansenpartnership.com (unknown [153.66.160.227]) by bedivere.hansenpartnership.com (Postfix) with ESMTP id 5BFFC128690C; Fri, 02 Aug 2024 16:26:44 -0400 (EDT) From: James Bottomley To: openssl-tpm2-engine@groups.io Cc: linux-integrity@vger.kernel.org, Jarkko Sakkinen Subject: [PATCH 2/8] libcommon: add ability to create a signing primary key Date: Fri, 2 Aug 2024 16:26:00 -0400 Message-Id: <20240802202606.12767-3-James.Bottomley@HansenPartnership.com> X-Mailer: git-send-email 2.35.3 In-Reply-To: <20240802202606.12767-1-James.Bottomley@HansenPartnership.com> References: <20240802202606.12767-1-James.Bottomley@HansenPartnership.com> Precedence: bulk X-Mailing-List: linux-integrity@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Having a primary key that can sign things is useful for conducting certification and quoting operations without having to go through the makecredential/activatecredential dance, which is unnecessary for a local TPM where you don't need privacy separated attestation keys. Add the ability to use the signing key template to tpm2_load_srk(). Signed-off-by: James Bottomley --- src/include/tpm2-common.h | 1 + src/libcommon/tpm2-common.c | 23 ++++++++++++++++++----- 2 files changed, 19 insertions(+), 5 deletions(-) diff --git a/src/include/tpm2-common.h b/src/include/tpm2-common.h index 4520f76..97b60f2 100644 --- a/src/include/tpm2-common.h +++ b/src/include/tpm2-common.h @@ -23,6 +23,7 @@ enum tpm2_type { TPM2_LOADABLE = 1, TPM2_IMPORTABLE = 2, TPM2_SEALED = 3, + TPM2_SIGNING = 4, }; struct policies { diff --git a/src/libcommon/tpm2-common.c b/src/libcommon/tpm2-common.c index 3b9f785..b70ac27 100644 --- a/src/libcommon/tpm2-common.c +++ b/src/libcommon/tpm2-common.c @@ -743,17 +743,30 @@ TPM_RC tpm2_load_srk(TSS_CONTEXT *tssContext, TPM_HANDLE *h, const char *auth, TPMA_OBJECT_NODA | TPMA_OBJECT_SENSITIVEDATAORIGIN | TPMA_OBJECT_USERWITHAUTH | - TPMA_OBJECT_DECRYPT | TPMA_OBJECT_RESTRICTED; + if (type == TPM2_SIGNING) + VAL(inPublic.publicArea.objectAttributes) |= + TPMA_OBJECT_SIGN; + else + VAL(inPublic.publicArea.objectAttributes) |= + TPMA_OBJECT_DECRYPT; if (type != TPM2_LEGACY) VAL(inPublic.publicArea.objectAttributes) |= TPMA_OBJECT_FIXEDPARENT | TPMA_OBJECT_FIXEDTPM; - 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; + if (type != TPM2_SIGNING) { + 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; + } else { + inPublic.publicArea.parameters.eccDetail.symmetric.algorithm = TPM_ALG_NULL; + inPublic.publicArea.parameters.eccDetail.symmetric.keyBits.aes = 0; + inPublic.publicArea.parameters.eccDetail.symmetric.mode.aes = TPM_ALG_NULL; + inPublic.publicArea.parameters.eccDetail.scheme.scheme = TPM_ALG_ECDSA; + inPublic.publicArea.parameters.eccDetail.scheme.details.ecdsa.hashAlg = TPM_ALG_SHA256; + } inPublic.publicArea.parameters.eccDetail.curveID = TPM_ECC_NIST_P256; inPublic.publicArea.parameters.eccDetail.kdf.scheme = TPM_ALG_NULL; From patchwork Fri Aug 2 20:26:01 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: James Bottomley X-Patchwork-Id: 13751964 Received: from bedivere.hansenpartnership.com (bedivere.hansenpartnership.com [96.44.175.130]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 584F2335C0 for ; Fri, 2 Aug 2024 20:26:53 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=96.44.175.130 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1722630414; cv=none; b=rTu/F2ZKVgudZr/WtZ6yhpAfEccMfHUMsMurE8ej4TXmia/E+gk1bwrmWZc9W9zqMD/evRSBzaK6ugwh5CmgUZtnGbltMz4Rm0e00PKOmFGcB4RVr7EYmItApMbmemfaZn6BFu+LaLwgAXpsELbrXl5h7G0MXBNDilvcOvUzhAg= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1722630414; c=relaxed/simple; bh=/FecCDLZ1DR5BrQqvYyJHHGzKOTUyQKiy/cycGXV2i8=; h=From:To:Cc:Subject:Date:Message-Id:In-Reply-To:References: MIME-Version; b=Ik3MoBwd/WYr3ZPGsiMGYxAoZ8cCO/MwDoKwyisW3Fg8LSnoR1hRDsVD+RZrbkqv5yv0cOuCdJA1L4pHKrLQLhMWxUV4S6EsztsN1egyMKb16SB01HwOqFfr3Unvn6YbAhsKF+YGu5SF4d0BnMD1pMNlJ6conetTQo0ZbVIg6uM= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=HansenPartnership.com; spf=pass smtp.mailfrom=HansenPartnership.com; dkim=pass (1024-bit key) header.d=hansenpartnership.com header.i=@hansenpartnership.com header.b=lVcUy6fV; arc=none smtp.client-ip=96.44.175.130 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=HansenPartnership.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=HansenPartnership.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (1024-bit key) header.d=hansenpartnership.com header.i=@hansenpartnership.com header.b="lVcUy6fV" DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=hansenpartnership.com; s=20151216; t=1722630412; bh=/FecCDLZ1DR5BrQqvYyJHHGzKOTUyQKiy/cycGXV2i8=; h=From:To:Subject:Date:Message-Id:In-Reply-To:References:From; b=lVcUy6fVSgFZcfN+jeAG16QI2tXFFv0j//653gzJR00gKNX00L9cPiqH5e5gnqJib kZvZafvwIpkCUu4sRRLS3Rk6Ewa+WwJSV/vC8eZ0R5ErmXx9cYFo9UA0vV7Efu//Cp fIJ+I9DrXzL9jMWqWKaHTtGIgecwVUacD2SzHZNw= Received: from localhost (localhost [127.0.0.1]) by bedivere.hansenpartnership.com (Postfix) with ESMTP id C404D1286A6B; Fri, 02 Aug 2024 16:26:52 -0400 (EDT) Received: from bedivere.hansenpartnership.com ([127.0.0.1]) by localhost (bedivere.hansenpartnership.com [127.0.0.1]) (amavis, port 10024) with ESMTP id NERE6xOfK9o6; Fri, 2 Aug 2024 16:26:52 -0400 (EDT) Received: from lingrow.int.hansenpartnership.com (unknown [153.66.160.227]) by bedivere.hansenpartnership.com (Postfix) with ESMTP id 30188128690C; Fri, 02 Aug 2024 16:26:52 -0400 (EDT) From: James Bottomley To: openssl-tpm2-engine@groups.io Cc: linux-integrity@vger.kernel.org, Jarkko Sakkinen Subject: [PATCH 3/8] libcommon: add bin2hex and tmp2_get_hexname Date: Fri, 2 Aug 2024 16:26:01 -0400 Message-Id: <20240802202606.12767-4-James.Bottomley@HansenPartnership.com> X-Mailer: git-send-email 2.35.3 In-Reply-To: <20240802202606.12767-1-James.Bottomley@HansenPartnership.com> References: <20240802202606.12767-1-James.Bottomley@HansenPartnership.com> Precedence: bulk X-Mailing-List: linux-integrity@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Signed-off-by: James Bottomley --- src/include/tpm2-common.h | 5 +++++ src/libcommon/tpm2-common.c | 16 ++++++++++++++++ 2 files changed, 21 insertions(+) diff --git a/src/include/tpm2-common.h b/src/include/tpm2-common.h index 97b60f2..0e0f28a 100644 --- a/src/include/tpm2-common.h +++ b/src/include/tpm2-common.h @@ -9,6 +9,9 @@ * not a TPM error, so don't process the rc as one */ #define NOT_TPM_ERROR (0xffffffff) +/* maximum space for a sha256 name in ascii */ +#define MAX_HEXNAME 132 + extern TPM_ALG_ID name_alg; struct policy_command { @@ -141,4 +144,6 @@ int tpm2_rsa_decrypt(const struct app_data *ad, PUBLIC_KEY_RSA_2B *cipherText, char *srk_auth); int tpm2_rm_signed_policy(char *tpmkey, int rmnum); int tpm2_get_signed_policy(char *tpmkey, STACK_OF(TSSAUTHPOLICY) **sk); +void bin2hex(char *dst, const unsigned char *src, size_t count); +void tpm2_get_hexname(char hexname[MAX_HEXNAME], TPM2B_PUBLIC *pub); #endif diff --git a/src/libcommon/tpm2-common.c b/src/libcommon/tpm2-common.c index b70ac27..3ffa773 100644 --- a/src/libcommon/tpm2-common.c +++ b/src/libcommon/tpm2-common.c @@ -2320,6 +2320,14 @@ int hex2bin(unsigned char *dst, const char *src, size_t count) return 0; } +void bin2hex(char *dst, const unsigned char *src, size_t count) +{ + int i; + + for (i = 0; i < count; i++) + sprintf(&dst[i<<1], "%02x", src[i]); +} + TPM_RC tpm2_parse_policy_file(const char *policy_file, STACK_OF(TSSOPTPOLICY) *sk, char *auth, TPMT_HA *digest) @@ -3376,6 +3384,14 @@ openssl_print_errors() ERR_print_errors_fp(stderr); } +void tpm2_get_hexname(char hexname[MAX_HEXNAME], TPM2B_PUBLIC *pub) +{ + NAME_2B n; + + tpm2_ObjectPublic_GetName(&n, &pub->publicArea); + bin2hex(hexname, (unsigned char *)n.name, n.size); +} + IMPLEMENT_ASN1_FUNCTIONS(TSSOPTPOLICY) IMPLEMENT_ASN1_FUNCTIONS(TSSAUTHPOLICY) IMPLEMENT_ASN1_FUNCTIONS(TSSLOADABLE) From patchwork Fri Aug 2 20:26:02 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: James Bottomley X-Patchwork-Id: 13751965 Received: from bedivere.hansenpartnership.com (bedivere.hansenpartnership.com [96.44.175.130]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 95101335C0 for ; Fri, 2 Aug 2024 20:26:59 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=96.44.175.130 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1722630421; cv=none; b=BSsXfFwD0WqSFwkBCf8/8pvmqLzD2VAP7eoEiUnZ1FBk3DR3hWkh8VTyuj53i8tAOTZQrLc72uev/yWgXbp5YbK5AgMkNzGhAUXaM6WWYpcFcbb3BzHb/xoCXlCTpIzBZdg6mxKSCV49HF/p5h7iciouWkz13XccC4qYI6Cxbmo= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1722630421; c=relaxed/simple; bh=/6f5JDDLTwh/hyHKM8I5DBdiE7qBwzHBvU+Igzw9x+c=; h=From:To:Cc:Subject:Date:Message-Id:In-Reply-To:References: MIME-Version; b=V7AvXKv3tV8+LBujVxmLOQY9/RRzqrqqWmhjut9ibWjaOeIUj9NDT4wTwlabobvpvU+gbKgrn2uFyd2Z8rQSzCyf9gC+ru+jXScJDqrq6TtKBb0zPOOVbwEjrMKb9SKonmrq9b/ehW3R7InMe/5AQJ2ocaJMGN7oVXsI/CeBwJU= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=HansenPartnership.com; spf=pass smtp.mailfrom=HansenPartnership.com; dkim=pass (1024-bit key) header.d=hansenpartnership.com header.i=@hansenpartnership.com header.b=BuMqCtQC; arc=none smtp.client-ip=96.44.175.130 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=HansenPartnership.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=HansenPartnership.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (1024-bit key) header.d=hansenpartnership.com header.i=@hansenpartnership.com header.b="BuMqCtQC" DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=hansenpartnership.com; s=20151216; t=1722630419; bh=/6f5JDDLTwh/hyHKM8I5DBdiE7qBwzHBvU+Igzw9x+c=; h=From:To:Subject:Date:Message-Id:In-Reply-To:References:From; b=BuMqCtQCiOJCUKgt5nvXQgxYsMY98m4IiZ6Jx1QgYLZafKeWtp4gglhcDX+DM/+UO UIi6C4GFtX64d/fVgbRbYxLmrKncP6dR71AT8nHAMTA/KcVlzq/vtE5SKYpI0BlFxN 4+/WdPg5QibW4GduI25jK0dQ9bP6v7CPw2QnHyAs= Received: from localhost (localhost [127.0.0.1]) by bedivere.hansenpartnership.com (Postfix) with ESMTP id 1C0501286A6B; Fri, 02 Aug 2024 16:26:59 -0400 (EDT) Received: from bedivere.hansenpartnership.com ([127.0.0.1]) by localhost (bedivere.hansenpartnership.com [127.0.0.1]) (amavis, port 10024) with ESMTP id BjV7tdSRJoc3; Fri, 2 Aug 2024 16:26:59 -0400 (EDT) Received: from lingrow.int.hansenpartnership.com (unknown [153.66.160.227]) by bedivere.hansenpartnership.com (Postfix) with ESMTP id 9EE5B128690C; Fri, 02 Aug 2024 16:26:58 -0400 (EDT) From: James Bottomley To: openssl-tpm2-engine@groups.io Cc: linux-integrity@vger.kernel.org, Jarkko Sakkinen Subject: [PATCH 4/8] libcommon: add primary creation from template Date: Fri, 2 Aug 2024 16:26:02 -0400 Message-Id: <20240802202606.12767-5-James.Bottomley@HansenPartnership.com> X-Mailer: git-send-email 2.35.3 In-Reply-To: <20240802202606.12767-1-James.Bottomley@HansenPartnership.com> References: <20240802202606.12767-1-James.Bottomley@HansenPartnership.com> Precedence: bulk X-Mailing-List: linux-integrity@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Although for usual operation we only need the standard template to create the keys, for EK operations we need to create the EK from the exact EK template (of which there are a few), so add a new function to allow the creation of a primary from any given template. Signed-off-by: James Bottomley --- src/include/tpm2-common.h | 3 +++ src/libcommon/tpm2-common.c | 54 +++++++++++++++++++++---------------- 2 files changed, 34 insertions(+), 23 deletions(-) diff --git a/src/include/tpm2-common.h b/src/include/tpm2-common.h index 0e0f28a..026a2ae 100644 --- a/src/include/tpm2-common.h +++ b/src/include/tpm2-common.h @@ -59,6 +59,9 @@ struct app_data { void tpm2_error(TPM_RC rc, const char *reason); TPM_RC tpm2_load_srk(TSS_CONTEXT *tssContext, TPM_HANDLE *h, const char *auth, TPM2B_PUBLIC *pub, TPM_HANDLE handle, enum tpm2_type type); +TPM_RC tpm2_load_srk_tmpl(TSS_CONTEXT *tssContext, TPM_HANDLE *h, + const char *auth, TPM2B_PUBLIC *tmpl, + TPM2B_PUBLIC *pub, TPM_HANDLE hierarchy); void tpm2_flush_handle(TSS_CONTEXT *tssContext, TPM_HANDLE h); EVP_PKEY *tpm2_to_openssl_public(TPMT_PUBLIC *pub); void tpm2_flush_srk(TSS_CONTEXT *tssContext, TPM_HANDLE hSRK); diff --git a/src/libcommon/tpm2-common.c b/src/libcommon/tpm2-common.c index 3ffa773..be3fe50 100644 --- a/src/libcommon/tpm2-common.c +++ b/src/libcommon/tpm2-common.c @@ -717,13 +717,12 @@ TPM_RC tpm2_ObjectPublic_GetName(NAME_2B *name, return rc; } -TPM_RC tpm2_load_srk(TSS_CONTEXT *tssContext, TPM_HANDLE *h, const char *auth, - TPM2B_PUBLIC *pub, TPM_HANDLE hierarchy, - enum tpm2_type type) +TPM_RC tpm2_load_srk_tmpl(TSS_CONTEXT *tssContext, TPM_HANDLE *h, + const char *auth, TPM2B_PUBLIC *tmpl, + TPM2B_PUBLIC *pub, TPM_HANDLE hierarchy) { TPM_RC rc; TPM2B_SENSITIVE_CREATE inSensitive; - TPM2B_PUBLIC inPublic; TPM_HANDLE session = TPM_RS_PW; if (auth) { @@ -736,7 +735,33 @@ TPM_RC tpm2_load_srk(TSS_CONTEXT *tssContext, TPM_HANDLE *h, const char *auth, /* no sensitive date for storage keys */ VAL_2B(inSensitive.sensitive.data, size) = 0; - /* public parameters for an RSA2048 key */ + /* use a bound session here because we have no known key objects + * to encrypt a salt to */ + if (auth) { + rc = tpm2_get_bound_handle(tssContext, &session, hierarchy, auth); + if (rc) + return rc; + } + + rc = tpm2_CreatePrimary(tssContext, hierarchy, &inSensitive, tmpl, + h, pub, session, auth); + + if (rc) { + tpm2_error(rc, "TSS_CreatePrimary"); + if (session != TPM_RS_PW) + tpm2_flush_handle(tssContext, session); + } + + return rc; +} + +TPM_RC tpm2_load_srk(TSS_CONTEXT *tssContext, TPM_HANDLE *h, const char *auth, + TPM2B_PUBLIC *pub, TPM_HANDLE hierarchy, + enum tpm2_type type) +{ + TPM2B_PUBLIC inPublic; + + /* public parameters for a P-256 key */ inPublic.publicArea.type = TPM_ALG_ECC; inPublic.publicArea.nameAlg = TPM_ALG_SHA256; VAL(inPublic.publicArea.objectAttributes) = @@ -774,24 +799,7 @@ TPM_RC tpm2_load_srk(TSS_CONTEXT *tssContext, TPM_HANDLE *h, const char *auth, VAL_2B(inPublic.publicArea.unique.ecc.y, size) = 0; VAL_2B(inPublic.publicArea.authPolicy, size) = 0; - /* use a bound session here because we have no known key objects - * to encrypt a salt to */ - if (auth) { - rc = tpm2_get_bound_handle(tssContext, &session, hierarchy, auth); - if (rc) - return rc; - } - - rc = tpm2_CreatePrimary(tssContext, hierarchy, &inSensitive, &inPublic, - h, pub, session, auth); - - if (rc) { - tpm2_error(rc, "TSS_CreatePrimary"); - if (session != TPM_RS_PW) - tpm2_flush_handle(tssContext, session); - } - - return rc; + return tpm2_load_srk_tmpl(tssContext, h, auth, &inPublic, pub, hierarchy); } void tpm2_flush_srk(TSS_CONTEXT *tssContext, TPM_HANDLE hSRK) From patchwork Fri Aug 2 20:26:03 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: James Bottomley X-Patchwork-Id: 13751966 Received: from bedivere.hansenpartnership.com (bedivere.hansenpartnership.com [96.44.175.130]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 39E0A49658 for ; Fri, 2 Aug 2024 20:27:06 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=96.44.175.130 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1722630427; cv=none; b=OVA1UbVcq+lCNu/1uHIALU1+vKq1mBihkeJRXpnXJg7layFpby5S+dvMiN2MUQ28bddb4unO5x5cKsuzgsV/HZLhvyaDLGaar9WKaHNkVg9M7vS3M/L7RpX9z9Oq+o1693CJiY58FLizULyBQiaslx8aeOWBS6DdjUgdgTiTZ04= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1722630427; c=relaxed/simple; bh=0R2yr2EPWtj7mnglV5x3DOhrjqkXbxmxsU9gnoCJf4g=; h=From:To:Cc:Subject:Date:Message-Id:In-Reply-To:References: MIME-Version; b=HCFddOnhy173bcg8Qq+8fcH2nkmfVDABPY7KliD5BANa1lKSOHPkohmwiODneP/2FumwNXEw3oiFaPYH/3Td8QLrJIwaUEqcH6GjKeqD0tq9teoSnghjTjSgiegKd/N8ia8Tx9c58rNfU52PieFp4l/AToVhPkSafVS75ft/U9A= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=HansenPartnership.com; spf=pass smtp.mailfrom=HansenPartnership.com; dkim=pass (1024-bit key) header.d=hansenpartnership.com header.i=@hansenpartnership.com header.b=P4atAKBq; arc=none smtp.client-ip=96.44.175.130 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=HansenPartnership.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=HansenPartnership.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (1024-bit key) header.d=hansenpartnership.com header.i=@hansenpartnership.com header.b="P4atAKBq" DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=hansenpartnership.com; s=20151216; t=1722630425; bh=0R2yr2EPWtj7mnglV5x3DOhrjqkXbxmxsU9gnoCJf4g=; h=From:To:Subject:Date:Message-Id:In-Reply-To:References:From; b=P4atAKBqSvbLVv5UkqbRwHmMMMdFofGFO83iM/1NHQFIDf5hQu/xZsQ1XzA7TvrN1 mDllaUAiu7fcmylzaEP56C9GSBHlqMNKnrBkeTqmslQVOeQmdipFXk5dUc1cWx/Qoq 4E1lEPAnoyMNKgkdShTLBFAk7z+MJ/Ickye9a6zo= Received: from localhost (localhost [127.0.0.1]) by bedivere.hansenpartnership.com (Postfix) with ESMTP id CA99C1286A6B; Fri, 02 Aug 2024 16:27:05 -0400 (EDT) Received: from bedivere.hansenpartnership.com ([127.0.0.1]) by localhost (bedivere.hansenpartnership.com [127.0.0.1]) (amavis, port 10024) with ESMTP id xi1AjlFFYM3H; Fri, 2 Aug 2024 16:27:05 -0400 (EDT) Received: from lingrow.int.hansenpartnership.com (unknown [153.66.160.227]) by bedivere.hansenpartnership.com (Postfix) with ESMTP id 4CD40128690C; Fri, 02 Aug 2024 16:27:05 -0400 (EDT) From: James Bottomley To: openssl-tpm2-engine@groups.io Cc: linux-integrity@vger.kernel.org, Jarkko Sakkinen Subject: [PATCH 5/8] tss: add tpm2_Certify, tpm2_ActivateCredential and tpm2_PolicyOR Date: Fri, 2 Aug 2024 16:26:03 -0400 Message-Id: <20240802202606.12767-6-James.Bottomley@HansenPartnership.com> X-Mailer: git-send-email 2.35.3 In-Reply-To: <20240802202606.12767-1-James.Bottomley@HansenPartnership.com> References: <20240802202606.12767-1-James.Bottomley@HansenPartnership.com> Precedence: bulk X-Mailing-List: linux-integrity@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 tpm2_Certify is used to verify that a given object is resident in the TPM. tpm2_ActivateCredential is used to decrypt a challenge from a privacyCA and constructing the high template for the EK to use with this requires PolicyOR. Signed-off-by: James Bottomley --- src/include/ibm-tss.h | 84 +++++++++++++++++++++++++++++++++++++++++ src/include/intel-tss.h | 77 ++++++++++++++++++++++++++++++++++++- 2 files changed, 160 insertions(+), 1 deletion(-) diff --git a/src/include/ibm-tss.h b/src/include/ibm-tss.h index 1b53319..b5da340 100644 --- a/src/include/ibm-tss.h +++ b/src/include/ibm-tss.h @@ -16,6 +16,7 @@ #define VAL(X) X.val #define VAL_2B(X, MEMBER) X.b.MEMBER #define VAL_2B_P(X, MEMBER) X->b.MEMBER +#define VAL_T(X, MEMBER) X.t.MEMBER static inline void tpm2_error(TPM_RC rc, const char *reason) @@ -695,6 +696,26 @@ tpm2_PolicySecret(TSS_CONTEXT *tssContext, TPM_HANDLE authHandle, return rc; } +static inline TPM_RC +tpm2_PolicyOR(TSS_CONTEXT *tssContext, TPM_HANDLE policySession, + TPML_DIGEST *pHashList) +{ + PolicyOR_In in; + TPM_RC rc; + + in.policySession = policySession; + in.pHashList = *pHashList; + + rc = TSS_Execute(tssContext, + NULL, + (COMMAND_PARAMETERS *)&in, + NULL, + TPM_CC_PolicyOR, + TPM_RH_NULL, NULL, 0); + + return rc; +} + static inline TPM_RC tpm2_PolicyGetDigest(TSS_CONTEXT *tssContext, TPM_HANDLE policySession, DIGEST_2B *digest) @@ -743,6 +764,69 @@ tpm2_PCR_Read(TSS_CONTEXT *tssContext, TPML_PCR_SELECTION *pcrSelectionIn, return rc; } +static inline TPM_RC +tpm2_Certify(TSS_CONTEXT *tssContext, TPM_HANDLE objectHandle, + TPM_HANDLE signHandle, DATA_2B *qualifyingData, + ATTEST_2B *certifyInfo, TPMT_SIGNATURE *signature) +{ + Certify_In in; + Certify_Out out; + TPM_RC rc; + + in.objectHandle = objectHandle; + in.signHandle = signHandle; + in.qualifyingData.t = *qualifyingData; + in.inScheme.scheme = TPM_ALG_NULL; + + rc = TSS_Execute(tssContext, + (RESPONSE_PARAMETERS *)&out, + (COMMAND_PARAMETERS *)&in, + NULL, + TPM_CC_Certify, + TPM_RS_PW, NULL, 0, + TPM_RS_PW, NULL, 0, + TPM_RH_NULL, NULL, 0); + + if (rc) + return rc; + + *certifyInfo = out.certifyInfo.t; + *signature = out.signature; + + return rc; +} + +static inline TPM_RC +tpm2_ActivateCredential(TSS_CONTEXT *tssContext, TPM_HANDLE activateHandle, + TPM_HANDLE keyHandle, ID_OBJECT_2B *credentialBlob, + ENCRYPTED_SECRET_2B *secret, DIGEST_2B *certinfo, + TPM_HANDLE auth) +{ + ActivateCredential_In in; + ActivateCredential_Out out; + TPM_RC rc; + + in.activateHandle = activateHandle; + in.keyHandle = keyHandle; + in.credentialBlob.t = *credentialBlob; + in.secret.t = *secret; + + rc = TSS_Execute(tssContext, + (RESPONSE_PARAMETERS *)&out, + (COMMAND_PARAMETERS *)&in, + NULL, + TPM_CC_ActivateCredential, + TPM_RS_PW, NULL, 0, + auth, NULL, TPMA_SESSION_ENCRYPT, + TPM_RH_NULL, NULL, 0); + if (rc) + return rc; + + *certinfo = out.certInfo.t; + + return rc; +} + static inline TPM_HANDLE tpm2_handle_int(TSS_CONTEXT *tssContext, TPM_HANDLE h) { diff --git a/src/include/intel-tss.h b/src/include/intel-tss.h index 5b8db20..3b8c18d 100644 --- a/src/include/intel-tss.h +++ b/src/include/intel-tss.h @@ -74,6 +74,7 @@ #define TPM_CC_PolicySecret TPM2_CC_PolicySecret #define TPM_ST_HASHCHECK TPM2_ST_HASHCHECK +#define TPM_ST_ATTEST_CERTIFY TPM2_ST_ATTEST_CERTIFY #define TPM_RH_OWNER ESYS_TR_RH_OWNER #define TPM_RH_PLATFORM ESYS_TR_RH_PLATFORM @@ -131,6 +132,7 @@ /* Intel and IBM have slightly different names for all the 2B structures */ +#define ATTEST_2B TPM2B_ATTEST #define NAME_2B TPM2B_NAME #define DATA_2B TPM2B_DATA #define PRIVATE_2B TPM2B_PRIVATE @@ -138,6 +140,7 @@ #define KEY_2B TPM2B_KEY #define TPM2B_KEY TPM2B_DATA #define DIGEST_2B TPM2B_DIGEST +#define ID_OBJECT_2B TPM2B_ID_OBJECT #define ECC_PARAMETER_2B TPM2B_ECC_PARAMETER #define SENSITIVE_DATA_2B TPM2B_SENSITIVE_DATA #define PUBLIC_KEY_RSA_2B TPM2B_PUBLIC_KEY_RSA @@ -196,8 +199,11 @@ TSS_CONVERT_MARSHAL(TPM2B_PRIVATE, ) TSS_CONVERT_MARSHAL(TPML_PCR_SELECTION, ) TSS_CONVERT_MARSHAL(TPMT_SIGNATURE, ) TSS_CONVERT_MARSHAL(UINT32, *) +#define Tss2_MU_TPM_HANDLE_Marshal Tss2_MU_TPM2_HANDLE_Marshal +TSS_CONVERT_MARSHAL(TPM_HANDLE, *) #define TSS_TPM_CC_Marshal TSS_UINT32_Marshal +TSS_CONVERT_UNMARSHAL(TPMS_ATTEST, ) TSS_CONVERT_UNMARSHAL(TPML_PCR_SELECTION, ) TSS_CONVERT_UNMARSHAL(TPM2B_PRIVATE, ) TSS_CONVERT_UNMARSHAL(TPM2B_PUBLIC, X) @@ -218,6 +224,7 @@ TSS_CONVERT_UNMARSHAL(TPMT_SIGNATURE, X) #define VAL(X) X #define VAL_2B(X, MEMBER) X.MEMBER #define VAL_2B_P(X, MEMBER) X->MEMBER +#define VAL_T(X, MEMBER) X.MEMBER static const struct { TPM_ALG_ID alg; @@ -409,7 +416,6 @@ TSS_HMAC_Generate(TPMT_HA *digest, const TPM2B_KEY *hmacKey, ...) OSSL_PARAM_construct_utf8_string("digest", TSS_GetDigestName(digest->hashAlg), 0), OSSL_PARAM_construct_end() }; - fprintf(stderr, "HMAC\n"); #endif int length; uint8_t *buffer; @@ -1124,6 +1130,15 @@ tpm2_PolicySecret(TSS_CONTEXT *tssContext, TPM_HANDLE authHandle, return rc; } +static inline TPM_RC +tpm2_PolicyOR(TSS_CONTEXT *tssContext, TPM_HANDLE policySession, + TPML_DIGEST *pHashList) +{ + return Esys_PolicyOR(tssContext, policySession, + ESYS_TR_NONE, ESYS_TR_NONE, ESYS_TR_NONE, + pHashList); +} + static inline TPM_RC tpm2_PolicyGetDigest(TSS_CONTEXT *tssContext, TPM_HANDLE policySession, DIGEST_2B *digest) @@ -1191,6 +1206,66 @@ tpm2_PCR_Read(TSS_CONTEXT *tssContext, TPML_PCR_SELECTION *pcrSelectionIn, return rc; } +static inline TPM_RC +tpm2_Certify(TSS_CONTEXT *tssContext, TPM_HANDLE objectHandle, + TPM_HANDLE signHandle, DATA_2B *qualifyingData, + ATTEST_2B *certifyInfo, TPMT_SIGNATURE *signature) +{ + TPM_RC rc; + TPMT_SIG_SCHEME inScheme; + ATTEST_2B *a; + TPMT_SIGNATURE *s; + TPM2B_AUTH auth; + + inScheme.scheme = TPM_ALG_NULL; + + auth.size = 0; + Esys_TR_SetAuth(tssContext, objectHandle, &auth); + Esys_TR_SetAuth(tssContext, signHandle, &auth); + + rc = Esys_Certify(tssContext, objectHandle, signHandle, + ESYS_TR_PASSWORD, ESYS_TR_PASSWORD, + ESYS_TR_NONE, qualifyingData, &inScheme, + &a, &s); + if (rc) + return rc; + + *certifyInfo = *a; + *signature = *s; + + free(a); + free(s); + + return rc; +} + +static inline TPM_RC +tpm2_ActivateCredential(TSS_CONTEXT *tssContext, TPM_HANDLE activateHandle, + TPM_HANDLE keyHandle, + const ID_OBJECT_2B *credentialBlob, + const ENCRYPTED_SECRET_2B *secret, DIGEST_2B *certinfo, + TPM_HANDLE authHandle) +{ + TPM_RC rc; + DIGEST_2B *cinfo; + TPM2B_AUTH auth; + + auth.size = 0; + Esys_TR_SetAuth(tssContext, activateHandle, &auth); + Esys_TR_SetAuth(tssContext, keyHandle, &auth); + intel_sess_helper(tssContext, authHandle, TPMA_SESSION_ENCRYPT); + rc = Esys_ActivateCredential(tssContext, activateHandle, keyHandle, + ESYS_TR_PASSWORD, authHandle, ESYS_TR_NONE, + credentialBlob, secret, &cinfo); + if (rc) + return rc; + + *certinfo = *cinfo; + free(cinfo); + + return rc; +} + static inline TPM_HANDLE tpm2_handle_ext(TSS_CONTEXT *tssContext, TPM_HANDLE esysh) { From patchwork Fri Aug 2 20:26:04 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: James Bottomley X-Patchwork-Id: 13751967 Received: from bedivere.hansenpartnership.com (bedivere.hansenpartnership.com [96.44.175.130]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 9F96933DF for ; Fri, 2 Aug 2024 20:27:13 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=96.44.175.130 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1722630435; cv=none; b=OEBTi2CdOU8D3FfEgWrzLiM9lHRt3itYhmRbxOW49gFVekEK7R0/fpwovWITV1PQEQMgzQerw2F90BOt+VA+L08qM6e8jm6BXUZBlSjS5WCw52XjDefr6OXFHL6xd2YRjJB5r9J4tzG/weZS3d8NelhgQ0XppDd2NP9FPL5FzBk= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1722630435; c=relaxed/simple; bh=1P8gmARFh364FqAVjRt8X6NbC0vHoMlo4eOOIMzUIvM=; h=From:To:Cc:Subject:Date:Message-Id:In-Reply-To:References: MIME-Version; b=iWIEbTBCuL2BpofGqHsVIImLT1prWNl7BanobMycqdlIZxQgzWTmdx+gK+85/yU08nJTlhTnBuc72J1nb4gmyzygfEMOGqVpxs2w48h+8qquL5vFnvECilYejEaSbU0F6oLbKw1Nmdc1dvlEgUV5IATEjGp0B3DTx40EyVGn9j8= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=HansenPartnership.com; spf=pass smtp.mailfrom=HansenPartnership.com; dkim=pass (1024-bit key) header.d=hansenpartnership.com header.i=@hansenpartnership.com header.b=mr+BJIps; arc=none smtp.client-ip=96.44.175.130 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=HansenPartnership.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=HansenPartnership.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (1024-bit key) header.d=hansenpartnership.com header.i=@hansenpartnership.com header.b="mr+BJIps" DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=hansenpartnership.com; s=20151216; t=1722630432; bh=1P8gmARFh364FqAVjRt8X6NbC0vHoMlo4eOOIMzUIvM=; h=From:To:Subject:Date:Message-Id:In-Reply-To:References:From; b=mr+BJIpsqSr5ZnyjjsgLfQLtN09Eetgw8DYEZnucckAldMw3vV21OODEyucIyfgp0 eUAqhBjs+S+RS8G/r16AUx0lvn4pFVJyTDRDYj5pFM2vDkAJmzx4JwOdlm0Cxy1ANk OGY59WJBHUxpbL8CCUuwtDsen9a7zPlO1sJ96xVE= Received: from localhost (localhost [127.0.0.1]) by bedivere.hansenpartnership.com (Postfix) with ESMTP id D25B01287046; Fri, 02 Aug 2024 16:27:12 -0400 (EDT) Received: from bedivere.hansenpartnership.com ([127.0.0.1]) by localhost (bedivere.hansenpartnership.com [127.0.0.1]) (amavis, port 10024) with ESMTP id v43xi-BuxHv6; Fri, 2 Aug 2024 16:27:12 -0400 (EDT) Received: from lingrow.int.hansenpartnership.com (unknown [153.66.160.227]) by bedivere.hansenpartnership.com (Postfix) with ESMTP id 8D232128690C; Fri, 02 Aug 2024 16:27:11 -0400 (EDT) From: James Bottomley To: openssl-tpm2-engine@groups.io Cc: linux-integrity@vger.kernel.org, Jarkko Sakkinen Subject: [PATCH 6/8] tools: add new attest_tpm2_primary command Date: Fri, 2 Aug 2024 16:26:04 -0400 Message-Id: <20240802202606.12767-7-James.Bottomley@HansenPartnership.com> X-Mailer: git-send-email 2.35.3 In-Reply-To: <20240802202606.12767-1-James.Bottomley@HansenPartnership.com> References: <20240802202606.12767-1-James.Bottomley@HansenPartnership.com> Precedence: bulk X-Mailing-List: linux-integrity@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 This command can be used for three things which allow a system to build an ongoing trust relationship with the TPM. For TPMs which don't have EK certificates (most fTPMs) it allows a trust on first use model where the EK is squirreled away in a permanent location on the filesystem as: attest_tpm2_primary --ek > /etc/eksign.name Which generates a signing EK that can be used to certify other objects and permanently stores the name in /etc (ideally this should be stored in an immutable location on OS install). If the TPM does have a signing certificate, the next step is to verify the cert back to the manufacturer and bind it to the signing EK by doing attest_tpm2_primary --attest --name /etc/eksign.name This will run a local makecredential/activatecredential on the signing EK using the public key in the . Once this happens the TPM is proven to be a genuine discrete TPM. Finally, having the permanent name file allows the signing EK to certify the NULL key used by the kernel on every boot via attest_tpm2_primary --certify null --name /etc/eksign.name /sys/class/tpm/tpm0/null_name Since the null_name changes on every boot this allows a user confidence that the TPM booted up correctly and isn't being snooped. Additionally, the command can generate the public SRK for importable keys by running a certification against the signing EK to verify it isn't being spoofed: attest_tpm2_primary --certify owner --name /etc/eksign.name --file srk.pub Signed-off-by: James Bottomley --- src/tools/Makefile.am | 6 +- src/tools/attest_tpm2_primary.c | 842 ++++++++++++++++++++++++++++++++ 2 files changed, 847 insertions(+), 1 deletion(-) create mode 100644 src/tools/attest_tpm2_primary.c diff --git a/src/tools/Makefile.am b/src/tools/Makefile.am index 572847c..7cca442 100644 --- a/src/tools/Makefile.am +++ b/src/tools/Makefile.am @@ -12,7 +12,7 @@ endif AM_CPPFLAGS = -I ../include ${DEPRECATION} bin_PROGRAMS=create_tpm2_key load_tpm2_key seal_tpm2_data unseal_tpm2_data \ - signed_tpm2_policy + signed_tpm2_policy attest_tpm2_primary COMMONLIB = ../libcommon/libcommon.a create_tpm2_key_SOURCES=create_tpm2_key.c @@ -35,6 +35,10 @@ signed_tpm2_policy_SOURCES=signed_tpm2_policy.c signed_tpm2_policy_LDADD=${COMMONLIB} ${DEPS_LIBS} signed_tpm2_policy_CFLAGS=${DEPS_CFLAGS} +attest_tpm2_primary_SOURCES=attest_tpm2_primary.c +attest_tpm2_primary_LDADD=${COMMONLIB} ${DEPS_LIBS} +attest_tpm2_primary_CFLAGS=${DEPS_CFLAGS} + $(builddir)/%.1: $(srcdir)/%.1.in $(builddir)/% $(HELP2MAN) --no-info -i $< -o $@ $(builddir)/$* diff --git a/src/tools/attest_tpm2_primary.c b/src/tools/attest_tpm2_primary.c new file mode 100644 index 0000000..cb252fe --- /dev/null +++ b/src/tools/attest_tpm2_primary.c @@ -0,0 +1,842 @@ +/* + * + * Copyright (C) 2024 James Bottomley + * + * SPDX-License-Identifier: LGPL-2.1-only + */ + + +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include + +#include "tpm2-tss.h" +#include "tpm2-asn.h" +#include "tpm2-common.h" + +/* + * + * --eksign [--name ] [--file ] + * + * create P-256 EK signing key and check the name against + * If name check is requested and passes, output the pem public key to . + * + * --attest [--name ] [--file ] + * + * derive the EK signing key and verify its name against + * (if present). Then attest it as a signing key against the EK + * certificate in using makecredential/activate credential. + * Optionally output the pub pem to if the certification + * works. + * + * --certify --name [--outname] [--file ] [] + * + * derive the storage primary in hierarchy and validate the name + * against that in the file if present. If it validates (or + * hname is not present), derive the EK P-256 signing key and validate + * the EK name is . Finally, certify the key derived from + * using EK which proves the TPM knows the secret part of EK if the + * certification signature verifies and that is genuine. If the + * signature verifies, return success and optionally output the PEM + * form of the public key of to and print the name. + * + */ + +static struct option long_options[] = { + {"help", 0, 0, 'h'}, + {"auth", 1, 0, 'a'}, + {"password", 1, 0, 'k'}, + {"eksign", 0, 0, 'E'}, + {"attest", 1, 0, 'A'}, + {"certify", 1, 0, 'C'}, + {"name", 1, 0, 'n'}, + {"outname", 0, 0, 'o'}, + {"file", 1, 0, 'f'}, + {0, 0, 0, 0} +}; + +void +usage(char *argv0) +{ + fprintf(stdout, "Usage: %s {--eksign|--attest|--certify} [options]\n\n" + "Options:\n" + "\t-E, --eksign construct a restricted signing EK and\n" + "\t output its name in hex if no other options\n" + "\t are given.\n" + "\t-A, --attest Attest the ek signing key based on the EK\n" + "\t certificate (in ) to prove it\n" + "\t is genuine.\n" + "\t-C, --certify construct the restricted storage key for\n" + "\t and certify it against the EK\n" + "\t signing key. The name file for the EK\n" + "\t signing key must be provided.\n" + "\t-h, --help print this help message.\n" + "\t-a, --auth provide EK authorization.\n" + "\t-k, --password use this password instead of prompting.\n" + "\t-n, --name force the checking of the constructed\n" + "\t hierarchy signing key against the name\n" + "\t in the give file. Fail if they do not\n" + "\t match.\n" + "\t-f, --file Output the constructed hierarchy signing\n" + "\t or storage public key as a PEM file\n" + "\t suitable for import or external\n" + "\t cryptosystem use.\n" + "\t-o, --outname Print out the name of the certified key\n" + "\n" + "Report bugs to " PACKAGE_BUGREPORT "\n", + argv0); + exit(-1); +} + +static int verify_hexname(const char *namefile, char hexname[MAX_HEXNAME]) +{ + int fd; + struct stat st; + const int len = strlen(hexname); + int rc = NOT_TPM_ERROR; + char name[MAX_HEXNAME]; + + if (stat(namefile, &st) == -1) { + fprintf(stderr, "File %s cannot be accessed\n", namefile); + return rc; + } + + /* sysfs null name is always 4096 to stat, so only check for too small */ + if (st.st_size < len) { + fprintf(stderr, "Name file is too small should be at least %d\n", + len); + return rc; + } + + fd = open(namefile, O_RDONLY); + if (fd < 0) { + perror("namefile can't be opened"); + return rc; + } + + if (!read(fd, name, len)) { + perror("namefile can't be read"); + goto out_close; + } + + if (memcmp(name, hexname, len) == 0) + rc = 0; + out_close: + close(fd); + + return rc; +} + +static int write_pubkey(const char *file, TPMT_PUBLIC *pub) +{ + BIO *bf; + int rc; + EVP_PKEY *pkey = tpm2_to_openssl_public(pub); + + if (!pkey) + goto openssl_err; + bf = BIO_new_file(file, "w"); + if (!bf) + goto openssl_err; + rc = PEM_write_bio_PUBKEY(bf, pkey); + BIO_free(bf); + if (!rc) + goto openssl_err; + + EVP_PKEY_free(pkey); + return 0; + + openssl_err: + ERR_print_errors_fp(stderr); + if (pkey) + EVP_PKEY_free(pkey); + return NOT_TPM_ERROR; +} + +/* analogue of tpm2_sign_digest from tpm2-common.c */ +static TPM_RC tpm2_verify_digest(EVP_PKEY *pkey, TPMT_HA *digest, + TPMT_SIGNATURE *sig) +{ + EVP_PKEY_CTX *ctx; + ECDSA_SIG *esig; + BIGNUM *r, *s; + unsigned char *p = NULL; + int p_len; + TPM_RC rc = NOT_TPM_ERROR; + + ctx = EVP_PKEY_CTX_new(pkey, NULL); + if (!ctx) + goto openssl_err; + esig = ECDSA_SIG_new(); + if (!esig) + goto openssl_ctx; + + r = BN_bin2bn(VAL_2B(sig->signature.ecdsa.signatureR, buffer), + VAL_2B(sig->signature.ecdsa.signatureR, size), NULL); + s = BN_bin2bn(VAL_2B(sig->signature.ecdsa.signatureS, buffer), + VAL_2B(sig->signature.ecdsa.signatureS, size), NULL); + +#if OPENSSL_VERSION_NUMBER < 0x10100000 + esig->r = r; + esig->s = s; +#else + ECDSA_SIG_set0(esig, r, s); +#endif + + p_len = i2d_ECDSA_SIG(esig, &p); + ECDSA_SIG_free(esig); + + EVP_PKEY_verify_init(ctx); + + if (EVP_PKEY_verify(ctx, p, p_len, (unsigned char *)&digest->digest, + SHA256_DIGEST_LENGTH) == 1) + rc = 0; + + OPENSSL_free(p); + + openssl_ctx: + EVP_PKEY_CTX_free(ctx); + + openssl_err: + if (rc) + ERR_print_errors_fp(stderr); + return rc; +} + +void do_certify(const char *auth, TPM_HANDLE handle, const char *namefile, + const char *file, const char *hname, int outname) +{ + TPM_HANDLE h, ek; + TPM2B_PUBLIC pubh, pubek; + char hexname[MAX_HEXNAME]; + const char *dir = tpm2_set_unique_tssdir(); + TSS_CONTEXT *tssContext; + int rc; + DATA_2B qualifying; + ATTEST_2B att; + TPMT_SIGNATURE sig; + EVP_PKEY *pkey; + TPMT_HA digest; + TPMS_ATTEST a; + NAME_2B tmpname; + + if (!namefile) { + fprintf(stderr, "signing EK name must be specified in --name argument\n"); + exit(1); + } + + rc = tpm2_create(&tssContext, dir); + if (rc) + goto out_rmdir; + + handle = tpm2_handle_int(tssContext, handle); + + /* + * FIXME: Assumption here is that only the endorsement + * hierarchy may have an authority password. However, this + * could be true of the owner hierarchy as well so might need + * an additional password parameter. + */ + rc = tpm2_load_srk(tssContext, &h, NULL, &pubh, handle, + TPM2_LOADABLE); + if (rc) + goto out_delete; + + if (hname) { + tpm2_get_hexname(hexname, &pubh); + rc = verify_hexname(hname, hexname); + if (rc) { + fprintf(stderr, "Error: Handle for certification failed name verification\n"); + goto out_free_h; + } + } + + rc = tpm2_load_srk(tssContext, &ek, auth, &pubek, TPM_RH_ENDORSEMENT, + TPM2_SIGNING); + if (rc) + goto out_free_h; + + tpm2_get_hexname(hexname, &pubek); + rc = verify_hexname(namefile, hexname); + if (rc) { + fprintf(stderr, "Error: signing EK failed name verification\n"); + goto out_free_ek; + } + qualifying.size = SHA256_DIGEST_LENGTH; + RAND_bytes(qualifying.buffer, qualifying.size); + + rc = tpm2_Certify(tssContext, h, ek, &qualifying, &att, &sig); + if (rc) { + tpm2_error(rc, "TPM2_Certify"); + goto out_free_ek; + } + + pkey = tpm2_to_openssl_public(&pubek.publicArea); + if (!pkey) + goto out_free_ek; + + digest.hashAlg = TPM_ALG_SHA256; + TSS_Hash_Generate(&digest, + att.size, att.attestationData, + 0, NULL); + rc = tpm2_verify_digest(pkey, &digest, &sig); + if (rc) { + fprintf(stderr, "verification of the cerification signature failed\n"); + goto out_free_ek; + } + + /* + * just proving the signature isn't enough, we need to verify + * the expected values in the attestation area to make sure + * this isn't a replay and that an attacker hasn't returned to + * us a genuinely signed and qualified attestation report + * containing differet keys. + */ + { + BYTE *buffer = att.attestationData; + INT32 size = att.size; + + rc = TPMS_ATTEST_Unmarshal(&a, &buffer, &size); + } + if (rc) { + tpm2_error(rc, "Unmarshalling attestation data"); + goto out_free_ek; + } + + rc = NOT_TPM_ERROR; + + if (a.type != TPM_ST_ATTEST_CERTIFY) { + fprintf(stderr, "Error: Attestation isn't for certification\n"); + goto out_free_ek; + } + + if (memcmp(qualifying.buffer, VAL_2B(a.extraData, buffer), + qualifying.size) != 0) { + fprintf(stderr, "Error: qualifying data is not correct\n"); + goto out_free_ek; + } + + { + /* construct qualifiedName for EK */ + NAME_2B ekn; + BYTE buffer[sizeof(TPM_HANDLE)]; + BYTE *buf = buffer; + UINT16 written =0; + INT32 size = sizeof(buffer); + const TPM_HANDLE perm_ek = EXT_TPM_RH_ENDORSEMENT; + + tpm2_ObjectPublic_GetName(&ekn, &pubek.publicArea); + TSS_TPM_HANDLE_Marshal(&perm_ek, &written, &buf, &size); + digest.hashAlg = TPM_ALG_SHA256; + TSS_Hash_Generate(&digest, + written, buffer, + ekn.size, ekn.name, + 0, NULL); + + /* copy the leading hash algorithm */ + memcpy(tmpname.name, ekn.name, 2); + memcpy(&tmpname.name[2], (char *)&digest.digest, + SHA256_DIGEST_LENGTH); + + if (memcmp(VAL_T(a.qualifiedSigner, name), + tmpname.name, VAL_T(a.qualifiedSigner, size)) != 0) { + fprintf(stderr, "Error: qualified signer does not match EK\n"); + goto out_free_ek; + } + } + + /* finally the certified key name */ + tpm2_ObjectPublic_GetName(&tmpname, &pubh.publicArea); + if (memcmp(VAL_T(a.attested.certify.name, name), + tmpname.name, tmpname.size) != 0) { + fprintf(stderr, "Error: certified object name does not match\n"); + goto out_free_ek; + } + + if (outname) { + tpm2_get_hexname(hexname, &pubh); + printf("%s\n", hexname); + } else { + printf("Good certification from TPM at %lu.%04d reset count %u\n", + a.clockInfo.clock/1000, (int)(a.clockInfo.clock%1000), + a.clockInfo.resetCount); + } + rc = 0; + if (file) + rc = write_pubkey(file, &pubh.publicArea); + + out_free_ek: + tpm2_flush_srk(tssContext, ek); + out_free_h: + tpm2_flush_srk(tssContext, h); + out_delete: + TSS_Delete(tssContext); + out_rmdir: + if (dir) + rmdir(dir); + + if (rc) + exit(1); +} + +void do_ek(const char *auth, const char *namefile, const char *file) +{ + const char *dir = tpm2_set_unique_tssdir(); + TSS_CONTEXT *tssContext; + TPM_RC rc; + TPM_HANDLE h; + TPM2B_PUBLIC pub; + char hexname[MAX_HEXNAME]; + + if (file && !namefile) { + fprintf(stderr, "for output of public key, require namefile to verify\n"); + exit(1); + } + + rc = tpm2_create(&tssContext, dir); + if (rc) + goto out_rmdir; + rc = tpm2_load_srk(tssContext, &h, auth, &pub, TPM_RH_ENDORSEMENT, + TPM2_SIGNING); + tpm2_flush_srk(tssContext, h); + if (rc) + goto out_delete; + + tpm2_get_hexname(hexname, &pub); + + if (namefile) { + rc = verify_hexname(namefile, hexname); + if (rc) + fprintf(stderr, "Error: signing EK failed name verification\n"); + } else { + printf("%s\n", hexname); + } + + if (file) + rc = write_pubkey(file, &pub.publicArea); + + out_delete: + TSS_Delete(tssContext); + out_rmdir: + if (dir) + rmdir(dir); + + if (rc) + exit(1); +} + +/* + * Try to find a template to construct the EK matching pkey + */ +static const unsigned char tcgPolicy[][SHA256_DIGEST_LENGTH] = { + /* Policy A - Low */ + { + 0x83, 0x71, 0x97, 0x67, 0x44, 0x84, 0xB3, 0xF8, + 0x1A, 0x90, 0xCC, 0x8D, 0x46, 0xA5, 0xD7, 0x24, + 0xFD, 0x52, 0xD7, 0x6E, 0x06, 0x52, 0x0B, 0x64, + 0xF2, 0xA1, 0xDA, 0x1B, 0x33, 0x14, 0x69, 0xAA, + }, + /* Policy B - High */ + { + 0xca, 0x3d, 0x0a, 0x99, 0xa2, 0xb9, 0x39, 0x06, + 0xf7, 0xa3, 0x34, 0x24, 0x14, 0xef, 0xcf, 0xb3, + 0xa3, 0x85, 0xd4, 0x4c, 0xd1, 0xfd, 0x45, 0x90, + 0x89, 0xd1, 0x9b, 0x50, 0x71, 0xc0, 0xb7, 0xa0, + }, + /* Policy C - B is OR of A and C */ + { + 0x37, 0x67, 0xe2, 0xed, 0xd4, 0x3f, 0xf4, 0x5a, + 0x3a, 0x7e, 0x1e, 0xae, 0xfc, 0xef, 0x78, 0x64, + 0x3d, 0xca, 0x96, 0x46, 0x32, 0xe7, 0xaa, 0xd8, + 0x2c, 0x67, 0x3a, 0x30, 0xd8, 0x63, 0x3f, 0xde, + }, +}; + +void get_template(EVP_PKEY *pkey, TPMT_PUBLIC *tmpl, int high) +{ + tmpl->nameAlg = TPM_ALG_SHA256; + VAL(tmpl->objectAttributes) = TPMA_OBJECT_FIXEDTPM | + TPMA_OBJECT_FIXEDPARENT | + TPMA_OBJECT_SENSITIVEDATAORIGIN | + TPMA_OBJECT_ADMINWITHPOLICY | + TPMA_OBJECT_RESTRICTED | + TPMA_OBJECT_DECRYPT; + if (high) + VAL(tmpl->objectAttributes) |= + TPMA_OBJECT_USERWITHAUTH; + VAL_T(tmpl->authPolicy, size) = sizeof(tcgPolicy[high]); + memcpy(&VAL_T(tmpl->authPolicy, buffer), tcgPolicy[high], + sizeof(tcgPolicy[high])); + switch (EVP_PKEY_id(pkey)) { + case EVP_PKEY_RSA: + tmpl->type = TPM_ALG_RSA; + tmpl->parameters.rsaDetail.symmetric.algorithm = TPM_ALG_AES; + tmpl->parameters.rsaDetail.symmetric.keyBits.aes = 128; + tmpl->parameters.rsaDetail.symmetric.mode.aes = TPM_ALG_CFB; + tmpl->parameters.rsaDetail.scheme.scheme = TPM_ALG_NULL; + tmpl->parameters.rsaDetail.scheme.details.anySig.hashAlg = 0; + tmpl->parameters.rsaDetail.keyBits = 2048; + tmpl->parameters.rsaDetail.exponent = 0; + if (high) { + VAL_T(tmpl->unique.rsa, size) = 0; + } else { + VAL_T(tmpl->unique.rsa, size) = 256; + memset(VAL_T(tmpl->unique.rsa, buffer), 0, 256); + } + break; + case EVP_PKEY_EC: + tmpl->type = TPM_ALG_ECC; + tmpl->parameters.eccDetail.symmetric.algorithm = TPM_ALG_AES; + tmpl->parameters.eccDetail.symmetric.keyBits.aes = 128; + tmpl->parameters.eccDetail.symmetric.mode.aes = TPM_ALG_CFB; + tmpl->parameters.eccDetail.scheme.scheme = TPM_ALG_NULL; + tmpl->parameters.eccDetail.scheme.details.anySig.hashAlg = 0; + tmpl->parameters.eccDetail.curveID = TPM_ECC_NIST_P256; + tmpl->parameters.eccDetail.kdf.scheme = TPM_ALG_NULL; + tmpl->parameters.eccDetail.kdf.details.mgf1.hashAlg = 0; + if (high) { + VAL_T(tmpl->unique.ecc.x, size) = 0; + VAL_T(tmpl->unique.ecc.y, size) = 0; + } else { + VAL_T(tmpl->unique.ecc.x, size) = 32; + memset(VAL_T(tmpl->unique.ecc.x, buffer), 0, 32); + VAL_T(tmpl->unique.ecc.y, size) = 32; + memset(VAL_T(tmpl->unique.ecc.y, buffer), 0, 32); + } + break; + default: + fprintf(stderr, "Unknown certificate key type\n"); + exit(1); + } +} + +int load_ek(TSS_CONTEXT *tssContext, TPM_HANDLE *h, int *highp, + const char *auth, EVP_PKEY *pkey) +{ + TPM2B_PUBLIC tmpl, target, pub; + TPM_RC rc; + int high; + + rc = openssl_to_tpm_public(&target, pkey); + + for (high = 0; high < 2; high++) { + get_template(pkey, &tmpl.publicArea, high); + + rc = tpm2_load_srk_tmpl(tssContext, h, auth, &tmpl, &pub, + TPM_RH_ENDORSEMENT); + if (rc) + return rc; + + if (target.publicArea.type == TPM_ALG_RSA && + memcmp(VAL_T(target.publicArea.unique.rsa, buffer), + VAL_T(pub.publicArea.unique.rsa, buffer), + VAL_T(target.publicArea.unique.rsa, size)) == 0) + break; + else if (target.publicArea.type == TPM_ALG_ECC && + memcmp(VAL_T(target.publicArea.unique.ecc.x, buffer), + VAL_T(pub.publicArea.unique.ecc.x, buffer), + VAL_T(target.publicArea.unique.ecc.x, size)) == 0 + && + memcmp(VAL_T(target.publicArea.unique.ecc.x, buffer), + VAL_T(pub.publicArea.unique.ecc.x, buffer), + VAL_T(target.publicArea.unique.ecc.x, size)) == 0) + break; + + tpm2_flush_srk(tssContext, *h); + *h = 0; + } + + if (*h == 0) { + fprintf(stderr, "Error: Can't find EK matching certificate\n"); + return TPM_RC_ASYMMETRIC; + } + *highp = high; + + return rc; +} + +void do_attest(const char *auth, const char *namefile, const char *file, + const char *certfile) +{ + const char *dir = tpm2_set_unique_tssdir(); + TSS_CONTEXT *tssContext; + BIO *bf; + X509 *x; + EVP_PKEY *pkey; + NAME_2B eksignname; + PRIVATE_2B private; + ENCRYPTED_SECRET_2B enc_secret; + uint8_t challenge[SHA256_DIGEST_LENGTH]; + TPM_HANDLE ek, eksign; + TPM_RC rc = NOT_TPM_ERROR; + TPM2B_PUBLIC pubeksign; + char hexname[MAX_HEXNAME]; + DIGEST_2B digest; + const int integrity_skip = SHA256_DIGEST_LENGTH + 2; + TPM_HANDLE policy; + BYTE *buf; + INT32 size; + UINT16 written = 0; + int high; + + bf = BIO_new_file(certfile, "r"); + if (!bf) + goto out; + + x = PEM_read_bio_X509(bf, NULL, NULL, NULL); + if (!x) { + BIO_reset(bf); + x = d2i_X509_bio(bf, NULL); + } + BIO_free(bf); + if (!x) { + X509_free(x); + goto out; + } + ERR_clear_error(); + pkey = X509_get_pubkey(x); + X509_free(x); + if (!pkey) + goto out; + + RAND_bytes(challenge, sizeof(challenge)); + + + rc = tpm2_create(&tssContext, dir); + if (rc) + goto out; + + rc = tpm2_load_srk(tssContext, &eksign, auth, &pubeksign, + TPM_RH_ENDORSEMENT, TPM2_SIGNING); + if (rc) + goto out; + + tpm2_ObjectPublic_GetName(&eksignname, &pubeksign.publicArea); + + if (namefile) { + bin2hex(hexname, (unsigned char *)eksignname.name, + eksignname.size); + rc = verify_hexname(namefile, hexname); + if (rc) { + fprintf(stderr, "Error: signing EK failed name verification\n"); + goto out_free_eksign; + } + } + + /* run MakeCredential using just openssl */ + memcpy(digest.buffer, challenge, sizeof(challenge)); + digest.size = sizeof(challenge); + size = digest.size + 2; /* size of marshalled digest */ + private.size = size + integrity_skip; + buf = &private.buffer[integrity_skip]; + TSS_TPM2B_DIGEST_Marshal((TPM2B_DIGEST *)&digest, &written, + &buf, &size); + rc = tpm2_hmacwrap(pkey, &eksignname, "IDENTITY", &private, &enc_secret); + if (rc) + goto out_free_eksign; + + rc = load_ek(tssContext, &ek, &high, auth, pkey); + if (rc) + goto out_free_eksign; + + /* now we have the EK, we can only use it with a policy */ + + rc = tpm2_get_session_handle(tssContext, &policy, 0, TPM_SE_POLICY, + TPM_ALG_SHA256); + if (rc) + goto out_free_ek; + + /* + * two different policies but amounting to the same thing + * + * low is policy A which is PolicySecret on the endorsement + * hierarchy with a zero size policyRef. + * + * High is the PolicyOR of policy A (which we should satisfy) + * and policyC (which we don't bother with because it's not + * supported by all TPMs). + */ + digest.size = 0; /* empty policyRef */ + rc = tpm2_PolicySecret(tssContext, TPM_RH_ENDORSEMENT, policy, + &digest, auth); + if (rc) { + tpm2_error(rc, "tpm2_PolicySecret"); + tpm2_FlushContext(tssContext, policy); + goto out_free_ek; + } + + if (high) { + /* high is PolicyOR of PolicyA and PolicyC */ + TPML_DIGEST digests; + + digests.count = 2; + /* PolicyA = tcgPolicy[0] */ + VAL_T(digests.digests[0], size) = sizeof(tcgPolicy[0]); + memcpy(VAL_T(digests.digests[0], buffer), tcgPolicy[0], + VAL_T(digests.digests[0], size)); + /* PolicyC = tcgPolicy[2] */ + VAL_T(digests.digests[1], size) = sizeof(tcgPolicy[2]); + memcpy(VAL_T(digests.digests[1], buffer), tcgPolicy[2], + VAL_T(digests.digests[1], size)); + + rc = tpm2_PolicyOR(tssContext, policy, &digests); + if (rc) { + tpm2_error(rc, "tpm2_PolicyOR"); + tpm2_FlushContext(tssContext, policy); + goto out_free_ek; + } + } + + rc = tpm2_ActivateCredential(tssContext, eksign, ek, + (ID_OBJECT_2B *)&private, &enc_secret, + &digest, policy); + if (rc) { + tpm2_error(rc, "ActivateCredential"); + tpm2_FlushContext(tssContext, policy); + goto out_free_ek; + } + + if (memcmp(digest.buffer, challenge, sizeof(challenge)) != 0) { + fprintf(stderr, "Error: ActivateCredential returned incorrect challenge\n"); + goto out_free_ek; + } + + rc = 0; + printf("Attestation of signing EK successful\n"); + + if (file) + rc = write_pubkey(file, &pubeksign.publicArea); + + out_free_ek: + tpm2_flush_srk(tssContext, ek); + out_free_eksign: + tpm2_flush_srk(tssContext, eksign); + + TSS_Delete(tssContext); + + out: + if (dir) + rmdir(dir); + + if (ERR_peek_error()) { + rc = NOT_TPM_ERROR; + ERR_print_errors_fp(stderr); + } + if (rc) + exit(1); +} + +int main(int argc, char **argv) +{ + char *auth = NULL, *pass = NULL; + char *file = NULL, *namefile = NULL; + char *handle_str = NULL, *certfile = NULL; + int ek = 0, outname = 0; + TPM_HANDLE handle; + const int max_auth_size = 128; +#define ATTEST (certfile ? 1 : 0) +#define CERTIFY (handle_str ? 1 : 0) + + + while (1) { + int option_index = 0, c; + + c = getopt_long(argc, argv, "ak:EA:C:n:f:o", + long_options, &option_index); + if (c == -1) + break; + + switch (c) { + case 'a': + auth = malloc(max_auth_size + 1); + break; + case 'k': + pass = optarg; + if (strlen(pass) > max_auth_size) { + fprintf(stderr, "password is too long\n"); + exit(1); + } + break; + case 'E': + ek = 1; + break; + case 'A': + certfile = optarg; + break; + case 'C': + handle_str = optarg; + break; + case 'n': + namefile = optarg; + break; + case 'f': + file = optarg; + break; + case 'h': + usage(argv[0]); + break; + case 'o': + outname = 1; + break; + default: + printf("Unknown option '%c'\n", c); + usage(argv[0]); + break; + } + } + + if (optind < argc - 1 || ((ek || ATTEST) && optind != argc)) { + printf("Unexpected additional arguments\n"); + usage(argv[0]); + } + + if (ek + ATTEST + CERTIFY > 1) { + fprintf(stderr, "only one of --ek, --attest or --certify may be specified\n"); + exit(1); + } else if (ek + ATTEST + CERTIFY == 0) { + fprintf(stderr, "at least one of --ek, --attest or --certify must be specified\n"); + exit(1); + } + + if (auth) { + if (pass) + strcpy(auth, pass); + else + EVP_read_pw_string(auth, max_auth_size, + "Enter EK hierarchy authority: ", 0); + } + + if (ek) { + do_ek(auth, namefile, file); + } else if (certfile) { + do_attest(auth, namefile, file, certfile); + } else if (handle_str) { + const char *handlename = NULL; + + handle = tpm2_get_parent_ext(handle_str); + if (!handle) { + fprintf(stderr, "Invalid handle for certification\n"); + exit(1); + } + + if (optind == argc - 1) + handlename = argv[argc - 1]; + do_certify(auth, handle, namefile, file, handlename, outname); + } +} From patchwork Fri Aug 2 20:26:05 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: James Bottomley X-Patchwork-Id: 13751968 Received: from bedivere.hansenpartnership.com (bedivere.hansenpartnership.com [96.44.175.130]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id BF98733DF for ; Fri, 2 Aug 2024 20:27:35 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=96.44.175.130 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1722630457; cv=none; b=Bk6EpMX5mZM7Ewjx+5u1tw8X+h/EUa2JQrCbipOkZ/w1/CtTEkDBjLPFFob3DZnQiQWJW/rJhAhVKgMDPyVzvGZZlWgN9yBxgHkvhsgeLhk0Sa+i7PSBHQze7ba3T+p7oBf2/vzgvJdFHKz22GftxWlzAxhZJditaDOiUosPock= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1722630457; c=relaxed/simple; bh=cU7MirEjue3zg6BCHr7QHRptOhzsj5tQgKiZMt610y4=; h=From:To:Cc:Subject:Date:Message-Id:In-Reply-To:References: MIME-Version; b=H8oGppv9UV5rQV6VOoHVGINkcttlHnedfPqhViBSp9uPNxe/1vAx28yet5nQKtgdawlp9clbpzlc7GOm27CR7zMHLS9WFvybkJp1YICI5VmzOS4N7t1D3wvxynncYN/azr3iDAuT5RMMRFOR/9wWwfGEbS2NZVLV8E3BQEPTa9w= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=HansenPartnership.com; spf=pass smtp.mailfrom=HansenPartnership.com; dkim=pass (1024-bit key) header.d=hansenpartnership.com header.i=@hansenpartnership.com header.b=dpzEChRN; arc=none smtp.client-ip=96.44.175.130 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=HansenPartnership.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=HansenPartnership.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (1024-bit key) header.d=hansenpartnership.com header.i=@hansenpartnership.com header.b="dpzEChRN" DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=hansenpartnership.com; s=20151216; t=1722630455; bh=cU7MirEjue3zg6BCHr7QHRptOhzsj5tQgKiZMt610y4=; h=From:To:Subject:Date:Message-Id:In-Reply-To:References:From; b=dpzEChRNgTYcYPduyzX/fPscWYDlx15bCnemXmAujDg2ZPZBI7wLhBVXiVwBy+d0H VJZNJFmLTnrHq0M5H4u3t/TLw3qXqVMK6ns+KA+82OzrScjCa83dAjA8+ivu0w9WBc f8XuLGruTXBosQbKDdkhskqKobWFBQNXEMQh3+yI= Received: from localhost (localhost [127.0.0.1]) by bedivere.hansenpartnership.com (Postfix) with ESMTP id 38E2D1286A6B; Fri, 02 Aug 2024 16:27:35 -0400 (EDT) Received: from bedivere.hansenpartnership.com ([127.0.0.1]) by localhost (bedivere.hansenpartnership.com [127.0.0.1]) (amavis, port 10024) with ESMTP id pmEJ-w4RAkkr; Fri, 2 Aug 2024 16:27:35 -0400 (EDT) Received: from lingrow.int.hansenpartnership.com (unknown [153.66.160.227]) by bedivere.hansenpartnership.com (Postfix) with ESMTP id 990CB12860B6; Fri, 02 Aug 2024 16:27:34 -0400 (EDT) From: James Bottomley To: openssl-tpm2-engine@groups.io Cc: linux-integrity@vger.kernel.org, Jarkko Sakkinen Subject: [PATCH 7/8] attest_tpm2_primary: add man page Date: Fri, 2 Aug 2024 16:26:05 -0400 Message-Id: <20240802202606.12767-8-James.Bottomley@HansenPartnership.com> X-Mailer: git-send-email 2.35.3 In-Reply-To: <20240802202606.12767-1-James.Bottomley@HansenPartnership.com> References: <20240802202606.12767-1-James.Bottomley@HansenPartnership.com> Precedence: bulk X-Mailing-List: linux-integrity@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Signed-off-by: James Bottomley --- src/tools/Makefile.am | 5 +- src/tools/attest_tpm2_primary.1.in | 103 +++++++++++++++++++++++++++++ 2 files changed, 106 insertions(+), 2 deletions(-) create mode 100644 src/tools/attest_tpm2_primary.1.in diff --git a/src/tools/Makefile.am b/src/tools/Makefile.am index 7cca442..3012411 100644 --- a/src/tools/Makefile.am +++ b/src/tools/Makefile.am @@ -1,9 +1,10 @@ if NATIVE_BUILD EXTRA_DIST = create_tpm2_key.1 load_tpm2_key.1 seal_tpm2_data.1 \ - unseal_tpm2_data.1 signed_tpm2_policy.1 openssl_tpm2_engine.7 + unseal_tpm2_data.1 signed_tpm2_policy.1 openssl_tpm2_engine.7 \ + attest_tpm2_primary.1 man1_MANS = create_tpm2_key.1 load_tpm2_key.1 seal_tpm2_data.1 \ - unseal_tpm2_data.1 signed_tpm2_policy.1 + unseal_tpm2_data.1 signed_tpm2_policy.1 attest_tpm2_primary.1 man7_MANS = openssl_tpm2_engine.7 CLEANFILES = $(man1_MANS) diff --git a/src/tools/attest_tpm2_primary.1.in b/src/tools/attest_tpm2_primary.1.in new file mode 100644 index 0000000..59476f7 --- /dev/null +++ b/src/tools/attest_tpm2_primary.1.in @@ -0,0 +1,103 @@ +[name] +attest_tpm2_primary - perform certification and attestation operations for primary keys + +[description] + +TPMs have a complex set of commands for verifying primary keys. Any +TPM created signing key can be used to produce a "certification" of +another key (a signed proof that key is present in the TPM). However, +the way this signing key is generated from a TPM X.509 certificate +involves a complicated challenge/response round trip. This tool is +designed to present a simple way to perform the mechanics of these +commands. + +[threat model] + +TPMs are vulnerable to man in the middle type attacks known as +interposer attacks. The first line of defence against them is to use +TPM sessions for encryption and HMAC checking. However, even after +this is done, several other possible attacks remain including a reset +based attack and a public key deception attack. For more details see +the Linux Kernel TPM security document: + +https://docs.kernel.org/security/tpm/tpm-security.html + +Public key deception is a problem because when salting sessions most +TPM applications simply ask the TPM for a public key to encrypt the +salt to. So, if the interposer returns a key of its choosing, to +which it has the private part, it can intercept and decrypt the +session salt (and re-encrypt it with the correct key to pass on to the +underlying TPM), significantly reducing or eliminating the security +provided by sessions. The solution to this problem is to verify the +TPM provided key before it is used. + +[Attestation Keys] + +The original design of the TPM was to derive many disposable +attestation keys (AKs) to frustrate tracking when used online. This +scheme involved a trusted PrivacyCA which would take the TPM EK, +certificate and Attestation Key and return an Attestation Key +Certificate if it all checked out. The way this worked is that the +PrivacyCA would construct a packet that could only be decrypted by a +TPM2_ActivateCredential command, which involved a decryption operation +that would only succeed if the TPM possessed the private parts of both +the EK and the AK. If this succeeded, the TPM could return the +decrypted challenge to the PrivacyCA which would then issue the +certificate. + +Unfortunately, no PrivacyCA was ever stood up and the threat model +above really requires us to verify the TPM locally (so no privacy +issues are involved). The quick fix is to get the TPM to derive a +signing EK key and attest it once with the TPMs EK certificate using +the MakeCredential/ActivateCredential round trip locally. + +Ideally the name (unique hash) of this signing key should be +permanently stored in the filesystem, say at /etc/eksign.name for use +across boots. Since this signing key is derived from the endorsement +seed, which never changes even across TPM ownership changes it should +be stable. + +For TPMs which don't have attestation certificates, this key should be +collected when a laptop is first powered on with: + + $ attest_tpm2_primary --eksign > /etc/eksign.name + +Which will derive the signing key and output it's name. + +If you do have an attestation certificate for your TPM, you should +verify this signing key using the MakeCredential/ActivateCredential +sequence thus: + + $ attest_tpm2_primary --attest tpm-certificate.crt \\ + --name /etc/eksign.name + +You should also verify tpm-certificate.crt chains back to the +manufacturer. + +[kernel TPM verification] + +From version 6.10 onward, the Linux kernel uses sessions encrypted to +the TPM NULL key to defeat interposer reset attacks. Since the kernel +exports the name of the NULL key it found, you can certify this key +against your signing EK on every boot to be sure of the fidelity of +the boot. + + $ attest_tpm2_primary --certify null --name /etc/eksign.name \\ + /sys/class/tpm/tpm0/null_name + +Which can be done via a systemd or other init system script. + +[Secure Import key] + +For importable keys and sealed objects, you need to be completely sure +that the parent public key is correct. Since most objects are stored +in the owner hierarchy under the Storage Root Key (SRK), you can +generate a verified public key to give out as an import key using + + $ attest_tpm2_primary --certify --owner --name /etc/eksign.name \\ + --file srk.pub + +Which will generate a PEM public key corresponding to the storage root +only if the public part of the storage key can be certified against +the signing EK, which ensures an interposer didn't give you the wrong +public key to use for import. From patchwork Fri Aug 2 20:26:06 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: James Bottomley X-Patchwork-Id: 13751969 Received: from bedivere.hansenpartnership.com (bedivere.hansenpartnership.com [96.44.175.130]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 103BA335C0 for ; Fri, 2 Aug 2024 20:27:36 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=96.44.175.130 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1722630458; cv=none; b=LLlxnj0+WDcj7k+ZFGqsnLCZY/KsE/SUM8u8tf0xJ9FAmetAhNYiV8rmdwnZXqzdwsOHD6bub7wwSGBnOnBFLdYRas55qexdliLvzfEb6IfPHIWurbq8gUxuaoUxNp4IUN4HBd6wNNVgtAw0lvn+oX1grzomt31iHyeAz+dWubQ= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1722630458; c=relaxed/simple; bh=ByhhAf6fSfJ3HhoOdGTjoMruS4DwqOoGivFFdWqOKaQ=; h=From:To:Cc:Subject:Date:Message-Id:In-Reply-To:References: MIME-Version; b=dfDImUmu3kC9jW4BUeBJtHpbGjV/zwfvGF61xGAm0vl7Z1SwffwsRQKW5SQ1FKVK2uC+9JTvjXsrrgcjuiU9Oz9/VGnvype/1ZbjUJQBW7SSXsI01k9iulq60IwbEfNYKDc1DGRzuA2SGDaH12vQEP5jHakmAuVDufl/cS4QfEk= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=HansenPartnership.com; spf=pass smtp.mailfrom=HansenPartnership.com; dkim=pass (1024-bit key) header.d=hansenpartnership.com header.i=@hansenpartnership.com header.b=iigZhOXW; arc=none smtp.client-ip=96.44.175.130 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=HansenPartnership.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=HansenPartnership.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (1024-bit key) header.d=hansenpartnership.com header.i=@hansenpartnership.com header.b="iigZhOXW" DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=hansenpartnership.com; s=20151216; t=1722630456; bh=ByhhAf6fSfJ3HhoOdGTjoMruS4DwqOoGivFFdWqOKaQ=; h=From:To:Subject:Date:Message-Id:In-Reply-To:References:From; b=iigZhOXWBm50F3/G17zSUfPzKkdgVc2SYGyerBWi9452SVnvGnw+zfNMf8oxJ7eqj +dAwPI2dkQakGA+fYjP/2QsXyvhKTN8LEvkZV6wXvmNQn0uS+O4KaJJZ78oZyGkNj6 N41z//d/rxyH017tX+s+TRkdxvhPQzfZtq1CCvxc= Received: from localhost (localhost [127.0.0.1]) by bedivere.hansenpartnership.com (Postfix) with ESMTP id 595501286AF9; Fri, 02 Aug 2024 16:27:36 -0400 (EDT) Received: from bedivere.hansenpartnership.com ([127.0.0.1]) by localhost (bedivere.hansenpartnership.com [127.0.0.1]) (amavis, port 10024) with ESMTP id X6gLxksNq6Qe; Fri, 2 Aug 2024 16:27:36 -0400 (EDT) Received: from lingrow.int.hansenpartnership.com (unknown [153.66.160.227]) by bedivere.hansenpartnership.com (Postfix) with ESMTP id D513812860B6; Fri, 02 Aug 2024 16:27:35 -0400 (EDT) From: James Bottomley To: openssl-tpm2-engine@groups.io Cc: linux-integrity@vger.kernel.org, Jarkko Sakkinen Subject: [PATCH 8/8] tests: add tests for attest_tpm2_primary Date: Fri, 2 Aug 2024 16:26:06 -0400 Message-Id: <20240802202606.12767-9-James.Bottomley@HansenPartnership.com> X-Mailer: git-send-email 2.35.3 In-Reply-To: <20240802202606.12767-1-James.Bottomley@HansenPartnership.com> References: <20240802202606.12767-1-James.Bottomley@HansenPartnership.com> Precedence: bulk X-Mailing-List: linux-integrity@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Signed-off-by: James Bottomley --- tests/attestation.sh | 30 ++++++++++++++++++++++++++++++ tests/check_importable.sh | 3 +-- tests/engine/Makefile.am | 3 ++- tests/provider/Makefile.am | 3 ++- tests/seal_unseal.sh | 3 +-- tests/start_sw_tpm.sh | 2 ++ 6 files changed, 38 insertions(+), 6 deletions(-) create mode 100755 tests/attestation.sh diff --git a/tests/attestation.sh b/tests/attestation.sh new file mode 100755 index 0000000..bd927fa --- /dev/null +++ b/tests/attestation.sh @@ -0,0 +1,30 @@ +#!/bin/bash +set -x + +## +# We already created eksign.name and null.name, so check them first +## +${bindir}/attest_tpm2_primary --eksign --name ${testdir}/eksign.name || exit 1 +${bindir}/attest_tpm2_primary --eksign --name ${testdir}/null.name && exit 1 +${bindir}/attest_tpm2_primary --certify null --name ${testdir}/eksign.name ${testdir}/null.name || exit 1 +## +# Run through certification of all the keys (already done null above +## +for h in owner endorsement platform; do + rm -f tmp.name + ${bindir}/attest_tpm2_primary -C ${h} -n ${testdir}/eksign.name -o > tmp.name || exit 1 + ${bindir}/attest_tpm2_primary -C ${h} -n ${testdir}/eksign.name tmp.name || exit 1 + ${bindir}/attest_tpm2_primary -C ${h} -n ${testdir}/eksign.name null.name && exit 1 +done +## +# attestation tests +# 1. create both P-256 and RSA2048 attestation certs +## +openssl genrsa 2048 > ca.key || exit 1 +# several EK templates exist, so try RSA and EC for each +for high in "" "-high"; do + for alg in "-rsa 2048" "-ecc nistp256"; do + tsscreateekcert ${high} ${alg} -cakey ca.key -of cert.der || exit 1 + ${bindir}/attest_tpm2_primary --attest cert.der --name ${testdir}/eksign.name || exit 1 + done +done diff --git a/tests/check_importable.sh b/tests/check_importable.sh index eeafe03..ee84f16 100755 --- a/tests/check_importable.sh +++ b/tests/check_importable.sh @@ -2,8 +2,7 @@ # export the parent key as a EC and RSA public key -prim=$(tsscreateprimary -ecc nistp256 -hi o -opem srk.pub | sed 's/Handle //') || exit 1 -tssflushcontext -ha ${prim} || exit 1 +${bindir}/attest_tpm2_primary --certify owner --name ${testdir}/eksign.name --file srk.pub || exit 1 prim=$(tsscreateprimary -rsa 2048 -hi o -opem srkrsa.pub | sed 's/Handle //') || exit 1 tssflushcontext -ha ${prim} || exit 1 diff --git a/tests/engine/Makefile.am b/tests/engine/Makefile.am index ec6f321..7bade2b 100644 --- a/tests/engine/Makefile.am +++ b/tests/engine/Makefile.am @@ -30,6 +30,7 @@ TESTS += ../check_curves.sh \ ../check_locality.sh \ ../check_secret_policies.sh \ ../dynamic_engine.sh \ + ../attestation.sh \ ../stop_sw_tpm.sh fail_connect.sh: tpm_server_found @@ -53,6 +54,6 @@ AM_TESTS_ENVIRONMENT = TPM_INTERFACE_TYPE=socsim; export TPM_INTERFACE_TYPE; \ TEST_EXTENSIONS = .sh -CLEANFILES = key*.tpm key*.pub key*.priv tmp.* NVChip h*.bin key*.der seal.* fifo tss2.* +CLEANFILES = key*.tpm key*.pub key*.priv tmp.* NVChip h*.bin key*.der seal.* fifo tss2.* *.name clean-local: rm -fr testdir diff --git a/tests/provider/Makefile.am b/tests/provider/Makefile.am index 1080036..05bbee1 100644 --- a/tests/provider/Makefile.am +++ b/tests/provider/Makefile.am @@ -31,6 +31,7 @@ TESTS += ../check_curves.sh \ ../check_signed_policies.sh \ ../check_locality.sh \ ../check_secret_policies.sh \ + ../attestation.sh \ ../stop_sw_tpm.sh fail_connect.sh: tpm_server_found @@ -56,7 +57,7 @@ endif TEST_EXTENSIONS = .sh -CLEANFILES = key*.tpm key*.pub key*.priv tmp.* NVChip h*.bin key*.der seal.* fifo tss2.* +CLEANFILES = key*.tpm key*.pub key*.priv tmp.* NVChip h*.bin key*.der seal.* fifo tss2.* *.name clean-local: rm -fr testdir diff --git a/tests/seal_unseal.sh b/tests/seal_unseal.sh index 6d05a4c..2df3aa8 100755 --- a/tests/seal_unseal.sh +++ b/tests/seal_unseal.sh @@ -48,8 +48,7 @@ for n in sha1 sha256 sha384; do else POLICYFILE="${testdir}/policies/policy_pcr${n}.txt" fi - prim=$(tsscreateprimary -hi o -st -ecc nistp256 -opem srk.pub | sed 's/Handle //') || exit 1 - tssflushcontext -ha $prim + ${bindir}/attest_tpm2_primary -C owner -n ${testdir}/eksign.name -f srk.pub || exit 1 TPM_INTERFACE_TYPE= echo $DATA | ${bindir}/seal_tpm2_data -n ${n} -a -k ${AUTH} --import srk.pub seal.tpm || exit 1; ${bindir}/unseal_tpm2_data -k ${AUTH} seal.tpm | grep -q "${DATA}" || exit 1; rm seal.tpm diff --git a/tests/start_sw_tpm.sh b/tests/start_sw_tpm.sh index 5f249a5..1e0e4db 100755 --- a/tests/start_sw_tpm.sh +++ b/tests/start_sw_tpm.sh @@ -56,3 +56,5 @@ key=$(tsscreateprimary -hi o -st -rsa|sed 's/Handle //') && \ tssevictcontrol -hi o -ho ${key} -hp 81000001 && \ tssflushcontext -ha ${key} +${bindir}/attest_tpm2_primary --ek > ${testdir}/eksign.name || exit 1 +${bindir}/attest_tpm2_primary --certify null --outname --name ${testdir}/eksign.name > ${testdir}/null.name || exit 1