linux-kernel.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [PATCH 0/2] crypto: Implement generic crypto statistics
@ 2018-01-11 19:56 Corentin Labbe
  2018-01-11 19:56 ` [PATCH 1/2] crypto: Implement a " Corentin Labbe
  2018-01-11 19:56 ` [PATCH 2/2] crypto: tools: Add cryptostat userspace Corentin Labbe
  0 siblings, 2 replies; 9+ messages in thread
From: Corentin Labbe @ 2018-01-11 19:56 UTC (permalink / raw)
  To: davem, herbert, nhorman, smueller
  Cc: linux-crypto, linux-kernel, Corentin Labbe

Hello

This patch is a try to implement a generic crypto driver statistics.
The goal is to have an "ifconfig" for crypto device.

Some driver tried to implement this via a debugfs interface.
This serie do it directly in the crypto API and give access to stats
via the crypto_user(netlink) API.
Then an userspace tool will collect information via netlink.
Note that this userspace tool is heavily copied from libkcapi and if
Stephan Mueller agree, I will made a PR for adding getstat to it.

Example of output:
gcc getstat.c -o getstat && ./getstat 
authenc(hmac(sha512-generic),cbc-des3_ede-asm)	AEAD
	Encrypt: 6 bytes: 768
	Decrypt: 0 bytes: 0
authenc(hmac(sha512-generic),cbc(des-generic))	AEAD
	Encrypt: 8 bytes: 1024
	Decrypt: 0 bytes: 0
authenc(hmac(sha384-generic),cbc-des3_ede-asm)	AEAD
	Encrypt: 6 bytes: 768
	Decrypt: 0 bytes: 0
authenc(hmac(sha384-generic),cbc(des-generic))	AEAD
	Encrypt: 8 bytes: 1024
	Decrypt: 0 bytes: 0
authenc(hmac(sha256-generic),cbc-des3_ede-asm)	AEAD
	Encrypt: 6 bytes: 768
	Decrypt: 0 bytes: 0
authenc(hmac(sha256-generic),cbc(des-generic))	AEAD
	Encrypt: 8 bytes: 1024
	Decrypt: 0 bytes: 0
authenc(hmac(sha224-generic),cbc-des3_ede-asm)	AEAD
	Encrypt: 6 bytes: 768
	Decrypt: 0 bytes: 0
authenc(hmac(sha224-generic),cbc(des-generic))	AEAD
	Encrypt: 8 bytes: 1024
	Decrypt: 0 bytes: 0
authenc(hmac(sha1-generic),cbc-des3_ede-asm)	AEAD
	Encrypt: 6 bytes: 768
	Decrypt: 0 bytes: 0
authenc(hmac(sha1-generic),cbc(des-generic))	AEAD
	Encrypt: 8 bytes: 1024
	Decrypt: 0 bytes: 0
authenc(hmac(sha1-generic),ecb-cipher_null)	AEAD
	Encrypt: 12 bytes: 366
	Decrypt: 12 bytes: 606
authenc(hmac(md5-generic),ecb-cipher_null)	AEAD
	Encrypt: 12 bytes: 366
	Decrypt: 12 bytes: 558
authenc(hmac(sha1-generic),virtio_crypto_aes_cbc)	AEAD
	Encrypt: 42 bytes: 2208
	Decrypt: 0 bytes: 0
cmac(des3_ede-asm)
	Hash: 32 bytes: 480
cmac(aes-asm)
	Hash: 48 bytes: 1472
rfc4543(gcm_base(ctr(aes-asm),ghash-generic))	AEAD
	Encrypt: 6 bytes: 312
	Decrypt: 12 bytes: 816
rfc4106(gcm_base(ctr(aes-asm),ghash-generic))	AEAD
	Encrypt: 138 bytes: 6864
	Decrypt: 138 bytes: 9072
crc32-generic
	Hash: 56 bytes: 10850
vmac(aes-asm)
	Hash: 88 bytes: 8328
xcbc(aes-asm)
	Hash: 64 bytes: 936
hmac(sha224-generic)
	Hash: 46 bytes: 3868
hmac(sha512-generic)
	Hash: 46 bytes: 3868
hmac(sha384-generic)
	Hash: 46 bytes: 3868
hmac(sha1-generic)
	Hash: 136 bytes: 7884
hmac(md5-generic)
	Hash: 80 bytes: 2940
crct10dif-generic
	Hash: 40 bytes: 4492
rfc4309(ccm_base(ctr(aes-asm),cbcmac(aes-asm)))	AEAD
	Encrypt: 138 bytes: 6864
	Decrypt: 138 bytes: 9072
ccm_base(ctr(aes-asm),cbcmac(aes-asm))	AEAD
	Encrypt: 222 bytes: 8946
	Decrypt: 240 bytes: 12246
cbcmac(aes-asm)
	Hash: 478 bytes: 21034
gcm_base(ctr(aes-asm),ghash-generic)	AEAD
	Encrypt: 196 bytes: 8424
	Decrypt: 196 bytes: 12304
rfc3686(ctr(aes-asm))	Cipher
	Encrypt: 40 bytes: 17264
	Decrypt: 36 bytes: 864
ctr(aes-asm)	Cipher
	Encrypt: 924 bytes: 59560
	Decrypt: 474 bytes: 36192
xts(ecb(aes-asm))	Cipher
	Encrypt: 44 bytes: 11008
	Decrypt: 44 bytes: 11008
lrw(ecb(aes-asm))	Cipher
	Encrypt: 68 bytes: 7040
	Decrypt: 68 bytes: 7040
ecb(aes-asm)	Cipher
	Encrypt: 140 bytes: 23296
	Decrypt: 140 bytes: 23296
ctr(des-generic)	Cipher
	Encrypt: 24 bytes: 5940
	Decrypt: 24 bytes: 5940
cbc(des-generic)	Cipher
	Encrypt: 88 bytes: 8576
	Decrypt: 40 bytes: 3200
ecb(des-generic)	Cipher
	Encrypt: 64 bytes: 3744
	Decrypt: 36 bytes: 3232
pkcs1pad(rsa-generic,sha1)	Akcipher
	Encrypt: 0 bytes: 0
	Decrypt: 0 bytes: 0
	Sign: 0
	Verify: 13
virtio_crypto_aes_cbc	Cipher
	Encrypt: 82 bytes: 8320
	Decrypt: 38 bytes: 6080
ecdh-generic	KPP
	Setsecret: 4
	Generate public key: 3
	Compute_shared_secret: 4
ghash-generic
	Hash: 440 bytes: 10728
jitterentropy_rng	RNG
	Seed: 0
	Generate: 0 bytes: 0
drbg_nopr_hmac_sha256	RNG
	Seed: 5
	Generate: 9 bytes: 1056
drbg_nopr_hmac_sha512	RNG
	Seed: 0
	Generate: 0 bytes: 0
drbg_nopr_hmac_sha384	RNG
	Seed: 0
	Generate: 0 bytes: 0
drbg_nopr_hmac_sha1	RNG
	Seed: 0
	Generate: 0 bytes: 0
hmac(sha256-generic)
	Hash: 94 bytes: 5592
drbg_pr_hmac_sha256	RNG
	Seed: 4
	Generate: 8 bytes: 1024
drbg_pr_hmac_sha512	RNG
	Seed: 0
	Generate: 0 bytes: 0
drbg_pr_hmac_sha384	RNG
	Seed: 0
	Generate: 0 bytes: 0
drbg_pr_hmac_sha1	RNG
	Seed: 0
	Generate: 0 bytes: 0
lzo-scomp	Compress
	Compress: 2 bytes: 229
	Decompress: 4 bytes: 367
lzo-generic	Compress
	Compress: 0 bytes: 0
	Decompress: 0 bytes: 0
crc32c-generic
	Hash: 176 bytes: 31652
zlib-deflate-scomp	Compress
	Compress: 2 bytes: 261
	Decompress: 4 bytes: 345
deflate-scomp	Compress
	Compress: 2 bytes: 261
	Decompress: 4 bytes: 320
deflate-generic	Compress
	Compress: 0 bytes: 0
	Decompress: 0 bytes: 0
poly1305-generic
	Hash: 66 bytes: 9294
chacha20-generic	Cipher
	Encrypt: 16 bytes: 8853
	Decrypt: 16 bytes: 8853
ecb(arc4)-generic	Cipher
	Encrypt: 42 bytes: 540
	Decrypt: 42 bytes: 540
arc4-generic	cipher
	Encrypt: 0 bytes: 0
	Decrypt: 0 bytes: 0
aes-generic	cipher
	Encrypt: 0 bytes: 0
	Decrypt: 0 bytes: 0
des3_ede-generic	cipher
	Encrypt: 0 bytes: 0
	Decrypt: 0 bytes: 0
des-generic	cipher
	Encrypt: 0 bytes: 0
	Decrypt: 0 bytes: 0
sha384-generic
	Hash: 48 bytes: 10072
sha512-generic
	Hash: 48 bytes: 10072
sha224-generic
	Hash: 40 bytes: 9056
sha256-generic
	Hash: 40 bytes: 9056
sha1-generic
	Hash: 48 bytes: 9728
md5-generic
	Hash: 56 bytes: 1436
md4-generic
	Hash: 56 bytes: 1436
digest_null-generic
	Hash: 0 bytes: 0
compress_null-generic	Compress
	Compress: 0 bytes: 0
	Decompress: 0 bytes: 0
ecb-cipher_null	Cipher
	Encrypt: 130 bytes: 2828
	Decrypt: 24 bytes: 732
cipher_null-generic	cipher
	Encrypt: 0 bytes: 0
	Decrypt: 0 bytes: 0
rsa-generic	Akcipher
	Encrypt: 7 bytes: 232
	Decrypt: 6 bytes: 1152
	Sign: 0
	Verify: 13
dh-generic	KPP
	Setsecret: 2
	Generate public key: 2
	Compute_shared_secret: 2
ctr-des3_ede-asm	Cipher
	Encrypt: 20 bytes: 9950
	Decrypt: 20 bytes: 9950
cbc-des3_ede-asm	Cipher
	Encrypt: 46 bytes: 9568
	Decrypt: 16 bytes: 5728
ecb-des3_ede-asm	Cipher
	Encrypt: 28 bytes: 5104
	Decrypt: 28 bytes: 5104
des3_ede-asm	cipher
	Encrypt: 0 bytes: 0
	Decrypt: 0 bytes: 0
aes-asm	cipher
	Encrypt: 0 bytes: 0
	Decrypt: 0 bytes: 0

Futur possible additions:
- Add a "number of needed fallback" statistics.
- maximum request size

Regards

Changes since RFC:
- Use cryptouser(netlink) instead of /sys
- Use atomic_t instead of unsigned long
- moved stat code into dedicated inline function
- spelling fixes

Corentin Labbe (2):
  crypto: Implement a generic crypto statistics
  crypto: tools: Add cryptostat userspace

 crypto/Kconfig                  |  11 ++
 crypto/ablkcipher.c             |   9 ++
 crypto/acompress.c              |   9 ++
 crypto/aead.c                   |  10 ++
 crypto/ahash.c                  |   8 ++
 crypto/akcipher.c               |  13 ++
 crypto/algapi.c                 |   6 +
 crypto/blkcipher.c              |   9 ++
 crypto/crypto_user.c            |  28 ++++
 crypto/kpp.c                    |   7 +
 crypto/rng.c                    |   8 ++
 crypto/scompress.c              |   9 ++
 crypto/shash.c                  |   5 +
 crypto/skcipher.c               |   9 ++
 include/crypto/acompress.h      |  22 ++++
 include/crypto/aead.h           |  10 ++
 include/crypto/akcipher.h       |  42 ++++++
 include/crypto/hash.h           |  10 ++
 include/crypto/kpp.h            |  28 ++++
 include/crypto/rng.h            |  17 +++
 include/crypto/skcipher.h       |  22 ++++
 include/linux/crypto.h          |  56 ++++++++
 include/uapi/linux/cryptouser.h |  34 +++++
 tools/crypto/getstat.c          | 279 ++++++++++++++++++++++++++++++++++++++++
 24 files changed, 661 insertions(+)
 create mode 100644 tools/crypto/getstat.c

-- 
2.13.6

^ permalink raw reply	[flat|nested] 9+ messages in thread

* [PATCH 1/2] crypto: Implement a generic crypto statistics
  2018-01-11 19:56 [PATCH 0/2] crypto: Implement generic crypto statistics Corentin Labbe
@ 2018-01-11 19:56 ` Corentin Labbe
  2018-01-12  6:49   ` Stephan Mueller
  2018-01-11 19:56 ` [PATCH 2/2] crypto: tools: Add cryptostat userspace Corentin Labbe
  1 sibling, 1 reply; 9+ messages in thread
From: Corentin Labbe @ 2018-01-11 19:56 UTC (permalink / raw)
  To: davem, herbert, nhorman, smueller
  Cc: linux-crypto, linux-kernel, Corentin Labbe

This patch implement a generic way to get statistics about all crypto
usages.

Signed-off-by: Corentin Labbe <clabbe@baylibre.com>
---
 crypto/Kconfig                  | 11 ++++++++
 crypto/ablkcipher.c             |  9 +++++++
 crypto/acompress.c              |  9 +++++++
 crypto/aead.c                   | 10 ++++++++
 crypto/ahash.c                  |  8 ++++++
 crypto/akcipher.c               | 13 ++++++++++
 crypto/algapi.c                 |  6 +++++
 crypto/blkcipher.c              |  9 +++++++
 crypto/crypto_user.c            | 28 +++++++++++++++++++++
 crypto/kpp.c                    |  7 ++++++
 crypto/rng.c                    |  8 ++++++
 crypto/scompress.c              |  9 +++++++
 crypto/shash.c                  |  5 ++++
 crypto/skcipher.c               |  9 +++++++
 include/crypto/acompress.h      | 22 ++++++++++++++++
 include/crypto/aead.h           | 22 ++++++++++++++++
 include/crypto/akcipher.h       | 42 +++++++++++++++++++++++++++++++
 include/crypto/hash.h           | 21 ++++++++++++++++
 include/crypto/kpp.h            | 28 +++++++++++++++++++++
 include/crypto/rng.h            | 17 +++++++++++++
 include/crypto/skcipher.h       | 22 ++++++++++++++++
 include/linux/crypto.h          | 56 +++++++++++++++++++++++++++++++++++++++++
 include/uapi/linux/cryptouser.h | 34 +++++++++++++++++++++++++
 23 files changed, 405 insertions(+)

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) + \
-- 
2.13.6

^ permalink raw reply related	[flat|nested] 9+ messages in thread

* [PATCH 2/2] crypto: tools: Add cryptostat userspace
  2018-01-11 19:56 [PATCH 0/2] crypto: Implement generic crypto statistics Corentin Labbe
  2018-01-11 19:56 ` [PATCH 1/2] crypto: Implement a " Corentin Labbe
@ 2018-01-11 19:56 ` Corentin Labbe
  1 sibling, 0 replies; 9+ messages in thread
From: Corentin Labbe @ 2018-01-11 19:56 UTC (permalink / raw)
  To: davem, herbert, nhorman, smueller
  Cc: linux-crypto, linux-kernel, Corentin Labbe

Signed-off-by: Corentin Labbe <clabbe@baylibre.com>
---
 tools/crypto/getstat.c | 283 +++++++++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 283 insertions(+)
 create mode 100644 tools/crypto/getstat.c

diff --git a/tools/crypto/getstat.c b/tools/crypto/getstat.c
new file mode 100644
index 000000000000..e73f2a73e0f6
--- /dev/null
+++ b/tools/crypto/getstat.c
@@ -0,0 +1,283 @@
+/* Heavily copied from libkcapi 2015 - 2017, Stephan Mueller <smueller@chronox.de> */
+#include <errno.h>
+#include <linux/cryptouser.h>
+#include <linux/netlink.h>
+#include <linux/rtnetlink.h>
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <time.h>
+#include <unistd.h>
+
+#define CR_RTA(x)  ((struct rtattr *)(((char *)(x)) + NLMSG_ALIGN(sizeof(struct crypto_user_alg))))
+
+static int get_stat(const char *drivername)
+{
+	struct {
+		struct nlmsghdr n;
+		struct crypto_user_alg cru;
+	} req;
+	struct sockaddr_nl nl;
+	int sd = 0, ret;
+	socklen_t addr_len;
+	struct iovec iov;
+	struct msghdr msg;
+	char buf[4096];
+	struct nlmsghdr *res_n = (struct nlmsghdr *)buf;
+	struct crypto_user_alg *cru_res = NULL;
+	int res_len = 0;
+	struct rtattr *tb[CRYPTOCFGA_MAX + 1];
+	struct rtattr *rta;
+
+	memset(&req, 0, sizeof(req));
+	memset(&buf, 0, sizeof(buf));
+	memset(&msg, 0, sizeof(msg));
+
+	req.n.nlmsg_len = NLMSG_LENGTH(sizeof(req.cru));
+	req.n.nlmsg_flags = NLM_F_REQUEST;
+	req.n.nlmsg_type = CRYPTO_MSG_GETALG;
+	req.n.nlmsg_seq = time(NULL);
+
+	strncpy(req.cru.cru_driver_name, drivername, strlen(drivername));
+
+	sd =  socket(AF_NETLINK, SOCK_RAW, NETLINK_CRYPTO);
+	if (sd < 0) {
+		fprintf(stderr, "Netlink error: cannot open netlink socket");
+		return -errno;
+	}
+	memset(&nl, 0, sizeof(nl));
+	nl.nl_family = AF_NETLINK;
+	if (bind(sd, (struct sockaddr *)&nl, sizeof(nl)) < 0) {
+		ret = -errno;
+		fprintf(stderr, "Netlink error: cannot bind netlink socket");
+		goto out;
+	}
+
+	/* sanity check that netlink socket was successfully opened */
+	addr_len = sizeof(nl);
+	if (getsockname(sd, (struct sockaddr *)&nl, &addr_len) < 0) {
+		ret = -errno;
+		printf("Netlink error: cannot getsockname");
+		goto out;
+	}
+	if (addr_len != sizeof(nl)) {
+		ret = -errno;
+		printf("Netlink error: wrong address length %d", addr_len);
+		goto out;
+	}
+	if (nl.nl_family != AF_NETLINK) {
+		ret = -errno;
+		printf("Netlink error: wrong address family %d",
+				nl.nl_family);
+		goto out;
+	}
+
+	memset(&nl, 0, sizeof(nl));
+	nl.nl_family = AF_NETLINK;
+	iov.iov_base = (void *)&req.n;
+	iov.iov_len = req.n.nlmsg_len;
+	msg.msg_name = &nl;
+	msg.msg_namelen = sizeof(nl);
+	msg.msg_iov = &iov;
+	msg.msg_iovlen = 1;
+	if (sendmsg(sd, &msg, 0) < 0) {
+		ret = -errno;
+		printf("Netlink error: sendmsg failed");
+		goto out;
+	}
+	memset(buf, 0, sizeof(buf));
+	iov.iov_base = buf;
+	while (1) {
+		iov.iov_len = sizeof(buf);
+		ret = recvmsg(sd, &msg, 0);
+		if (ret < 0) {
+			if (errno == EINTR || errno == EAGAIN)
+				continue;
+			ret = -errno;
+			printf("Netlink error: netlink receive error");
+			goto out;
+		}
+		if (ret == 0) {
+			ret = -errno;
+			printf("Netlink error: no data");
+			goto out;
+		}
+		if (ret > sizeof(buf)) {
+			ret = -errno;
+			printf("Netlink error: received too much data");
+			goto out;
+		}
+		break;
+	}
+
+	ret = -EFAULT;
+	res_len = res_n->nlmsg_len;
+	if (res_n->nlmsg_type == NLMSG_ERROR) {
+		/*
+		 * return -EAGAIN -- this error will occur if we received a
+		 * driver name, but used it for a generic name. Allow caller
+		 * to invoke function again where driver name is looked up
+		 */
+		ret = -EAGAIN;
+		goto out;
+	}
+
+	if (res_n->nlmsg_type == CRYPTO_MSG_GETALG) {
+		cru_res = NLMSG_DATA(res_n);
+		res_len -= NLMSG_SPACE(sizeof(*cru_res));
+	}
+	if (res_len < 0) {
+		printf("Netlink error: nlmsg len %d\n", res_len);
+		goto out;
+	}
+
+	if (!cru_res) {
+		ret = -EFAULT;
+		printf("Netlink error: no cru_res\n");
+		goto out;
+	}
+
+	rta = CR_RTA(cru_res);
+	memset(tb, 0, sizeof(struct rtattr *) * (CRYPTOCFGA_MAX + 1));
+	while (RTA_OK(rta, res_len)) {
+		if ((rta->rta_type <= CRYPTOCFGA_MAX) && (!tb[rta->rta_type]))
+			tb[rta->rta_type] = rta;
+		rta = RTA_NEXT(rta, res_len);
+	}
+	if (res_len) {
+		printf("Netlink error: unprocessed data %d",
+				res_len);
+		goto out;
+	}
+
+	if (tb[CRYPTOCFGA_REPORT_HASH]) {
+		struct rtattr *rta = tb[CRYPTOCFGA_REPORT_HASH];
+		struct crypto_report_hash *rhash =
+			(struct crypto_report_hash *)RTA_DATA(rta);
+		printf("%s\tHash\n\tHash: %llu bytes: %llu\n",
+			drivername,
+			rhash->stat_hash, rhash->stat_hash_tlen);
+	} else if (tb[CRYPTOCFGA_REPORT_COMPRESS]) {
+		struct rtattr *rta = tb[CRYPTOCFGA_REPORT_COMPRESS];
+		struct crypto_report_comp *rblk =
+			(struct crypto_report_comp *)RTA_DATA(rta);
+		printf("%s\tCompress\n\tCompress: %llu bytes: %llu\n\tDecompress: %llu bytes: %llu\n",
+			drivername,
+			rblk->stat_compress_cnt, rblk->stat_compress_tlen,
+			rblk->stat_decompress_cnt, rblk->stat_decompress_tlen);
+	} else if (tb[CRYPTOCFGA_REPORT_ACOMP]) {
+		struct rtattr *rta = tb[CRYPTOCFGA_REPORT_ACOMP];
+		struct crypto_report_acomp *rcomp =
+			(struct crypto_report_acomp *)RTA_DATA(rta);
+		printf("%s\tACompress\n\tCompress: %llu bytes: %llu\n\tDecompress: %llu bytes: %llu\n",
+			drivername,
+			rcomp->stat_compress_cnt, rcomp->stat_compress_tlen,
+			rcomp->stat_decompress_cnt, rcomp->stat_decompress_tlen);
+	} else if (tb[CRYPTOCFGA_REPORT_AEAD]) {
+		struct rtattr *rta = tb[CRYPTOCFGA_REPORT_AEAD];
+		struct crypto_report_aead *raead =
+			(struct crypto_report_aead *) RTA_DATA(rta);
+		printf("%s\tAEAD\n\tEncrypt: %llu bytes: %llu\n\tDecrypt: %llu bytes: %llu\n",
+			drivername,
+			raead->stat_encrypt_cnt, raead->stat_encrypt_tlen,
+			raead->stat_decrypt_cnt, raead->stat_decrypt_tlen);
+	} else if (tb[CRYPTOCFGA_REPORT_BLKCIPHER]) {
+		struct rtattr *rta = tb[CRYPTOCFGA_REPORT_BLKCIPHER];
+		struct crypto_report_blkcipher *rblk =
+			(struct crypto_report_blkcipher *)RTA_DATA(rta);
+		printf("%s\tCipher\n\tEncrypt: %llu bytes: %llu\n\tDecrypt: %llu bytes: %llu\n",
+			drivername,
+			rblk->stat_encrypt_cnt, rblk->stat_encrypt_tlen,
+			rblk->stat_decrypt_cnt, rblk->stat_decrypt_tlen);
+	} else if (tb[CRYPTOCFGA_REPORT_AKCIPHER]) {
+		struct rtattr *rta = tb[CRYPTOCFGA_REPORT_AKCIPHER];
+		struct crypto_report_akcipher *rblk =
+			(struct crypto_report_akcipher *)RTA_DATA(rta);
+		printf("%s\tAkcipher\n\tEncrypt: %llu bytes: %llu\n\tDecrypt: %llu bytes: %llu\n\tSign: %llu\n\tVerify: %llu\n",
+			drivername,
+			rblk->stat_encrypt_cnt, rblk->stat_encrypt_tlen,
+			rblk->stat_decrypt_cnt, rblk->stat_decrypt_tlen,
+			rblk->stat_sign_cnt, rblk->stat_verify_cnt);
+	} else if (tb[CRYPTOCFGA_REPORT_CIPHER]) {
+		struct rtattr *rta = tb[CRYPTOCFGA_REPORT_CIPHER];
+		struct crypto_report_cipher *rblk =
+			(struct crypto_report_cipher *) RTA_DATA(rta);
+		printf("%s\tcipher\n\tEncrypt: %llu bytes: %llu\n\tDecrypt: %llu bytes: %llu\n",
+			drivername,
+			rblk->stat_encrypt_cnt, rblk->stat_encrypt_tlen,
+			rblk->stat_decrypt_cnt, rblk->stat_decrypt_tlen);
+	} else if (tb[CRYPTOCFGA_REPORT_RNG]) {
+		struct rtattr *rta = tb[CRYPTOCFGA_REPORT_RNG];
+		struct crypto_report_rng *rrng =
+			(struct crypto_report_rng *) RTA_DATA(rta);
+		printf("%s\tRNG\n\tSeed: %llu\n\tGenerate: %llu bytes: %llu\n",
+			drivername,
+			rrng->stat_seed_cnt,
+			rrng->stat_generate_cnt, rrng->stat_generate_tlen);
+	} else if (tb[CRYPTOCFGA_REPORT_KPP]) {
+		struct rtattr *rta = tb[CRYPTOCFGA_REPORT_KPP];
+		struct crypto_report_kpp *rkpp =
+			(struct crypto_report_kpp *)RTA_DATA(rta);
+		printf("%s\tKPP\n\tSetsecret: %llu\n\tGenerate public key: %llu\n\tCompute_shared_secret: %llu\n",
+			drivername,
+			rkpp->stat_setsecret_cnt,
+			rkpp->stat_generate_public_key_cnt,
+			rkpp->stat_compute_shared_secret_cnt);
+	} else {
+		fprintf(stderr, "%s is of an unknown algorithm\n", drivername);
+	}
+	ret = 0;
+out:
+	close(sd);
+	return ret;
+}
+
+int main(int argc, const char *argv[])
+{
+	char buf[4096];
+	FILE *procfd;
+	int i, lastspace;
+	int ret;
+
+	procfd = fopen("/proc/crypto", "r");
+	if (!procfd) {
+		ret = errno;
+		fprintf(stderr, "Cannot open /proc/crypto %s\n", strerror(errno));
+		return ret;
+	}
+	if (argc > 1) {
+		if (!strcmp(argv[1], "-h") || !strcmp(argv[1], "--help")) {
+			printf("Usage: %s [-h|--help] display this help\n", argv[0]);
+			printf("Usage: %s display all crypto statistics\n", argv[0]);
+			printf("Usage: %s drivername1 drivername2 ... = display crypto statistics about drivername1 ...\n", argv[0]);
+			return 0;
+		}
+		for (i = 1; i < argc; i++) {
+			ret = get_stat(argv[i]);
+			if (ret)
+				return ret;
+		}
+		return 0;
+	}
+
+	while (fgets(buf, sizeof(buf), procfd)) {
+		if (!strncmp(buf, "driver", 6)) {
+			lastspace = 0;
+			i = 0;
+			while (i < strlen(buf)) {
+				i++;
+				if (buf[i] == ' ')
+					lastspace = i;
+			}
+			buf[strlen(buf) - 1] = '\0';
+			ret = get_stat(buf + lastspace + 1);
+			if (ret)
+				goto out;
+		}
+	}
+out:
+	fclose(procfd);
+	return ret;
+}
-- 
2.13.6

^ permalink raw reply related	[flat|nested] 9+ messages in thread

* Re: [PATCH 1/2] crypto: Implement a generic crypto statistics
  2018-01-11 19:56 ` [PATCH 1/2] crypto: Implement a " Corentin Labbe
@ 2018-01-12  6:49   ` Stephan Mueller
  2018-01-12  9:07     ` LABBE Corentin
  0 siblings, 1 reply; 9+ messages in thread
From: Stephan Mueller @ 2018-01-12  6:49 UTC (permalink / raw)
  To: Corentin Labbe; +Cc: davem, herbert, nhorman, linux-crypto, linux-kernel

Am Donnerstag, 11. Januar 2018, 20:56:56 CET schrieb Corentin Labbe:

Hi Corentin,

> This patch implement a generic way to get statistics about all crypto
> usages.
> 
> Signed-off-by: Corentin Labbe <clabbe@baylibre.com>
> ---
>  crypto/Kconfig                  | 11 ++++++++
>  crypto/ablkcipher.c             |  9 +++++++
>  crypto/acompress.c              |  9 +++++++
>  crypto/aead.c                   | 10 ++++++++
>  crypto/ahash.c                  |  8 ++++++
>  crypto/akcipher.c               | 13 ++++++++++
>  crypto/algapi.c                 |  6 +++++
>  crypto/blkcipher.c              |  9 +++++++
>  crypto/crypto_user.c            | 28 +++++++++++++++++++++
>  crypto/kpp.c                    |  7 ++++++
>  crypto/rng.c                    |  8 ++++++
>  crypto/scompress.c              |  9 +++++++
>  crypto/shash.c                  |  5 ++++
>  crypto/skcipher.c               |  9 +++++++
>  include/crypto/acompress.h      | 22 ++++++++++++++++
>  include/crypto/aead.h           | 22 ++++++++++++++++
>  include/crypto/akcipher.h       | 42 +++++++++++++++++++++++++++++++
>  include/crypto/hash.h           | 21 ++++++++++++++++
>  include/crypto/kpp.h            | 28 +++++++++++++++++++++
>  include/crypto/rng.h            | 17 +++++++++++++
>  include/crypto/skcipher.h       | 22 ++++++++++++++++
>  include/linux/crypto.h          | 56
> +++++++++++++++++++++++++++++++++++++++++ include/uapi/linux/cryptouser.h |
> 34 +++++++++++++++++++++++++
>  23 files changed, 405 insertions(+)
> 
> 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);

In general: should'nt the statistics increment only happen if the associated 
operation was successful?

>  /**
>   * 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);

In case you roll another update: please remove the blank line.

> 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;

Why do you use __u64? The atomic_t variable is an int, i.e. 32 bit. Thus I 
would think that __u32 would suffice?


> +	__u64 stat_hash_tlen;
>  };

What I am slightly unsure here is: how should user space detect whether these 
additional parameters are part of the NETLINK_USER API or not? I use that 
interface in my libkcapi whose binary may be used on multiple different kernel 
versions. How should that library operate if one kernel has these parameters 
and another does not?

Ciao
Stephan

^ permalink raw reply	[flat|nested] 9+ messages in thread

* Re: [PATCH 1/2] crypto: Implement a generic crypto statistics
  2018-01-12  6:49   ` Stephan Mueller
@ 2018-01-12  9:07     ` LABBE Corentin
  2018-01-12  9:11       ` Stephan Mueller
  0 siblings, 1 reply; 9+ messages in thread
From: LABBE Corentin @ 2018-01-12  9:07 UTC (permalink / raw)
  To: Stephan Mueller; +Cc: davem, herbert, nhorman, linux-crypto, linux-kernel

On Fri, Jan 12, 2018 at 07:49:43AM +0100, Stephan Mueller wrote:
> Am Donnerstag, 11. Januar 2018, 20:56:56 CET schrieb Corentin Labbe:
> 
> Hi Corentin,
> 
> > This patch implement a generic way to get statistics about all crypto
> > usages.
> > 
> > Signed-off-by: Corentin Labbe <clabbe@baylibre.com>
> > ---
> >  crypto/Kconfig                  | 11 ++++++++
> >  crypto/ablkcipher.c             |  9 +++++++
> >  crypto/acompress.c              |  9 +++++++
> >  crypto/aead.c                   | 10 ++++++++
> >  crypto/ahash.c                  |  8 ++++++
> >  crypto/akcipher.c               | 13 ++++++++++
> >  crypto/algapi.c                 |  6 +++++
> >  crypto/blkcipher.c              |  9 +++++++
> >  crypto/crypto_user.c            | 28 +++++++++++++++++++++
> >  crypto/kpp.c                    |  7 ++++++
> >  crypto/rng.c                    |  8 ++++++
> >  crypto/scompress.c              |  9 +++++++
> >  crypto/shash.c                  |  5 ++++
> >  crypto/skcipher.c               |  9 +++++++
> >  include/crypto/acompress.h      | 22 ++++++++++++++++
> >  include/crypto/aead.h           | 22 ++++++++++++++++
> >  include/crypto/akcipher.h       | 42 +++++++++++++++++++++++++++++++
> >  include/crypto/hash.h           | 21 ++++++++++++++++
> >  include/crypto/kpp.h            | 28 +++++++++++++++++++++
> >  include/crypto/rng.h            | 17 +++++++++++++
> >  include/crypto/skcipher.h       | 22 ++++++++++++++++
> >  include/linux/crypto.h          | 56
> > +++++++++++++++++++++++++++++++++++++++++ include/uapi/linux/cryptouser.h |
> > 34 +++++++++++++++++++++++++
> >  23 files changed, 405 insertions(+)
> > 
> > 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
> > 

[...]
> >   * 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);
> 
> In general: should'nt the statistics increment only happen if the associated 
> operation was successful?
> 

I will do it.
This bring also a possibility to get errors counters.

> >  /**
> >   * 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);
> 
> In case you roll another update: please remove the blank line.

Ok
 
> > 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;
> 
> Why do you use __u64? The atomic_t variable is an int, i.e. 32 bit. Thus I 
> would think that __u32 would suffice?

You are right, I will downgrade to __u32
But I think I will set len stats to atomic64/__u64 and keep count on atomic_t/__u32.

> 
> 
> > +	__u64 stat_hash_tlen;
> >  };
> 
> What I am slightly unsure here is: how should user space detect whether these 
> additional parameters are part of the NETLINK_USER API or not? I use that 
> interface in my libkcapi whose binary may be used on multiple different kernel 
> versions. How should that library operate if one kernel has these parameters 
> and another does not?
> 

Userspace could check for kernel version and know if stat are present or not.
Another way is to add a new netlink request.

Thanks for your review.
Regards
Corentin Labbe

^ permalink raw reply	[flat|nested] 9+ messages in thread

* Re: [PATCH 1/2] crypto: Implement a generic crypto statistics
  2018-01-12  9:07     ` LABBE Corentin
@ 2018-01-12  9:11       ` Stephan Mueller
  2018-01-18  8:58         ` LABBE Corentin
  0 siblings, 1 reply; 9+ messages in thread
From: Stephan Mueller @ 2018-01-12  9:11 UTC (permalink / raw)
  To: LABBE Corentin; +Cc: davem, herbert, nhorman, linux-crypto, linux-kernel

Am Freitag, 12. Januar 2018, 10:07:30 CET schrieb LABBE Corentin:

Hi LABBE,

> 
> > > 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;
> > 
> > Why do you use __u64? The atomic_t variable is an int, i.e. 32 bit. Thus I
> > would think that __u32 would suffice?
> 
> You are right, I will downgrade to __u32
> But I think I will set len stats to atomic64/__u64 and keep count on
> atomic_t/__u32.

Fine with me.

> > > +	__u64 stat_hash_tlen;
> > > 
> > >  };
> > 
> > What I am slightly unsure here is: how should user space detect whether
> > these additional parameters are part of the NETLINK_USER API or not? I
> > use that interface in my libkcapi whose binary may be used on multiple
> > different kernel versions. How should that library operate if one kernel
> > has these parameters and another does not?
> 
> Userspace could check for kernel version and know if stat are present or
> not. Another way is to add a new netlink request.

Well, I am not sure that checking the kernel version is good enough. Distros 
and other vendors may backport this patch. This means that for some older 
kernel versions this interface is present.

Hence I would rather opt for a separate stat message where the user spacee 
caller receives an error on kernels that does not support it.

Ciao
Stephan

^ permalink raw reply	[flat|nested] 9+ messages in thread

* Re: [PATCH 1/2] crypto: Implement a generic crypto statistics
  2018-01-12  9:11       ` Stephan Mueller
@ 2018-01-18  8:58         ` LABBE Corentin
  2018-01-26 15:43           ` Herbert Xu
  0 siblings, 1 reply; 9+ messages in thread
From: LABBE Corentin @ 2018-01-18  8:58 UTC (permalink / raw)
  To: herbert; +Cc: davem, nhorman, linux-crypto, linux-kernel, smueller

On Fri, Jan 12, 2018 at 10:11:18AM +0100, Stephan Mueller wrote:
> Am Freitag, 12. Januar 2018, 10:07:30 CET schrieb LABBE Corentin:
> 
> > > > +	__u64 stat_hash_tlen;
> > > > 
> > > >  };
> > > 
> > > What I am slightly unsure here is: how should user space detect whether
> > > these additional parameters are part of the NETLINK_USER API or not? I
> > > use that interface in my libkcapi whose binary may be used on multiple
> > > different kernel versions. How should that library operate if one kernel
> > > has these parameters and another does not?
> > 
> > Userspace could check for kernel version and know if stat are present or
> > not. Another way is to add a new netlink request.
> 
> Well, I am not sure that checking the kernel version is good enough. Distros 
> and other vendors may backport this patch. This means that for some older 
> kernel versions this interface is present.
> 
> Hence I would rather opt for a separate stat message where the user spacee 
> caller receives an error on kernels that does not support it.
> 
Herbert,
I have two way of adding a new netlink request
- keep the current patch and simply add a new CRYPTO_MSG_GETSTAT which use the same function than CRYPTO_MSG_GETALG
	=> minimal changes, in fact CRYPTO_MSG_GETSTAT and CRYPTO_MSG_GETALG would be the same, but it is easy for userspace to test presence of stat.
- Create a new CRYPTO_MSG_GETSTAT which imply lot of code and add a new crypto_user_stat.c
	=> this imply also to change makefile (rename crypto_user.c to crypto_user_base.c) since crypto_user.ko is made of two files.

Which one do you prefer ?

Regards

^ permalink raw reply	[flat|nested] 9+ messages in thread

* Re: [PATCH 1/2] crypto: Implement a generic crypto statistics
  2018-01-18  8:58         ` LABBE Corentin
@ 2018-01-26 15:43           ` Herbert Xu
  2018-01-31  8:33             ` Steffen Klassert
  0 siblings, 1 reply; 9+ messages in thread
From: Herbert Xu @ 2018-01-26 15:43 UTC (permalink / raw)
  To: LABBE Corentin
  Cc: davem, nhorman, linux-crypto, linux-kernel, smueller, Steffen Klassert

On Thu, Jan 18, 2018 at 09:58:13AM +0100, LABBE Corentin wrote:
>
> I have two way of adding a new netlink request
> - keep the current patch and simply add a new CRYPTO_MSG_GETSTAT which use the same function than CRYPTO_MSG_GETALG
> 	=> minimal changes, in fact CRYPTO_MSG_GETSTAT and CRYPTO_MSG_GETALG would be the same, but it is easy for userspace to test presence of stat.
> - Create a new CRYPTO_MSG_GETSTAT which imply lot of code and add a new crypto_user_stat.c
> 	=> this imply also to change makefile (rename crypto_user.c to crypto_user_base.c) since crypto_user.ko is made of two files.
> 
> Which one do you prefer ?

I think you should check with the crconf author, Steffen Klassert
since that will be affected by this change.

Thanks,
-- 
Email: Herbert Xu <herbert@gondor.apana.org.au>
Home Page: http://gondor.apana.org.au/~herbert/
PGP Key: http://gondor.apana.org.au/~herbert/pubkey.txt

^ permalink raw reply	[flat|nested] 9+ messages in thread

* Re: [PATCH 1/2] crypto: Implement a generic crypto statistics
  2018-01-26 15:43           ` Herbert Xu
@ 2018-01-31  8:33             ` Steffen Klassert
  0 siblings, 0 replies; 9+ messages in thread
From: Steffen Klassert @ 2018-01-31  8:33 UTC (permalink / raw)
  To: Herbert Xu
  Cc: LABBE Corentin, davem, nhorman, linux-crypto, linux-kernel, smueller

On Fri, Jan 26, 2018 at 11:43:28PM +0800, Herbert Xu wrote:
> On Thu, Jan 18, 2018 at 09:58:13AM +0100, LABBE Corentin wrote:
> >
> > I have two way of adding a new netlink request
> > - keep the current patch and simply add a new CRYPTO_MSG_GETSTAT which use the same function than CRYPTO_MSG_GETALG
> > 	=> minimal changes, in fact CRYPTO_MSG_GETSTAT and CRYPTO_MSG_GETALG would be the same, but it is easy for userspace to test presence of stat.
> > - Create a new CRYPTO_MSG_GETSTAT which imply lot of code and add a new crypto_user_stat.c
> > 	=> this imply also to change makefile (rename crypto_user.c to crypto_user_base.c) since crypto_user.ko is made of two files.
> > 
> > Which one do you prefer ?
> 
> I think you should check with the crconf author, Steffen Klassert
> since that will be affected by this change.

I still haven't had time to look into the details, but I'm
fine with everything that does not break existing userspace.
Everything else would be a 'no go'.

^ permalink raw reply	[flat|nested] 9+ messages in thread

end of thread, other threads:[~2018-01-31  8:33 UTC | newest]

Thread overview: 9+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2018-01-11 19:56 [PATCH 0/2] crypto: Implement generic crypto statistics Corentin Labbe
2018-01-11 19:56 ` [PATCH 1/2] crypto: Implement a " Corentin Labbe
2018-01-12  6:49   ` Stephan Mueller
2018-01-12  9:07     ` LABBE Corentin
2018-01-12  9:11       ` Stephan Mueller
2018-01-18  8:58         ` LABBE Corentin
2018-01-26 15:43           ` Herbert Xu
2018-01-31  8:33             ` Steffen Klassert
2018-01-11 19:56 ` [PATCH 2/2] crypto: tools: Add cryptostat userspace Corentin Labbe

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).