Merge tag 'riscv-for-linus-6.4-mw1' of git://git.kernel.org/pub/scm/linux/kernel...
[linux-block.git] / crypto / skcipher.c
index 7bf4871fec8006ac09c686fc88413256312bf255..6caca02d7e5527ef1559c1169b1caa498f1363f5 100644 (file)
 #include <crypto/scatterwalk.h>
 #include <linux/bug.h>
 #include <linux/cryptouser.h>
-#include <linux/compiler.h>
+#include <linux/err.h>
+#include <linux/kernel.h>
 #include <linux/list.h>
+#include <linux/mm.h>
 #include <linux/module.h>
-#include <linux/rtnetlink.h>
 #include <linux/seq_file.h>
+#include <linux/slab.h>
+#include <linux/string.h>
 #include <net/netlink.h>
 
 #include "internal.h"
@@ -77,6 +80,35 @@ static inline u8 *skcipher_get_spot(u8 *start, unsigned int len)
        return max(start, end_page);
 }
 
+static inline struct skcipher_alg *__crypto_skcipher_alg(
+       struct crypto_alg *alg)
+{
+       return container_of(alg, struct skcipher_alg, base);
+}
+
+static inline struct crypto_istat_cipher *skcipher_get_stat(
+       struct skcipher_alg *alg)
+{
+#ifdef CONFIG_CRYPTO_STATS
+       return &alg->stat;
+#else
+       return NULL;
+#endif
+}
+
+static inline int crypto_skcipher_errstat(struct skcipher_alg *alg, int err)
+{
+       struct crypto_istat_cipher *istat = skcipher_get_stat(alg);
+
+       if (!IS_ENABLED(CONFIG_CRYPTO_STATS))
+               return err;
+
+       if (err && err != -EINPROGRESS && err != -EBUSY)
+               atomic64_inc(&istat->err_cnt);
+
+       return err;
+}
+
 static int skcipher_done_slow(struct skcipher_walk *walk, unsigned int bsize)
 {
        u8 *addr;
@@ -605,34 +637,44 @@ EXPORT_SYMBOL_GPL(crypto_skcipher_setkey);
 int crypto_skcipher_encrypt(struct skcipher_request *req)
 {
        struct crypto_skcipher *tfm = crypto_skcipher_reqtfm(req);
-       struct crypto_alg *alg = tfm->base.__crt_alg;
-       unsigned int cryptlen = req->cryptlen;
+       struct skcipher_alg *alg = crypto_skcipher_alg(tfm);
        int ret;
 
-       crypto_stats_get(alg);
+       if (IS_ENABLED(CONFIG_CRYPTO_STATS)) {
+               struct crypto_istat_cipher *istat = skcipher_get_stat(alg);
+
+               atomic64_inc(&istat->encrypt_cnt);
+               atomic64_add(req->cryptlen, &istat->encrypt_tlen);
+       }
+
        if (crypto_skcipher_get_flags(tfm) & CRYPTO_TFM_NEED_KEY)
                ret = -ENOKEY;
        else
-               ret = crypto_skcipher_alg(tfm)->encrypt(req);
-       crypto_stats_skcipher_encrypt(cryptlen, ret, alg);
-       return ret;
+               ret = alg->encrypt(req);
+
+       return crypto_skcipher_errstat(alg, ret);
 }
 EXPORT_SYMBOL_GPL(crypto_skcipher_encrypt);
 
 int crypto_skcipher_decrypt(struct skcipher_request *req)
 {
        struct crypto_skcipher *tfm = crypto_skcipher_reqtfm(req);
-       struct crypto_alg *alg = tfm->base.__crt_alg;
-       unsigned int cryptlen = req->cryptlen;
+       struct skcipher_alg *alg = crypto_skcipher_alg(tfm);
        int ret;
 
-       crypto_stats_get(alg);
+       if (IS_ENABLED(CONFIG_CRYPTO_STATS)) {
+               struct crypto_istat_cipher *istat = skcipher_get_stat(alg);
+
+               atomic64_inc(&istat->decrypt_cnt);
+               atomic64_add(req->cryptlen, &istat->decrypt_tlen);
+       }
+
        if (crypto_skcipher_get_flags(tfm) & CRYPTO_TFM_NEED_KEY)
                ret = -ENOKEY;
        else
-               ret = crypto_skcipher_alg(tfm)->decrypt(req);
-       crypto_stats_skcipher_decrypt(cryptlen, ret, alg);
-       return ret;
+               ret = alg->decrypt(req);
+
+       return crypto_skcipher_errstat(alg, ret);
 }
 EXPORT_SYMBOL_GPL(crypto_skcipher_decrypt);
 
@@ -672,8 +714,7 @@ static void crypto_skcipher_show(struct seq_file *m, struct crypto_alg *alg)
        __maybe_unused;
 static void crypto_skcipher_show(struct seq_file *m, struct crypto_alg *alg)
 {
-       struct skcipher_alg *skcipher = container_of(alg, struct skcipher_alg,
-                                                    base);
+       struct skcipher_alg *skcipher = __crypto_skcipher_alg(alg);
 
        seq_printf(m, "type         : skcipher\n");
        seq_printf(m, "async        : %s\n",
@@ -686,12 +727,11 @@ static void crypto_skcipher_show(struct seq_file *m, struct crypto_alg *alg)
        seq_printf(m, "walksize     : %u\n", skcipher->walksize);
 }
 
-#ifdef CONFIG_NET
-static int crypto_skcipher_report(struct sk_buff *skb, struct crypto_alg *alg)
+static int __maybe_unused crypto_skcipher_report(
+       struct sk_buff *skb, struct crypto_alg *alg)
 {
+       struct skcipher_alg *skcipher = __crypto_skcipher_alg(alg);
        struct crypto_report_blkcipher rblkcipher;
-       struct skcipher_alg *skcipher = container_of(alg, struct skcipher_alg,
-                                                    base);
 
        memset(&rblkcipher, 0, sizeof(rblkcipher));
 
@@ -706,12 +746,28 @@ static int crypto_skcipher_report(struct sk_buff *skb, struct crypto_alg *alg)
        return nla_put(skb, CRYPTOCFGA_REPORT_BLKCIPHER,
                       sizeof(rblkcipher), &rblkcipher);
 }
-#else
-static int crypto_skcipher_report(struct sk_buff *skb, struct crypto_alg *alg)
+
+static int __maybe_unused crypto_skcipher_report_stat(
+       struct sk_buff *skb, struct crypto_alg *alg)
 {
-       return -ENOSYS;
+       struct skcipher_alg *skcipher = __crypto_skcipher_alg(alg);
+       struct crypto_istat_cipher *istat;
+       struct crypto_stat_cipher rcipher;
+
+       istat = skcipher_get_stat(skcipher);
+
+       memset(&rcipher, 0, sizeof(rcipher));
+
+       strscpy(rcipher.type, "cipher", sizeof(rcipher.type));
+
+       rcipher.stat_encrypt_cnt = atomic64_read(&istat->encrypt_cnt);
+       rcipher.stat_encrypt_tlen = atomic64_read(&istat->encrypt_tlen);
+       rcipher.stat_decrypt_cnt =  atomic64_read(&istat->decrypt_cnt);
+       rcipher.stat_decrypt_tlen = atomic64_read(&istat->decrypt_tlen);
+       rcipher.stat_err_cnt =  atomic64_read(&istat->err_cnt);
+
+       return nla_put(skb, CRYPTOCFGA_STAT_CIPHER, sizeof(rcipher), &rcipher);
 }
-#endif
 
 static const struct crypto_type crypto_skcipher_type = {
        .extsize = crypto_alg_extsize,
@@ -720,7 +776,12 @@ static const struct crypto_type crypto_skcipher_type = {
 #ifdef CONFIG_PROC_FS
        .show = crypto_skcipher_show,
 #endif
+#ifdef CONFIG_CRYPTO_USER
        .report = crypto_skcipher_report,
+#endif
+#ifdef CONFIG_CRYPTO_STATS
+       .report_stat = crypto_skcipher_report_stat,
+#endif
        .maskclear = ~CRYPTO_ALG_TYPE_MASK,
        .maskset = CRYPTO_ALG_TYPE_MASK,
        .type = CRYPTO_ALG_TYPE_SKCIPHER,
@@ -775,6 +836,7 @@ EXPORT_SYMBOL_GPL(crypto_has_skcipher);
 
 static int skcipher_prepare_alg(struct skcipher_alg *alg)
 {
+       struct crypto_istat_cipher *istat = skcipher_get_stat(alg);
        struct crypto_alg *base = &alg->base;
 
        if (alg->ivsize > PAGE_SIZE / 8 || alg->chunksize > PAGE_SIZE / 8 ||
@@ -790,6 +852,9 @@ static int skcipher_prepare_alg(struct skcipher_alg *alg)
        base->cra_flags &= ~CRYPTO_ALG_TYPE_MASK;
        base->cra_flags |= CRYPTO_ALG_TYPE_SKCIPHER;
 
+       if (IS_ENABLED(CONFIG_CRYPTO_STATS))
+               memset(istat, 0, sizeof(*istat));
+
        return 0;
 }