[Bionic,1/1] Revert "crypto: hash - prevent using keyed hashes without setting key"

Message ID ed3754277de594fc0157bf7386bd2abf9911fce1.1522439362.git.joseph.salisbury@canonical.com
State New
Headers show
Series
  • Revert "crypto: hash - prevent using keyed hashes without setting key"
Related show

Commit Message

Joseph Salisbury April 3, 2018, 5:47 p.m.
BugLink: http://bugs.launchpad.net/bugs/1759791

This reverts commit 9fa68f620041be04720d0cbfb1bd3ddfc6310b24.
---
 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, 60 insertions(+), 75 deletions(-)

Patch

diff --git a/crypto/ahash.c b/crypto/ahash.c
index 266fc1d..d2c8895 100644
--- a/crypto/ahash.c
+++ b/crypto/ahash.c
@@ -193,18 +193,11 @@  int crypto_ahash_setkey(struct crypto_ahash *tfm, const u8 *key,
 			unsigned int keylen)
 {
 	unsigned long alignmask = crypto_ahash_alignmask(tfm);
-	int err;
 
 	if ((unsigned long)key & alignmask)
-		err = ahash_setkey_unaligned(tfm, key, keylen);
-	else
-		err = tfm->setkey(tfm, key, keylen);
-
-	if (err)
-		return err;
+		return ahash_setkey_unaligned(tfm, key, keylen);
 
-	crypto_ahash_clear_flags(tfm, CRYPTO_TFM_NEED_KEY);
-	return 0;
+	return tfm->setkey(tfm, key, keylen);
 }
 EXPORT_SYMBOL_GPL(crypto_ahash_setkey);
 
@@ -375,12 +368,7 @@  EXPORT_SYMBOL_GPL(crypto_ahash_finup);
 
 int crypto_ahash_digest(struct ahash_request *req)
 {
-	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);
+	return crypto_ahash_op(req, crypto_ahash_reqtfm(req)->digest);
 }
 EXPORT_SYMBOL_GPL(crypto_ahash_digest);
 
@@ -462,6 +450,7 @@  static int crypto_ahash_init_tfm(struct crypto_tfm *tfm)
 	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;
 
@@ -476,8 +465,7 @@  static int crypto_ahash_init_tfm(struct crypto_tfm *tfm)
 
 	if (alg->setkey) {
 		hash->setkey = alg->setkey;
-		if (!(alg->halg.base.cra_flags & CRYPTO_ALG_OPTIONAL_KEY))
-			crypto_ahash_set_flags(hash, CRYPTO_TFM_NEED_KEY);
+		hash->has_setkey = true;
 	}
 	if (alg->export)
 		hash->export = alg->export;
diff --git a/crypto/algif_hash.c b/crypto/algif_hash.c
index 6c9b192..76d2e71 100644
--- a/crypto/algif_hash.c
+++ b/crypto/algif_hash.c
@@ -34,6 +34,11 @@  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;
@@ -302,7 +307,7 @@  static int hash_check_key(struct socket *sock)
 	int err = 0;
 	struct sock *psk;
 	struct alg_sock *pask;
-	struct crypto_ahash *tfm;
+	struct algif_hash_tfm *tfm;
 	struct sock *sk = sock->sk;
 	struct alg_sock *ask = alg_sk(sk);
 
@@ -316,7 +321,7 @@  static int hash_check_key(struct socket *sock)
 
 	err = -ENOKEY;
 	lock_sock_nested(psk, SINGLE_DEPTH_NESTING);
-	if (crypto_ahash_get_flags(tfm) & CRYPTO_TFM_NEED_KEY)
+	if (!tfm->has_key)
 		goto unlock;
 
 	if (!pask->refcnt++)
@@ -407,17 +412,41 @@  static struct proto_ops algif_hash_ops_nokey = {
 
 static void *hash_bind(const char *name, u32 type, u32 mask)
 {
-	return crypto_alloc_ahash(name, type, 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;
 }
 
 static void hash_release(void *private)
 {
-	crypto_free_ahash(private);
+	struct algif_hash_tfm *tfm = private;
+
+	crypto_free_ahash(tfm->hash);
+	kfree(tfm);
 }
 
 static int hash_setkey(void *private, const u8 *key, unsigned int keylen)
 {
-	return crypto_ahash_setkey(private, key, keylen);
+	struct algif_hash_tfm *tfm = private;
+	int err;
+
+	err = crypto_ahash_setkey(tfm->hash, key, keylen);
+	tfm->has_key = !err;
+
+	return err;
 }
 
 static void hash_sock_destruct(struct sock *sk)
@@ -432,10 +461,11 @@  static void hash_sock_destruct(struct sock *sk)
 
 static int hash_accept_parent_nokey(void *private, struct sock *sk)
 {
-	struct crypto_ahash *tfm = private;
-	struct alg_sock *ask = alg_sk(sk);
 	struct hash_ctx *ctx;
-	unsigned int len = sizeof(*ctx) + crypto_ahash_reqsize(tfm);
+	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);
 
 	ctx = sock_kmalloc(sk, len, GFP_KERNEL);
 	if (!ctx)
@@ -448,7 +478,7 @@  static int hash_accept_parent_nokey(void *private, struct sock *sk)
 
 	ask->private = ctx;
 
-	ahash_request_set_tfm(&ctx->req, tfm);
+	ahash_request_set_tfm(&ctx->req, hash);
 	ahash_request_set_callback(&ctx->req, CRYPTO_TFM_REQ_MAY_BACKLOG,
 				   crypto_req_done, &ctx->wait);
 
@@ -459,9 +489,9 @@  static int hash_accept_parent_nokey(void *private, struct sock *sk)
 
 static int hash_accept_parent(void *private, struct sock *sk)
 {
-	struct crypto_ahash *tfm = private;
+	struct algif_hash_tfm *tfm = private;
 
-	if (crypto_ahash_get_flags(tfm) & CRYPTO_TFM_NEED_KEY)
+	if (!tfm->has_key && crypto_ahash_has_setkey(tfm->hash))
 		return -ENOKEY;
 
 	return hash_accept_parent_nokey(private, sk);
diff --git a/crypto/shash.c b/crypto/shash.c
index 5d732c6..e849d3e 100644
--- a/crypto/shash.c
+++ b/crypto/shash.c
@@ -58,18 +58,11 @@  int crypto_shash_setkey(struct crypto_shash *tfm, const u8 *key,
 {
 	struct shash_alg *shash = crypto_shash_alg(tfm);
 	unsigned long alignmask = crypto_shash_alignmask(tfm);
-	int err;
 
 	if ((unsigned long)key & alignmask)
-		err = shash_setkey_unaligned(tfm, key, keylen);
-	else
-		err = shash->setkey(tfm, key, keylen);
-
-	if (err)
-		return err;
+		return shash_setkey_unaligned(tfm, key, keylen);
 
-	crypto_shash_clear_flags(tfm, CRYPTO_TFM_NEED_KEY);
-	return 0;
+	return shash->setkey(tfm, key, keylen);
 }
 EXPORT_SYMBOL_GPL(crypto_shash_setkey);
 
@@ -188,9 +181,6 @@  int crypto_shash_digest(struct shash_desc *desc, const u8 *data,
 	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);
 
@@ -370,8 +360,7 @@  int crypto_init_shash_ops_async(struct crypto_tfm *tfm)
 	crt->digest = shash_async_digest;
 	crt->setkey = shash_async_setkey;
 
-	crypto_ahash_set_flags(crt, crypto_shash_get_flags(shash) &
-				    CRYPTO_TFM_NEED_KEY);
+	crt->has_setkey = alg->setkey != shash_no_setkey;
 
 	if (alg->export)
 		crt->export = shash_async_export;
@@ -386,14 +375,8 @@  int crypto_init_shash_ops_async(struct crypto_tfm *tfm)
 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;
 }
 
diff --git a/include/crypto/hash.h b/include/crypto/hash.h
index 3880793..0ed31fd 100644
--- a/include/crypto/hash.h
+++ b/include/crypto/hash.h
@@ -210,6 +210,7 @@  struct crypto_ahash {
 		      unsigned int keylen);
 
 	unsigned int reqsize;
+	bool has_setkey;
 	struct crypto_tfm base;
 };
 
@@ -409,6 +410,11 @@  static inline void *ahash_request_ctx(struct ahash_request *req)
 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,12 +487,7 @@  static inline int crypto_ahash_export(struct ahash_request *req, void *out)
  */
 static inline int crypto_ahash_import(struct ahash_request *req, const void *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);
+	return crypto_ahash_reqtfm(req)->import(req, in);
 }
 
 /**
@@ -502,12 +503,7 @@  static inline int crypto_ahash_import(struct ahash_request *req, const void *in)
  */
 static inline int crypto_ahash_init(struct ahash_request *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);
+	return crypto_ahash_reqtfm(req)->init(req);
 }
 
 /**
@@ -859,12 +855,7 @@  static inline int crypto_shash_export(struct shash_desc *desc, void *out)
  */
 static inline int crypto_shash_import(struct shash_desc *desc, const void *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);
+	return crypto_shash_alg(desc->tfm)->import(desc, in);
 }
 
 /**
@@ -880,12 +871,7 @@  static inline int crypto_shash_import(struct shash_desc *desc, const void *in)
  */
 static inline int crypto_shash_init(struct shash_desc *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);
+	return crypto_shash_alg(desc->tfm)->init(desc);
 }
 
 /**
diff --git a/include/linux/crypto.h b/include/linux/crypto.h
index 29c4257..72e47b3 100644
--- a/include/linux/crypto.h
+++ b/include/linux/crypto.h
@@ -115,8 +115,6 @@ 
 /*
  * 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