summary refs log tree commit diff
path: root/crypto
diff options
context:
space:
mode:
Diffstat (limited to 'crypto')
-rw-r--r--crypto/ahash.c2
-rw-r--r--crypto/algapi.c6
-rw-r--r--crypto/api.c35
-rw-r--r--crypto/authenc.c24
-rw-r--r--crypto/blkcipher.c2
-rw-r--r--crypto/ccm.c2
-rw-r--r--crypto/lrw.c8
-rw-r--r--crypto/scatterwalk.c3
-rw-r--r--crypto/shash.c7
9 files changed, 62 insertions, 27 deletions
diff --git a/crypto/ahash.c b/crypto/ahash.c
index ba5292d69ebd..b2d1ee32cfe8 100644
--- a/crypto/ahash.c
+++ b/crypto/ahash.c
@@ -214,7 +214,7 @@ static void crypto_ahash_show(struct seq_file *m, struct crypto_alg *alg)
 	seq_printf(m, "async        : %s\n", alg->cra_flags & CRYPTO_ALG_ASYNC ?
 					     "yes" : "no");
 	seq_printf(m, "blocksize    : %u\n", alg->cra_blocksize);
-	seq_printf(m, "digestsize   : %u\n", alg->cra_hash.digestsize);
+	seq_printf(m, "digestsize   : %u\n", alg->cra_ahash.digestsize);
 }
 
 const struct crypto_type crypto_ahash_type = {
diff --git a/crypto/algapi.c b/crypto/algapi.c
index 7c41e7405c41..56c62e2858d5 100644
--- a/crypto/algapi.c
+++ b/crypto/algapi.c
@@ -149,6 +149,9 @@ static struct crypto_larval *__crypto_register_alg(struct crypto_alg *alg)
 		if (q == alg)
 			goto err;
 
+		if (crypto_is_moribund(q))
+			continue;
+
 		if (crypto_is_larval(q)) {
 			if (!strcmp(alg->cra_driver_name, q->cra_driver_name))
 				goto err;
@@ -197,7 +200,7 @@ void crypto_alg_tested(const char *name, int err)
 
 	down_write(&crypto_alg_sem);
 	list_for_each_entry(q, &crypto_alg_list, cra_list) {
-		if (!crypto_is_larval(q))
+		if (crypto_is_moribund(q) || !crypto_is_larval(q))
 			continue;
 
 		test = (struct crypto_larval *)q;
@@ -210,6 +213,7 @@ void crypto_alg_tested(const char *name, int err)
 	goto unlock;
 
 found:
+	q->cra_flags |= CRYPTO_ALG_DEAD;
 	alg = test->adult;
 	if (err || list_empty(&alg->cra_list))
 		goto complete;
diff --git a/crypto/api.c b/crypto/api.c
index 9975a7bd246c..38a2bc02a98c 100644
--- a/crypto/api.c
+++ b/crypto/api.c
@@ -215,8 +215,19 @@ struct crypto_alg *crypto_larval_lookup(const char *name, u32 type, u32 mask)
 	mask &= ~(CRYPTO_ALG_LARVAL | CRYPTO_ALG_DEAD);
 	type &= mask;
 
-	alg = try_then_request_module(crypto_alg_lookup(name, type, mask),
-				      name);
+	alg = crypto_alg_lookup(name, type, mask);
+	if (!alg) {
+		char tmp[CRYPTO_MAX_ALG_NAME];
+
+		request_module(name);
+
+		if (!((type ^ CRYPTO_ALG_NEED_FALLBACK) & mask) &&
+		    snprintf(tmp, sizeof(tmp), "%s-all", name) < sizeof(tmp))
+			request_module(tmp);
+
+		alg = crypto_alg_lookup(name, type, mask);
+	}
+
 	if (alg)
 		return crypto_is_larval(alg) ? crypto_larval_wait(alg) : alg;
 
@@ -557,34 +568,34 @@ err:
 	return ERR_PTR(err);
 }
 EXPORT_SYMBOL_GPL(crypto_alloc_tfm);
- 
+
 /*
- *	crypto_free_tfm - Free crypto transform
+ *	crypto_destroy_tfm - Free crypto transform
+ *	@mem: Start of tfm slab
  *	@tfm: Transform to free
  *
- *	crypto_free_tfm() frees up the transform and any associated resources,
+ *	This function frees up the transform and any associated resources,
  *	then drops the refcount on the associated algorithm.
  */
-void crypto_free_tfm(struct crypto_tfm *tfm)
+void crypto_destroy_tfm(void *mem, struct crypto_tfm *tfm)
 {
 	struct crypto_alg *alg;
 	int size;
 
-	if (unlikely(!tfm))
+	if (unlikely(!mem))
 		return;
 
 	alg = tfm->__crt_alg;
-	size = sizeof(*tfm) + alg->cra_ctxsize;
+	size = ksize(mem);
 
 	if (!tfm->exit && alg->cra_exit)
 		alg->cra_exit(tfm);
 	crypto_exit_ops(tfm);
 	crypto_mod_put(alg);
-	memset(tfm, 0, size);
-	kfree(tfm);
+	memset(mem, 0, size);
+	kfree(mem);
 }
-
-EXPORT_SYMBOL_GPL(crypto_free_tfm);
+EXPORT_SYMBOL_GPL(crypto_destroy_tfm);
 
 int crypto_has_alg(const char *name, u32 type, u32 mask)
 {
diff --git a/crypto/authenc.c b/crypto/authenc.c
index 40b6e9ec9e3a..5793b64c81a8 100644
--- a/crypto/authenc.c
+++ b/crypto/authenc.c
@@ -158,16 +158,19 @@ static int crypto_authenc_genicv(struct aead_request *req, u8 *iv,
 	dstp = sg_page(dst);
 	vdst = PageHighMem(dstp) ? NULL : page_address(dstp) + dst->offset;
 
-	sg_init_table(cipher, 2);
-	sg_set_buf(cipher, iv, ivsize);
-	authenc_chain(cipher, dst, vdst == iv + ivsize);
+	if (ivsize) {
+		sg_init_table(cipher, 2);
+		sg_set_buf(cipher, iv, ivsize);
+		authenc_chain(cipher, dst, vdst == iv + ivsize);
+		dst = cipher;
+	}
 
 	cryptlen = req->cryptlen + ivsize;
-	hash = crypto_authenc_hash(req, flags, cipher, cryptlen);
+	hash = crypto_authenc_hash(req, flags, dst, cryptlen);
 	if (IS_ERR(hash))
 		return PTR_ERR(hash);
 
-	scatterwalk_map_and_copy(hash, cipher, cryptlen,
+	scatterwalk_map_and_copy(hash, dst, cryptlen,
 				 crypto_aead_authsize(authenc), 1);
 	return 0;
 }
@@ -285,11 +288,14 @@ static int crypto_authenc_iverify(struct aead_request *req, u8 *iv,
 	srcp = sg_page(src);
 	vsrc = PageHighMem(srcp) ? NULL : page_address(srcp) + src->offset;
 
-	sg_init_table(cipher, 2);
-	sg_set_buf(cipher, iv, ivsize);
-	authenc_chain(cipher, src, vsrc == iv + ivsize);
+	if (ivsize) {
+		sg_init_table(cipher, 2);
+		sg_set_buf(cipher, iv, ivsize);
+		authenc_chain(cipher, src, vsrc == iv + ivsize);
+		src = cipher;
+	}
 
-	return crypto_authenc_verify(req, cipher, cryptlen + ivsize);
+	return crypto_authenc_verify(req, src, cryptlen + ivsize);
 }
 
 static int crypto_authenc_decrypt(struct aead_request *req)
diff --git a/crypto/blkcipher.c b/crypto/blkcipher.c
index 4a7e65c4df4d..d70a41c002df 100644
--- a/crypto/blkcipher.c
+++ b/crypto/blkcipher.c
@@ -124,6 +124,7 @@ int blkcipher_walk_done(struct blkcipher_desc *desc,
 	scatterwalk_done(&walk->in, 0, nbytes);
 	scatterwalk_done(&walk->out, 1, nbytes);
 
+err:
 	walk->total = nbytes;
 	walk->nbytes = nbytes;
 
@@ -132,7 +133,6 @@ int blkcipher_walk_done(struct blkcipher_desc *desc,
 		return blkcipher_walk_next(desc, walk);
 	}
 
-err:
 	if (walk->iv != desc->info)
 		memcpy(desc->info, walk->iv, crypto_blkcipher_ivsize(tfm));
 	if (walk->buffer != walk->page)
diff --git a/crypto/ccm.c b/crypto/ccm.c
index 7cf7e5a6b781..c36d654cf56a 100644
--- a/crypto/ccm.c
+++ b/crypto/ccm.c
@@ -266,6 +266,8 @@ static int crypto_ccm_auth(struct aead_request *req, struct scatterlist *plain,
 	if (assoclen) {
 		pctx->ilen = format_adata(idata, assoclen);
 		get_data_to_compute(cipher, pctx, req->assoc, req->assoclen);
+	} else {
+		pctx->ilen = 0;
 	}
 
 	/* compute plaintext into mac */
diff --git a/crypto/lrw.c b/crypto/lrw.c
index 8ef664e3bcd9..358f80be2bf9 100644
--- a/crypto/lrw.c
+++ b/crypto/lrw.c
@@ -45,7 +45,13 @@ struct priv {
 
 static inline void setbit128_bbe(void *b, int bit)
 {
-	__set_bit(bit ^ 0x78, b);
+	__set_bit(bit ^ (0x80 -
+#ifdef __BIG_ENDIAN
+			 BITS_PER_LONG
+#else
+			 BITS_PER_BYTE
+#endif
+			), b);
 }
 
 static int setkey(struct crypto_tfm *parent, const u8 *key,
diff --git a/crypto/scatterwalk.c b/crypto/scatterwalk.c
index 9aeeb52004a5..3de89a424401 100644
--- a/crypto/scatterwalk.c
+++ b/crypto/scatterwalk.c
@@ -54,7 +54,8 @@ static void scatterwalk_pagedone(struct scatter_walk *walk, int out,
 		struct page *page;
 
 		page = sg_page(walk->sg) + ((walk->offset - 1) >> PAGE_SHIFT);
-		flush_dcache_page(page);
+		if (!PageSlab(page))
+			flush_dcache_page(page);
 	}
 
 	if (more) {
diff --git a/crypto/shash.c b/crypto/shash.c
index c9df367332ff..d5a2b619c55f 100644
--- a/crypto/shash.c
+++ b/crypto/shash.c
@@ -388,10 +388,15 @@ static int crypto_init_shash_ops_compat(struct crypto_tfm *tfm)
 	struct shash_desc *desc = crypto_tfm_ctx(tfm);
 	struct crypto_shash *shash;
 
+	if (!crypto_mod_get(calg))
+		return -EAGAIN;
+
 	shash = __crypto_shash_cast(crypto_create_tfm(
 		calg, &crypto_shash_type));
-	if (IS_ERR(shash))
+	if (IS_ERR(shash)) {
+		crypto_mod_put(calg);
 		return PTR_ERR(shash);
+	}
 
 	desc->tfm = shash;
 	tfm->exit = crypto_exit_shash_ops_compat;