diff --git a/crypto/Kconfig b/crypto/Kconfig
index 971d558494c3..3b88fba14b59 100644
--- a/crypto/Kconfig
+++ b/crypto/Kconfig
@@ -1780,6 +1780,17 @@ config CRYPTO_USER_API_AEAD
 	  This option enables the user-spaces interface for AEAD
 	  cipher algorithms.
 
+config CRYPTO_STATS
+	bool "Crypto usage statistics for User-space"
+	help
+	  This option enables the gathering of crypto stats.
+	  This will collect:
+	  - encrypt/decrypt size and numbers of symmeric operations
+	  - compress/decompress size and numbers of compress operations
+	  - size and numbers of hash operations
+	  - encrypt/decrypt/sign/verify numbers for asymmetric operations
+	  - generate/seed numbers for rng operations
+
 config CRYPTO_HASH_INFO
 	bool
 
diff --git a/crypto/ablkcipher.c b/crypto/ablkcipher.c
index d880a4897159..f6d20e4ca977 100644
--- a/crypto/ablkcipher.c
+++ b/crypto/ablkcipher.c
@@ -369,6 +369,7 @@ static int crypto_init_ablkcipher_ops(struct crypto_tfm *tfm, u32 type,
 static int crypto_ablkcipher_report(struct sk_buff *skb, struct crypto_alg *alg)
 {
 	struct crypto_report_blkcipher rblkcipher;
+	u64 v;
 
 	strncpy(rblkcipher.type, "ablkcipher", sizeof(rblkcipher.type));
 	strncpy(rblkcipher.geniv, alg->cra_ablkcipher.geniv ?: "<default>",
@@ -378,6 +379,14 @@ static int crypto_ablkcipher_report(struct sk_buff *skb, struct crypto_alg *alg)
 	rblkcipher.min_keysize = alg->cra_ablkcipher.min_keysize;
 	rblkcipher.max_keysize = alg->cra_ablkcipher.max_keysize;
 	rblkcipher.ivsize = alg->cra_ablkcipher.ivsize;
+	v = atomic_read(&alg->encrypt_cnt);
+	rblkcipher.stat_encrypt_cnt = v;
+	v = atomic_read(&alg->encrypt_tlen);
+	rblkcipher.stat_encrypt_tlen = v;
+	v = atomic_read(&alg->decrypt_cnt);
+	rblkcipher.stat_decrypt_cnt = v;
+	v = atomic_read(&alg->decrypt_tlen);
+	rblkcipher.stat_decrypt_tlen = v;
 
 	if (nla_put(skb, CRYPTOCFGA_REPORT_BLKCIPHER,
 		    sizeof(struct crypto_report_blkcipher), &rblkcipher))
diff --git a/crypto/acompress.c b/crypto/acompress.c
index 1544b7c057fb..524c8a3e3f80 100644
--- a/crypto/acompress.c
+++ b/crypto/acompress.c
@@ -32,8 +32,17 @@ static const struct crypto_type crypto_acomp_type;
 static int crypto_acomp_report(struct sk_buff *skb, struct crypto_alg *alg)
 {
 	struct crypto_report_acomp racomp;
+	u64 v;
 
 	strncpy(racomp.type, "acomp", sizeof(racomp.type));
+	v = atomic_read(&alg->compress_cnt);
+	racomp.stat_compress_cnt = v;
+	v = atomic_read(&alg->compress_tlen);
+	racomp.stat_compress_tlen = v;
+	v = atomic_read(&alg->decompress_cnt);
+	racomp.stat_decompress_cnt = v;
+	v = atomic_read(&alg->decompress_tlen);
+	racomp.stat_decompress_tlen = v;
 
 	if (nla_put(skb, CRYPTOCFGA_REPORT_ACOMP,
 		    sizeof(struct crypto_report_acomp), &racomp))
diff --git a/crypto/aead.c b/crypto/aead.c
index fe00cbd7243d..de13bd345d8b 100644
--- a/crypto/aead.c
+++ b/crypto/aead.c
@@ -109,6 +109,7 @@ static int crypto_aead_report(struct sk_buff *skb, struct crypto_alg *alg)
 {
 	struct crypto_report_aead raead;
 	struct aead_alg *aead = container_of(alg, struct aead_alg, base);
+	u64 v;
 
 	strncpy(raead.type, "aead", sizeof(raead.type));
 	strncpy(raead.geniv, "<none>", sizeof(raead.geniv));
@@ -116,6 +117,15 @@ static int crypto_aead_report(struct sk_buff *skb, struct crypto_alg *alg)
 	raead.blocksize = alg->cra_blocksize;
 	raead.maxauthsize = aead->maxauthsize;
 	raead.ivsize = aead->ivsize;
+	v = atomic_read(&alg->encrypt_cnt);
+	raead.stat_encrypt_cnt = v;
+	v = atomic_read(&alg->encrypt_tlen);
+	raead.stat_encrypt_tlen = v;
+	v = atomic_read(&alg->decrypt_cnt);
+	raead.stat_decrypt_cnt = v;
+	v = atomic_read(&alg->decrypt_tlen);
+	raead.stat_decrypt_tlen = v;
+
 
 	if (nla_put(skb, CRYPTOCFGA_REPORT_AEAD,
 		    sizeof(struct crypto_report_aead), &raead))
diff --git a/crypto/ahash.c b/crypto/ahash.c
index 3a35d67de7d9..e718f387039c 100644
--- a/crypto/ahash.c
+++ b/crypto/ahash.c
@@ -356,18 +356,21 @@ static int crypto_ahash_op(struct ahash_request *req,
 
 int crypto_ahash_final(struct ahash_request *req)
 {
+	crypto_stat_ahash_final(req);
 	return crypto_ahash_op(req, crypto_ahash_reqtfm(req)->final);
 }
 EXPORT_SYMBOL_GPL(crypto_ahash_final);
 
 int crypto_ahash_finup(struct ahash_request *req)
 {
+	crypto_stat_ahash_final(req);
 	return crypto_ahash_op(req, crypto_ahash_reqtfm(req)->finup);
 }
 EXPORT_SYMBOL_GPL(crypto_ahash_finup);
 
 int crypto_ahash_digest(struct ahash_request *req)
 {
+	crypto_stat_ahash_final(req);
 	return crypto_ahash_op(req, crypto_ahash_reqtfm(req)->digest);
 }
 EXPORT_SYMBOL_GPL(crypto_ahash_digest);
@@ -487,11 +490,16 @@ static unsigned int crypto_ahash_extsize(struct crypto_alg *alg)
 static int crypto_ahash_report(struct sk_buff *skb, struct crypto_alg *alg)
 {
 	struct crypto_report_hash rhash;
+	u64 v;
 
 	strncpy(rhash.type, "ahash", sizeof(rhash.type));
 
 	rhash.blocksize = alg->cra_blocksize;
 	rhash.digestsize = __crypto_hash_alg_common(alg)->digestsize;
+	v = atomic_read(&alg->hash_cnt);
+	rhash.stat_hash = v;
+	v = atomic_read(&alg->hash_tlen);
+	rhash.stat_hash_tlen = v;
 
 	if (nla_put(skb, CRYPTOCFGA_REPORT_HASH,
 		    sizeof(struct crypto_report_hash), &rhash))
diff --git a/crypto/akcipher.c b/crypto/akcipher.c
index cfbdb06d8ca8..02cb06824637 100644
--- a/crypto/akcipher.c
+++ b/crypto/akcipher.c
@@ -29,8 +29,21 @@
 static int crypto_akcipher_report(struct sk_buff *skb, struct crypto_alg *alg)
 {
 	struct crypto_report_akcipher rakcipher;
+	u64 v;
 
 	strncpy(rakcipher.type, "akcipher", sizeof(rakcipher.type));
+	v = atomic_read(&alg->encrypt_cnt);
+	rakcipher.stat_encrypt_cnt = v;
+	v = atomic_read(&alg->encrypt_tlen);
+	rakcipher.stat_encrypt_tlen = v;
+	v = atomic_read(&alg->decrypt_cnt);
+	rakcipher.stat_decrypt_cnt = v;
+	v = atomic_read(&alg->decrypt_tlen);
+	rakcipher.stat_decrypt_tlen = v;
+	v = atomic_read(&alg->sign_cnt);
+	rakcipher.stat_sign_cnt = v;
+	v = atomic_read(&alg->verify_cnt);
+	rakcipher.stat_verify_cnt = v;
 
 	if (nla_put(skb, CRYPTOCFGA_REPORT_AKCIPHER,
 		    sizeof(struct crypto_report_akcipher), &rakcipher))
diff --git a/crypto/algapi.c b/crypto/algapi.c
index 395b082d03a9..cf563f9f4be9 100644
--- a/crypto/algapi.c
+++ b/crypto/algapi.c
@@ -243,6 +243,12 @@ static struct crypto_larval *__crypto_register_alg(struct crypto_alg *alg)
 	list_add(&alg->cra_list, &crypto_alg_list);
 	list_add(&larval->alg.cra_list, &crypto_alg_list);
 
+	atomic_set(&alg->encrypt_cnt, 0);
+	atomic_set(&alg->decrypt_cnt, 0);
+	atomic_set(&alg->encrypt_tlen, 0);
+	atomic_set(&alg->decrypt_tlen, 0);
+	atomic_set(&alg->verify_cnt, 0);
+
 out:
 	return larval;
 
diff --git a/crypto/blkcipher.c b/crypto/blkcipher.c
index 01c0d4aa2563..bae369c1a1d1 100644
--- a/crypto/blkcipher.c
+++ b/crypto/blkcipher.c
@@ -508,6 +508,7 @@ static int crypto_init_blkcipher_ops(struct crypto_tfm *tfm, u32 type, u32 mask)
 static int crypto_blkcipher_report(struct sk_buff *skb, struct crypto_alg *alg)
 {
 	struct crypto_report_blkcipher rblkcipher;
+	u64 v;
 
 	strncpy(rblkcipher.type, "blkcipher", sizeof(rblkcipher.type));
 	strncpy(rblkcipher.geniv, alg->cra_blkcipher.geniv ?: "<default>",
@@ -517,6 +518,14 @@ static int crypto_blkcipher_report(struct sk_buff *skb, struct crypto_alg *alg)
 	rblkcipher.min_keysize = alg->cra_blkcipher.min_keysize;
 	rblkcipher.max_keysize = alg->cra_blkcipher.max_keysize;
 	rblkcipher.ivsize = alg->cra_blkcipher.ivsize;
+	v = atomic_read(&alg->encrypt_cnt);
+	rblkcipher.stat_encrypt_cnt = v;
+	v = atomic_read(&alg->encrypt_tlen);
+	rblkcipher.stat_encrypt_tlen = v;
+	v = atomic_read(&alg->decrypt_cnt);
+	rblkcipher.stat_decrypt_cnt = v;
+	v = atomic_read(&alg->decrypt_tlen);
+	rblkcipher.stat_decrypt_tlen = v;
 
 	if (nla_put(skb, CRYPTOCFGA_REPORT_BLKCIPHER,
 		    sizeof(struct crypto_report_blkcipher), &rblkcipher))
diff --git a/crypto/crypto_user.c b/crypto/crypto_user.c
index 5c291eedaa70..bd62f71a1ed1 100644
--- a/crypto/crypto_user.c
+++ b/crypto/crypto_user.c
@@ -82,12 +82,21 @@ static struct crypto_alg *crypto_alg_match(struct crypto_user_alg *p, int exact)
 static int crypto_report_cipher(struct sk_buff *skb, struct crypto_alg *alg)
 {
 	struct crypto_report_cipher rcipher;
+	u64 v;
 
 	strlcpy(rcipher.type, "cipher", sizeof(rcipher.type));
 
 	rcipher.blocksize = alg->cra_blocksize;
 	rcipher.min_keysize = alg->cra_cipher.cia_min_keysize;
 	rcipher.max_keysize = alg->cra_cipher.cia_max_keysize;
+	v = atomic_read(&alg->encrypt_cnt);
+	rcipher.stat_encrypt_cnt = v;
+	v = atomic_read(&alg->encrypt_tlen);
+	rcipher.stat_encrypt_tlen = v;
+	v = atomic_read(&alg->decrypt_cnt);
+	rcipher.stat_decrypt_cnt = v;
+	v = atomic_read(&alg->decrypt_tlen);
+	rcipher.stat_decrypt_tlen = v;
 
 	if (nla_put(skb, CRYPTOCFGA_REPORT_CIPHER,
 		    sizeof(struct crypto_report_cipher), &rcipher))
@@ -101,8 +110,18 @@ static int crypto_report_cipher(struct sk_buff *skb, struct crypto_alg *alg)
 static int crypto_report_comp(struct sk_buff *skb, struct crypto_alg *alg)
 {
 	struct crypto_report_comp rcomp;
+	u64 v;
 
 	strlcpy(rcomp.type, "compression", sizeof(rcomp.type));
+	v = atomic_read(&alg->compress_cnt);
+	rcomp.stat_compress_cnt = v;
+	v = atomic_read(&alg->compress_tlen);
+	rcomp.stat_compress_tlen = v;
+	v = atomic_read(&alg->decompress_cnt);
+	rcomp.stat_decompress_cnt = v;
+	v = atomic_read(&alg->decompress_tlen);
+	rcomp.stat_decompress_tlen = v;
+
 	if (nla_put(skb, CRYPTOCFGA_REPORT_COMPRESS,
 		    sizeof(struct crypto_report_comp), &rcomp))
 		goto nla_put_failure;
@@ -115,8 +134,17 @@ static int crypto_report_comp(struct sk_buff *skb, struct crypto_alg *alg)
 static int crypto_report_acomp(struct sk_buff *skb, struct crypto_alg *alg)
 {
 	struct crypto_report_acomp racomp;
+	u64 v;
 
 	strlcpy(racomp.type, "acomp", sizeof(racomp.type));
+	v = atomic_read(&alg->compress_cnt);
+	racomp.stat_compress_cnt = v;
+	v = atomic_read(&alg->compress_tlen);
+	racomp.stat_compress_tlen = v;
+	v = atomic_read(&alg->decompress_cnt);
+	racomp.stat_decompress_cnt = v;
+	v = atomic_read(&alg->decompress_tlen);
+	racomp.stat_decompress_tlen = v;
 
 	if (nla_put(skb, CRYPTOCFGA_REPORT_ACOMP,
 		    sizeof(struct crypto_report_acomp), &racomp))
diff --git a/crypto/kpp.c b/crypto/kpp.c
index a90edc27af77..3db941345818 100644
--- a/crypto/kpp.c
+++ b/crypto/kpp.c
@@ -29,8 +29,15 @@
 static int crypto_kpp_report(struct sk_buff *skb, struct crypto_alg *alg)
 {
 	struct crypto_report_kpp rkpp;
+	u64 v;
 
 	strncpy(rkpp.type, "kpp", sizeof(rkpp.type));
+	v = atomic_read(&alg->setsecret_cnt);
+	rkpp.stat_setsecret_cnt = v;
+	v = atomic_read(&alg->generate_public_key_cnt);
+	rkpp.stat_generate_public_key_cnt = v;
+	v = atomic_read(&alg->compute_shared_secret_cnt);
+	rkpp.stat_compute_shared_secret_cnt = v;
 
 	if (nla_put(skb, CRYPTOCFGA_REPORT_KPP,
 		    sizeof(struct crypto_report_kpp), &rkpp))
diff --git a/crypto/rng.c b/crypto/rng.c
index b4a618668161..4cf1de1722ee 100644
--- a/crypto/rng.c
+++ b/crypto/rng.c
@@ -49,6 +49,7 @@ int crypto_rng_reset(struct crypto_rng *tfm, const u8 *seed, unsigned int slen)
 		seed = buf;
 	}
 
+	crypto_stat_rng_seed(tfm);
 	err = crypto_rng_alg(tfm)->seed(tfm, seed, slen);
 out:
 	kzfree(buf);
@@ -72,10 +73,17 @@ static unsigned int seedsize(struct crypto_alg *alg)
 static int crypto_rng_report(struct sk_buff *skb, struct crypto_alg *alg)
 {
 	struct crypto_report_rng rrng;
+	u64 v;
 
 	strncpy(rrng.type, "rng", sizeof(rrng.type));
 
 	rrng.seedsize = seedsize(alg);
+	v = atomic_read(&alg->generate_cnt);
+	rrng.stat_generate_cnt = v;
+	v = atomic_read(&alg->generate_tlen);
+	rrng.stat_generate_tlen = v;
+	v = atomic_read(&alg->seed_cnt);
+	rrng.stat_seed_cnt = v;
 
 	if (nla_put(skb, CRYPTOCFGA_REPORT_RNG,
 		    sizeof(struct crypto_report_rng), &rrng))
diff --git a/crypto/scompress.c b/crypto/scompress.c
index 968bbcf65c94..3c3115f5378e 100644
--- a/crypto/scompress.c
+++ b/crypto/scompress.c
@@ -39,8 +39,17 @@ static DEFINE_MUTEX(scomp_lock);
 static int crypto_scomp_report(struct sk_buff *skb, struct crypto_alg *alg)
 {
 	struct crypto_report_comp rscomp;
+	u64 v;
 
 	strncpy(rscomp.type, "scomp", sizeof(rscomp.type));
+	v = atomic_read(&alg->compress_cnt);
+	rscomp.stat_compress_cnt = v;
+	v = atomic_read(&alg->compress_tlen);
+	rscomp.stat_compress_tlen = v;
+	v = atomic_read(&alg->decompress_cnt);
+	rscomp.stat_decompress_cnt = v;
+	v = atomic_read(&alg->decompress_tlen);
+	rscomp.stat_decompress_tlen = v;
 
 	if (nla_put(skb, CRYPTOCFGA_REPORT_COMPRESS,
 		    sizeof(struct crypto_report_comp), &rscomp))
diff --git a/crypto/shash.c b/crypto/shash.c
index e849d3ee2e27..c1d086fa03e7 100644
--- a/crypto/shash.c
+++ b/crypto/shash.c
@@ -385,11 +385,16 @@ static int crypto_shash_report(struct sk_buff *skb, struct crypto_alg *alg)
 {
 	struct crypto_report_hash rhash;
 	struct shash_alg *salg = __crypto_shash_alg(alg);
+	u64 v;
 
 	strncpy(rhash.type, "shash", sizeof(rhash.type));
 
 	rhash.blocksize = alg->cra_blocksize;
 	rhash.digestsize = salg->digestsize;
+	v = atomic_read(&alg->hash_cnt);
+	rhash.stat_hash = v;
+	v = atomic_read(&alg->hash_tlen);
+	rhash.stat_hash_tlen = v;
 
 	if (nla_put(skb, CRYPTOCFGA_REPORT_HASH,
 		    sizeof(struct crypto_report_hash), &rhash))
diff --git a/crypto/skcipher.c b/crypto/skcipher.c
index 11af5fd6a443..102194ecaa7d 100644
--- a/crypto/skcipher.c
+++ b/crypto/skcipher.c
@@ -875,6 +875,7 @@ static int crypto_skcipher_report(struct sk_buff *skb, struct crypto_alg *alg)
 	struct crypto_report_blkcipher rblkcipher;
 	struct skcipher_alg *skcipher = container_of(alg, struct skcipher_alg,
 						     base);
+	u64 v;
 
 	strncpy(rblkcipher.type, "skcipher", sizeof(rblkcipher.type));
 	strncpy(rblkcipher.geniv, "<none>", sizeof(rblkcipher.geniv));
@@ -883,6 +884,14 @@ static int crypto_skcipher_report(struct sk_buff *skb, struct crypto_alg *alg)
 	rblkcipher.min_keysize = skcipher->min_keysize;
 	rblkcipher.max_keysize = skcipher->max_keysize;
 	rblkcipher.ivsize = skcipher->ivsize;
+	v = atomic_read(&alg->encrypt_cnt);
+	rblkcipher.stat_encrypt_cnt = v;
+	v = atomic_read(&alg->encrypt_tlen);
+	rblkcipher.stat_encrypt_tlen = v;
+	v = atomic_read(&alg->decrypt_cnt);
+	rblkcipher.stat_decrypt_cnt = v;
+	v = atomic_read(&alg->decrypt_tlen);
+	rblkcipher.stat_decrypt_tlen = v;
 
 	if (nla_put(skb, CRYPTOCFGA_REPORT_BLKCIPHER,
 		    sizeof(struct crypto_report_blkcipher), &rblkcipher))
diff --git a/include/crypto/acompress.h b/include/crypto/acompress.h
index e328b52425a8..aed36031c6c1 100644
--- a/include/crypto/acompress.h
+++ b/include/crypto/acompress.h
@@ -234,6 +234,26 @@ static inline void acomp_request_set_params(struct acomp_req *req,
 		req->flags |= CRYPTO_ACOMP_ALLOC_OUTPUT;
 }
 
+static inline void crypto_stat_compress(struct acomp_req *req)
+{
+#ifdef CONFIG_CRYPTO_STATS
+	struct crypto_acomp *tfm = crypto_acomp_reqtfm(req);
+
+	atomic_inc(&tfm->base.__crt_alg->compress_cnt);
+	atomic_add(req->slen, &tfm->base.__crt_alg->compress_tlen);
+#endif
+}
+
+static inline void crypto_stat_decompress(struct acomp_req *req)
+{
+#ifdef CONFIG_CRYPTO_STATS
+	struct crypto_acomp *tfm = crypto_acomp_reqtfm(req);
+
+	atomic_inc(&tfm->base.__crt_alg->decompress_cnt);
+	atomic_add(req->slen, &tfm->base.__crt_alg->decompress_tlen);
+#endif
+}
+
 /**
  * crypto_acomp_compress() -- Invoke asynchronous compress operation
  *
@@ -247,6 +267,7 @@ static inline int crypto_acomp_compress(struct acomp_req *req)
 {
 	struct crypto_acomp *tfm = crypto_acomp_reqtfm(req);
 
+	crypto_stat_compress(req);
 	return tfm->compress(req);
 }
 
@@ -263,6 +284,7 @@ static inline int crypto_acomp_decompress(struct acomp_req *req)
 {
 	struct crypto_acomp *tfm = crypto_acomp_reqtfm(req);
 
+	crypto_stat_decompress(req);
 	return tfm->decompress(req);
 }
 
diff --git a/include/crypto/aead.h b/include/crypto/aead.h
index 03b97629442c..951f530b5abc 100644
--- a/include/crypto/aead.h
+++ b/include/crypto/aead.h
@@ -306,6 +306,26 @@ static inline struct crypto_aead *crypto_aead_reqtfm(struct aead_request *req)
 	return __crypto_aead_cast(req->base.tfm);
 }
 
+static inline void crypto_stat_aead_encrypt(struct aead_request *req)
+{
+#ifdef CONFIG_CRYPTO_STATS
+	struct crypto_aead *tfm = crypto_aead_reqtfm(req);
+
+	atomic_inc(&tfm->base.__crt_alg->encrypt_cnt);
+	atomic_add(req->cryptlen, &tfm->base.__crt_alg->encrypt_tlen);
+#endif
+}
+
+static inline void crypto_stat_aead_decrypt(struct aead_request *req)
+{
+#ifdef CONFIG_CRYPTO_STATS
+	struct crypto_aead *tfm = crypto_aead_reqtfm(req);
+
+	atomic_inc(&tfm->base.__crt_alg->decrypt_cnt);
+	atomic_add(req->cryptlen, &tfm->base.__crt_alg->decrypt_tlen);
+#endif
+}
+
 /**
  * crypto_aead_encrypt() - encrypt plaintext
  * @req: reference to the aead_request handle that holds all information
@@ -327,6 +347,7 @@ static inline struct crypto_aead *crypto_aead_reqtfm(struct aead_request *req)
  */
 static inline int crypto_aead_encrypt(struct aead_request *req)
 {
+	crypto_stat_aead_encrypt(req);
 	return crypto_aead_alg(crypto_aead_reqtfm(req))->encrypt(req);
 }
 
@@ -359,6 +380,7 @@ static inline int crypto_aead_decrypt(struct aead_request *req)
 	if (req->cryptlen < crypto_aead_authsize(aead))
 		return -EINVAL;
 
+	crypto_stat_aead_decrypt(req);
 	return crypto_aead_alg(aead)->decrypt(req);
 }
 
diff --git a/include/crypto/akcipher.h b/include/crypto/akcipher.h
index 8e0f752286e4..eb4fed99bce7 100644
--- a/include/crypto/akcipher.h
+++ b/include/crypto/akcipher.h
@@ -271,6 +271,44 @@ static inline unsigned int crypto_akcipher_maxsize(struct crypto_akcipher *tfm)
 	return alg->max_size(tfm);
 }
 
+static inline void crypto_stat_akcipher_encrypt(struct akcipher_request *req)
+{
+#ifdef CONFIG_CRYPTO_STATS
+	struct crypto_akcipher *tfm = crypto_akcipher_reqtfm(req);
+
+	atomic_inc(&tfm->base.__crt_alg->encrypt_cnt);
+	atomic_add(req->src_len, &tfm->base.__crt_alg->encrypt_tlen);
+#endif
+}
+
+static inline void crypto_stat_akcipher_decrypt(struct akcipher_request *req)
+{
+#ifdef CONFIG_CRYPTO_STATS
+	struct crypto_akcipher *tfm = crypto_akcipher_reqtfm(req);
+
+	atomic_inc(&tfm->base.__crt_alg->decrypt_cnt);
+	atomic_add(req->src_len, &tfm->base.__crt_alg->decrypt_tlen);
+#endif
+}
+
+static inline void crypto_stat_akcipher_sign(struct akcipher_request *req)
+{
+#ifdef CONFIG_CRYPTO_STATS
+	struct crypto_akcipher *tfm = crypto_akcipher_reqtfm(req);
+
+	atomic_inc(&tfm->base.__crt_alg->sign_cnt);
+#endif
+}
+
+static inline void crypto_stat_akcipher_verify(struct akcipher_request *req)
+{
+#ifdef CONFIG_CRYPTO_STATS
+	struct crypto_akcipher *tfm = crypto_akcipher_reqtfm(req);
+
+	atomic_inc(&tfm->base.__crt_alg->verify_cnt);
+#endif
+}
+
 /**
  * crypto_akcipher_encrypt() - Invoke public key encrypt operation
  *
@@ -286,6 +324,7 @@ static inline int crypto_akcipher_encrypt(struct akcipher_request *req)
 	struct crypto_akcipher *tfm = crypto_akcipher_reqtfm(req);
 	struct akcipher_alg *alg = crypto_akcipher_alg(tfm);
 
+	crypto_stat_akcipher_encrypt(req);
 	return alg->encrypt(req);
 }
 
@@ -304,6 +343,7 @@ static inline int crypto_akcipher_decrypt(struct akcipher_request *req)
 	struct crypto_akcipher *tfm = crypto_akcipher_reqtfm(req);
 	struct akcipher_alg *alg = crypto_akcipher_alg(tfm);
 
+	crypto_stat_akcipher_decrypt(req);
 	return alg->decrypt(req);
 }
 
@@ -322,6 +362,7 @@ static inline int crypto_akcipher_sign(struct akcipher_request *req)
 	struct crypto_akcipher *tfm = crypto_akcipher_reqtfm(req);
 	struct akcipher_alg *alg = crypto_akcipher_alg(tfm);
 
+	crypto_stat_akcipher_sign(req);
 	return alg->sign(req);
 }
 
@@ -340,6 +381,7 @@ static inline int crypto_akcipher_verify(struct akcipher_request *req)
 	struct crypto_akcipher *tfm = crypto_akcipher_reqtfm(req);
 	struct akcipher_alg *alg = crypto_akcipher_alg(tfm);
 
+	crypto_stat_akcipher_verify(req);
 	return alg->verify(req);
 }
 
diff --git a/include/crypto/hash.h b/include/crypto/hash.h
index 0ed31fd80242..fd12d575e72f 100644
--- a/include/crypto/hash.h
+++ b/include/crypto/hash.h
@@ -415,6 +415,25 @@ static inline bool crypto_ahash_has_setkey(struct crypto_ahash *tfm)
 	return tfm->has_setkey;
 }
 
+static inline void crypto_stat_ahash_update(struct ahash_request *req)
+{
+#ifdef CONFIG_CRYPTO_STATS
+	struct crypto_ahash *tfm = crypto_ahash_reqtfm(req);
+
+	atomic_add(req->nbytes, &tfm->base.__crt_alg->hash_tlen);
+#endif
+}
+
+static inline void crypto_stat_ahash_final(struct ahash_request *req)
+{
+#ifdef CONFIG_CRYPTO_STATS
+	struct crypto_ahash *tfm = crypto_ahash_reqtfm(req);
+
+	atomic_inc(&tfm->base.__crt_alg->hash_cnt);
+	atomic_add(req->nbytes, &tfm->base.__crt_alg->hash_tlen);
+#endif
+}
+
 /**
  * crypto_ahash_finup() - update and finalize message digest
  * @req: reference to the ahash_request handle that holds all information
@@ -519,6 +538,8 @@ static inline int crypto_ahash_init(struct ahash_request *req)
  */
 static inline int crypto_ahash_update(struct ahash_request *req)
 {
+
+	crypto_stat_ahash_update(req);
 	return crypto_ahash_reqtfm(req)->update(req);
 }
 
diff --git a/include/crypto/kpp.h b/include/crypto/kpp.h
index 1bde0a6514fa..734fc70a80e7 100644
--- a/include/crypto/kpp.h
+++ b/include/crypto/kpp.h
@@ -268,6 +268,31 @@ struct kpp_secret {
 	unsigned short len;
 };
 
+static inline void crypto_stat_kpp_set_secret(struct crypto_kpp *tfm)
+{
+#ifdef CONFIG_CRYPTO_STATS
+	atomic_inc(&tfm->base.__crt_alg->setsecret_cnt);
+#endif
+}
+
+static inline void crypto_stat_kpp_generate_public_key(struct kpp_request *req)
+{
+#ifdef CONFIG_CRYPTO_STATS
+	struct crypto_kpp *tfm = crypto_kpp_reqtfm(req);
+
+	atomic_inc(&tfm->base.__crt_alg->generate_public_key_cnt);
+#endif
+}
+
+static inline void crypto_stat_kpp_compute_shared_secret(struct kpp_request *req)
+{
+#ifdef CONFIG_CRYPTO_STATS
+	struct crypto_kpp *tfm = crypto_kpp_reqtfm(req);
+
+	atomic_inc(&tfm->base.__crt_alg->compute_shared_secret_cnt);
+#endif
+}
+
 /**
  * crypto_kpp_set_secret() - Invoke kpp operation
  *
@@ -288,6 +313,7 @@ static inline int crypto_kpp_set_secret(struct crypto_kpp *tfm,
 {
 	struct kpp_alg *alg = crypto_kpp_alg(tfm);
 
+	crypto_stat_kpp_set_secret(tfm);
 	return alg->set_secret(tfm, buffer, len);
 }
 
@@ -309,6 +335,7 @@ static inline int crypto_kpp_generate_public_key(struct kpp_request *req)
 	struct crypto_kpp *tfm = crypto_kpp_reqtfm(req);
 	struct kpp_alg *alg = crypto_kpp_alg(tfm);
 
+	crypto_stat_kpp_generate_public_key(req);
 	return alg->generate_public_key(req);
 }
 
@@ -327,6 +354,7 @@ static inline int crypto_kpp_compute_shared_secret(struct kpp_request *req)
 	struct crypto_kpp *tfm = crypto_kpp_reqtfm(req);
 	struct kpp_alg *alg = crypto_kpp_alg(tfm);
 
+	crypto_stat_kpp_compute_shared_secret(req);
 	return alg->compute_shared_secret(req);
 }
 
diff --git a/include/crypto/rng.h b/include/crypto/rng.h
index 42811936a361..a50d8ce464e3 100644
--- a/include/crypto/rng.h
+++ b/include/crypto/rng.h
@@ -122,6 +122,22 @@ static inline void crypto_free_rng(struct crypto_rng *tfm)
 	crypto_destroy_tfm(tfm, crypto_rng_tfm(tfm));
 }
 
+static inline void crypto_stat_rng_seed(struct crypto_rng *tfm)
+{
+#ifdef CONFIG_CRYPTO_STATS
+	atomic_inc(&tfm->base.__crt_alg->seed_cnt);
+#endif
+}
+
+static inline void crypto_stat_rng_generate(struct crypto_rng *tfm,
+					    unsigned int dlen)
+{
+#ifdef CONFIG_CRYPTO_STATS
+	atomic_inc(&tfm->base.__crt_alg->generate_cnt);
+	atomic_add(dlen, &tfm->base.__crt_alg->generate_tlen);
+#endif
+}
+
 /**
  * crypto_rng_generate() - get random number
  * @tfm: cipher handle
@@ -140,6 +156,7 @@ static inline int crypto_rng_generate(struct crypto_rng *tfm,
 				      const u8 *src, unsigned int slen,
 				      u8 *dst, unsigned int dlen)
 {
+	crypto_stat_rng_generate(tfm, dlen);
 	return crypto_rng_alg(tfm)->generate(tfm, src, slen, dst, dlen);
 }
 
diff --git a/include/crypto/skcipher.h b/include/crypto/skcipher.h
index 562001cb412b..476502a80861 100644
--- a/include/crypto/skcipher.h
+++ b/include/crypto/skcipher.h
@@ -427,6 +427,26 @@ static inline struct crypto_skcipher *crypto_skcipher_reqtfm(
 	return __crypto_skcipher_cast(req->base.tfm);
 }
 
+static inline void crypto_stat_skcipher_encrypt(struct skcipher_request *req)
+{
+#ifdef CONFIG_CRYPTO_STATS
+	struct crypto_skcipher *tfm = crypto_skcipher_reqtfm(req);
+
+	atomic_inc(&tfm->base.__crt_alg->encrypt_cnt);
+	atomic_add(req->cryptlen, &tfm->base.__crt_alg->encrypt_tlen);
+#endif
+}
+
+static inline void crypto_stat_skcipher_decrypt(struct skcipher_request *req)
+{
+#ifdef CONFIG_CRYPTO_STATS
+	struct crypto_skcipher *tfm = crypto_skcipher_reqtfm(req);
+
+	atomic_inc(&tfm->base.__crt_alg->decrypt_cnt);
+	atomic_add(req->cryptlen, &tfm->base.__crt_alg->decrypt_tlen);
+#endif
+}
+
 /**
  * crypto_skcipher_encrypt() - encrypt plaintext
  * @req: reference to the skcipher_request handle that holds all information
@@ -442,6 +462,7 @@ static inline int crypto_skcipher_encrypt(struct skcipher_request *req)
 {
 	struct crypto_skcipher *tfm = crypto_skcipher_reqtfm(req);
 
+	crypto_stat_skcipher_encrypt(req);
 	return tfm->encrypt(req);
 }
 
@@ -460,6 +481,7 @@ static inline int crypto_skcipher_decrypt(struct skcipher_request *req)
 {
 	struct crypto_skcipher *tfm = crypto_skcipher_reqtfm(req);
 
+	crypto_stat_skcipher_decrypt(req);
 	return tfm->decrypt(req);
 }
 
diff --git a/include/linux/crypto.h b/include/linux/crypto.h
index 231e59f90d32..3ba299720aaa 100644
--- a/include/linux/crypto.h
+++ b/include/linux/crypto.h
@@ -466,6 +466,36 @@ struct crypto_alg {
 	void (*cra_destroy)(struct crypto_alg *alg);
 	
 	struct module *cra_module;
+
+	union {
+		atomic_t encrypt_cnt;
+		atomic_t compress_cnt;
+		atomic_t generate_cnt;
+		atomic_t hash_cnt;
+		atomic_t setsecret_cnt;
+	};
+	union {
+		atomic_t encrypt_tlen;
+		atomic_t compress_tlen;
+		atomic_t generate_tlen;
+		atomic_t hash_tlen;
+	};
+	union {
+		atomic_t decrypt_cnt;
+		atomic_t decompress_cnt;
+		atomic_t seed_cnt;
+		atomic_t generate_public_key_cnt;
+	};
+	union {
+		atomic_t decrypt_tlen;
+		atomic_t decompress_tlen;
+	};
+	union {
+		atomic_t verify_cnt;
+		atomic_t compute_shared_secret_cnt;
+	};
+	atomic_t sign_cnt;
+
 } CRYPTO_MINALIGN_ATTR;
 
 /*
@@ -886,6 +916,28 @@ static inline struct crypto_ablkcipher *crypto_ablkcipher_reqtfm(
 	return __crypto_ablkcipher_cast(req->base.tfm);
 }
 
+static inline void crypto_stat_ablkcipher_encrypt(struct ablkcipher_request *req)
+{
+#ifdef CONFIG_CRYPTO_STATS
+	struct ablkcipher_tfm *crt =
+		crypto_ablkcipher_crt(crypto_ablkcipher_reqtfm(req));
+
+	atomic_inc(&crt->base->base.__crt_alg->encrypt_cnt);
+	atomic_add(req->nbytes, &crt->base->base.__crt_alg->encrypt_tlen);
+#endif
+}
+
+static inline void crypto_stat_ablkcipher_decrypt(struct ablkcipher_request *req)
+{
+#ifdef CONFIG_CRYPTO_STATS
+	struct ablkcipher_tfm *crt =
+		crypto_ablkcipher_crt(crypto_ablkcipher_reqtfm(req));
+
+	atomic_inc(&crt->base->base.__crt_alg->decrypt_cnt);
+	atomic_add(req->nbytes, &crt->base->base.__crt_alg->decrypt_tlen);
+#endif
+}
+
 /**
  * crypto_ablkcipher_encrypt() - encrypt plaintext
  * @req: reference to the ablkcipher_request handle that holds all information
@@ -901,6 +953,8 @@ static inline int crypto_ablkcipher_encrypt(struct ablkcipher_request *req)
 {
 	struct ablkcipher_tfm *crt =
 		crypto_ablkcipher_crt(crypto_ablkcipher_reqtfm(req));
+
+	crypto_stat_ablkcipher_encrypt(req);
 	return crt->encrypt(req);
 }
 
@@ -919,6 +973,8 @@ static inline int crypto_ablkcipher_decrypt(struct ablkcipher_request *req)
 {
 	struct ablkcipher_tfm *crt =
 		crypto_ablkcipher_crt(crypto_ablkcipher_reqtfm(req));
+
+	crypto_stat_ablkcipher_decrypt(req);
 	return crt->decrypt(req);
 }
 
diff --git a/include/uapi/linux/cryptouser.h b/include/uapi/linux/cryptouser.h
index 19bf0ca6d635..15e51ccb3679 100644
--- a/include/uapi/linux/cryptouser.h
+++ b/include/uapi/linux/cryptouser.h
@@ -73,6 +73,8 @@ struct crypto_report_hash {
 	char type[CRYPTO_MAX_NAME];
 	unsigned int blocksize;
 	unsigned int digestsize;
+	__u64 stat_hash;
+	__u64 stat_hash_tlen;
 };
 
 struct crypto_report_cipher {
@@ -80,6 +82,10 @@ struct crypto_report_cipher {
 	unsigned int blocksize;
 	unsigned int min_keysize;
 	unsigned int max_keysize;
+	__u64 stat_encrypt_cnt;
+	__u64 stat_encrypt_tlen;
+	__u64 stat_decrypt_cnt;
+	__u64 stat_decrypt_tlen;
 };
 
 struct crypto_report_blkcipher {
@@ -89,6 +95,10 @@ struct crypto_report_blkcipher {
 	unsigned int min_keysize;
 	unsigned int max_keysize;
 	unsigned int ivsize;
+	__u64 stat_encrypt_cnt;
+	__u64 stat_encrypt_tlen;
+	__u64 stat_decrypt_cnt;
+	__u64 stat_decrypt_tlen;
 };
 
 struct crypto_report_aead {
@@ -97,27 +107,51 @@ struct crypto_report_aead {
 	unsigned int blocksize;
 	unsigned int maxauthsize;
 	unsigned int ivsize;
+	__u64 stat_encrypt_cnt;
+	__u64 stat_encrypt_tlen;
+	__u64 stat_decrypt_cnt;
+	__u64 stat_decrypt_tlen;
 };
 
 struct crypto_report_comp {
 	char type[CRYPTO_MAX_NAME];
+	__u64 stat_compress_cnt;
+	__u64 stat_compress_tlen;
+	__u64 stat_decompress_cnt;
+	__u64 stat_decompress_tlen;
 };
 
 struct crypto_report_rng {
 	char type[CRYPTO_MAX_NAME];
 	unsigned int seedsize;
+	__u64 stat_generate_cnt;
+	__u64 stat_generate_tlen;
+	__u64 stat_seed_cnt;
 };
 
 struct crypto_report_akcipher {
 	char type[CRYPTO_MAX_NAME];
+	__u64 stat_encrypt_cnt;
+	__u64 stat_encrypt_tlen;
+	__u64 stat_decrypt_cnt;
+	__u64 stat_decrypt_tlen;
+	__u64 stat_verify_cnt;
+	__u64 stat_sign_cnt;
 };
 
 struct crypto_report_kpp {
 	char type[CRYPTO_MAX_NAME];
+	__u64 stat_setsecret_cnt;
+	__u64 stat_generate_public_key_cnt;
+	__u64 stat_compute_shared_secret_cnt;
 };
 
 struct crypto_report_acomp {
 	char type[CRYPTO_MAX_NAME];
+	__u64 stat_compress_cnt;
+	__u64 stat_compress_tlen;
+	__u64 stat_decompress_cnt;
+	__u64 stat_decompress_tlen;
 };
 
 #define CRYPTO_REPORT_MAXSIZE (sizeof(struct crypto_user_alg) + \
