Commit cac5818c authored by Corentin Labbe's avatar Corentin Labbe Committed by Herbert Xu

crypto: user - Implement a generic crypto statistics

This patch implement a generic way to get statistics about all crypto
usages.
Signed-off-by: default avatarCorentin Labbe <clabbe@baylibre.com>
Signed-off-by: default avatarHerbert Xu <herbert@gondor.apana.org.au>
parent a9cbfe4c
...@@ -1799,6 +1799,17 @@ config CRYPTO_USER_API_AEAD ...@@ -1799,6 +1799,17 @@ config CRYPTO_USER_API_AEAD
This option enables the user-spaces interface for AEAD This option enables the user-spaces interface for AEAD
cipher algorithms. 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 config CRYPTO_HASH_INFO
bool bool
......
...@@ -54,6 +54,7 @@ cryptomgr-y := algboss.o testmgr.o ...@@ -54,6 +54,7 @@ cryptomgr-y := algboss.o testmgr.o
obj-$(CONFIG_CRYPTO_MANAGER2) += cryptomgr.o obj-$(CONFIG_CRYPTO_MANAGER2) += cryptomgr.o
obj-$(CONFIG_CRYPTO_USER) += crypto_user.o obj-$(CONFIG_CRYPTO_USER) += crypto_user.o
crypto_user-y := crypto_user_base.o crypto_user_stat.o
obj-$(CONFIG_CRYPTO_CMAC) += cmac.o obj-$(CONFIG_CRYPTO_CMAC) += cmac.o
obj-$(CONFIG_CRYPTO_HMAC) += hmac.o obj-$(CONFIG_CRYPTO_HMAC) += hmac.o
obj-$(CONFIG_CRYPTO_VMAC) += vmac.o obj-$(CONFIG_CRYPTO_VMAC) += vmac.o
......
...@@ -364,24 +364,35 @@ static int crypto_ahash_op(struct ahash_request *req, ...@@ -364,24 +364,35 @@ static int crypto_ahash_op(struct ahash_request *req,
int crypto_ahash_final(struct ahash_request *req) int crypto_ahash_final(struct ahash_request *req)
{ {
return crypto_ahash_op(req, crypto_ahash_reqtfm(req)->final); int ret;
ret = crypto_ahash_op(req, crypto_ahash_reqtfm(req)->final);
crypto_stat_ahash_final(req, ret);
return ret;
} }
EXPORT_SYMBOL_GPL(crypto_ahash_final); EXPORT_SYMBOL_GPL(crypto_ahash_final);
int crypto_ahash_finup(struct ahash_request *req) int crypto_ahash_finup(struct ahash_request *req)
{ {
return crypto_ahash_op(req, crypto_ahash_reqtfm(req)->finup); int ret;
ret = crypto_ahash_op(req, crypto_ahash_reqtfm(req)->finup);
crypto_stat_ahash_final(req, ret);
return ret;
} }
EXPORT_SYMBOL_GPL(crypto_ahash_finup); EXPORT_SYMBOL_GPL(crypto_ahash_finup);
int crypto_ahash_digest(struct ahash_request *req) int crypto_ahash_digest(struct ahash_request *req)
{ {
struct crypto_ahash *tfm = crypto_ahash_reqtfm(req); struct crypto_ahash *tfm = crypto_ahash_reqtfm(req);
int ret;
if (crypto_ahash_get_flags(tfm) & CRYPTO_TFM_NEED_KEY) if (crypto_ahash_get_flags(tfm) & CRYPTO_TFM_NEED_KEY)
return -ENOKEY; ret = -ENOKEY;
else
return crypto_ahash_op(req, tfm->digest); ret = crypto_ahash_op(req, tfm->digest);
crypto_stat_ahash_final(req, ret);
return ret;
} }
EXPORT_SYMBOL_GPL(crypto_ahash_digest); EXPORT_SYMBOL_GPL(crypto_ahash_digest);
......
...@@ -258,6 +258,14 @@ static struct crypto_larval *__crypto_register_alg(struct crypto_alg *alg) ...@@ -258,6 +258,14 @@ static struct crypto_larval *__crypto_register_alg(struct crypto_alg *alg)
list_add(&alg->cra_list, &crypto_alg_list); list_add(&alg->cra_list, &crypto_alg_list);
list_add(&larval->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);
atomic64_set(&alg->encrypt_tlen, 0);
atomic64_set(&alg->decrypt_tlen, 0);
atomic_set(&alg->verify_cnt, 0);
atomic_set(&alg->cipher_err_cnt, 0);
atomic_set(&alg->sign_cnt, 0);
out: out:
return larval; return larval;
......
...@@ -29,6 +29,7 @@ ...@@ -29,6 +29,7 @@
#include <crypto/internal/rng.h> #include <crypto/internal/rng.h>
#include <crypto/akcipher.h> #include <crypto/akcipher.h>
#include <crypto/kpp.h> #include <crypto/kpp.h>
#include <crypto/internal/cryptouser.h>
#include "internal.h" #include "internal.h"
...@@ -37,7 +38,7 @@ ...@@ -37,7 +38,7 @@
static DEFINE_MUTEX(crypto_cfg_mutex); static DEFINE_MUTEX(crypto_cfg_mutex);
/* The crypto netlink socket */ /* The crypto netlink socket */
static struct sock *crypto_nlsk; struct sock *crypto_nlsk;
struct crypto_dump_info { struct crypto_dump_info {
struct sk_buff *in_skb; struct sk_buff *in_skb;
...@@ -46,7 +47,7 @@ struct crypto_dump_info { ...@@ -46,7 +47,7 @@ struct crypto_dump_info {
u16 nlmsg_flags; u16 nlmsg_flags;
}; };
static struct crypto_alg *crypto_alg_match(struct crypto_user_alg *p, int exact) struct crypto_alg *crypto_alg_match(struct crypto_user_alg *p, int exact)
{ {
struct crypto_alg *q, *alg = NULL; struct crypto_alg *q, *alg = NULL;
...@@ -461,6 +462,7 @@ static const int crypto_msg_min[CRYPTO_NR_MSGTYPES] = { ...@@ -461,6 +462,7 @@ static const int crypto_msg_min[CRYPTO_NR_MSGTYPES] = {
[CRYPTO_MSG_UPDATEALG - CRYPTO_MSG_BASE] = MSGSIZE(crypto_user_alg), [CRYPTO_MSG_UPDATEALG - CRYPTO_MSG_BASE] = MSGSIZE(crypto_user_alg),
[CRYPTO_MSG_GETALG - CRYPTO_MSG_BASE] = MSGSIZE(crypto_user_alg), [CRYPTO_MSG_GETALG - CRYPTO_MSG_BASE] = MSGSIZE(crypto_user_alg),
[CRYPTO_MSG_DELRNG - CRYPTO_MSG_BASE] = 0, [CRYPTO_MSG_DELRNG - CRYPTO_MSG_BASE] = 0,
[CRYPTO_MSG_GETSTAT - CRYPTO_MSG_BASE] = MSGSIZE(crypto_user_alg),
}; };
static const struct nla_policy crypto_policy[CRYPTOCFGA_MAX+1] = { static const struct nla_policy crypto_policy[CRYPTOCFGA_MAX+1] = {
...@@ -481,6 +483,9 @@ static const struct crypto_link { ...@@ -481,6 +483,9 @@ static const struct crypto_link {
.dump = crypto_dump_report, .dump = crypto_dump_report,
.done = crypto_dump_report_done}, .done = crypto_dump_report_done},
[CRYPTO_MSG_DELRNG - CRYPTO_MSG_BASE] = { .doit = crypto_del_rng }, [CRYPTO_MSG_DELRNG - CRYPTO_MSG_BASE] = { .doit = crypto_del_rng },
[CRYPTO_MSG_GETSTAT - CRYPTO_MSG_BASE] = { .doit = crypto_reportstat,
.dump = crypto_dump_reportstat,
.done = crypto_dump_reportstat_done},
}; };
static int crypto_user_rcv_msg(struct sk_buff *skb, struct nlmsghdr *nlh, static int crypto_user_rcv_msg(struct sk_buff *skb, struct nlmsghdr *nlh,
......
This diff is collapsed.
...@@ -50,6 +50,7 @@ int crypto_rng_reset(struct crypto_rng *tfm, const u8 *seed, unsigned int slen) ...@@ -50,6 +50,7 @@ int crypto_rng_reset(struct crypto_rng *tfm, const u8 *seed, unsigned int slen)
} }
err = crypto_rng_alg(tfm)->seed(tfm, seed, slen); err = crypto_rng_alg(tfm)->seed(tfm, seed, slen);
crypto_stat_rng_seed(tfm, err);
out: out:
kzfree(buf); kzfree(buf);
return err; return err;
......
...@@ -234,6 +234,34 @@ static inline void acomp_request_set_params(struct acomp_req *req, ...@@ -234,6 +234,34 @@ static inline void acomp_request_set_params(struct acomp_req *req,
req->flags |= CRYPTO_ACOMP_ALLOC_OUTPUT; req->flags |= CRYPTO_ACOMP_ALLOC_OUTPUT;
} }
static inline void crypto_stat_compress(struct acomp_req *req, int ret)
{
#ifdef CONFIG_CRYPTO_STATS
struct crypto_acomp *tfm = crypto_acomp_reqtfm(req);
if (ret && ret != -EINPROGRESS && ret != -EBUSY) {
atomic_inc(&tfm->base.__crt_alg->compress_err_cnt);
} else {
atomic_inc(&tfm->base.__crt_alg->compress_cnt);
atomic64_add(req->slen, &tfm->base.__crt_alg->compress_tlen);
}
#endif
}
static inline void crypto_stat_decompress(struct acomp_req *req, int ret)
{
#ifdef CONFIG_CRYPTO_STATS
struct crypto_acomp *tfm = crypto_acomp_reqtfm(req);
if (ret && ret != -EINPROGRESS && ret != -EBUSY) {
atomic_inc(&tfm->base.__crt_alg->compress_err_cnt);
} else {
atomic_inc(&tfm->base.__crt_alg->decompress_cnt);
atomic64_add(req->slen, &tfm->base.__crt_alg->decompress_tlen);
}
#endif
}
/** /**
* crypto_acomp_compress() -- Invoke asynchronous compress operation * crypto_acomp_compress() -- Invoke asynchronous compress operation
* *
...@@ -246,8 +274,11 @@ static inline void acomp_request_set_params(struct acomp_req *req, ...@@ -246,8 +274,11 @@ static inline void acomp_request_set_params(struct acomp_req *req,
static inline int crypto_acomp_compress(struct acomp_req *req) static inline int crypto_acomp_compress(struct acomp_req *req)
{ {
struct crypto_acomp *tfm = crypto_acomp_reqtfm(req); struct crypto_acomp *tfm = crypto_acomp_reqtfm(req);
int ret;
return tfm->compress(req); ret = tfm->compress(req);
crypto_stat_compress(req, ret);
return ret;
} }
/** /**
...@@ -262,8 +293,11 @@ static inline int crypto_acomp_compress(struct acomp_req *req) ...@@ -262,8 +293,11 @@ static inline int crypto_acomp_compress(struct acomp_req *req)
static inline int crypto_acomp_decompress(struct acomp_req *req) static inline int crypto_acomp_decompress(struct acomp_req *req)
{ {
struct crypto_acomp *tfm = crypto_acomp_reqtfm(req); struct crypto_acomp *tfm = crypto_acomp_reqtfm(req);
int ret;
return tfm->decompress(req); ret = tfm->decompress(req);
crypto_stat_decompress(req, ret);
return ret;
} }
#endif #endif
...@@ -306,6 +306,34 @@ static inline struct crypto_aead *crypto_aead_reqtfm(struct aead_request *req) ...@@ -306,6 +306,34 @@ static inline struct crypto_aead *crypto_aead_reqtfm(struct aead_request *req)
return __crypto_aead_cast(req->base.tfm); return __crypto_aead_cast(req->base.tfm);
} }
static inline void crypto_stat_aead_encrypt(struct aead_request *req, int ret)
{
#ifdef CONFIG_CRYPTO_STATS
struct crypto_aead *tfm = crypto_aead_reqtfm(req);
if (ret && ret != -EINPROGRESS && ret != -EBUSY) {
atomic_inc(&tfm->base.__crt_alg->aead_err_cnt);
} else {
atomic_inc(&tfm->base.__crt_alg->encrypt_cnt);
atomic64_add(req->cryptlen, &tfm->base.__crt_alg->encrypt_tlen);
}
#endif
}
static inline void crypto_stat_aead_decrypt(struct aead_request *req, int ret)
{
#ifdef CONFIG_CRYPTO_STATS
struct crypto_aead *tfm = crypto_aead_reqtfm(req);
if (ret && ret != -EINPROGRESS && ret != -EBUSY) {
atomic_inc(&tfm->base.__crt_alg->aead_err_cnt);
} else {
atomic_inc(&tfm->base.__crt_alg->decrypt_cnt);
atomic64_add(req->cryptlen, &tfm->base.__crt_alg->decrypt_tlen);
}
#endif
}
/** /**
* crypto_aead_encrypt() - encrypt plaintext * crypto_aead_encrypt() - encrypt plaintext
* @req: reference to the aead_request handle that holds all information * @req: reference to the aead_request handle that holds all information
...@@ -328,11 +356,14 @@ static inline struct crypto_aead *crypto_aead_reqtfm(struct aead_request *req) ...@@ -328,11 +356,14 @@ static inline struct crypto_aead *crypto_aead_reqtfm(struct aead_request *req)
static inline int crypto_aead_encrypt(struct aead_request *req) static inline int crypto_aead_encrypt(struct aead_request *req)
{ {
struct crypto_aead *aead = crypto_aead_reqtfm(req); struct crypto_aead *aead = crypto_aead_reqtfm(req);
int ret;
if (crypto_aead_get_flags(aead) & CRYPTO_TFM_NEED_KEY) if (crypto_aead_get_flags(aead) & CRYPTO_TFM_NEED_KEY)
return -ENOKEY; ret = -ENOKEY;
else
return crypto_aead_alg(aead)->encrypt(req); ret = crypto_aead_alg(aead)->encrypt(req);
crypto_stat_aead_encrypt(req, ret);
return ret;
} }
/** /**
...@@ -360,14 +391,16 @@ static inline int crypto_aead_encrypt(struct aead_request *req) ...@@ -360,14 +391,16 @@ static inline int crypto_aead_encrypt(struct aead_request *req)
static inline int crypto_aead_decrypt(struct aead_request *req) static inline int crypto_aead_decrypt(struct aead_request *req)
{ {
struct crypto_aead *aead = crypto_aead_reqtfm(req); struct crypto_aead *aead = crypto_aead_reqtfm(req);
int ret;
if (crypto_aead_get_flags(aead) & CRYPTO_TFM_NEED_KEY) if (crypto_aead_get_flags(aead) & CRYPTO_TFM_NEED_KEY)
return -ENOKEY; ret = -ENOKEY;
else if (req->cryptlen < crypto_aead_authsize(aead))
if (req->cryptlen < crypto_aead_authsize(aead)) ret = -EINVAL;
return -EINVAL; else
ret = crypto_aead_alg(aead)->decrypt(req);
return crypto_aead_alg(aead)->decrypt(req); crypto_stat_aead_decrypt(req, ret);
return ret;
} }
/** /**
......
...@@ -271,6 +271,62 @@ static inline unsigned int crypto_akcipher_maxsize(struct crypto_akcipher *tfm) ...@@ -271,6 +271,62 @@ static inline unsigned int crypto_akcipher_maxsize(struct crypto_akcipher *tfm)
return alg->max_size(tfm); return alg->max_size(tfm);
} }
static inline void crypto_stat_akcipher_encrypt(struct akcipher_request *req,
int ret)
{
#ifdef CONFIG_CRYPTO_STATS
struct crypto_akcipher *tfm = crypto_akcipher_reqtfm(req);
if (ret && ret != -EINPROGRESS && ret != -EBUSY) {
atomic_inc(&tfm->base.__crt_alg->akcipher_err_cnt);
} else {
atomic_inc(&tfm->base.__crt_alg->encrypt_cnt);
atomic64_add(req->src_len, &tfm->base.__crt_alg->encrypt_tlen);
}
#endif
}
static inline void crypto_stat_akcipher_decrypt(struct akcipher_request *req,
int ret)
{
#ifdef CONFIG_CRYPTO_STATS
struct crypto_akcipher *tfm = crypto_akcipher_reqtfm(req);
if (ret && ret != -EINPROGRESS && ret != -EBUSY) {
atomic_inc(&tfm->base.__crt_alg->akcipher_err_cnt);
} else {
atomic_inc(&tfm->base.__crt_alg->decrypt_cnt);
atomic64_add(req->src_len, &tfm->base.__crt_alg->decrypt_tlen);
}
#endif
}
static inline void crypto_stat_akcipher_sign(struct akcipher_request *req,
int ret)
{
#ifdef CONFIG_CRYPTO_STATS
struct crypto_akcipher *tfm = crypto_akcipher_reqtfm(req);
if (ret && ret != -EINPROGRESS && ret != -EBUSY)
atomic_inc(&tfm->base.__crt_alg->akcipher_err_cnt);
else
atomic_inc(&tfm->base.__crt_alg->sign_cnt);
#endif
}
static inline void crypto_stat_akcipher_verify(struct akcipher_request *req,
int ret)
{
#ifdef CONFIG_CRYPTO_STATS
struct crypto_akcipher *tfm = crypto_akcipher_reqtfm(req);
if (ret && ret != -EINPROGRESS && ret != -EBUSY)
atomic_inc(&tfm->base.__crt_alg->akcipher_err_cnt);
else
atomic_inc(&tfm->base.__crt_alg->verify_cnt);
#endif
}
/** /**
* crypto_akcipher_encrypt() - Invoke public key encrypt operation * crypto_akcipher_encrypt() - Invoke public key encrypt operation
* *
...@@ -285,8 +341,11 @@ static inline int crypto_akcipher_encrypt(struct akcipher_request *req) ...@@ -285,8 +341,11 @@ static inline int crypto_akcipher_encrypt(struct akcipher_request *req)
{ {
struct crypto_akcipher *tfm = crypto_akcipher_reqtfm(req); struct crypto_akcipher *tfm = crypto_akcipher_reqtfm(req);
struct akcipher_alg *alg = crypto_akcipher_alg(tfm); struct akcipher_alg *alg = crypto_akcipher_alg(tfm);
int ret;
return alg->encrypt(req); ret = alg->encrypt(req);
crypto_stat_akcipher_encrypt(req, ret);
return ret;
} }
/** /**
...@@ -303,8 +362,11 @@ static inline int crypto_akcipher_decrypt(struct akcipher_request *req) ...@@ -303,8 +362,11 @@ static inline int crypto_akcipher_decrypt(struct akcipher_request *req)
{ {
struct crypto_akcipher *tfm = crypto_akcipher_reqtfm(req); struct crypto_akcipher *tfm = crypto_akcipher_reqtfm(req);
struct akcipher_alg *alg = crypto_akcipher_alg(tfm); struct akcipher_alg *alg = crypto_akcipher_alg(tfm);
int ret;
return alg->decrypt(req); ret = alg->decrypt(req);
crypto_stat_akcipher_decrypt(req, ret);
return ret;
} }
/** /**
...@@ -321,8 +383,11 @@ static inline int crypto_akcipher_sign(struct akcipher_request *req) ...@@ -321,8 +383,11 @@ static inline int crypto_akcipher_sign(struct akcipher_request *req)
{ {
struct crypto_akcipher *tfm = crypto_akcipher_reqtfm(req); struct crypto_akcipher *tfm = crypto_akcipher_reqtfm(req);
struct akcipher_alg *alg = crypto_akcipher_alg(tfm); struct akcipher_alg *alg = crypto_akcipher_alg(tfm);
int ret;
return alg->sign(req); ret = alg->sign(req);
crypto_stat_akcipher_sign(req, ret);
return ret;
} }
/** /**
...@@ -339,8 +404,11 @@ static inline int crypto_akcipher_verify(struct akcipher_request *req) ...@@ -339,8 +404,11 @@ static inline int crypto_akcipher_verify(struct akcipher_request *req)
{ {
struct crypto_akcipher *tfm = crypto_akcipher_reqtfm(req); struct crypto_akcipher *tfm = crypto_akcipher_reqtfm(req);
struct akcipher_alg *alg = crypto_akcipher_alg(tfm); struct akcipher_alg *alg = crypto_akcipher_alg(tfm);
int ret;
return alg->verify(req); ret = alg->verify(req);
crypto_stat_akcipher_verify(req, ret);
return ret;
} }
/** /**
......
...@@ -412,6 +412,32 @@ static inline void *ahash_request_ctx(struct ahash_request *req) ...@@ -412,6 +412,32 @@ static inline void *ahash_request_ctx(struct ahash_request *req)
int crypto_ahash_setkey(struct crypto_ahash *tfm, const u8 *key, int crypto_ahash_setkey(struct crypto_ahash *tfm, const u8 *key,
unsigned int keylen); unsigned int keylen);
static inline void crypto_stat_ahash_update(struct ahash_request *req, int ret)
{
#ifdef CONFIG_CRYPTO_STATS
struct crypto_ahash *tfm = crypto_ahash_reqtfm(req);
if (ret && ret != -EINPROGRESS && ret != -EBUSY)
atomic_inc(&tfm->base.__crt_alg->hash_err_cnt);
else
atomic64_add(req->nbytes, &tfm->base.__crt_alg->hash_tlen);
#endif
}
static inline void crypto_stat_ahash_final(struct ahash_request *req, int ret)
{
#ifdef CONFIG_CRYPTO_STATS
struct crypto_ahash *tfm = crypto_ahash_reqtfm(req);
if (ret && ret != -EINPROGRESS && ret != -EBUSY) {
atomic_inc(&tfm->base.__crt_alg->hash_err_cnt);
} else {
atomic_inc(&tfm->base.__crt_alg->hash_cnt);
atomic64_add(req->nbytes, &tfm->base.__crt_alg->hash_tlen);
}
#endif
}
/** /**
* crypto_ahash_finup() - update and finalize message digest * crypto_ahash_finup() - update and finalize message digest
* @req: reference to the ahash_request handle that holds all information * @req: reference to the ahash_request handle that holds all information
...@@ -526,7 +552,11 @@ static inline int crypto_ahash_init(struct ahash_request *req) ...@@ -526,7 +552,11 @@ static inline int crypto_ahash_init(struct ahash_request *req)
*/ */
static inline int crypto_ahash_update(struct ahash_request *req) static inline int crypto_ahash_update(struct ahash_request *req)
{ {
return crypto_ahash_reqtfm(req)->update(req); int ret;
ret = crypto_ahash_reqtfm(req)->update(req);
crypto_stat_ahash_update(req, ret);
return ret;
} }
/** /**
......
/* SPDX-License-Identifier: GPL-2.0 */
#include <net/netlink.h>
struct crypto_alg *crypto_alg_match(struct crypto_user_alg *p, int exact);
int crypto_dump_reportstat(struct sk_buff *skb, struct netlink_callback *cb);
int crypto_reportstat(struct sk_buff *in_skb, struct nlmsghdr *in_nlh, struct nlattr **attrs);
int crypto_dump_reportstat_done(struct netlink_callback *cb);
...@@ -268,6 +268,42 @@ struct kpp_secret { ...@@ -268,6 +268,42 @@ struct kpp_secret {
unsigned short len; unsigned short len;
}; };
static inline void crypto_stat_kpp_set_secret(struct crypto_kpp *tfm, int ret)
{
#ifdef CONFIG_CRYPTO_STATS
if (ret)
atomic_inc(&tfm->base.__crt_alg->kpp_err_cnt);
else
atomic_inc(&tfm->base.__crt_alg->setsecret_cnt);
#endif
}
static inline void crypto_stat_kpp_generate_public_key(struct kpp_request *req,
int ret)
{
#ifdef CONFIG_CRYPTO_STATS
struct crypto_kpp *tfm = crypto_kpp_reqtfm(req);
if (ret)
atomic_inc(&tfm->base.__crt_alg->kpp_err_cnt);
else
atomic_inc(&tfm->base.__crt_alg->generate_public_key_cnt);
#endif
}
static inline void crypto_stat_kpp_compute_shared_secret(struct kpp_request *req,
int ret)
{
#ifdef CONFIG_CRYPTO_STATS
struct crypto_kpp *tfm = crypto_kpp_reqtfm(req);
if (ret)
atomic_inc(&tfm->base.__crt_alg->kpp_err_cnt);
else
atomic_inc(&tfm->base.__crt_alg->compute_shared_secret_cnt);
#endif
}
/** /**
* crypto_kpp_set_secret() - Invoke kpp operation * crypto_kpp_set_secret() - Invoke kpp operation
* *
...@@ -287,8 +323,11 @@ static inline int crypto_kpp_set_secret(struct crypto_kpp *tfm, ...@@ -287,8 +323,11 @@ static inline int crypto_kpp_set_secret(struct crypto_kpp *tfm,
const void *buffer, unsigned int len) const void *buffer, unsigned int len)
{ {
struct kpp_alg *alg = crypto_kpp_alg(tfm); struct kpp_alg *alg = crypto_kpp_alg(tfm);
int ret;
return alg->set_secret(tfm, buffer, len); ret = alg->set_secret(tfm, buffer, len);
crypto_stat_kpp_set_secret(tfm, ret);
return ret;
} }
/** /**
...@@ -308,8 +347,11 @@ static inline int crypto_kpp_generate_public_key(struct kpp_request *req) ...@@ -308,8 +347,11 @@ static inline int crypto_kpp_generate_public_key(struct kpp_request *req)
{ {
struct crypto_kpp *tfm = crypto_kpp_reqtfm(req); struct crypto_kpp *tfm = crypto_kpp_reqtfm(req);
struct kpp_alg *alg = crypto_kpp_alg(tfm); struct kpp_alg *alg = crypto_kpp_alg(tfm);
int ret;
return alg->generate_public_key(req); ret = alg->generate_public_key(req);
crypto_stat_kpp_generate_public_key(req, ret);
return ret;
} }
/** /**
...@@ -326,8 +368,11 @@ static inline int crypto_kpp_compute_shared_secret(struct kpp_request *req) ...@@ -326,8 +368,11 @@ static inline int crypto_kpp_compute_shared_secret(struct kpp_request *req)
{ {
struct crypto_kpp *tfm = crypto_kpp_reqtfm(req); struct crypto_kpp *tfm = crypto_kpp_reqtfm(req);
struct kpp_alg *alg = crypto_kpp_alg(tfm); struct kpp_alg *alg = crypto_kpp_alg(tfm);
int ret;
return alg->compute_shared_secret(req); ret = alg->compute_shared_secret(req);
crypto_stat_kpp_compute_shared_secret(req, ret);
return ret;
} }
/** /**
......
...@@ -122,6 +122,29 @@ static inline void crypto_free_rng(struct crypto_rng *tfm) ...@@ -122,6 +122,29 @@ static inline void crypto_free_rng(struct crypto_rng *tfm)
crypto_destroy_tfm(tfm, crypto_rng_tfm(tfm)); crypto_destroy_tfm(tfm, crypto_rng_tfm(tfm));
} }
static inline void crypto_stat_rng_seed(struct crypto_rng *tfm, int ret)
{
#ifdef CONFIG_CRYPTO_STATS
if (ret && ret != -EINPROGRESS && ret != -EBUSY)
atomic_inc(&tfm->base.__crt_alg->rng_err_cnt);
else
atomic_inc(&tfm->base.__crt_alg->seed_cnt);
#endif
}
static inline void crypto_stat_rng_generate(struct crypto_rng *tfm,
unsigned int dlen, int ret)
{
#ifdef CONFIG_CRYPTO_STATS
if (ret && ret != -EINPROGRESS && ret != -EBUSY) {
atomic_inc(&tfm->base.__crt_alg->rng_err_cnt);
} else {
atomic_inc(&tfm->base.__crt_alg->generate_cnt);
atomic64_add(dlen, &tfm->base.__crt_alg->generate_tlen);
}
#endif
}
/** /**
* crypto_rng_generate() - get random number * crypto_rng_generate() - get random number
* @tfm: cipher handle * @tfm: cipher handle
...@@ -140,7 +163,11 @@ static inline int crypto_rng_generate(struct crypto_rng *tfm, ...@@ -140,7 +163,11 @@ static inline int crypto_rng_generate(struct crypto_rng *tfm,
const u8 *src, unsigned int slen, const u8 *src, unsigned int slen,
u8 *dst, unsigned int dlen) u8 *dst, unsigned int dlen)
{ {
return crypto_rng_alg(tfm)->generate(tfm, src, slen, dst, dlen); int ret;
ret = crypto_rng_alg(tfm)->generate(tfm, src, slen, dst, dlen);
crypto_stat_rng_generate(tfm, dlen, ret);
return ret;
} }
/** /**
......
...@@ -486,6 +486,32 @@ static inline struct crypto_sync_skcipher *crypto_sync_skcipher_reqtfm( ...@@ -486,6 +486,32 @@ static inline struct crypto_sync_skcipher *crypto_sync_skcipher_reqtfm(
return container_of(tfm, struct crypto_sync_skcipher, base); return container_of(tfm, struct crypto_sync_skcipher, base);
} }
static inline void crypto_stat_skcipher_encrypt(struct skcipher_request *req,
int ret, struct crypto_alg *alg)
{
#ifdef CONFIG_CRYPTO_STATS
if (ret && ret != -EINPROGRESS && ret != -EBUSY) {
atomic_inc(&alg->cipher_err_cnt);
} else {
atomic_inc(&alg->encrypt_cnt);
atomic64_add(req->cryptlen, &alg->encrypt_tlen);
}
#endif
}
static inline void crypto_stat_skcipher_decrypt(struct skcipher_request *req,
int ret, struct crypto_alg *alg)
{
#ifdef CONFIG_CRYPTO_STATS
if (ret && ret != -EINPROGRESS && ret != -EBUSY) {
atomic_inc(&alg->cipher_err_cnt);
} else {
atomic_inc(&alg->decrypt_cnt);
atomic64_add(req->cryptlen, &alg->decrypt_tlen);
}
#endif
}
/** /**
* crypto_skcipher_encrypt() - encrypt plaintext * crypto_skcipher_encrypt() - encrypt plaintext
* @req: reference to the skcipher_request handle that holds all information * @req: reference to the skcipher_request handle that holds all information
...@@ -500,11 +526,14 @@ static inline struct crypto_sync_skcipher *crypto_sync_skcipher_reqtfm( ...@@ -500,11 +526,14 @@ static inline struct crypto_sync_skcipher *crypto_sync_skcipher_reqtfm(
static inline int crypto_skcipher_encrypt(struct skcipher_request *req) static inline int crypto_skcipher_encrypt(struct skcipher_request *req)
{ {
struct crypto_skcipher *tfm = crypto_skcipher_reqtfm(req); struct crypto_skcipher *tfm = crypto_skcipher_reqtfm(req);
int ret;
if (crypto_skcipher_get_flags(tfm) & CRYPTO_TFM_NEED_KEY) if (crypto_skcipher_get_flags(tfm) & CRYPTO_TFM_NEED_KEY)
return -ENOKEY; ret = -ENOKEY;
else
return tfm->encrypt(req); ret = tfm->encrypt(req);
crypto_stat_skcipher_encrypt(req, ret, tfm->base.__crt_alg);
return ret;
} }
/** /**
...@@ -521,11 +550,14 @@ static inline int crypto_skcipher_encrypt(struct skcipher_request *req) ...@@ -521,11 +550,14 @@ static inline int crypto_skcipher_encrypt(struct skcipher_request *req)
static inline int crypto_skcipher_decrypt(struct skcipher_request *req) static inline int crypto_skcipher_decrypt(struct skcipher_request *req)
{ {
struct crypto_skcipher *tfm = crypto_skcipher_reqtfm(req); struct crypto_skcipher *tfm = crypto_skcipher_reqtfm(req);
int ret;
if (crypto_skcipher_get_flags(tfm) & CRYPTO_TFM_NEED_KEY) if (crypto_skcipher_get_flags(tfm) & CRYPTO_TFM_NEED_KEY)
return -ENOKEY; ret = -ENOKEY;
else
return tfm->decrypt(req); ret = tfm->decrypt(req);
crypto_stat_skcipher_decrypt(req, ret, tfm->base.__crt_alg);
return ret;
} }
/** /**
......
...@@ -454,6 +454,33 @@ struct compress_alg { ...@@ -454,6 +454,33 @@ struct compress_alg {
* @cra_refcnt: internally used * @cra_refcnt: internally used
* @cra_destroy: internally used * @cra_destroy: internally used
* *
* All following statistics are for this crypto_alg
* @encrypt_cnt: number of encrypt requests
* @decrypt_cnt: number of decrypt requests
* @compress_cnt: number of compress requests
* @decompress_cnt: number of decompress requests
* @generate_cnt: number of RNG generate requests
* @seed_cnt: number of times the rng was seeded
* @hash_cnt: number of hash requests
* @sign_cnt: number of sign requests
* @setsecret_cnt: number of setsecrey operation
* @generate_public_key_cnt: number of generate_public_key operation
* @verify_cnt: number of verify operation
* @compute_shared_secret_cnt: number of compute_shared_secret operation
* @encrypt_tlen: total data size handled by encrypt requests
* @decrypt_tlen: total data size handled by decrypt requests
* @compress_tlen: total data size handled by compress requests
* @decompress_tlen: total data size handled by decompress requests
* @generate_tlen: total data size of generated data by the RNG
* @hash_tlen: total data size hashed
* @akcipher_err_cnt: number of error for akcipher requests
* @cipher_err_cnt: number of error for akcipher requests
* @compress_err_cnt: number of error for akcipher requests
* @aead_err_cnt: number of error for akcipher requests
* @hash_err_cnt: number of error for akcipher requests
* @rng_err_cnt: number of error for akcipher requests
* @kpp_err_cnt: number of error for akcipher requests
*
* The struct crypto_alg describes a generic Crypto API algorithm and is common * The struct crypto_alg describes a generic Crypto API algorithm and is common
* for all of the transformations. Any variable not documented here shall not * for all of the transformations. Any variable not documented here shall not
* be used by a cipher implementation as it is internal to the Crypto API. * be used by a cipher implementation as it is internal to the Crypto API.
...@@ -487,6 +514,45 @@ struct crypto_alg { ...@@ -487,6 +514,45 @@ struct crypto_alg {
void (*cra_destroy)(struct crypto_alg *alg); void (*cra_destroy)(struct crypto_alg *alg);
struct module *cra_module; 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 {
atomic64_t encrypt_tlen;
atomic64_t compress_tlen;
atomic64_t generate_tlen;
atomic64_t hash_tlen;
};
union {
atomic_t akcipher_err_cnt;
atomic_t cipher_err_cnt;
atomic_t compress_err_cnt;
atomic_t aead_err_cnt;
atomic_t hash_err_cnt;
atomic_t rng_err_cnt;
atomic_t kpp_err_cnt;
};
union {
atomic_t decrypt_cnt;
atomic_t decompress_cnt;
atomic_t seed_cnt;
atomic_t generate_public_key_cnt;
};
union {
atomic64_t decrypt_tlen;
atomic64_t decompress_tlen;
};
union {
atomic_t verify_cnt;
atomic_t compute_shared_secret_cnt;
};
atomic_t sign_cnt;
} CRYPTO_MINALIGN_ATTR; } CRYPTO_MINALIGN_ATTR;
/* /*
...@@ -907,6 +973,38 @@ static inline struct crypto_ablkcipher *crypto_ablkcipher_reqtfm( ...@@ -907,6 +973,38 @@ static inline struct crypto_ablkcipher *crypto_ablkcipher_reqtfm(
return __crypto_ablkcipher_cast(req->base.tfm); return __crypto_ablkcipher_cast(req->base.tfm);
} }
static inline void crypto_stat_ablkcipher_encrypt(struct ablkcipher_request *req,
int ret)
{
#ifdef CONFIG_CRYPTO_STATS
struct ablkcipher_tfm *crt =
crypto_ablkcipher_crt(crypto_ablkcipher_reqtfm(req));
if (ret && ret != -EINPROGRESS && ret != -EBUSY) {
atomic_inc(&crt->base->base.__crt_alg->cipher_err_cnt);
} else {
atomic_inc(&crt->base->base.__crt_alg->encrypt_cnt);
atomic64_add(req->nbytes, &crt->base->base.__crt_alg->encrypt_tlen);
}
#endif
}
static inline void crypto_stat_ablkcipher_decrypt(struct ablkcipher_request *req,
int ret)
{
#ifdef CONFIG_CRYPTO_STATS
struct ablkcipher_tfm *crt =
crypto_ablkcipher_crt(crypto_ablkcipher_reqtfm(req));
if (ret && ret != -EINPROGRESS && ret != -EBUSY) {
atomic_inc(&crt->base->base.__crt_alg->cipher_err_cnt);
} else {
atomic_inc(&crt->base->base.__crt_alg->decrypt_cnt);
atomic64_add(req->nbytes, &crt->base->base.__crt_alg->decrypt_tlen);
}
#endif
}
/** /**
* crypto_ablkcipher_encrypt() - encrypt plaintext * crypto_ablkcipher_encrypt() - encrypt plaintext
* @req: reference to the ablkcipher_request handle that holds all information * @req: reference to the ablkcipher_request handle that holds all information
...@@ -922,7 +1020,11 @@ static inline int crypto_ablkcipher_encrypt(struct ablkcipher_request *req) ...@@ -922,7 +1020,11 @@ static inline int crypto_ablkcipher_encrypt(struct ablkcipher_request *req)
{ {
struct ablkcipher_tfm *crt = struct ablkcipher_tfm *crt =
crypto_ablkcipher_crt(crypto_ablkcipher_reqtfm(req)); crypto_ablkcipher_crt(crypto_ablkcipher_reqtfm(req));
return crt->encrypt(req); int ret;
ret = crt->encrypt(req);
crypto_stat_ablkcipher_encrypt(req, ret);
return ret;
} }
/** /**
...@@ -940,7 +1042,11 @@ static inline int crypto_ablkcipher_decrypt(struct ablkcipher_request *req) ...@@ -940,7 +1042,11 @@ static inline int crypto_ablkcipher_decrypt(struct ablkcipher_request *req)
{ {
struct ablkcipher_tfm *crt = struct ablkcipher_tfm *crt =
crypto_ablkcipher_crt(crypto_ablkcipher_reqtfm(req)); crypto_ablkcipher_crt(crypto_ablkcipher_reqtfm(req));
return crt->decrypt(req); int ret;
ret = crt->decrypt(req);
crypto_stat_ablkcipher_decrypt(req, ret);
return ret;
} }
/** /**
......
...@@ -29,6 +29,7 @@ enum { ...@@ -29,6 +29,7 @@ enum {
CRYPTO_MSG_UPDATEALG, CRYPTO_MSG_UPDATEALG,
CRYPTO_MSG_GETALG, CRYPTO_MSG_GETALG,
CRYPTO_MSG_DELRNG, CRYPTO_MSG_DELRNG,
CRYPTO_MSG_GETSTAT,
__CRYPTO_MSG_MAX __CRYPTO_MSG_MAX
}; };
#define CRYPTO_MSG_MAX (__CRYPTO_MSG_MAX - 1) #define CRYPTO_MSG_MAX (__CRYPTO_MSG_MAX - 1)
...@@ -50,6 +51,16 @@ enum crypto_attr_type_t { ...@@ -50,6 +51,16 @@ enum crypto_attr_type_t {
CRYPTOCFGA_REPORT_AKCIPHER, /* struct crypto_report_akcipher */ CRYPTOCFGA_REPORT_AKCIPHER, /* struct crypto_report_akcipher */
CRYPTOCFGA_REPORT_KPP, /* struct crypto_report_kpp */ CRYPTOCFGA_REPORT_KPP, /* struct crypto_report_kpp */
CRYPTOCFGA_REPORT_ACOMP, /* struct crypto_report_acomp */ CRYPTOCFGA_REPORT_ACOMP, /* struct crypto_report_acomp */
CRYPTOCFGA_STAT_LARVAL, /* struct crypto_stat */
CRYPTOCFGA_STAT_HASH, /* struct crypto_stat */
CRYPTOCFGA_STAT_BLKCIPHER, /* struct crypto_stat */
CRYPTOCFGA_STAT_AEAD, /* struct crypto_stat */
CRYPTOCFGA_STAT_COMPRESS, /* struct crypto_stat */
CRYPTOCFGA_STAT_RNG, /* struct crypto_stat */
CRYPTOCFGA_STAT_CIPHER, /* struct crypto_stat */
CRYPTOCFGA_STAT_AKCIPHER, /* struct crypto_stat */
CRYPTOCFGA_STAT_KPP, /* struct crypto_stat */
CRYPTOCFGA_STAT_ACOMP, /* struct crypto_stat */
__CRYPTOCFGA_MAX __CRYPTOCFGA_MAX
#define CRYPTOCFGA_MAX (__CRYPTOCFGA_MAX - 1) #define CRYPTOCFGA_MAX (__CRYPTOCFGA_MAX - 1)
...@@ -65,6 +76,47 @@ struct crypto_user_alg { ...@@ -65,6 +76,47 @@ struct crypto_user_alg {
__u32 cru_flags; __u32 cru_flags;
}; };
struct crypto_stat {
char type[CRYPTO_MAX_NAME];
union {
__u32 stat_encrypt_cnt;
__u32 stat_compress_cnt;
__u32 stat_generate_cnt;
__u32 stat_hash_cnt;
__u32 stat_setsecret_cnt;
};
union {
__u64 stat_encrypt_tlen;
__u64 stat_compress_tlen;
__u64 stat_generate_tlen;
__u64 stat_hash_tlen;
};
union {
__u32 stat_akcipher_err_cnt;
__u32 stat_cipher_err_cnt;
__u32 stat_compress_err_cnt;
__u32 stat_aead_err_cnt;
__u32 stat_hash_err_cnt;
__u32 stat_rng_err_cnt;
__u32 stat_kpp_err_cnt;
};
union {
__u32 stat_decrypt_cnt;
__u32 stat_decompress_cnt;
__u32 stat_seed_cnt;
__u32 stat_generate_public_key_cnt;
};
union {
__u64 stat_decrypt_tlen;
__u64 stat_decompress_tlen;
};
union {
__u32 stat_verify_cnt;
__u32 stat_compute_shared_secret_cnt;
};
__u32 stat_sign_cnt;
};
struct crypto_report_larval { struct crypto_report_larval {
char type[CRYPTO_MAX_NAME]; char type[CRYPTO_MAX_NAME];
}; };
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment