linux-integrity.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
From: Ard Biesheuvel <ard.biesheuvel@linaro.org>
To: James Bottomley <James.Bottomley@hansenpartnership.com>
Cc: linux-integrity <linux-integrity@vger.kernel.org>,
	"open list:HARDWARE RANDOM NUMBER GENERATOR CORE" 
	<linux-crypto@vger.kernel.org>,
	linux-security-module <linux-security-module@vger.kernel.org>,
	Jarkko Sakkinen <jarkko.sakkinen@linux.intel.com>
Subject: Re: [PATCH v4 2/7] tpm2-sessions: Add full HMAC and encrypt/decrypt session handling
Date: Tue, 23 Oct 2018 07:08:24 -0300	[thread overview]
Message-ID: <CAKv+Gu8T8yGEu2GWWKzLXR=wgd=mYHcTYLrD69_zpaddQK3Zxw@mail.gmail.com> (raw)
In-Reply-To: <1540278091.3347.9.camel@HansenPartnership.com>

On 23 October 2018 at 04:01, James Bottomley
<James.Bottomley@hansenpartnership.com> wrote:
> On Mon, 2018-10-22 at 19:19 -0300, Ard Biesheuvel wrote:
> [...]
>> > +static void hmac_init(struct shash_desc *desc, u8 *key, int
>> > keylen)
>> > +{
>> > +       u8 pad[SHA256_BLOCK_SIZE];
>> > +       int i;
>> > +
>> > +       desc->tfm = sha256_hash;
>> > +       desc->flags = CRYPTO_TFM_REQ_MAY_SLEEP;
>>
>> I don't think this actually does anything in the shash API
>> implementation, so you can drop this.
>
> OK, I find crypto somewhat hard to follow.  There were bits I had to
> understand, like when I wrote the CFB implementation or when I fixed
> the ECDH scatterlist handling, but I've got to confess, in time
> honoured tradition I simply copied this from EVM crypto without
> actually digging into the code to understand why.
>

Yeah, it is notoriously hard to use, and we should try to improve that.

>>  However, I take it this means that hmac_init() is never called in
>> contexts where sleeping is not allowed? For the relevance of that,
>> please see below.
>
> Right, these routines are always called as an adjunct to a TPM
> operation and TPM operations can sleep, so we must at least have kernel
> thread context.
>
> [...]
>> > +       /* encrypt before HMAC */
>> > +       if (auth->attrs & TPM2_SA_DECRYPT) {
>> > +               struct scatterlist sg[1];
>> > +               u16 len;
>> > +               SKCIPHER_REQUEST_ON_STACK(req, auth->aes);
>> > +
>> > +               skcipher_request_set_tfm(req, auth->aes);
>> > +               skcipher_request_set_callback(req,
>> > CRYPTO_TFM_REQ_MAY_SLEEP,
>> > +                                             NULL, NULL);
>> > +
>>
>> Your crypto_alloc_skcipher() call [further down] does not mask out
>> CRYPTO_ALG_ASYNC, and so it permits asynchronous implementations to
>> be selected. Your generic cfb template only permits synchronous
>> implementations, since it wraps the cipher directly (which is always
>> synchronous). However, we have support in the tree for some
>> accelerators that implement cfb(aes), and those will return
>> -EINPROGRESS when invoking crypto_skcipher_en/decrypt(req), which you
>> are not set up to handle.
>>
>> So the simple solution is to call 'crypto_alloc_skcipher("cfb(aes)",
>> 0, CRYPTO_ALG_ASYNC)' below instead.
>>
>> However, I would prefer it if we permit asynchronous skciphers here.
>> The reason is that, on a given platform, the accelerator may be the
>> only truly time invariant AES implementation that is available, and
>> since we are dealing with the TPM, a bit of paranoia does not hurt.
>> It also makes it easier to implement it as a [time invariant] SIMD
>> based asynchronous skcipher, which are simpler than synchronous ones
>> since they don't require a non-SIMD fallback path for calls from
>> contexts where the SIMD unit may not be used.
>>
>> I have already implemented cfb(aes) for arm64/NEON. I will post the
>> patch after the merge window closes.
>>
>> > +               /* need key and IV */
>> > +               KDFa(auth->session_key, SHA256_DIGEST_SIZE
>> > +                    + auth->passphraselen, "CFB", auth->our_nonce,
>> > +                    auth->tpm_nonce, AES_KEYBYTES +
>> > AES_BLOCK_SIZE,
>> > +                    auth->scratch);
>> > +               crypto_skcipher_setkey(auth->aes, auth->scratch,
>> > AES_KEYBYTES);
>> > +               len = tpm_get_inc_u16(&p);
>> > +               sg_init_one(sg, p, len);
>> > +               skcipher_request_set_crypt(req, sg, sg, len,
>> > +                                          auth->scratch +
>> > AES_KEYBYTES);
>> > +               crypto_skcipher_encrypt(req);
>>
>> So please consider replacing this with something like.
>>
>> DECLARE_CRYPTO_WAIT(wait); [further up]
>> skcipher_request_set_callback(req, CRYPTO_TFM_REQ_MAY_SLEEP,
>>                               crypto_req_done, &wait);
>> crypto_wait_req(crypto_skcipher_encrypt(req), &wait);
>
> Sure, I can do this ... the crypto skcipher handling was also cut and
> paste, but I forget where from this time.  So what I think you're
> asking for is below as the incremental diff?  I've tested this out and
> it all works fine in my session testing environment (and on my real
> laptop) ... although since I'm fully sync, I won't really have tested
> the -EINPROGRESS do the wait case.
>

Yes that looks fine. I will try to test this on one of my arm64
systems, but it may take me some time to get around to it.

In any case,

Reviewed-by: Ard Biesheuvel <ard.biesheuvel@linaro.org> # crypto API parts

>
> diff --git a/drivers/char/tpm/tpm2-sessions.c b/drivers/char/tpm/tpm2-sessions.c
> index 422c3ec64f8c..bbd3e8580954 100644
> --- a/drivers/char/tpm/tpm2-sessions.c
> +++ b/drivers/char/tpm/tpm2-sessions.c
> @@ -165,7 +165,6 @@ static void hmac_init(struct shash_desc *desc, u8 *key, int keylen)
>         int i;
>
>         desc->tfm = sha256_hash;
> -       desc->flags = CRYPTO_TFM_REQ_MAY_SLEEP;
>         crypto_shash_init(desc);
>         for (i = 0; i < sizeof(pad); i++) {
>                 if (i < keylen)
> @@ -244,7 +243,6 @@ static void KDFe(u8 z[EC_PT_SZ], const char *str, u8 *pt_u, u8 *pt_v,
>         __be32 c = cpu_to_be32(1);
>
>         desc->tfm = sha256_hash;
> -       desc->flags = CRYPTO_TFM_REQ_MAY_SLEEP;
>
>         crypto_shash_init(desc);
>         /* counter (BE) */
> @@ -445,7 +443,6 @@ void tpm_buf_fill_hmac_session(struct tpm_buf *buf, struct tpm2_auth *auth)
>         auth->ordinal = head->ordinal;
>
>         desc->tfm = sha256_hash;
> -       desc->flags = CRYPTO_TFM_REQ_MAY_SLEEP;
>
>         cc = be32_to_cpu(head->ordinal);
>
> @@ -514,10 +511,11 @@ void tpm_buf_fill_hmac_session(struct tpm_buf *buf, struct tpm2_auth *auth)
>                 struct scatterlist sg[1];
>                 u16 len;
>                 SKCIPHER_REQUEST_ON_STACK(req, auth->aes);
> +               DECLARE_CRYPTO_WAIT(wait);
>
>                 skcipher_request_set_tfm(req, auth->aes);
>                 skcipher_request_set_callback(req, CRYPTO_TFM_REQ_MAY_SLEEP,
> -                                             NULL, NULL);
> +                                             crypto_req_done, &wait);
>
>                 /* need key and IV */
>                 KDFa(auth->session_key, SHA256_DIGEST_SIZE
> @@ -529,7 +527,7 @@ void tpm_buf_fill_hmac_session(struct tpm_buf *buf, struct tpm2_auth *auth)
>                 sg_init_one(sg, p, len);
>                 skcipher_request_set_crypt(req, sg, sg, len,
>                                            auth->scratch + AES_KEYBYTES);
> -               crypto_skcipher_encrypt(req);
> +               crypto_wait_req(crypto_skcipher_encrypt(req), &wait);
>                 /* reset p to beginning of parameters for HMAC */
>                 p -= 2;
>         }
> @@ -755,7 +753,6 @@ int tpm_buf_check_hmac_response(struct tpm_buf *buf, struct tpm2_auth *auth,
>          * with rphash
>          */
>         desc->tfm = sha256_hash;
> -       desc->flags = CRYPTO_TFM_REQ_MAY_SLEEP;
>         crypto_shash_init(desc);
>         /* yes, I know this is now zero, but it's what the standard says */
>         crypto_shash_update(desc, (u8 *)&head->return_code,
> @@ -786,10 +783,11 @@ int tpm_buf_check_hmac_response(struct tpm_buf *buf, struct tpm2_auth *auth,
>         if (auth->attrs & TPM2_SA_ENCRYPT) {
>                 struct scatterlist sg[1];
>                 SKCIPHER_REQUEST_ON_STACK(req, auth->aes);
> +               DECLARE_CRYPTO_WAIT(wait);
>
>                 skcipher_request_set_tfm(req, auth->aes);
>                 skcipher_request_set_callback(req, CRYPTO_TFM_REQ_MAY_SLEEP,
> -                                             NULL, NULL);
> +                                             crypto_req_done, &wait);
>
>                 /* need key and IV */
>                 KDFa(auth->session_key, SHA256_DIGEST_SIZE
> @@ -801,7 +799,7 @@ int tpm_buf_check_hmac_response(struct tpm_buf *buf, struct tpm2_auth *auth,
>                 sg_init_one(sg, p, len);
>                 skcipher_request_set_crypt(req, sg, sg, len,
>                                            auth->scratch + AES_KEYBYTES);
> -               crypto_skcipher_decrypt(req);
> +               crypto_wait_req(crypto_skcipher_decrypt(req), &wait);
>         }
>
>   out:
> @@ -965,7 +963,6 @@ static int parse_create_primary(struct tpm_chip *chip, u8 *data)
>         tmp = resp;
>         /* now we have the public area, compute the name of the object */
>         desc->tfm = sha256_hash;
> -       desc->flags = CRYPTO_TFM_REQ_MAY_SLEEP;
>         put_unaligned_be16(TPM2_ALG_SHA256, chip->tpmkeyname);
>         crypto_shash_init(desc);
>         crypto_shash_update(desc, resp, len);

  reply	other threads:[~2018-10-23 10:08 UTC|newest]

Thread overview: 31+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2018-10-22  7:33 [PATCH v4 0/7] add integrity and security to TPM2 transactions James Bottomley
2018-10-22  7:35 ` [PATCH v4 1/7] tpm-buf: create new functions for handling TPM buffers James Bottomley
2018-10-23 19:12   ` Jarkko Sakkinen
2018-10-23 19:16   ` Jarkko Sakkinen
2018-10-22  7:36 ` [PATCH v4 2/7] tpm2-sessions: Add full HMAC and encrypt/decrypt session handling James Bottomley
2018-10-22 22:19   ` Ard Biesheuvel
2018-10-23  7:01     ` James Bottomley
2018-10-23 10:08       ` Ard Biesheuvel [this message]
2018-10-24  8:40         ` Jarkko Sakkinen
2018-10-23 23:48   ` Jarkko Sakkinen
2018-10-24  9:31     ` James Bottomley
2018-10-25 15:56       ` Jarkko Sakkinen
2018-10-22  7:37 ` [PATCH v4 3/7] tpm2: add hmac checks to tpm2_pcr_extend() James Bottomley
2018-10-22  7:37 ` [PATCH v4 4/7] tpm2: add session encryption protection to tpm2_get_random() James Bottomley
2018-10-22  7:38 ` [PATCH v4 5/7] trusted keys: Add session encryption protection to the seal/unseal path James Bottomley
2018-10-24  0:03   ` Jarkko Sakkinen
2018-10-22  7:39 ` [PATCH v4 6/7] tpm: add the null key name as a tpm2 sysfs variable James Bottomley
2018-10-22  7:40 ` [PATCH v4 7/7] tpm2-sessions: NOT FOR COMMITTING add sessions testing James Bottomley
2018-10-22 13:53 ` [PATCH v4 0/7] add integrity and security to TPM2 transactions Ken Goldman
2018-10-22 14:18   ` James Bottomley
2018-10-22 15:50     ` Ken Goldman
2018-10-22 15:55       ` James Bottomley
2018-10-24  0:13     ` Jarkko Sakkinen
2018-10-24  7:41       ` James Bottomley
2018-10-25 15:39         ` Jarkko Sakkinen
2018-10-24  0:06   ` Jarkko Sakkinen
2018-10-24  7:34     ` James Bottomley
2018-10-25 16:53       ` Ken Goldman
2018-10-23 23:51 ` Jarkko Sakkinen
2018-10-24  7:43   ` James Bottomley
2018-10-25 15:42     ` Jarkko Sakkinen

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to='CAKv+Gu8T8yGEu2GWWKzLXR=wgd=mYHcTYLrD69_zpaddQK3Zxw@mail.gmail.com' \
    --to=ard.biesheuvel@linaro.org \
    --cc=James.Bottomley@hansenpartnership.com \
    --cc=jarkko.sakkinen@linux.intel.com \
    --cc=linux-crypto@vger.kernel.org \
    --cc=linux-integrity@vger.kernel.org \
    --cc=linux-security-module@vger.kernel.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).