From patchwork Fri May 24 13:04:57 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: James Bottomley X-Patchwork-Id: 13673150 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 346DC86263; Fri, 24 May 2024 13:06:20 +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=1716555982; cv=none; b=hC4T0KXCL5gT4IVslhLbkFDGE7OxCLHGND6ZQu4VTx0WnItZUFvcTmnfjPFwBpxBXB1AzV70oVQbTgbTEKU/fanuaaKrp+T82hUGohyqGbPp9ALQE7L+nhNRpTZbPSo2z+0+nF9uVUFHZrc6SVFBpwACiwiSz74s/986InTVyTI= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1716555982; c=relaxed/simple; bh=WuHncCS8nw5ODW9EEIWujAE9H53k3f1JcybWYCKQKyk=; h=From:To:Cc:Subject:Date:Message-Id:In-Reply-To:References: MIME-Version; b=sCkkbFuFAFPs7yjPB2bgL6MiIfUcgCnS7ccLQIHpmHchaXiOnzhcUG7IkX7iK3Y/WERMfG2GW+KtfeODFGQSgt5V3TKh3JDA0AqBqPn/yZ2dDpKeiYgOGZ4yBm0bL6H2i4b5LNzSiDqMQGv0O67rdfx/s88MwffoeO2BV1zBOu8= 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=XIZLUM4J; 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="XIZLUM4J" DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=hansenpartnership.com; s=20151216; t=1716555980; bh=WuHncCS8nw5ODW9EEIWujAE9H53k3f1JcybWYCKQKyk=; h=From:To:Subject:Date:Message-Id:In-Reply-To:References:From; b=XIZLUM4J7LRFY8muOIOruQFgy+aXJa+t32F6zfO/bEztZbUkk25QTZvgO+dsS08GD TwM3Ob/bcUFUxSZ3JWxLTWPbDY82O51iBogevkLYMbD72qSm/7BOaNBL9dSk3nZlJ8 xiZP0bzjzsugnmVk22A9YocSXAl7APPIk2pjSbgw= Received: from localhost (localhost [127.0.0.1]) by bedivere.hansenpartnership.com (Postfix) with ESMTP id 877601287771; Fri, 24 May 2024 09:06:20 -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 06v4lgLpwuxK; Fri, 24 May 2024 09:06:20 -0400 (EDT) Received: from lingrow.int.hansenpartnership.com (unknown [153.66.160.227]) by bedivere.hansenpartnership.com (Postfix) with ESMTP id 10EA81280355; Fri, 24 May 2024 09:06:19 -0400 (EDT) From: James Bottomley To: linux-integrity@vger.kernel.org Cc: Jarkko Sakkinen , keyrings@vger.kernel.org Subject: [PATCH 4/6] KEYS: trusted: add ability to specify arbitrary policy Date: Fri, 24 May 2024 09:04:57 -0400 Message-Id: <20240524130459.21510-5-James.Bottomley@HansenPartnership.com> X-Mailer: git-send-email 2.35.3 In-Reply-To: <20240524130459.21510-1-James.Bottomley@HansenPartnership.com> References: <20240524130459.21510-1-James.Bottomley@HansenPartnership.com> Precedence: bulk X-Mailing-List: keyrings@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 This patch adds a policy= argument to key creation. The policy is the standard tss policymaker format and each separate policy line must have a newline after it. Thus to construct a policy requiring authorized value and pcr 16 locking using a sha256 hash, the policy (policy.txt) file would be two lines: 0000017F00000001000B03000001303095B49BE85E381E5B20E557E46363EF55B0F43B132C2D8E3DE9AC436656F2 0000016b This can be inserted into the key with keyctl add trusted kmk "new 32 policy=`cat policy.txt` keyhandle=0x81000001 hash=sha256" @u Note that although a few policies work like this, most require special handling which must be added to the kernel policy construction routine. Signed-off-by: James Bottomley --- .../security/keys/trusted-encrypted.rst | 17 +++++- security/keys/trusted-keys/tpm2-policy.c | 53 +++++++++++++++++++ security/keys/trusted-keys/tpm2-policy.h | 5 ++ security/keys/trusted-keys/trusted_tpm1.c | 15 ++++++ 4 files changed, 89 insertions(+), 1 deletion(-) diff --git a/Documentation/security/keys/trusted-encrypted.rst b/Documentation/security/keys/trusted-encrypted.rst index c37c08956ec1..fbb41cf16f30 100644 --- a/Documentation/security/keys/trusted-encrypted.rst +++ b/Documentation/security/keys/trusted-encrypted.rst @@ -233,6 +233,9 @@ Usage:: policyhandle= handle to an authorization policy session that defines the same policy and with the same hash algorithm as was used to seal the key. + policy= specify an arbitrary set of policies. These must + be in policymaker format with each separate + policy line newline terminated. "keyctl print" returns an ascii hex copy of the sealed key, which is in standard TPM_STORED_DATA format. The key length for new keys are always in bytes. @@ -377,6 +380,19 @@ the sha1 pcr16 bank you'd say:: because the trailing hash is the sha256sum of 20 zero bytes. +You can also specify arbitrary policy in policymaker format, so a two +value policy (the pcr example above and authvalue) would look like +this in policymaker format:: + + 0000017F000000010004030000016768033e216468247bd031a0a2d9876d79818f8f + 0000016b + +This can be placed in a file (say policy.txt) and then added to the key as:: + + $ keyctl add trusted kmk "new 32 keyhandle=0x81000001 hash=sha1 policy=`cat policy.txt`" @u + +The newlines in the file policy.txt will be automatically processed. + Reseal (TPM specific) a trusted key under new PCR values:: $ keyctl update 268728824 "update pcrinfo=`cat pcr.blob`" @@ -447,7 +463,6 @@ Another new format 'enc32' has been defined in order to support encrypted keys with payload size of 32 bytes. This will initially be used for nvdimm security but may expand to other usages that require 32 bytes payload. - TPM 2.0 ASN.1 Key Format ------------------------ diff --git a/security/keys/trusted-keys/tpm2-policy.c b/security/keys/trusted-keys/tpm2-policy.c index 8c3a09762c10..a731c10d9bba 100644 --- a/security/keys/trusted-keys/tpm2-policy.c +++ b/security/keys/trusted-keys/tpm2-policy.c @@ -323,3 +323,56 @@ int tpm2_get_policy_session(struct tpm_chip *chip, struct tpm2_policies *pols) return 0; } + +int tpm2_parse_policies(struct tpm2_policies **ppols, char *str) +{ + struct tpm2_policies *pols; + char *p; + u8 *ptr; + int i = 0, left = PAGE_SIZE, res; + + pols = kmalloc(left, GFP_KERNEL); + if (!pols) + return -ENOMEM; + + ptr = (u8 *)(pols + 1); + left -= ptr - (u8 *)pols; + + while ((p = strsep(&str, "\n"))) { + if (*p == '\0' || *p == '\n') + continue; + + pols->len[i] = strlen(p)/2; + if (pols->len[i] > left) { + res = -E2BIG; + goto err; + } + + res = hex2bin(ptr, p, pols->len[i]); + if (res) + goto err; + + /* get command code and skip past */ + pols->code[i] = get_unaligned_be32(ptr); + pols->policies[i] = ptr + 4; + ptr += pols->len[i]; + left -= pols->len[i]; + pols->len[i] -= 4; + + /* + * FIXME: this does leave the code embedded in dead + * regions of the memory, but it's easier than + * hexdumping to a temporary or copying over + */ + i++; + } + + pols->count = i; + *ppols = pols; + + return 0; + + err: + kfree(pols); + return res; +} diff --git a/security/keys/trusted-keys/tpm2-policy.h b/security/keys/trusted-keys/tpm2-policy.h index b20e9c3e2f06..8ddf235b3fec 100644 --- a/security/keys/trusted-keys/tpm2-policy.h +++ b/security/keys/trusted-keys/tpm2-policy.h @@ -28,6 +28,7 @@ int tpm2_generate_policy_digest(struct tpm2_policies *pols, u32 hash, u8 *policydigest, u32 *plen); int tpm2_encode_policy(struct tpm2_policies *pols, u8 **data, u32 *len); int tpm2_get_policy_session(struct tpm_chip *chip, struct tpm2_policies *pols); +int tpm2_parse_policies(struct tpm2_policies **ppols, char *str); #else static inline int tpm2_key_policy_process(struct tpm2_key_context *ctx, struct trusted_key_payload *payload) @@ -50,4 +51,8 @@ static inline int tpm2_get_policy_session(struct tpm_chip *chip, { return -EINVAL; } +static inline int tpm2_parse_policies(struct tpm2_policies **ppols, char *str) +{ + return -EINVAL; +} #endif diff --git a/security/keys/trusted-keys/trusted_tpm1.c b/security/keys/trusted-keys/trusted_tpm1.c index 89c9798d1800..4dcc1373dd05 100644 --- a/security/keys/trusted-keys/trusted_tpm1.c +++ b/security/keys/trusted-keys/trusted_tpm1.c @@ -22,6 +22,8 @@ #include +#include "tpm2-policy.h" + static const char hmac_alg[] = "hmac(sha1)"; static const char hash_alg[] = "sha1"; static struct tpm_chip *chip; @@ -724,6 +726,7 @@ enum { Opt_hash, Opt_policydigest, Opt_policyhandle, + Opt_policy, }; static const match_table_t key_tokens = { @@ -736,6 +739,7 @@ static const match_table_t key_tokens = { {Opt_hash, "hash=%s"}, {Opt_policydigest, "policydigest=%s"}, {Opt_policyhandle, "policyhandle=%s"}, + {Opt_policy, "policy=%s"}, {Opt_err, NULL} }; @@ -869,6 +873,17 @@ static int getoptions(char *c, struct trusted_key_payload *pay, return -EINVAL; opt->policyhandle = handle; break; + + case Opt_policy: + if (pay->policies) + return -EINVAL; + if (!tpm2) + return -EINVAL; + res = tpm2_parse_policies(&pay->policies, args[0].from); + if (res) + return res; + break; + default: return -EINVAL; }