This patch implement a generic way to get statistics about all crypto usages. Signed-off-by: Corentin Labbe <clabbe@xxxxxxxxxxxx> --- 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