]> git.ipfire.org Git - thirdparty/kernel/stable-queue.git/commitdiff
4.13-stable patches
authorGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Mon, 2 Oct 2017 09:56:55 +0000 (11:56 +0200)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Mon, 2 Oct 2017 09:56:55 +0000 (11:56 +0200)
added patches:
keys-fix-writing-past-end-of-user-supplied-buffer-in-keyring_read.patch
keys-prevent-creating-a-different-user-s-keyrings.patch
security-keys-properly-zero-out-sensitive-key-material-in-big_key.patch
security-keys-rewrite-all-of-big_key-crypto.patch

queue-4.13/keys-fix-writing-past-end-of-user-supplied-buffer-in-keyring_read.patch [new file with mode: 0644]
queue-4.13/keys-prevent-creating-a-different-user-s-keyrings.patch [new file with mode: 0644]
queue-4.13/security-keys-properly-zero-out-sensitive-key-material-in-big_key.patch [new file with mode: 0644]
queue-4.13/security-keys-rewrite-all-of-big_key-crypto.patch [new file with mode: 0644]
queue-4.13/series

diff --git a/queue-4.13/keys-fix-writing-past-end-of-user-supplied-buffer-in-keyring_read.patch b/queue-4.13/keys-fix-writing-past-end-of-user-supplied-buffer-in-keyring_read.patch
new file mode 100644 (file)
index 0000000..4b042cf
--- /dev/null
@@ -0,0 +1,66 @@
+From e645016abc803dafc75e4b8f6e4118f088900ffb Mon Sep 17 00:00:00 2001
+From: Eric Biggers <ebiggers@google.com>
+Date: Mon, 18 Sep 2017 11:36:45 -0700
+Subject: KEYS: fix writing past end of user-supplied buffer in keyring_read()
+
+From: Eric Biggers <ebiggers@google.com>
+
+commit e645016abc803dafc75e4b8f6e4118f088900ffb upstream.
+
+Userspace can call keyctl_read() on a keyring to get the list of IDs of
+keys in the keyring.  But if the user-supplied buffer is too small, the
+kernel would write the full list anyway --- which will corrupt whatever
+userspace memory happened to be past the end of the buffer.  Fix it by
+only filling the space that is available.
+
+Fixes: b2a4df200d57 ("KEYS: Expand the capacity of a keyring")
+Signed-off-by: Eric Biggers <ebiggers@google.com>
+Signed-off-by: David Howells <dhowells@redhat.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ security/keys/keyring.c |   14 +++++---------
+ 1 file changed, 5 insertions(+), 9 deletions(-)
+
+--- a/security/keys/keyring.c
++++ b/security/keys/keyring.c
+@@ -423,7 +423,7 @@ static void keyring_describe(const struc
+ }
+ struct keyring_read_iterator_context {
+-      size_t                  qty;
++      size_t                  buflen;
+       size_t                  count;
+       key_serial_t __user     *buffer;
+ };
+@@ -435,9 +435,9 @@ static int keyring_read_iterator(const v
+       int ret;
+       kenter("{%s,%d},,{%zu/%zu}",
+-             key->type->name, key->serial, ctx->count, ctx->qty);
++             key->type->name, key->serial, ctx->count, ctx->buflen);
+-      if (ctx->count >= ctx->qty)
++      if (ctx->count >= ctx->buflen)
+               return 1;
+       ret = put_user(key->serial, ctx->buffer);
+@@ -472,16 +472,12 @@ static long keyring_read(const struct ke
+               return 0;
+       /* Calculate how much data we could return */
+-      ctx.qty = nr_keys * sizeof(key_serial_t);
+-
+       if (!buffer || !buflen)
+-              return ctx.qty;
+-
+-      if (buflen > ctx.qty)
+-              ctx.qty = buflen;
++              return nr_keys * sizeof(key_serial_t);
+       /* Copy the IDs of the subscribed keys into the buffer */
+       ctx.buffer = (key_serial_t __user *)buffer;
++      ctx.buflen = buflen;
+       ctx.count = 0;
+       ret = assoc_array_iterate(&keyring->keys, keyring_read_iterator, &ctx);
+       if (ret < 0) {
diff --git a/queue-4.13/keys-prevent-creating-a-different-user-s-keyrings.patch b/queue-4.13/keys-prevent-creating-a-different-user-s-keyrings.patch
new file mode 100644 (file)
index 0000000..d692fbf
--- /dev/null
@@ -0,0 +1,149 @@
+From 237bbd29f7a049d310d907f4b2716a7feef9abf3 Mon Sep 17 00:00:00 2001
+From: Eric Biggers <ebiggers@google.com>
+Date: Mon, 18 Sep 2017 11:37:03 -0700
+Subject: KEYS: prevent creating a different user's keyrings
+
+From: Eric Biggers <ebiggers@google.com>
+
+commit 237bbd29f7a049d310d907f4b2716a7feef9abf3 upstream.
+
+It was possible for an unprivileged user to create the user and user
+session keyrings for another user.  For example:
+
+    sudo -u '#3000' sh -c 'keyctl add keyring _uid.4000 "" @u
+                           keyctl add keyring _uid_ses.4000 "" @u
+                           sleep 15' &
+    sleep 1
+    sudo -u '#4000' keyctl describe @u
+    sudo -u '#4000' keyctl describe @us
+
+This is problematic because these "fake" keyrings won't have the right
+permissions.  In particular, the user who created them first will own
+them and will have full access to them via the possessor permissions,
+which can be used to compromise the security of a user's keys:
+
+    -4: alswrv-----v------------  3000     0 keyring: _uid.4000
+    -5: alswrv-----v------------  3000     0 keyring: _uid_ses.4000
+
+Fix it by marking user and user session keyrings with a flag
+KEY_FLAG_UID_KEYRING.  Then, when searching for a user or user session
+keyring by name, skip all keyrings that don't have the flag set.
+
+Fixes: 69664cf16af4 ("keys: don't generate user and user session keyrings unless they're accessed")
+Signed-off-by: Eric Biggers <ebiggers@google.com>
+Signed-off-by: David Howells <dhowells@redhat.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ include/linux/key.h          |    2 ++
+ security/keys/internal.h     |    2 +-
+ security/keys/key.c          |    2 ++
+ security/keys/keyring.c      |   23 ++++++++++++++---------
+ security/keys/process_keys.c |    6 ++++--
+ 5 files changed, 23 insertions(+), 12 deletions(-)
+
+--- a/include/linux/key.h
++++ b/include/linux/key.h
+@@ -187,6 +187,7 @@ struct key {
+ #define KEY_FLAG_BUILTIN      8       /* set if key is built in to the kernel */
+ #define KEY_FLAG_ROOT_CAN_INVAL       9       /* set if key can be invalidated by root without permission */
+ #define KEY_FLAG_KEEP         10      /* set if key should not be removed */
++#define KEY_FLAG_UID_KEYRING  11      /* set if key is a user or user session keyring */
+       /* the key type and key description string
+        * - the desc is used to match a key against search criteria
+@@ -243,6 +244,7 @@ extern struct key *key_alloc(struct key_
+ #define KEY_ALLOC_NOT_IN_QUOTA                0x0002  /* not in quota */
+ #define KEY_ALLOC_BUILT_IN            0x0004  /* Key is built into kernel */
+ #define KEY_ALLOC_BYPASS_RESTRICTION  0x0008  /* Override the check on restricted keyrings */
++#define KEY_ALLOC_UID_KEYRING         0x0010  /* allocating a user or user session keyring */
+ extern void key_revoke(struct key *key);
+ extern void key_invalidate(struct key *key);
+--- a/security/keys/internal.h
++++ b/security/keys/internal.h
+@@ -141,7 +141,7 @@ extern key_ref_t keyring_search_aux(key_
+ extern key_ref_t search_my_process_keyrings(struct keyring_search_context *ctx);
+ extern key_ref_t search_process_keyrings(struct keyring_search_context *ctx);
+-extern struct key *find_keyring_by_name(const char *name, bool skip_perm_check);
++extern struct key *find_keyring_by_name(const char *name, bool uid_keyring);
+ extern int install_user_keyrings(void);
+ extern int install_thread_keyring_to_cred(struct cred *);
+--- a/security/keys/key.c
++++ b/security/keys/key.c
+@@ -302,6 +302,8 @@ struct key *key_alloc(struct key_type *t
+               key->flags |= 1 << KEY_FLAG_IN_QUOTA;
+       if (flags & KEY_ALLOC_BUILT_IN)
+               key->flags |= 1 << KEY_FLAG_BUILTIN;
++      if (flags & KEY_ALLOC_UID_KEYRING)
++              key->flags |= 1 << KEY_FLAG_UID_KEYRING;
+ #ifdef KEY_DEBUGGING
+       key->magic = KEY_DEBUG_MAGIC;
+--- a/security/keys/keyring.c
++++ b/security/keys/keyring.c
+@@ -1097,15 +1097,15 @@ found:
+ /*
+  * Find a keyring with the specified name.
+  *
+- * All named keyrings in the current user namespace are searched, provided they
+- * grant Search permission directly to the caller (unless this check is
+- * skipped).  Keyrings whose usage points have reached zero or who have been
+- * revoked are skipped.
++ * Only keyrings that have nonzero refcount, are not revoked, and are owned by a
++ * user in the current user namespace are considered.  If @uid_keyring is %true,
++ * the keyring additionally must have been allocated as a user or user session
++ * keyring; otherwise, it must grant Search permission directly to the caller.
+  *
+  * Returns a pointer to the keyring with the keyring's refcount having being
+  * incremented on success.  -ENOKEY is returned if a key could not be found.
+  */
+-struct key *find_keyring_by_name(const char *name, bool skip_perm_check)
++struct key *find_keyring_by_name(const char *name, bool uid_keyring)
+ {
+       struct key *keyring;
+       int bucket;
+@@ -1133,10 +1133,15 @@ struct key *find_keyring_by_name(const c
+                       if (strcmp(keyring->description, name) != 0)
+                               continue;
+-                      if (!skip_perm_check &&
+-                          key_permission(make_key_ref(keyring, 0),
+-                                         KEY_NEED_SEARCH) < 0)
+-                              continue;
++                      if (uid_keyring) {
++                              if (!test_bit(KEY_FLAG_UID_KEYRING,
++                                            &keyring->flags))
++                                      continue;
++                      } else {
++                              if (key_permission(make_key_ref(keyring, 0),
++                                                 KEY_NEED_SEARCH) < 0)
++                                      continue;
++                      }
+                       /* we've got a match but we might end up racing with
+                        * key_cleanup() if the keyring is currently 'dead'
+--- a/security/keys/process_keys.c
++++ b/security/keys/process_keys.c
+@@ -77,7 +77,8 @@ int install_user_keyrings(void)
+               if (IS_ERR(uid_keyring)) {
+                       uid_keyring = keyring_alloc(buf, user->uid, INVALID_GID,
+                                                   cred, user_keyring_perm,
+-                                                  KEY_ALLOC_IN_QUOTA,
++                                                  KEY_ALLOC_UID_KEYRING |
++                                                      KEY_ALLOC_IN_QUOTA,
+                                                   NULL, NULL);
+                       if (IS_ERR(uid_keyring)) {
+                               ret = PTR_ERR(uid_keyring);
+@@ -94,7 +95,8 @@ int install_user_keyrings(void)
+                       session_keyring =
+                               keyring_alloc(buf, user->uid, INVALID_GID,
+                                             cred, user_keyring_perm,
+-                                            KEY_ALLOC_IN_QUOTA,
++                                            KEY_ALLOC_UID_KEYRING |
++                                                KEY_ALLOC_IN_QUOTA,
+                                             NULL, NULL);
+                       if (IS_ERR(session_keyring)) {
+                               ret = PTR_ERR(session_keyring);
diff --git a/queue-4.13/security-keys-properly-zero-out-sensitive-key-material-in-big_key.patch b/queue-4.13/security-keys-properly-zero-out-sensitive-key-material-in-big_key.patch
new file mode 100644 (file)
index 0000000..080fe7d
--- /dev/null
@@ -0,0 +1,74 @@
+From 910801809b2e40a4baedd080ef5d80b4a180e70e Mon Sep 17 00:00:00 2001
+From: "Jason A. Donenfeld" <Jason@zx2c4.com>
+Date: Wed, 20 Sep 2017 16:58:38 +0200
+Subject: security/keys: properly zero out sensitive key material in big_key
+
+From: Jason A. Donenfeld <Jason@zx2c4.com>
+
+commit 910801809b2e40a4baedd080ef5d80b4a180e70e upstream.
+
+Error paths forgot to zero out sensitive material, so this patch changes
+some kfrees into a kzfrees.
+
+Signed-off-by: Jason A. Donenfeld <Jason@zx2c4.com>
+Signed-off-by: David Howells <dhowells@redhat.com>
+Reviewed-by: Eric Biggers <ebiggers3@gmail.com>
+Cc: Herbert Xu <herbert@gondor.apana.org.au>
+Cc: Kirill Marinushkin <k.marinushkin@gmail.com>
+Cc: security@kernel.org
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ security/keys/big_key.c |   12 ++++++------
+ 1 file changed, 6 insertions(+), 6 deletions(-)
+
+--- a/security/keys/big_key.c
++++ b/security/keys/big_key.c
+@@ -194,7 +194,7 @@ int big_key_preparse(struct key_preparse
+               *path = file->f_path;
+               path_get(path);
+               fput(file);
+-              kfree(data);
++              kzfree(data);
+       } else {
+               /* Just store the data in a buffer */
+               void *data = kmalloc(datalen, GFP_KERNEL);
+@@ -210,9 +210,9 @@ int big_key_preparse(struct key_preparse
+ err_fput:
+       fput(file);
+ err_enckey:
+-      kfree(enckey);
++      kzfree(enckey);
+ error:
+-      kfree(data);
++      kzfree(data);
+       return ret;
+ }
+@@ -226,7 +226,7 @@ void big_key_free_preparse(struct key_pr
+               path_put(path);
+       }
+-      kfree(prep->payload.data[big_key_data]);
++      kzfree(prep->payload.data[big_key_data]);
+ }
+ /*
+@@ -258,7 +258,7 @@ void big_key_destroy(struct key *key)
+               path->mnt = NULL;
+               path->dentry = NULL;
+       }
+-      kfree(key->payload.data[big_key_data]);
++      kzfree(key->payload.data[big_key_data]);
+       key->payload.data[big_key_data] = NULL;
+ }
+@@ -326,7 +326,7 @@ long big_key_read(const struct key *key,
+ err_fput:
+               fput(file);
+ error:
+-              kfree(data);
++              kzfree(data);
+       } else {
+               ret = datalen;
+               if (copy_to_user(buffer, key->payload.data[big_key_data],
diff --git a/queue-4.13/security-keys-rewrite-all-of-big_key-crypto.patch b/queue-4.13/security-keys-rewrite-all-of-big_key-crypto.patch
new file mode 100644 (file)
index 0000000..1cadbd0
--- /dev/null
@@ -0,0 +1,297 @@
+From 428490e38b2e352812e0b765d8bceafab0ec441d Mon Sep 17 00:00:00 2001
+From: "Jason A. Donenfeld" <Jason@zx2c4.com>
+Date: Wed, 20 Sep 2017 16:58:39 +0200
+Subject: security/keys: rewrite all of big_key crypto
+
+From: Jason A. Donenfeld <Jason@zx2c4.com>
+
+commit 428490e38b2e352812e0b765d8bceafab0ec441d upstream.
+
+This started out as just replacing the use of crypto/rng with
+get_random_bytes_wait, so that we wouldn't use bad randomness at boot
+time. But, upon looking further, it appears that there were even deeper
+underlying cryptographic problems, and that this seems to have been
+committed with very little crypto review. So, I rewrote the whole thing,
+trying to keep to the conventions introduced by the previous author, to
+fix these cryptographic flaws.
+
+It makes no sense to seed crypto/rng at boot time and then keep
+using it like this, when in fact there's already get_random_bytes_wait,
+which can ensure there's enough entropy and be a much more standard way
+of generating keys. Since this sensitive material is being stored
+untrusted, using ECB and no authentication is simply not okay at all. I
+find it surprising and a bit horrifying that this code even made it past
+basic crypto review, which perhaps points to some larger issues. This
+patch moves from using AES-ECB to using AES-GCM. Since keys are uniquely
+generated each time, we can set the nonce to zero. There was also a race
+condition in which the same key would be reused at the same time in
+different threads. A mutex fixes this issue now.
+
+So, to summarize, this commit fixes the following vulnerabilities:
+
+  * Low entropy key generation, allowing an attacker to potentially
+    guess or predict keys.
+  * Unauthenticated encryption, allowing an attacker to modify the
+    cipher text in particular ways in order to manipulate the plaintext,
+    which is is even more frightening considering the next point.
+  * Use of ECB mode, allowing an attacker to trivially swap blocks or
+    compare identical plaintext blocks.
+  * Key re-use.
+  * Faulty memory zeroing.
+
+Signed-off-by: Jason A. Donenfeld <Jason@zx2c4.com>
+Reviewed-by: Eric Biggers <ebiggers3@gmail.com>
+Signed-off-by: David Howells <dhowells@redhat.com>
+Cc: Herbert Xu <herbert@gondor.apana.org.au>
+Cc: Kirill Marinushkin <k.marinushkin@gmail.com>
+Cc: security@kernel.org
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ security/keys/Kconfig   |    4 -
+ security/keys/big_key.c |  124 ++++++++++++++++++++++--------------------------
+ 2 files changed, 59 insertions(+), 69 deletions(-)
+
+--- a/security/keys/Kconfig
++++ b/security/keys/Kconfig
+@@ -45,10 +45,8 @@ config BIG_KEYS
+       bool "Large payload keys"
+       depends on KEYS
+       depends on TMPFS
+-      depends on (CRYPTO_ANSI_CPRNG = y || CRYPTO_DRBG = y)
+       select CRYPTO_AES
+-      select CRYPTO_ECB
+-      select CRYPTO_RNG
++      select CRYPTO_GCM
+       help
+         This option provides support for holding large keys within the kernel
+         (for example Kerberos ticket caches).  The data may be stored out to
+--- a/security/keys/big_key.c
++++ b/security/keys/big_key.c
+@@ -1,5 +1,6 @@
+ /* Large capacity key type
+  *
++ * Copyright (C) 2017 Jason A. Donenfeld <Jason@zx2c4.com>. All Rights Reserved.
+  * Copyright (C) 2013 Red Hat, Inc. All Rights Reserved.
+  * Written by David Howells (dhowells@redhat.com)
+  *
+@@ -16,10 +17,10 @@
+ #include <linux/shmem_fs.h>
+ #include <linux/err.h>
+ #include <linux/scatterlist.h>
++#include <linux/random.h>
+ #include <keys/user-type.h>
+ #include <keys/big_key-type.h>
+-#include <crypto/rng.h>
+-#include <crypto/skcipher.h>
++#include <crypto/aead.h>
+ /*
+  * Layout of key payload words.
+@@ -49,7 +50,12 @@ enum big_key_op {
+ /*
+  * Key size for big_key data encryption
+  */
+-#define ENC_KEY_SIZE  16
++#define ENC_KEY_SIZE 32
++
++/*
++ * Authentication tag length
++ */
++#define ENC_AUTHTAG_SIZE 16
+ /*
+  * big_key defined keys take an arbitrary string as the description and an
+@@ -64,57 +70,62 @@ struct key_type key_type_big_key = {
+       .destroy                = big_key_destroy,
+       .describe               = big_key_describe,
+       .read                   = big_key_read,
++      /* no ->update(); don't add it without changing big_key_crypt() nonce */
+ };
+ /*
+- * Crypto names for big_key data encryption
++ * Crypto names for big_key data authenticated encryption
+  */
+-static const char big_key_rng_name[] = "stdrng";
+-static const char big_key_alg_name[] = "ecb(aes)";
++static const char big_key_alg_name[] = "gcm(aes)";
+ /*
+- * Crypto algorithms for big_key data encryption
++ * Crypto algorithms for big_key data authenticated encryption
+  */
+-static struct crypto_rng *big_key_rng;
+-static struct crypto_skcipher *big_key_skcipher;
++static struct crypto_aead *big_key_aead;
+ /*
+- * Generate random key to encrypt big_key data
++ * Since changing the key affects the entire object, we need a mutex.
+  */
+-static inline int big_key_gen_enckey(u8 *key)
+-{
+-      return crypto_rng_get_bytes(big_key_rng, key, ENC_KEY_SIZE);
+-}
++static DEFINE_MUTEX(big_key_aead_lock);
+ /*
+  * Encrypt/decrypt big_key data
+  */
+ static int big_key_crypt(enum big_key_op op, u8 *data, size_t datalen, u8 *key)
+ {
+-      int ret = -EINVAL;
++      int ret;
+       struct scatterlist sgio;
+-      SKCIPHER_REQUEST_ON_STACK(req, big_key_skcipher);
++      struct aead_request *aead_req;
++      /* We always use a zero nonce. The reason we can get away with this is
++       * because we're using a different randomly generated key for every
++       * different encryption. Notably, too, key_type_big_key doesn't define
++       * an .update function, so there's no chance we'll wind up reusing the
++       * key to encrypt updated data. Simply put: one key, one encryption.
++       */
++      u8 zero_nonce[crypto_aead_ivsize(big_key_aead)];
++
++      aead_req = aead_request_alloc(big_key_aead, GFP_KERNEL);
++      if (!aead_req)
++              return -ENOMEM;
++
++      memset(zero_nonce, 0, sizeof(zero_nonce));
++      sg_init_one(&sgio, data, datalen + (op == BIG_KEY_ENC ? ENC_AUTHTAG_SIZE : 0));
++      aead_request_set_crypt(aead_req, &sgio, &sgio, datalen, zero_nonce);
++      aead_request_set_callback(aead_req, CRYPTO_TFM_REQ_MAY_SLEEP, NULL, NULL);
++      aead_request_set_ad(aead_req, 0);
+-      if (crypto_skcipher_setkey(big_key_skcipher, key, ENC_KEY_SIZE)) {
++      mutex_lock(&big_key_aead_lock);
++      if (crypto_aead_setkey(big_key_aead, key, ENC_KEY_SIZE)) {
+               ret = -EAGAIN;
+               goto error;
+       }
+-
+-      skcipher_request_set_tfm(req, big_key_skcipher);
+-      skcipher_request_set_callback(req, CRYPTO_TFM_REQ_MAY_SLEEP,
+-                                    NULL, NULL);
+-
+-      sg_init_one(&sgio, data, datalen);
+-      skcipher_request_set_crypt(req, &sgio, &sgio, datalen, NULL);
+-
+       if (op == BIG_KEY_ENC)
+-              ret = crypto_skcipher_encrypt(req);
++              ret = crypto_aead_encrypt(aead_req);
+       else
+-              ret = crypto_skcipher_decrypt(req);
+-
+-      skcipher_request_zero(req);
+-
++              ret = crypto_aead_decrypt(aead_req);
+ error:
++      mutex_unlock(&big_key_aead_lock);
++      aead_request_free(aead_req);
+       return ret;
+ }
+@@ -146,15 +157,13 @@ int big_key_preparse(struct key_preparse
+                *
+                * File content is stored encrypted with randomly generated key.
+                */
+-              size_t enclen = ALIGN(datalen, crypto_skcipher_blocksize(big_key_skcipher));
++              size_t enclen = datalen + ENC_AUTHTAG_SIZE;
+-              /* prepare aligned data to encrypt */
+               data = kmalloc(enclen, GFP_KERNEL);
+               if (!data)
+                       return -ENOMEM;
+               memcpy(data, prep->data, datalen);
+-              memset(data + datalen, 0x00, enclen - datalen);
+               /* generate random key */
+               enckey = kmalloc(ENC_KEY_SIZE, GFP_KERNEL);
+@@ -162,13 +171,12 @@ int big_key_preparse(struct key_preparse
+                       ret = -ENOMEM;
+                       goto error;
+               }
+-
+-              ret = big_key_gen_enckey(enckey);
+-              if (ret)
++              ret = get_random_bytes_wait(enckey, ENC_KEY_SIZE);
++              if (unlikely(ret))
+                       goto err_enckey;
+               /* encrypt aligned data */
+-              ret = big_key_crypt(BIG_KEY_ENC, data, enclen, enckey);
++              ret = big_key_crypt(BIG_KEY_ENC, data, datalen, enckey);
+               if (ret)
+                       goto err_enckey;
+@@ -294,7 +302,7 @@ long big_key_read(const struct key *key,
+               struct file *file;
+               u8 *data;
+               u8 *enckey = (u8 *)key->payload.data[big_key_data];
+-              size_t enclen = ALIGN(datalen, crypto_skcipher_blocksize(big_key_skcipher));
++              size_t enclen = datalen + ENC_AUTHTAG_SIZE;
+               data = kmalloc(enclen, GFP_KERNEL);
+               if (!data)
+@@ -342,47 +350,31 @@ error:
+  */
+ static int __init big_key_init(void)
+ {
+-      struct crypto_skcipher *cipher;
+-      struct crypto_rng *rng;
+       int ret;
+-      rng = crypto_alloc_rng(big_key_rng_name, 0, 0);
+-      if (IS_ERR(rng)) {
+-              pr_err("Can't alloc rng: %ld\n", PTR_ERR(rng));
+-              return PTR_ERR(rng);
+-      }
+-
+-      big_key_rng = rng;
+-
+-      /* seed RNG */
+-      ret = crypto_rng_reset(rng, NULL, crypto_rng_seedsize(rng));
+-      if (ret) {
+-              pr_err("Can't reset rng: %d\n", ret);
+-              goto error_rng;
+-      }
+-
+       /* init block cipher */
+-      cipher = crypto_alloc_skcipher(big_key_alg_name, 0, CRYPTO_ALG_ASYNC);
+-      if (IS_ERR(cipher)) {
+-              ret = PTR_ERR(cipher);
++      big_key_aead = crypto_alloc_aead(big_key_alg_name, 0, CRYPTO_ALG_ASYNC);
++      if (IS_ERR(big_key_aead)) {
++              ret = PTR_ERR(big_key_aead);
+               pr_err("Can't alloc crypto: %d\n", ret);
+-              goto error_rng;
++              return ret;
++      }
++      ret = crypto_aead_setauthsize(big_key_aead, ENC_AUTHTAG_SIZE);
++      if (ret < 0) {
++              pr_err("Can't set crypto auth tag len: %d\n", ret);
++              goto free_aead;
+       }
+-
+-      big_key_skcipher = cipher;
+       ret = register_key_type(&key_type_big_key);
+       if (ret < 0) {
+               pr_err("Can't register type: %d\n", ret);
+-              goto error_cipher;
++              goto free_aead;
+       }
+       return 0;
+-error_cipher:
+-      crypto_free_skcipher(big_key_skcipher);
+-error_rng:
+-      crypto_free_rng(big_key_rng);
++free_aead:
++      crypto_free_aead(big_key_aead);
+       return ret;
+ }
index 3fd92e450020e672c043b0b10fa9f522b78a47eb..fddb6b14d9eb34364b2ad50406a4e5c252363652 100644 (file)
@@ -38,4 +38,8 @@ crypto-drbg-fix-freeing-of-resources.patch
 crypto-talitos-don-t-provide-setkey-for-non-hmac-hashing-algs.patch
 crypto-talitos-fix-sha224.patch
 crypto-talitos-fix-hashing.patch
+security-keys-properly-zero-out-sensitive-key-material-in-big_key.patch
+security-keys-rewrite-all-of-big_key-crypto.patch
+keys-fix-writing-past-end-of-user-supplied-buffer-in-keyring_read.patch
+keys-prevent-creating-a-different-user-s-keyrings.patch
 crypto-af_alg-remove-sgl-terminator-indicator-when-chaining.patch