From: Greg Kroah-Hartman Date: Wed, 14 Feb 2018 18:57:37 +0000 (+0100) Subject: 4.14-stable patches X-Git-Tag: v4.15.4~32 X-Git-Url: http://git.ipfire.org/gitweb.cgi?a=commitdiff_plain;h=bddd95c3c664d9819a7ff191944b3c3ce50ee81a;p=thirdparty%2Fkernel%2Fstable-queue.git 4.14-stable patches added patches: crypto-cryptd-pass-through-absence-of-setkey.patch crypto-hash-annotate-algorithms-taking-optional-key.patch crypto-hash-introduce-crypto_hash_alg_has_setkey.patch crypto-hash-prevent-using-keyed-hashes-without-setting-key.patch crypto-mcryptd-pass-through-absence-of-setkey.patch crypto-poly1305-remove-setkey-method.patch --- diff --git a/queue-4.14/crypto-cryptd-pass-through-absence-of-setkey.patch b/queue-4.14/crypto-cryptd-pass-through-absence-of-setkey.patch new file mode 100644 index 00000000000..a9417557645 --- /dev/null +++ b/queue-4.14/crypto-cryptd-pass-through-absence-of-setkey.patch @@ -0,0 +1,34 @@ +From 841a3ff329713f796a63356fef6e2f72e4a3f6a3 Mon Sep 17 00:00:00 2001 +From: Eric Biggers +Date: Wed, 3 Jan 2018 11:16:23 -0800 +Subject: crypto: cryptd - pass through absence of ->setkey() + +From: Eric Biggers + +commit 841a3ff329713f796a63356fef6e2f72e4a3f6a3 upstream. + +When the cryptd template is used to wrap an unkeyed hash algorithm, +don't install a ->setkey() method to the cryptd instance. This change +is necessary for cryptd to keep working with unkeyed hash algorithms +once we start enforcing that ->setkey() is called when present. + +Signed-off-by: Eric Biggers +Signed-off-by: Herbert Xu +Signed-off-by: Greg Kroah-Hartman + +--- + crypto/cryptd.c | 3 ++- + 1 file changed, 2 insertions(+), 1 deletion(-) + +--- a/crypto/cryptd.c ++++ b/crypto/cryptd.c +@@ -913,7 +913,8 @@ static int cryptd_create_hash(struct cry + inst->alg.finup = cryptd_hash_finup_enqueue; + inst->alg.export = cryptd_hash_export; + inst->alg.import = cryptd_hash_import; +- inst->alg.setkey = cryptd_hash_setkey; ++ if (crypto_shash_alg_has_setkey(salg)) ++ inst->alg.setkey = cryptd_hash_setkey; + inst->alg.digest = cryptd_hash_digest_enqueue; + + err = ahash_register_instance(tmpl, inst); diff --git a/queue-4.14/crypto-hash-annotate-algorithms-taking-optional-key.patch b/queue-4.14/crypto-hash-annotate-algorithms-taking-optional-key.patch new file mode 100644 index 00000000000..fc1b1455ff2 --- /dev/null +++ b/queue-4.14/crypto-hash-annotate-algorithms-taking-optional-key.patch @@ -0,0 +1,258 @@ +From a208fa8f33031b9e0aba44c7d1b7e68eb0cbd29e Mon Sep 17 00:00:00 2001 +From: Eric Biggers +Date: Wed, 3 Jan 2018 11:16:26 -0800 +Subject: crypto: hash - annotate algorithms taking optional key + +From: Eric Biggers + +commit a208fa8f33031b9e0aba44c7d1b7e68eb0cbd29e upstream. + +We need to consistently enforce that keyed hashes cannot be used without +setting the key. To do this we need a reliable way to determine whether +a given hash algorithm is keyed or not. AF_ALG currently does this by +checking for the presence of a ->setkey() method. However, this is +actually slightly broken because the CRC-32 algorithms implement +->setkey() but can also be used without a key. (The CRC-32 "key" is not +actually a cryptographic key but rather represents the initial state. +If not overridden, then a default initial state is used.) + +Prepare to fix this by introducing a flag CRYPTO_ALG_OPTIONAL_KEY which +indicates that the algorithm has a ->setkey() method, but it is not +required to be called. Then set it on all the CRC-32 algorithms. + +The same also applies to the Adler-32 implementation in Lustre. + +Also, the cryptd and mcryptd templates have to pass through the flag +from their underlying algorithm. + +Signed-off-by: Eric Biggers +Signed-off-by: Herbert Xu +Signed-off-by: Greg Kroah-Hartman + +--- + arch/arm/crypto/crc32-ce-glue.c | 2 ++ + arch/arm64/crypto/crc32-ce-glue.c | 2 ++ + arch/powerpc/crypto/crc32c-vpmsum_glue.c | 1 + + arch/s390/crypto/crc32-vx.c | 3 +++ + arch/sparc/crypto/crc32c_glue.c | 1 + + arch/x86/crypto/crc32-pclmul_glue.c | 1 + + arch/x86/crypto/crc32c-intel_glue.c | 1 + + crypto/crc32_generic.c | 1 + + crypto/crc32c_generic.c | 1 + + crypto/cryptd.c | 7 +++---- + crypto/mcryptd.c | 7 +++---- + drivers/crypto/bfin_crc.c | 3 ++- + drivers/crypto/stm32/stm32_crc32.c | 2 ++ + drivers/staging/lustre/lnet/libcfs/linux/linux-crypto-adler.c | 1 + + include/linux/crypto.h | 6 ++++++ + 15 files changed, 30 insertions(+), 9 deletions(-) + +--- a/arch/arm/crypto/crc32-ce-glue.c ++++ b/arch/arm/crypto/crc32-ce-glue.c +@@ -188,6 +188,7 @@ static struct shash_alg crc32_pmull_algs + .base.cra_name = "crc32", + .base.cra_driver_name = "crc32-arm-ce", + .base.cra_priority = 200, ++ .base.cra_flags = CRYPTO_ALG_OPTIONAL_KEY, + .base.cra_blocksize = 1, + .base.cra_module = THIS_MODULE, + }, { +@@ -203,6 +204,7 @@ static struct shash_alg crc32_pmull_algs + .base.cra_name = "crc32c", + .base.cra_driver_name = "crc32c-arm-ce", + .base.cra_priority = 200, ++ .base.cra_flags = CRYPTO_ALG_OPTIONAL_KEY, + .base.cra_blocksize = 1, + .base.cra_module = THIS_MODULE, + } }; +--- a/arch/arm64/crypto/crc32-ce-glue.c ++++ b/arch/arm64/crypto/crc32-ce-glue.c +@@ -185,6 +185,7 @@ static struct shash_alg crc32_pmull_algs + .base.cra_name = "crc32", + .base.cra_driver_name = "crc32-arm64-ce", + .base.cra_priority = 200, ++ .base.cra_flags = CRYPTO_ALG_OPTIONAL_KEY, + .base.cra_blocksize = 1, + .base.cra_module = THIS_MODULE, + }, { +@@ -200,6 +201,7 @@ static struct shash_alg crc32_pmull_algs + .base.cra_name = "crc32c", + .base.cra_driver_name = "crc32c-arm64-ce", + .base.cra_priority = 200, ++ .base.cra_flags = CRYPTO_ALG_OPTIONAL_KEY, + .base.cra_blocksize = 1, + .base.cra_module = THIS_MODULE, + } }; +--- a/arch/powerpc/crypto/crc32c-vpmsum_glue.c ++++ b/arch/powerpc/crypto/crc32c-vpmsum_glue.c +@@ -141,6 +141,7 @@ static struct shash_alg alg = { + .cra_name = "crc32c", + .cra_driver_name = "crc32c-vpmsum", + .cra_priority = 200, ++ .cra_flags = CRYPTO_ALG_OPTIONAL_KEY, + .cra_blocksize = CHKSUM_BLOCK_SIZE, + .cra_ctxsize = sizeof(u32), + .cra_module = THIS_MODULE, +--- a/arch/s390/crypto/crc32-vx.c ++++ b/arch/s390/crypto/crc32-vx.c +@@ -238,6 +238,7 @@ static struct shash_alg crc32_vx_algs[] + .cra_name = "crc32", + .cra_driver_name = "crc32-vx", + .cra_priority = 200, ++ .cra_flags = CRYPTO_ALG_OPTIONAL_KEY, + .cra_blocksize = CRC32_BLOCK_SIZE, + .cra_ctxsize = sizeof(struct crc_ctx), + .cra_module = THIS_MODULE, +@@ -258,6 +259,7 @@ static struct shash_alg crc32_vx_algs[] + .cra_name = "crc32be", + .cra_driver_name = "crc32be-vx", + .cra_priority = 200, ++ .cra_flags = CRYPTO_ALG_OPTIONAL_KEY, + .cra_blocksize = CRC32_BLOCK_SIZE, + .cra_ctxsize = sizeof(struct crc_ctx), + .cra_module = THIS_MODULE, +@@ -278,6 +280,7 @@ static struct shash_alg crc32_vx_algs[] + .cra_name = "crc32c", + .cra_driver_name = "crc32c-vx", + .cra_priority = 200, ++ .cra_flags = CRYPTO_ALG_OPTIONAL_KEY, + .cra_blocksize = CRC32_BLOCK_SIZE, + .cra_ctxsize = sizeof(struct crc_ctx), + .cra_module = THIS_MODULE, +--- a/arch/sparc/crypto/crc32c_glue.c ++++ b/arch/sparc/crypto/crc32c_glue.c +@@ -133,6 +133,7 @@ static struct shash_alg alg = { + .cra_name = "crc32c", + .cra_driver_name = "crc32c-sparc64", + .cra_priority = SPARC_CR_OPCODE_PRIORITY, ++ .cra_flags = CRYPTO_ALG_OPTIONAL_KEY, + .cra_blocksize = CHKSUM_BLOCK_SIZE, + .cra_ctxsize = sizeof(u32), + .cra_alignmask = 7, +--- a/arch/x86/crypto/crc32-pclmul_glue.c ++++ b/arch/x86/crypto/crc32-pclmul_glue.c +@@ -162,6 +162,7 @@ static struct shash_alg alg = { + .cra_name = "crc32", + .cra_driver_name = "crc32-pclmul", + .cra_priority = 200, ++ .cra_flags = CRYPTO_ALG_OPTIONAL_KEY, + .cra_blocksize = CHKSUM_BLOCK_SIZE, + .cra_ctxsize = sizeof(u32), + .cra_module = THIS_MODULE, +--- a/arch/x86/crypto/crc32c-intel_glue.c ++++ b/arch/x86/crypto/crc32c-intel_glue.c +@@ -226,6 +226,7 @@ static struct shash_alg alg = { + .cra_name = "crc32c", + .cra_driver_name = "crc32c-intel", + .cra_priority = 200, ++ .cra_flags = CRYPTO_ALG_OPTIONAL_KEY, + .cra_blocksize = CHKSUM_BLOCK_SIZE, + .cra_ctxsize = sizeof(u32), + .cra_module = THIS_MODULE, +--- a/crypto/crc32_generic.c ++++ b/crypto/crc32_generic.c +@@ -133,6 +133,7 @@ static struct shash_alg alg = { + .cra_name = "crc32", + .cra_driver_name = "crc32-generic", + .cra_priority = 100, ++ .cra_flags = CRYPTO_ALG_OPTIONAL_KEY, + .cra_blocksize = CHKSUM_BLOCK_SIZE, + .cra_ctxsize = sizeof(u32), + .cra_module = THIS_MODULE, +--- a/crypto/crc32c_generic.c ++++ b/crypto/crc32c_generic.c +@@ -146,6 +146,7 @@ static struct shash_alg alg = { + .cra_name = "crc32c", + .cra_driver_name = "crc32c-generic", + .cra_priority = 100, ++ .cra_flags = CRYPTO_ALG_OPTIONAL_KEY, + .cra_blocksize = CHKSUM_BLOCK_SIZE, + .cra_alignmask = 3, + .cra_ctxsize = sizeof(struct chksum_ctx), +--- a/crypto/cryptd.c ++++ b/crypto/cryptd.c +@@ -895,10 +895,9 @@ static int cryptd_create_hash(struct cry + if (err) + goto out_free_inst; + +- type = CRYPTO_ALG_ASYNC; +- if (alg->cra_flags & CRYPTO_ALG_INTERNAL) +- type |= CRYPTO_ALG_INTERNAL; +- inst->alg.halg.base.cra_flags = type; ++ inst->alg.halg.base.cra_flags = CRYPTO_ALG_ASYNC | ++ (alg->cra_flags & (CRYPTO_ALG_INTERNAL | ++ CRYPTO_ALG_OPTIONAL_KEY)); + + inst->alg.halg.digestsize = salg->digestsize; + inst->alg.halg.statesize = salg->statesize; +--- a/crypto/mcryptd.c ++++ b/crypto/mcryptd.c +@@ -517,10 +517,9 @@ static int mcryptd_create_hash(struct cr + if (err) + goto out_free_inst; + +- type = CRYPTO_ALG_ASYNC; +- if (alg->cra_flags & CRYPTO_ALG_INTERNAL) +- type |= CRYPTO_ALG_INTERNAL; +- inst->alg.halg.base.cra_flags = type; ++ inst->alg.halg.base.cra_flags = CRYPTO_ALG_ASYNC | ++ (alg->cra_flags & (CRYPTO_ALG_INTERNAL | ++ CRYPTO_ALG_OPTIONAL_KEY)); + + inst->alg.halg.digestsize = halg->digestsize; + inst->alg.halg.statesize = halg->statesize; +--- a/drivers/crypto/bfin_crc.c ++++ b/drivers/crypto/bfin_crc.c +@@ -494,7 +494,8 @@ static struct ahash_alg algs = { + .cra_driver_name = DRIVER_NAME, + .cra_priority = 100, + .cra_flags = CRYPTO_ALG_TYPE_AHASH | +- CRYPTO_ALG_ASYNC, ++ CRYPTO_ALG_ASYNC | ++ CRYPTO_ALG_OPTIONAL_KEY, + .cra_blocksize = CHKSUM_BLOCK_SIZE, + .cra_ctxsize = sizeof(struct bfin_crypto_crc_ctx), + .cra_alignmask = 3, +--- a/drivers/crypto/stm32/stm32_crc32.c ++++ b/drivers/crypto/stm32/stm32_crc32.c +@@ -208,6 +208,7 @@ static struct shash_alg algs[] = { + .cra_name = "crc32", + .cra_driver_name = DRIVER_NAME, + .cra_priority = 200, ++ .cra_flags = CRYPTO_ALG_OPTIONAL_KEY, + .cra_blocksize = CHKSUM_BLOCK_SIZE, + .cra_alignmask = 3, + .cra_ctxsize = sizeof(struct stm32_crc_ctx), +@@ -229,6 +230,7 @@ static struct shash_alg algs[] = { + .cra_name = "crc32c", + .cra_driver_name = DRIVER_NAME, + .cra_priority = 200, ++ .cra_flags = CRYPTO_ALG_OPTIONAL_KEY, + .cra_blocksize = CHKSUM_BLOCK_SIZE, + .cra_alignmask = 3, + .cra_ctxsize = sizeof(struct stm32_crc_ctx), +--- a/drivers/staging/lustre/lnet/libcfs/linux/linux-crypto-adler.c ++++ b/drivers/staging/lustre/lnet/libcfs/linux/linux-crypto-adler.c +@@ -119,6 +119,7 @@ static struct shash_alg alg = { + .cra_name = "adler32", + .cra_driver_name = "adler32-zlib", + .cra_priority = 100, ++ .cra_flags = CRYPTO_ALG_OPTIONAL_KEY, + .cra_blocksize = CHKSUM_BLOCK_SIZE, + .cra_ctxsize = sizeof(u32), + .cra_module = THIS_MODULE, +--- a/include/linux/crypto.h ++++ b/include/linux/crypto.h +@@ -106,6 +106,12 @@ + #define CRYPTO_ALG_INTERNAL 0x00002000 + + /* ++ * Set if the algorithm has a ->setkey() method but can be used without ++ * calling it first, i.e. there is a default key. ++ */ ++#define CRYPTO_ALG_OPTIONAL_KEY 0x00004000 ++ ++/* + * Transform masks and values (for crt_flags). + */ + #define CRYPTO_TFM_REQ_MASK 0x000fff00 diff --git a/queue-4.14/crypto-hash-introduce-crypto_hash_alg_has_setkey.patch b/queue-4.14/crypto-hash-introduce-crypto_hash_alg_has_setkey.patch new file mode 100644 index 00000000000..e6042523a30 --- /dev/null +++ b/queue-4.14/crypto-hash-introduce-crypto_hash_alg_has_setkey.patch @@ -0,0 +1,55 @@ +From cd6ed77ad5d223dc6299fb58f62e0f5267f7e2ba Mon Sep 17 00:00:00 2001 +From: Eric Biggers +Date: Wed, 3 Jan 2018 11:16:22 -0800 +Subject: crypto: hash - introduce crypto_hash_alg_has_setkey() + +From: Eric Biggers + +commit cd6ed77ad5d223dc6299fb58f62e0f5267f7e2ba upstream. + +Templates that use an shash spawn can use crypto_shash_alg_has_setkey() +to determine whether the underlying algorithm requires a key or not. +But there was no corresponding function for ahash spawns. Add it. + +Note that the new function actually has to support both shash and ahash +algorithms, since the ahash API can be used with either. + +Signed-off-by: Eric Biggers +Signed-off-by: Herbert Xu +Signed-off-by: Greg Kroah-Hartman + +--- + crypto/ahash.c | 11 +++++++++++ + include/crypto/internal/hash.h | 2 ++ + 2 files changed, 13 insertions(+) + +--- a/crypto/ahash.c ++++ b/crypto/ahash.c +@@ -655,5 +655,16 @@ struct hash_alg_common *ahash_attr_alg(s + } + EXPORT_SYMBOL_GPL(ahash_attr_alg); + ++bool crypto_hash_alg_has_setkey(struct hash_alg_common *halg) ++{ ++ struct crypto_alg *alg = &halg->base; ++ ++ if (alg->cra_type != &crypto_ahash_type) ++ return crypto_shash_alg_has_setkey(__crypto_shash_alg(alg)); ++ ++ return __crypto_ahash_alg(alg)->setkey != NULL; ++} ++EXPORT_SYMBOL_GPL(crypto_hash_alg_has_setkey); ++ + MODULE_LICENSE("GPL"); + MODULE_DESCRIPTION("Asynchronous cryptographic hash type"); +--- a/include/crypto/internal/hash.h ++++ b/include/crypto/internal/hash.h +@@ -90,6 +90,8 @@ static inline bool crypto_shash_alg_has_ + return alg->setkey != shash_no_setkey; + } + ++bool crypto_hash_alg_has_setkey(struct hash_alg_common *halg); ++ + int crypto_init_ahash_spawn(struct crypto_ahash_spawn *spawn, + struct hash_alg_common *alg, + struct crypto_instance *inst); diff --git a/queue-4.14/crypto-hash-prevent-using-keyed-hashes-without-setting-key.patch b/queue-4.14/crypto-hash-prevent-using-keyed-hashes-without-setting-key.patch new file mode 100644 index 00000000000..b943325f72d --- /dev/null +++ b/queue-4.14/crypto-hash-prevent-using-keyed-hashes-without-setting-key.patch @@ -0,0 +1,368 @@ +From 9fa68f620041be04720d0cbfb1bd3ddfc6310b24 Mon Sep 17 00:00:00 2001 +From: Eric Biggers +Date: Wed, 3 Jan 2018 11:16:27 -0800 +Subject: crypto: hash - prevent using keyed hashes without setting key + +From: Eric Biggers + +commit 9fa68f620041be04720d0cbfb1bd3ddfc6310b24 upstream. + +Currently, almost none of the keyed hash algorithms check whether a key +has been set before proceeding. Some algorithms are okay with this and +will effectively just use a key of all 0's or some other bogus default. +However, others will severely break, as demonstrated using +"hmac(sha3-512-generic)", the unkeyed use of which causes a kernel crash +via a (potentially exploitable) stack buffer overflow. + +A while ago, this problem was solved for AF_ALG by pairing each hash +transform with a 'has_key' bool. However, there are still other places +in the kernel where userspace can specify an arbitrary hash algorithm by +name, and the kernel uses it as unkeyed hash without checking whether it +is really unkeyed. Examples of this include: + + - KEYCTL_DH_COMPUTE, via the KDF extension + - dm-verity + - dm-crypt, via the ESSIV support + - dm-integrity, via the "internal hash" mode with no key given + - drbd (Distributed Replicated Block Device) + +This bug is especially bad for KEYCTL_DH_COMPUTE as that requires no +privileges to call. + +Fix the bug for all users by adding a flag CRYPTO_TFM_NEED_KEY to the +->crt_flags of each hash transform that indicates whether the transform +still needs to be keyed or not. Then, make the hash init, import, and +digest functions return -ENOKEY if the key is still needed. + +The new flag also replaces the 'has_key' bool which algif_hash was +previously using, thereby simplifying the algif_hash implementation. + +Reported-by: syzbot +Signed-off-by: Eric Biggers +Signed-off-by: Herbert Xu +Signed-off-by: Greg Kroah-Hartman + +--- + crypto/ahash.c | 22 ++++++++++++++++---- + crypto/algif_hash.c | 52 ++++++++++--------------------------------------- + crypto/shash.c | 25 +++++++++++++++++++---- + include/crypto/hash.h | 34 ++++++++++++++++++++++---------- + include/linux/crypto.h | 2 + + 5 files changed, 75 insertions(+), 60 deletions(-) + +--- a/crypto/ahash.c ++++ b/crypto/ahash.c +@@ -193,11 +193,18 @@ int crypto_ahash_setkey(struct crypto_ah + unsigned int keylen) + { + unsigned long alignmask = crypto_ahash_alignmask(tfm); ++ int err; + + if ((unsigned long)key & alignmask) +- return ahash_setkey_unaligned(tfm, key, keylen); ++ err = ahash_setkey_unaligned(tfm, key, keylen); ++ else ++ err = tfm->setkey(tfm, key, keylen); ++ ++ if (err) ++ return err; + +- return tfm->setkey(tfm, key, keylen); ++ crypto_ahash_clear_flags(tfm, CRYPTO_TFM_NEED_KEY); ++ return 0; + } + EXPORT_SYMBOL_GPL(crypto_ahash_setkey); + +@@ -370,7 +377,12 @@ EXPORT_SYMBOL_GPL(crypto_ahash_finup); + + int crypto_ahash_digest(struct ahash_request *req) + { +- return crypto_ahash_op(req, crypto_ahash_reqtfm(req)->digest); ++ struct crypto_ahash *tfm = crypto_ahash_reqtfm(req); ++ ++ if (crypto_ahash_get_flags(tfm) & CRYPTO_TFM_NEED_KEY) ++ return -ENOKEY; ++ ++ return crypto_ahash_op(req, tfm->digest); + } + EXPORT_SYMBOL_GPL(crypto_ahash_digest); + +@@ -456,7 +468,6 @@ static int crypto_ahash_init_tfm(struct + struct ahash_alg *alg = crypto_ahash_alg(hash); + + hash->setkey = ahash_nosetkey; +- hash->has_setkey = false; + hash->export = ahash_no_export; + hash->import = ahash_no_import; + +@@ -471,7 +482,8 @@ static int crypto_ahash_init_tfm(struct + + if (alg->setkey) { + hash->setkey = alg->setkey; +- hash->has_setkey = true; ++ if (!(alg->halg.base.cra_flags & CRYPTO_ALG_OPTIONAL_KEY)) ++ crypto_ahash_set_flags(hash, CRYPTO_TFM_NEED_KEY); + } + if (alg->export) + hash->export = alg->export; +--- a/crypto/algif_hash.c ++++ b/crypto/algif_hash.c +@@ -34,11 +34,6 @@ struct hash_ctx { + struct ahash_request req; + }; + +-struct algif_hash_tfm { +- struct crypto_ahash *hash; +- bool has_key; +-}; +- + static int hash_alloc_result(struct sock *sk, struct hash_ctx *ctx) + { + unsigned ds; +@@ -309,7 +304,7 @@ static int hash_check_key(struct socket + int err = 0; + struct sock *psk; + struct alg_sock *pask; +- struct algif_hash_tfm *tfm; ++ struct crypto_ahash *tfm; + struct sock *sk = sock->sk; + struct alg_sock *ask = alg_sk(sk); + +@@ -323,7 +318,7 @@ static int hash_check_key(struct socket + + err = -ENOKEY; + lock_sock_nested(psk, SINGLE_DEPTH_NESTING); +- if (!tfm->has_key) ++ if (crypto_ahash_get_flags(tfm) & CRYPTO_TFM_NEED_KEY) + goto unlock; + + if (!pask->refcnt++) +@@ -414,41 +409,17 @@ static struct proto_ops algif_hash_ops_n + + static void *hash_bind(const char *name, u32 type, u32 mask) + { +- struct algif_hash_tfm *tfm; +- struct crypto_ahash *hash; +- +- tfm = kzalloc(sizeof(*tfm), GFP_KERNEL); +- if (!tfm) +- return ERR_PTR(-ENOMEM); +- +- hash = crypto_alloc_ahash(name, type, mask); +- if (IS_ERR(hash)) { +- kfree(tfm); +- return ERR_CAST(hash); +- } +- +- tfm->hash = hash; +- +- return tfm; ++ return crypto_alloc_ahash(name, type, mask); + } + + static void hash_release(void *private) + { +- struct algif_hash_tfm *tfm = private; +- +- crypto_free_ahash(tfm->hash); +- kfree(tfm); ++ crypto_free_ahash(private); + } + + static int hash_setkey(void *private, const u8 *key, unsigned int keylen) + { +- struct algif_hash_tfm *tfm = private; +- int err; +- +- err = crypto_ahash_setkey(tfm->hash, key, keylen); +- tfm->has_key = !err; +- +- return err; ++ return crypto_ahash_setkey(private, key, keylen); + } + + static void hash_sock_destruct(struct sock *sk) +@@ -463,11 +434,10 @@ static void hash_sock_destruct(struct so + + static int hash_accept_parent_nokey(void *private, struct sock *sk) + { +- struct hash_ctx *ctx; ++ struct crypto_ahash *tfm = private; + struct alg_sock *ask = alg_sk(sk); +- struct algif_hash_tfm *tfm = private; +- struct crypto_ahash *hash = tfm->hash; +- unsigned len = sizeof(*ctx) + crypto_ahash_reqsize(hash); ++ struct hash_ctx *ctx; ++ unsigned int len = sizeof(*ctx) + crypto_ahash_reqsize(tfm); + + ctx = sock_kmalloc(sk, len, GFP_KERNEL); + if (!ctx) +@@ -480,7 +450,7 @@ static int hash_accept_parent_nokey(void + + ask->private = ctx; + +- ahash_request_set_tfm(&ctx->req, hash); ++ ahash_request_set_tfm(&ctx->req, tfm); + ahash_request_set_callback(&ctx->req, CRYPTO_TFM_REQ_MAY_BACKLOG, + af_alg_complete, &ctx->completion); + +@@ -491,9 +461,9 @@ static int hash_accept_parent_nokey(void + + static int hash_accept_parent(void *private, struct sock *sk) + { +- struct algif_hash_tfm *tfm = private; ++ struct crypto_ahash *tfm = private; + +- if (!tfm->has_key && crypto_ahash_has_setkey(tfm->hash)) ++ if (crypto_ahash_get_flags(tfm) & CRYPTO_TFM_NEED_KEY) + return -ENOKEY; + + return hash_accept_parent_nokey(private, sk); +--- a/crypto/shash.c ++++ b/crypto/shash.c +@@ -58,11 +58,18 @@ int crypto_shash_setkey(struct crypto_sh + { + struct shash_alg *shash = crypto_shash_alg(tfm); + unsigned long alignmask = crypto_shash_alignmask(tfm); ++ int err; + + if ((unsigned long)key & alignmask) +- return shash_setkey_unaligned(tfm, key, keylen); ++ err = shash_setkey_unaligned(tfm, key, keylen); ++ else ++ err = shash->setkey(tfm, key, keylen); ++ ++ if (err) ++ return err; + +- return shash->setkey(tfm, key, keylen); ++ crypto_shash_clear_flags(tfm, CRYPTO_TFM_NEED_KEY); ++ return 0; + } + EXPORT_SYMBOL_GPL(crypto_shash_setkey); + +@@ -181,6 +188,9 @@ int crypto_shash_digest(struct shash_des + struct shash_alg *shash = crypto_shash_alg(tfm); + unsigned long alignmask = crypto_shash_alignmask(tfm); + ++ if (crypto_shash_get_flags(tfm) & CRYPTO_TFM_NEED_KEY) ++ return -ENOKEY; ++ + if (((unsigned long)data | (unsigned long)out) & alignmask) + return shash_digest_unaligned(desc, data, len, out); + +@@ -360,7 +370,8 @@ int crypto_init_shash_ops_async(struct c + crt->digest = shash_async_digest; + crt->setkey = shash_async_setkey; + +- crt->has_setkey = alg->setkey != shash_no_setkey; ++ crypto_ahash_set_flags(crt, crypto_shash_get_flags(shash) & ++ CRYPTO_TFM_NEED_KEY); + + if (alg->export) + crt->export = shash_async_export; +@@ -375,8 +386,14 @@ int crypto_init_shash_ops_async(struct c + static int crypto_shash_init_tfm(struct crypto_tfm *tfm) + { + struct crypto_shash *hash = __crypto_shash_cast(tfm); ++ struct shash_alg *alg = crypto_shash_alg(hash); ++ ++ hash->descsize = alg->descsize; ++ ++ if (crypto_shash_alg_has_setkey(alg) && ++ !(alg->base.cra_flags & CRYPTO_ALG_OPTIONAL_KEY)) ++ crypto_shash_set_flags(hash, CRYPTO_TFM_NEED_KEY); + +- hash->descsize = crypto_shash_alg(hash)->descsize; + return 0; + } + +--- a/include/crypto/hash.h ++++ b/include/crypto/hash.h +@@ -205,7 +205,6 @@ struct crypto_ahash { + unsigned int keylen); + + unsigned int reqsize; +- bool has_setkey; + struct crypto_tfm base; + }; + +@@ -405,11 +404,6 @@ static inline void *ahash_request_ctx(st + int crypto_ahash_setkey(struct crypto_ahash *tfm, const u8 *key, + unsigned int keylen); + +-static inline bool crypto_ahash_has_setkey(struct crypto_ahash *tfm) +-{ +- return tfm->has_setkey; +-} +- + /** + * crypto_ahash_finup() - update and finalize message digest + * @req: reference to the ahash_request handle that holds all information +@@ -481,7 +475,12 @@ static inline int crypto_ahash_export(st + */ + static inline int crypto_ahash_import(struct ahash_request *req, const void *in) + { +- return crypto_ahash_reqtfm(req)->import(req, in); ++ struct crypto_ahash *tfm = crypto_ahash_reqtfm(req); ++ ++ if (crypto_ahash_get_flags(tfm) & CRYPTO_TFM_NEED_KEY) ++ return -ENOKEY; ++ ++ return tfm->import(req, in); + } + + /** +@@ -498,7 +497,12 @@ static inline int crypto_ahash_import(st + */ + static inline int crypto_ahash_init(struct ahash_request *req) + { +- return crypto_ahash_reqtfm(req)->init(req); ++ struct crypto_ahash *tfm = crypto_ahash_reqtfm(req); ++ ++ if (crypto_ahash_get_flags(tfm) & CRYPTO_TFM_NEED_KEY) ++ return -ENOKEY; ++ ++ return tfm->init(req); + } + + /** +@@ -851,7 +855,12 @@ static inline int crypto_shash_export(st + */ + static inline int crypto_shash_import(struct shash_desc *desc, const void *in) + { +- return crypto_shash_alg(desc->tfm)->import(desc, in); ++ struct crypto_shash *tfm = desc->tfm; ++ ++ if (crypto_shash_get_flags(tfm) & CRYPTO_TFM_NEED_KEY) ++ return -ENOKEY; ++ ++ return crypto_shash_alg(tfm)->import(desc, in); + } + + /** +@@ -867,7 +876,12 @@ static inline int crypto_shash_import(st + */ + static inline int crypto_shash_init(struct shash_desc *desc) + { +- return crypto_shash_alg(desc->tfm)->init(desc); ++ struct crypto_shash *tfm = desc->tfm; ++ ++ if (crypto_shash_get_flags(tfm) & CRYPTO_TFM_NEED_KEY) ++ return -ENOKEY; ++ ++ return crypto_shash_alg(tfm)->init(desc); + } + + /** +--- a/include/linux/crypto.h ++++ b/include/linux/crypto.h +@@ -114,6 +114,8 @@ + /* + * Transform masks and values (for crt_flags). + */ ++#define CRYPTO_TFM_NEED_KEY 0x00000001 ++ + #define CRYPTO_TFM_REQ_MASK 0x000fff00 + #define CRYPTO_TFM_RES_MASK 0xfff00000 + diff --git a/queue-4.14/crypto-mcryptd-pass-through-absence-of-setkey.patch b/queue-4.14/crypto-mcryptd-pass-through-absence-of-setkey.patch new file mode 100644 index 00000000000..5e4364f273d --- /dev/null +++ b/queue-4.14/crypto-mcryptd-pass-through-absence-of-setkey.patch @@ -0,0 +1,34 @@ +From fa59b92d299f2787e6bae1ff078ee0982e80211f Mon Sep 17 00:00:00 2001 +From: Eric Biggers +Date: Wed, 3 Jan 2018 11:16:24 -0800 +Subject: crypto: mcryptd - pass through absence of ->setkey() + +From: Eric Biggers + +commit fa59b92d299f2787e6bae1ff078ee0982e80211f upstream. + +When the mcryptd template is used to wrap an unkeyed hash algorithm, +don't install a ->setkey() method to the mcryptd instance. This change +is necessary for mcryptd to keep working with unkeyed hash algorithms +once we start enforcing that ->setkey() is called when present. + +Signed-off-by: Eric Biggers +Signed-off-by: Herbert Xu +Signed-off-by: Greg Kroah-Hartman + +--- + crypto/mcryptd.c | 3 ++- + 1 file changed, 2 insertions(+), 1 deletion(-) + +--- a/crypto/mcryptd.c ++++ b/crypto/mcryptd.c +@@ -535,7 +535,8 @@ static int mcryptd_create_hash(struct cr + inst->alg.finup = mcryptd_hash_finup_enqueue; + inst->alg.export = mcryptd_hash_export; + inst->alg.import = mcryptd_hash_import; +- inst->alg.setkey = mcryptd_hash_setkey; ++ if (crypto_hash_alg_has_setkey(halg)) ++ inst->alg.setkey = mcryptd_hash_setkey; + inst->alg.digest = mcryptd_hash_digest_enqueue; + + err = ahash_register_instance(tmpl, inst); diff --git a/queue-4.14/crypto-poly1305-remove-setkey-method.patch b/queue-4.14/crypto-poly1305-remove-setkey-method.patch new file mode 100644 index 00000000000..51544d6c5b0 --- /dev/null +++ b/queue-4.14/crypto-poly1305-remove-setkey-method.patch @@ -0,0 +1,90 @@ +From a16e772e664b9a261424107784804cffc8894977 Mon Sep 17 00:00:00 2001 +From: Eric Biggers +Date: Wed, 3 Jan 2018 11:16:25 -0800 +Subject: crypto: poly1305 - remove ->setkey() method + +From: Eric Biggers + +commit a16e772e664b9a261424107784804cffc8894977 upstream. + +Since Poly1305 requires a nonce per invocation, the Linux kernel +implementations of Poly1305 don't use the crypto API's keying mechanism +and instead expect the key and nonce as the first 32 bytes of the data. +But ->setkey() is still defined as a stub returning an error code. This +prevents Poly1305 from being used through AF_ALG and will also break it +completely once we start enforcing that all crypto API users (not just +AF_ALG) call ->setkey() if present. + +Fix it by removing crypto_poly1305_setkey(), leaving ->setkey as NULL. + +Signed-off-by: Eric Biggers +Signed-off-by: Herbert Xu +Signed-off-by: Greg Kroah-Hartman + +--- + arch/x86/crypto/poly1305_glue.c | 1 - + crypto/poly1305_generic.c | 17 +++++------------ + include/crypto/poly1305.h | 2 -- + 3 files changed, 5 insertions(+), 15 deletions(-) + +--- a/arch/x86/crypto/poly1305_glue.c ++++ b/arch/x86/crypto/poly1305_glue.c +@@ -164,7 +164,6 @@ static struct shash_alg alg = { + .init = poly1305_simd_init, + .update = poly1305_simd_update, + .final = crypto_poly1305_final, +- .setkey = crypto_poly1305_setkey, + .descsize = sizeof(struct poly1305_simd_desc_ctx), + .base = { + .cra_name = "poly1305", +--- a/crypto/poly1305_generic.c ++++ b/crypto/poly1305_generic.c +@@ -47,17 +47,6 @@ int crypto_poly1305_init(struct shash_de + } + EXPORT_SYMBOL_GPL(crypto_poly1305_init); + +-int crypto_poly1305_setkey(struct crypto_shash *tfm, +- const u8 *key, unsigned int keylen) +-{ +- /* Poly1305 requires a unique key for each tag, which implies that +- * we can't set it on the tfm that gets accessed by multiple users +- * simultaneously. Instead we expect the key as the first 32 bytes in +- * the update() call. */ +- return -ENOTSUPP; +-} +-EXPORT_SYMBOL_GPL(crypto_poly1305_setkey); +- + static void poly1305_setrkey(struct poly1305_desc_ctx *dctx, const u8 *key) + { + /* r &= 0xffffffc0ffffffc0ffffffc0fffffff */ +@@ -76,6 +65,11 @@ static void poly1305_setskey(struct poly + dctx->s[3] = get_unaligned_le32(key + 12); + } + ++/* ++ * Poly1305 requires a unique key for each tag, which implies that we can't set ++ * it on the tfm that gets accessed by multiple users simultaneously. Instead we ++ * expect the key as the first 32 bytes in the update() call. ++ */ + unsigned int crypto_poly1305_setdesckey(struct poly1305_desc_ctx *dctx, + const u8 *src, unsigned int srclen) + { +@@ -281,7 +275,6 @@ static struct shash_alg poly1305_alg = { + .init = crypto_poly1305_init, + .update = crypto_poly1305_update, + .final = crypto_poly1305_final, +- .setkey = crypto_poly1305_setkey, + .descsize = sizeof(struct poly1305_desc_ctx), + .base = { + .cra_name = "poly1305", +--- a/include/crypto/poly1305.h ++++ b/include/crypto/poly1305.h +@@ -31,8 +31,6 @@ struct poly1305_desc_ctx { + }; + + int crypto_poly1305_init(struct shash_desc *desc); +-int crypto_poly1305_setkey(struct crypto_shash *tfm, +- const u8 *key, unsigned int keylen); + unsigned int crypto_poly1305_setdesckey(struct poly1305_desc_ctx *dctx, + const u8 *src, unsigned int srclen); + int crypto_poly1305_update(struct shash_desc *desc, diff --git a/queue-4.14/series b/queue-4.14/series index 355421b56b8..ea02f0f3ec6 100644 --- a/queue-4.14/series +++ b/queue-4.14/series @@ -111,3 +111,9 @@ kernfs-fix-regression-in-kernfs_fop_write-caused-by-wrong-type.patch ahci-annotate-pci-ids-for-mobile-intel-chipsets-as-such.patch ahci-add-pci-ids-for-intel-bay-trail-cherry-trail-and-apollo-lake-ahci.patch ahci-add-intel-cannon-lake-pch-h-pci-id.patch +crypto-hash-introduce-crypto_hash_alg_has_setkey.patch +crypto-cryptd-pass-through-absence-of-setkey.patch +crypto-mcryptd-pass-through-absence-of-setkey.patch +crypto-poly1305-remove-setkey-method.patch +crypto-hash-annotate-algorithms-taking-optional-key.patch +crypto-hash-prevent-using-keyed-hashes-without-setting-key.patch