Re: [PATCH RFC 2/3] crypto: Implement a generic crypto statistics

From: LABBE Corentin
Date: Thu Dec 21 2017 - 15:03:52 EST


On Thu, Dec 21, 2017 at 07:38:35AM +0100, Stephan Mueller wrote:
> Am Mittwoch, 20. Dezember 2017, 21:09:26 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@xxxxxxxxxxxx>
> > ---
> > crypto/Kconfig | 11 +++
> > crypto/ahash.c | 18 +++++
> > crypto/algapi.c | 186
> > +++++++++++++++++++++++++++++++++++++++++++++ crypto/rng.c |
> > 3 +
> > include/crypto/acompress.h | 10 +++
> > include/crypto/akcipher.h | 12 +++
> > include/crypto/kpp.h | 9 +++
> > include/crypto/rng.h | 5 ++
> > include/crypto/skcipher.h | 8 ++
> > include/linux/crypto.h | 22 ++++++
> > 10 files changed, 284 insertions(+)
> >
> > diff --git a/crypto/Kconfig b/crypto/Kconfig
> > index d6e9b60fc063..69f1822a026b 100644
> > --- a/crypto/Kconfig
> > +++ b/crypto/Kconfig
> > @@ -1781,6 +1781,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/ahash.c b/crypto/ahash.c
> > index 3a35d67de7d9..93b56892f1b8 100644
> > --- a/crypto/ahash.c
> > +++ b/crypto/ahash.c
> > @@ -356,18 +356,36 @@ static int crypto_ahash_op(struct ahash_request *req,
> >
> > int crypto_ahash_final(struct ahash_request *req)
> > {
> > +#ifdef CONFIG_CRYPTO_STATS
> > + struct crypto_ahash *tfm = crypto_ahash_reqtfm(req);
> > +
> > + tfm->base.__crt_alg->enc_cnt++;
> > + tfm->base.__crt_alg->enc_tlen += req->nbytes;
> > +#endif
> > return crypto_ahash_op(req, crypto_ahash_reqtfm(req)->final);
> > }
> > EXPORT_SYMBOL_GPL(crypto_ahash_final);
> >
> > int crypto_ahash_finup(struct ahash_request *req)
> > {
> > +#ifdef CONFIG_CRYPTO_STATS
> > + struct crypto_ahash *tfm = crypto_ahash_reqtfm(req);
> > +
> > + tfm->base.__crt_alg->enc_cnt++;
> > + tfm->base.__crt_alg->enc_tlen += req->nbytes;
> > +#endif
> > return crypto_ahash_op(req, crypto_ahash_reqtfm(req)->finup);
> > }
> > EXPORT_SYMBOL_GPL(crypto_ahash_finup);
> >
> > int crypto_ahash_digest(struct ahash_request *req)
> > {
> > +#ifdef CONFIG_CRYPTO_STATS
> > + struct crypto_ahash *tfm = crypto_ahash_reqtfm(req);
> > +
> > + tfm->base.__crt_alg->enc_cnt++;
> > + tfm->base.__crt_alg->enc_tlen += req->nbytes;
> > +#endif
>
> This is ugly. May I ask that one inlne function is made that has these ifdefs
> instead of adding them throughout multiple functions? This comment would apply
> to the other instrumentation code below as well. The issue is that these
> ifdefs should not be spread around through the code.
>
> Besides, I would think that the use of normal integers is not thread-safe.
> What about using atomic_t?

I will do all your suggestions.

>
> > return crypto_ahash_op(req, crypto_ahash_reqtfm(req)->digest);
> > }
> > EXPORT_SYMBOL_GPL(crypto_ahash_digest);
> > diff --git a/crypto/algapi.c b/crypto/algapi.c
> > index b8f6122f37e9..4fca4576af78 100644
> > --- a/crypto/algapi.c
> > +++ b/crypto/algapi.c
> > @@ -20,11 +20,158 @@
> > #include <linux/rtnetlink.h>
> > #include <linux/slab.h>
> > #include <linux/string.h>
> > +#include <linux/kobject.h>
> >
> > #include "internal.h"
> >
> > static LIST_HEAD(crypto_template_list);
> >
> > +#ifdef CONFIG_CRYPTO_STATS
>
> Instead of ifdefing in the code, may I suggest adding a new file that is
> compiled / not compiled via the Makefile?

I agree, it will be better.

>
> > +static struct kobject *crypto_root_kobj;
> > +
> > +static struct kobj_type dynamic_kobj_ktype = {
> > + .sysfs_ops = &kobj_sysfs_ops,
> > +};
> > +
> > +static ssize_t fcrypto_priority(struct kobject *kobj,
> > + struct kobj_attribute *attr, char *buf)
> > +{
> > + struct crypto_alg *alg;
> > +
> > + alg = container_of(kobj, struct crypto_alg, cra_stat_obj);
> > + return snprintf(buf, 9, "%d\n", alg->cra_priority);
> > +}
> > +
> > +static ssize_t fcrypto_stat_enc_cnt(struct kobject *kobj,
> > + struct kobj_attribute *attr, char *buf)
> > +{
> > + struct crypto_alg *alg;
> > +
> > + alg = container_of(kobj, struct crypto_alg, cra_stat_obj);
> > + return snprintf(buf, 9, "%lu\n", alg->enc_cnt);
> > +}
> > +
> > +static ssize_t fcrypto_stat_enc_tlen(struct kobject *kobj,
> > + struct kobj_attribute *attr, char *buf)
> > +{
> > + struct crypto_alg *alg;
> > +
> > + alg = container_of(kobj, struct crypto_alg, cra_stat_obj);
> > + return snprintf(buf, 9, "%lu\n", alg->enc_tlen);
> > +}
> > +
> > +static ssize_t fcrypto_stat_dec_cnt(struct kobject *kobj,
> > + struct kobj_attribute *attr, char *buf)
> > +{
> > + struct crypto_alg *alg;
> > +
> > + alg = container_of(kobj, struct crypto_alg, cra_stat_obj);
> > + return snprintf(buf, 9, "%lu\n", alg->dec_cnt);
> > +}
> > +
> > +static ssize_t fcrypto_stat_dec_tlen(struct kobject *kobj,
> > + struct kobj_attribute *attr, char *buf)
> > +{
> > + struct crypto_alg *alg;
> > +
> > + alg = container_of(kobj, struct crypto_alg, cra_stat_obj);
> > + return snprintf(buf, 9, "%lu\n", alg->dec_tlen);
> > +}
> > +
> > +static ssize_t fcrypto_stat_verify_cnt(struct kobject *kobj,
> > + struct kobj_attribute *attr, char *buf)
> > +{
> > + struct crypto_alg *alg;
> > +
> > + alg = container_of(kobj, struct crypto_alg, cra_stat_obj);
> > + return snprintf(buf, 9, "%lu\n", alg->verify_cnt);
> > +}
> > +
> > +static ssize_t fcrypto_stat_sign_cnt(struct kobject *kobj,
> > + struct kobj_attribute *attr, char *buf)
> > +{
> > + struct crypto_alg *alg;
> > +
> > + alg = container_of(kobj, struct crypto_alg, cra_stat_obj);
> > + return snprintf(buf, 9, "%lu\n", alg->sign_cnt);
> > +}
> > +
> > +static ssize_t fcrypto_stat_type(struct kobject *kobj,
> > + struct kobj_attribute *attr, char *buf)
> > +{
> > + struct crypto_alg *alg;
> > + u32 type;
> > +
> > + alg = container_of(kobj, struct crypto_alg, cra_stat_obj);
> > + type = (alg->cra_flags & CRYPTO_ALG_TYPE_MASK);
> > + if (type == CRYPTO_ALG_TYPE_ABLKCIPHER ||
> > + type == CRYPTO_ALG_TYPE_SKCIPHER ||
> > + type == CRYPTO_ALG_TYPE_CIPHER ||
> > + type == CRYPTO_ALG_TYPE_BLKCIPHER
> > + )
> > + return snprintf(buf, 9, "cipher\n");
>
> "skcipher" ?

Fixed!

Thanks for your review.
Regards
Corentin Labbe