Received: by 2002:a05:6a10:a841:0:0:0:0 with SMTP id d1csp444608pxy; Wed, 21 Apr 2021 06:50:03 -0700 (PDT) X-Google-Smtp-Source: ABdhPJy7Op/3cGSbJtxlaCaPdRiHM7QgUQ+T96GMyahwW4NNyKrWdDzzZmvBTp06atnI5MwOLmh4 X-Received: by 2002:a17:906:4746:: with SMTP id j6mr33605584ejs.39.1619013003477; Wed, 21 Apr 2021 06:50:03 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1619013003; cv=none; d=google.com; s=arc-20160816; b=sezZMm8GVKgh+r47pWUlQ0XoFvYrpThjDT817txh6SddXL53M3Cg9mT7lhY6pnay2N 4kfwhm2zJ58K95k4T2OactKbyfW/orjkln3U2/G15vgzswaK5ANI5FcZF1BjoSfgO/p1 +T5QVUxYxOdd6H3q8b/e3r1y/JXL0t1whezMDlT/Kd8SKT3uPfI7aKWcnBb5BpB+ydYl vt9M+ZQ6YkrE83WLXkguarGo6DVjM5h33IzM1rI00l0Nik5cpqCBRPLn2vVozypcnovM kGtPiNagVhZlgpUXDlWsX4hS0TeIZJ6WPg4qmZ6OIK+5mcy5Zmxj2pqODvvacRjjPCfn yI/w== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=list-id:precedence:cc:to:subject:message-id:date:from:in-reply-to :references:mime-version:dkim-signature; bh=5vsFMFaKIMkhP70S7ONG1ckJYw2FgvZBNb6u59s1fGc=; b=mWpIi6Y3YBltKVRz3evRGPw7fqQzty5C5bFE124TiPmPSR6G1Ino922VA6zBWuFtvx MnEkkUudZuokpzBcKxtvL1bEy9bbGZnqySFgLjwOkqQ2oaQcFAOUMhyi2tXuPuJ1G1pe DhzPTI6Ta3gi6sqQBrorkcAKOvv5olbzx4VtXzkrzQyJ/e9pAYWdz4VHD4fVgN3Y443f DaJBtnr+/3XYwM+k53SO+cXes9Uk//QcAs+vWRV7HxuYMa7fhs0uSteToXpDWcn6AXBd pouxQ8Lyv9pEdiJrdxjlZpxKO1A7AbES9DNBsUcCACJyIOGPnB/Qj1BfARQpimbMy7NB oU9Q== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@linaro.org header.s=google header.b=ZBT06dLs; spf=pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 23.128.96.18 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=linaro.org Return-Path: Received: from vger.kernel.org (vger.kernel.org. [23.128.96.18]) by mx.google.com with ESMTP id b25si1849691eja.29.2021.04.21.06.49.39; Wed, 21 Apr 2021 06:50:03 -0700 (PDT) Received-SPF: pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 23.128.96.18 as permitted sender) client-ip=23.128.96.18; Authentication-Results: mx.google.com; dkim=pass header.i=@linaro.org header.s=google header.b=ZBT06dLs; spf=pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 23.128.96.18 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=linaro.org Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S238233AbhDULJK (ORCPT + 99 others); Wed, 21 Apr 2021 07:09:10 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:40962 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S235131AbhDULJB (ORCPT ); Wed, 21 Apr 2021 07:09:01 -0400 Received: from mail-lj1-x230.google.com (mail-lj1-x230.google.com [IPv6:2a00:1450:4864:20::230]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 9EBB0C06138A for ; Wed, 21 Apr 2021 04:08:26 -0700 (PDT) Received: by mail-lj1-x230.google.com with SMTP id u4so47215961ljo.6 for ; Wed, 21 Apr 2021 04:08:26 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linaro.org; s=google; h=mime-version:references:in-reply-to:from:date:message-id:subject:to :cc; bh=5vsFMFaKIMkhP70S7ONG1ckJYw2FgvZBNb6u59s1fGc=; b=ZBT06dLsvztfw1xjQmmB/pjvhgkf7DMWRfAgP5YYSnz2HDVhcMXMiNOAyBXCcOvoHa V0kTOSdtqSAGODZ0r0EZCgc6Z3dGLyQWzrN/d1oU1BQmVR0wIAUcPZVNIa8Af9j1FPYM ff+2+S64VEiFGOaBDRgn1ifYr0tUQy7DoZjcCO7OjYHB+8v5tfeiF2ddXgauIwV+uNQ4 rj1zLdAzdhSiJ40iHxbdOkQzvmD1ONghDlJzZ38ncJ/wqUjHrSUUeE0FpLhLP3aYZ23S ATZ5Qgm4/Rry1sJhqvHJ2wj4ouR72yFt8EkiAUtTZQkqxiweqcS7wbvYsQSiNviJUs5+ QJ+A== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:mime-version:references:in-reply-to:from:date :message-id:subject:to:cc; bh=5vsFMFaKIMkhP70S7ONG1ckJYw2FgvZBNb6u59s1fGc=; b=DsLwxCCR5GrFteuGY+evy7dkck/JHYmMDRhsUTiUXFE18T6d4SXZvsGtKH5ePwglBa fVX4yw64I7tDv32X8InL6v2L+uM9kRHzgVEUGd/d/loaYRJU51Si5xccMt7fhTLvRbCg A+idtCl5mnfPxolXe2VKyVugD1l3ZOaFqYj8HI5DNk/rheHg4Pjoz2SdAwDyvxKk6yPM RHufQvLesJwcMoKZuGcoTS31MP1VpeJ3TY0n9cCcDMC8Ei39UMGMEwjM/4psjZczI8Kz +W3JP5WYfCffFCPVJivC79QOF8M2GZJXQbK+EHV+8/MbXn8o9ANatI/OjtOposJ9emcj kbrg== X-Gm-Message-State: AOAM531AmFKvJzY4+DggsZHj+jutalo7IHpYLEFYZl45M36TLAS73fMM aH2b9kGo5QkGNRBoT5ofXF7i7m0zFGeh/4ct+LdfUA== X-Received: by 2002:a2e:9741:: with SMTP id f1mr7648316ljj.226.1619003304914; Wed, 21 Apr 2021 04:08:24 -0700 (PDT) MIME-Version: 1.0 References: <20210301131127.793707-1-sumit.garg@linaro.org> <20210301131127.793707-2-sumit.garg@linaro.org> <65dcc9fa28833e6beb1eadf98b0ed3402404d693.camel@linux.ibm.com> In-Reply-To: <65dcc9fa28833e6beb1eadf98b0ed3402404d693.camel@linux.ibm.com> From: Sumit Garg Date: Wed, 21 Apr 2021 16:38:13 +0530 Message-ID: Subject: Re: [PATCH v9 1/4] KEYS: trusted: Add generic trusted keys framework To: James Bottomley Cc: Jarkko Sakkinen , Mimi Zohar , David Howells , Jens Wiklander , Jonathan Corbet , James Morris , "Serge E. Hallyn" , Casey Schaufler , Janne Karhunen , Daniel Thompson , Markus Wamser , Luke Hinds , Elaine Palmer , Ahmad Fatoum , "open list:ASYMMETRIC KEYS" , linux-integrity , "open list:SECURITY SUBSYSTEM" , Linux Doc Mailing List , Linux Kernel Mailing List , linux-arm-kernel , op-tee@lists.trustedfirmware.org Content-Type: text/plain; charset="UTF-8" Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org Hi James, On Wed, 21 Apr 2021 at 04:47, James Bottomley wrote: > > On Mon, 2021-03-01 at 18:41 +0530, Sumit Garg wrote: > > Current trusted keys framework is tightly coupled to use TPM device > > as an underlying implementation which makes it difficult for > > implementations like Trusted Execution Environment (TEE) etc. to > > provide trusted keys support in case platform doesn't posses a TPM > > device. > > > > Add a generic trusted keys framework where underlying implementations > > can be easily plugged in. Create struct trusted_key_ops to achieve > > this, which contains necessary functions of a backend. > > > > Also, define a module parameter in order to select a particular trust > > source in case a platform support multiple trust sources. In case its > > not specified then implementation itetrates through trust sources > > list starting with TPM and assign the first trust source as a backend > > which has initiazed successfully during iteration. > > > > Note that current implementation only supports a single trust source > > at runtime which is either selectable at compile time or during boot > > via aforementioned module parameter. > > You never actually tested this, did you? I'm now getting EINVAL from > all the trusted TPM key operations because of this patch. > Unfortunately, I don't possess a development machine with a TPM device. So mine testing was entirely based on TEE as a backend which doesn't support any optional parameters. And that being the reason I didn't catch this issue at first instance. Is there any TPM emulation environment available that I can use for testing? > The reason is quite simple: this function: > > > index 000000000000..0db86b44605d > > --- /dev/null > > +++ b/security/keys/trusted-keys/trusted_core.c > [...] > > +static int datablob_parse(char *datablob, struct trusted_key_payload > > *p) > > +{ > > + substring_t args[MAX_OPT_ARGS]; > > + long keylen; > > + int ret = -EINVAL; > > + int key_cmd; > > + char *c; > > + > > + /* main command */ > > + c = strsep(&datablob, " \t"); > > Modifies its argument to consume tokens and separates them with NULL. > > so the arguments for > > keyctl add trusted kmk "new 34 keyhandle=0x81000001" > > Go into this function as > > datablob="new 34 keyhandle=0x81000001" > > After we leave it, it looks like > > datablob="new\034\0keyhandle=0x81000001" > > However here: > > > +static int trusted_instantiate(struct key *key, > > + struct key_preparsed_payload *prep) > > +{ > > + struct trusted_key_payload *payload = NULL; > > + size_t datalen = prep->datalen; > > + char *datablob; > > + int ret = 0; > > + int key_cmd; > > + size_t key_len; > > + > > + if (datalen <= 0 || datalen > 32767 || !prep->data) > > + return -EINVAL; > > + > > + datablob = kmalloc(datalen + 1, GFP_KERNEL); > > + if (!datablob) > > + return -ENOMEM; > > + memcpy(datablob, prep->data, datalen); > > + datablob[datalen] = '\0'; > > + > > + payload = trusted_payload_alloc(key); > > + if (!payload) { > > + ret = -ENOMEM; > > + goto out; > > + } > > + > > + key_cmd = datablob_parse(datablob, payload); > > + if (key_cmd < 0) { > > + ret = key_cmd; > > + goto out; > > + } > > + > > + dump_payload(payload); > > + > > + switch (key_cmd) { > > + case Opt_load: > > + ret = static_call(trusted_key_unseal)(payload, > > datablob); > > We're passing the unmodified > > datablob="new\034\0keyhandle=0x81000001" > > Into the tpm trusted_key_unseal function. However, it only sees "new" > and promply gives EINVAL because you've removed the ability to process > the new option from it. What should have happened is you should have > moved data blob up to passed the consumed tokens, so it actually reads > > datablob="keyhandle=0x81000001" > > However, to do that you'd have to have the updated pointer passed out > of your datablob_parse() above. Thanks for the detailed explanation. > > There's also a lost !tpm2 in the check for options->keyhandle, but I > suspect Jarkko lost that merging the two patches. I think what's below > fixes all of this, so if you can test it for trusted_tee, I'll package > it up as two separate patches fixing all of this. > Below fixes look good to me and I have tested them using TEE as a backend too. So feel free to add: Tested-by: Sumit Garg -Sumit > James > > --- > > diff --git a/security/keys/trusted-keys/trusted_core.c b/security/keys/trusted-keys/trusted_core.c > index ec3a066a4b42..7c636212429b 100644 > --- a/security/keys/trusted-keys/trusted_core.c > +++ b/security/keys/trusted-keys/trusted_core.c > @@ -62,7 +62,7 @@ static const match_table_t key_tokens = { > * > * On success returns 0, otherwise -EINVAL. > */ > -static int datablob_parse(char *datablob, struct trusted_key_payload *p) > +static int datablob_parse(char **datablob, struct trusted_key_payload *p) > { > substring_t args[MAX_OPT_ARGS]; > long keylen; > @@ -71,14 +71,14 @@ static int datablob_parse(char *datablob, struct trusted_key_payload *p) > char *c; > > /* main command */ > - c = strsep(&datablob, " \t"); > + c = strsep(datablob, " \t"); > if (!c) > return -EINVAL; > key_cmd = match_token(c, key_tokens, args); > switch (key_cmd) { > case Opt_new: > /* first argument is key size */ > - c = strsep(&datablob, " \t"); > + c = strsep(datablob, " \t"); > if (!c) > return -EINVAL; > ret = kstrtol(c, 10, &keylen); > @@ -89,7 +89,7 @@ static int datablob_parse(char *datablob, struct trusted_key_payload *p) > break; > case Opt_load: > /* first argument is sealed blob */ > - c = strsep(&datablob, " \t"); > + c = strsep(datablob, " \t"); > if (!c) > return -EINVAL; > p->blob_len = strlen(c) / 2; > @@ -138,7 +138,7 @@ static int trusted_instantiate(struct key *key, > { > struct trusted_key_payload *payload = NULL; > size_t datalen = prep->datalen; > - char *datablob; > + char *datablob, *orig_datablob; > int ret = 0; > int key_cmd; > size_t key_len; > @@ -146,7 +146,7 @@ static int trusted_instantiate(struct key *key, > if (datalen <= 0 || datalen > 32767 || !prep->data) > return -EINVAL; > > - datablob = kmalloc(datalen + 1, GFP_KERNEL); > + orig_datablob = datablob = kmalloc(datalen + 1, GFP_KERNEL); > if (!datablob) > return -ENOMEM; > memcpy(datablob, prep->data, datalen); > @@ -158,7 +158,7 @@ static int trusted_instantiate(struct key *key, > goto out; > } > > - key_cmd = datablob_parse(datablob, payload); > + key_cmd = datablob_parse(&datablob, payload); > if (key_cmd < 0) { > ret = key_cmd; > goto out; > @@ -194,7 +194,7 @@ static int trusted_instantiate(struct key *key, > ret = -EINVAL; > } > out: > - kfree_sensitive(datablob); > + kfree_sensitive(orig_datablob); > if (!ret) > rcu_assign_keypointer(key, payload); > else > @@ -218,7 +218,7 @@ static int trusted_update(struct key *key, struct key_preparsed_payload *prep) > struct trusted_key_payload *p; > struct trusted_key_payload *new_p; > size_t datalen = prep->datalen; > - char *datablob; > + char *datablob, *orig_datablob; > int ret = 0; > > if (key_is_negative(key)) > @@ -229,7 +229,7 @@ static int trusted_update(struct key *key, struct key_preparsed_payload *prep) > if (datalen <= 0 || datalen > 32767 || !prep->data) > return -EINVAL; > > - datablob = kmalloc(datalen + 1, GFP_KERNEL); > + orig_datablob = datablob = kmalloc(datalen + 1, GFP_KERNEL); > if (!datablob) > return -ENOMEM; > > @@ -241,7 +241,7 @@ static int trusted_update(struct key *key, struct key_preparsed_payload *prep) > > memcpy(datablob, prep->data, datalen); > datablob[datalen] = '\0'; > - ret = datablob_parse(datablob, new_p); > + ret = datablob_parse(&datablob, new_p); > if (ret != Opt_update) { > ret = -EINVAL; > kfree_sensitive(new_p); > @@ -265,7 +265,7 @@ static int trusted_update(struct key *key, struct key_preparsed_payload *prep) > rcu_assign_keypointer(key, new_p); > call_rcu(&p->rcu, trusted_rcu_free); > out: > - kfree_sensitive(datablob); > + kfree_sensitive(orig_datablob); > return ret; > } > > diff --git a/security/keys/trusted-keys/trusted_tpm1.c b/security/keys/trusted-keys/trusted_tpm1.c > index 4e5c50138f92..bc702ba0a596 100644 > --- a/security/keys/trusted-keys/trusted_tpm1.c > +++ b/security/keys/trusted-keys/trusted_tpm1.c > @@ -747,6 +747,9 @@ static int getoptions(char *c, struct trusted_key_payload *pay, > > opt->hash = tpm2 ? HASH_ALGO_SHA256 : HASH_ALGO_SHA1; > > + if (!c) > + return 0; > + > while ((p = strsep(&c, " \t"))) { > if (*p == '\0' || *p == ' ' || *p == '\t') > continue; > @@ -944,7 +947,7 @@ static int trusted_tpm_unseal(struct trusted_key_payload *p, char *datablob) > goto out; > dump_options(options); > > - if (!options->keyhandle) { > + if (!options->keyhandle && !tpm2) { > ret = -EINVAL; > goto out; > } > >