Follow @Openwall on Twitter for new release announcements and other news
[<prev] [next>] [<thread-prev] [thread-next>] [day] [month] [year] [list]
Message-ID: <20200501230913.GB915@sol.localdomain>
Date: Fri, 1 May 2020 16:09:13 -0700
From: Eric Biggers <ebiggers@...nel.org>
To: "Jason A. Donenfeld" <Jason@...c4.com>
Cc: dhowells@...hat.com, keyrings@...r.kernel.org,
	Andy Lutomirski <luto@...nel.org>,
	Greg KH <gregkh@...uxfoundation.org>,
	Linus Torvalds <torvalds@...ux-foundation.org>,
	kernel-hardening@...ts.openwall.com
Subject: Re: [PATCH] security/keys: rewrite big_key crypto to use Zinc

On Fri, May 01, 2020 at 04:23:57PM -0600, Jason A. Donenfeld wrote:
> A while back, I noticed that the crypto and crypto API usage in big_keys
> were entirely broken in multiple ways, so I rewrote it. Now, I'm
> rewriting it again, but this time using Zinc's ChaCha20Poly1305
> function. This makes the file considerably more simple; the diffstat
> alone should justify this commit. It also should be faster, since it no
> longer requires a mutex around the "aead api object" (nor allocations),
> allowing us to encrypt multiple items in parallel. We also benefit from
> being able to pass any type of pointer, so we can get rid of the
> ridiculously complex custom page allocator that big_key really doesn't
> need.
> 
> Cc: David Howells <dhowells@...hat.com>
> Cc: Andy Lutomirski <luto@...nel.org>
> Cc: Greg KH <gregkh@...uxfoundation.org>
> Cc: Linus Torvalds <torvalds@...ux-foundation.org>
> Cc: kernel-hardening@...ts.openwall.com
> Signed-off-by: Jason A. Donenfeld <Jason@...c4.com>
> ---
> I finally got around to updating this patch from the mailing list posts
> back in 2017-2018, using the library interface that we eventually merged
> in 2019. I haven't retested this for functionality, but nothing much has
> changed, so I suspect things should still be good to go.
> 
>  security/keys/Kconfig   |   4 +-
>  security/keys/big_key.c | 230 +++++-----------------------------------
>  2 files changed, 28 insertions(+), 206 deletions(-)
> 
> diff --git a/security/keys/Kconfig b/security/keys/Kconfig
> index 47c041563d41..5aa442490d52 100644
> --- a/security/keys/Kconfig
> +++ b/security/keys/Kconfig
> @@ -60,9 +60,7 @@ config BIG_KEYS
>  	bool "Large payload keys"
>  	depends on KEYS
>  	depends on TMPFS
> -	select CRYPTO
> -	select CRYPTO_AES
> -	select CRYPTO_GCM
> +	select CRYPTO_LIB_CHACHA20POLY1305
>  	help
>  	  This option provides support for holding large keys within the kernel
>  	  (for example Kerberos ticket caches).  The data may be stored out to

The 'select CRYPTO' is actually still needed because CRYPTO_LIB_CHACHA20POLY1305
is under the CRYPTO menuconfig:

make allnoconfig
cat >> .config << EOF
CONFIG_SHMEM=y
CONFIG_TMPFS=y
CONFIG_KEYS=y
CONFIG_BIG_KEYS=y
EOF
make olddefconfig

WARNING: unmet direct dependencies detected for CRYPTO_LIB_CHACHA20POLY1305
  Depends on [n]: CRYPTO [=n] && (CRYPTO_ARCH_HAVE_LIB_CHACHA [=n] || !CRYPTO_ARCH_HAVE_LIB_CHACHA [=n]) && (CRYPTO_ARCH_HAVE_LIB_POLY1305 [=n] || !CRYPTO_ARCH_HAVE_LIB_POLY1305 [=n])
  Selected by [y]:
  - BIG_KEYS [=y] && KEYS [=y] && TMPFS [=y]


Maybe the 'source "lib/crypto/Kconfig"' in crypto/Kconfig should be moved to
lib/Kconfig so that it's under "Library routines" and the crypto library options
can be selected without the full CRYPTO framework?

But lib/crypto/libchacha.c uses crypto_xor_cpy(), and
lib/crypto/chacha20poly1305.c uses crypto_memneq().  So those functions would
first need to be pulled into lib/crypto/ too.

> @@ -265,7 +121,7 @@ int big_key_preparse(struct key_preparsed_payload *prep)
>  		*path = file->f_path;
>  		path_get(path);
>  		fput(file);
> -		big_key_free_buffer(buf);
> +		kvfree(buf);
>  	} else {
>  		/* Just store the data in a buffer */
>  		void *data = kmalloc(datalen, GFP_KERNEL);
> @@ -283,7 +139,7 @@ int big_key_preparse(struct key_preparsed_payload *prep)
>  err_enckey:
>  	kzfree(enckey);
>  error:
> -	big_key_free_buffer(buf);
> +	kvfree(buf);
>  	return ret;
>  }

There should be a 'memzero_explicit(buf, enclen);' before the above two calls to
kvfree().

Or even better these should use kvfree_sensitive(), but that hasn't been merged
yet.  It was under discussion last month:
https://lkml.kernel.org/lkml/20200407200318.11711-1-longman@redhat.com/

>  
> -		ret = big_key_crypt(BIG_KEY_DEC, buf, enclen, enckey);
> -		if (ret)
> +		ret = chacha20poly1305_decrypt(buf, buf, enclen, NULL, 0, 0,
> +					       enckey) ? 0 : -EINVAL;
> +		if (unlikely(ret))
>  			goto err_fput;

-EINVAL is often unclear, since everyone uses it for everything.  How about
using -EBADMSG, which is what was used before via crypto_aead_decrypt()?

>  
>  		ret = datalen;
>  
>  		/* copy out decrypted data */
> -		memcpy(buffer, buf->virt, datalen);
> +		memcpy(buffer, buf, datalen);
>  
>  err_fput:
>  		fput(file);
>  error:
> -		big_key_free_buffer(buf);
> +		kvfree(buf);

Likewise, the buffer should be zeroed before freeing here.

- Eric

Powered by blists - more mailing lists

Confused about mailing lists and their use? Read about mailing lists on Wikipedia and check out these guidelines on proper formatting of your messages.