aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorCorentin Labbe <clabbe@baylibre.com>2018-09-19 06:10:54 -0400
committerHerbert Xu <herbert@gondor.apana.org.au>2018-09-28 00:46:25 -0400
commitcac5818c25d0423bda73e2b6997404ed0a7ed9e3 (patch)
tree3a443fa0e9a8e96799e2802552cd1f6435213569
parenta9cbfe4c784436368790f0c59674f99ba97ae21e (diff)
crypto: user - Implement a generic crypto statistics
This patch implement a generic way to get statistics about all crypto usages. Signed-off-by: Corentin Labbe <clabbe@baylibre.com> Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>
-rw-r--r--crypto/Kconfig11
-rw-r--r--crypto/Makefile1
-rw-r--r--crypto/ahash.c21
-rw-r--r--crypto/algapi.c8
-rw-r--r--crypto/crypto_user_base.c (renamed from crypto/crypto_user.c)9
-rw-r--r--crypto/crypto_user_stat.c463
-rw-r--r--crypto/rng.c1
-rw-r--r--include/crypto/acompress.h38
-rw-r--r--include/crypto/aead.h51
-rw-r--r--include/crypto/akcipher.h76
-rw-r--r--include/crypto/hash.h32
-rw-r--r--include/crypto/internal/cryptouser.h8
-rw-r--r--include/crypto/kpp.h51
-rw-r--r--include/crypto/rng.h29
-rw-r--r--include/crypto/skcipher.h44
-rw-r--r--include/linux/crypto.h110
-rw-r--r--include/uapi/linux/cryptouser.h52
17 files changed, 970 insertions, 35 deletions
diff --git a/crypto/Kconfig b/crypto/Kconfig
index 90f2811fac5f..4ef95b0b25a3 100644
--- a/crypto/Kconfig
+++ b/crypto/Kconfig
@@ -1799,6 +1799,17 @@ config CRYPTO_USER_API_AEAD
1799 This option enables the user-spaces interface for AEAD 1799 This option enables the user-spaces interface for AEAD
1800 cipher algorithms. 1800 cipher algorithms.
1801 1801
1802config CRYPTO_STATS
1803 bool "Crypto usage statistics for User-space"
1804 help
1805 This option enables the gathering of crypto stats.
1806 This will collect:
1807 - encrypt/decrypt size and numbers of symmeric operations
1808 - compress/decompress size and numbers of compress operations
1809 - size and numbers of hash operations
1810 - encrypt/decrypt/sign/verify numbers for asymmetric operations
1811 - generate/seed numbers for rng operations
1812
1802config CRYPTO_HASH_INFO 1813config CRYPTO_HASH_INFO
1803 bool 1814 bool
1804 1815
diff --git a/crypto/Makefile b/crypto/Makefile
index d719843f8b6e..ff5c2bbda04a 100644
--- a/crypto/Makefile
+++ b/crypto/Makefile
@@ -54,6 +54,7 @@ cryptomgr-y := algboss.o testmgr.o
54 54
55obj-$(CONFIG_CRYPTO_MANAGER2) += cryptomgr.o 55obj-$(CONFIG_CRYPTO_MANAGER2) += cryptomgr.o
56obj-$(CONFIG_CRYPTO_USER) += crypto_user.o 56obj-$(CONFIG_CRYPTO_USER) += crypto_user.o
57crypto_user-y := crypto_user_base.o crypto_user_stat.o
57obj-$(CONFIG_CRYPTO_CMAC) += cmac.o 58obj-$(CONFIG_CRYPTO_CMAC) += cmac.o
58obj-$(CONFIG_CRYPTO_HMAC) += hmac.o 59obj-$(CONFIG_CRYPTO_HMAC) += hmac.o
59obj-$(CONFIG_CRYPTO_VMAC) += vmac.o 60obj-$(CONFIG_CRYPTO_VMAC) += vmac.o
diff --git a/crypto/ahash.c b/crypto/ahash.c
index 78aaf2158c43..e21667b4e10a 100644
--- a/crypto/ahash.c
+++ b/crypto/ahash.c
@@ -364,24 +364,35 @@ static int crypto_ahash_op(struct ahash_request *req,
364 364
365int crypto_ahash_final(struct ahash_request *req) 365int crypto_ahash_final(struct ahash_request *req)
366{ 366{
367 return crypto_ahash_op(req, crypto_ahash_reqtfm(req)->final); 367 int ret;
368
369 ret = crypto_ahash_op(req, crypto_ahash_reqtfm(req)->final);
370 crypto_stat_ahash_final(req, ret);
371 return ret;
368} 372}
369EXPORT_SYMBOL_GPL(crypto_ahash_final); 373EXPORT_SYMBOL_GPL(crypto_ahash_final);
370 374
371int crypto_ahash_finup(struct ahash_request *req) 375int crypto_ahash_finup(struct ahash_request *req)
372{ 376{
373 return crypto_ahash_op(req, crypto_ahash_reqtfm(req)->finup); 377 int ret;
378
379 ret = crypto_ahash_op(req, crypto_ahash_reqtfm(req)->finup);
380 crypto_stat_ahash_final(req, ret);
381 return ret;
374} 382}
375EXPORT_SYMBOL_GPL(crypto_ahash_finup); 383EXPORT_SYMBOL_GPL(crypto_ahash_finup);
376 384
377int crypto_ahash_digest(struct ahash_request *req) 385int crypto_ahash_digest(struct ahash_request *req)
378{ 386{
379 struct crypto_ahash *tfm = crypto_ahash_reqtfm(req); 387 struct crypto_ahash *tfm = crypto_ahash_reqtfm(req);
388 int ret;
380 389
381 if (crypto_ahash_get_flags(tfm) & CRYPTO_TFM_NEED_KEY) 390 if (crypto_ahash_get_flags(tfm) & CRYPTO_TFM_NEED_KEY)
382 return -ENOKEY; 391 ret = -ENOKEY;
383 392 else
384 return crypto_ahash_op(req, tfm->digest); 393 ret = crypto_ahash_op(req, tfm->digest);
394 crypto_stat_ahash_final(req, ret);
395 return ret;
385} 396}
386EXPORT_SYMBOL_GPL(crypto_ahash_digest); 397EXPORT_SYMBOL_GPL(crypto_ahash_digest);
387 398
diff --git a/crypto/algapi.c b/crypto/algapi.c
index 38daa8677da9..2545c5f89c4c 100644
--- a/crypto/algapi.c
+++ b/crypto/algapi.c
@@ -258,6 +258,14 @@ static struct crypto_larval *__crypto_register_alg(struct crypto_alg *alg)
258 list_add(&alg->cra_list, &crypto_alg_list); 258 list_add(&alg->cra_list, &crypto_alg_list);
259 list_add(&larval->alg.cra_list, &crypto_alg_list); 259 list_add(&larval->alg.cra_list, &crypto_alg_list);
260 260
261 atomic_set(&alg->encrypt_cnt, 0);
262 atomic_set(&alg->decrypt_cnt, 0);
263 atomic64_set(&alg->encrypt_tlen, 0);
264 atomic64_set(&alg->decrypt_tlen, 0);
265 atomic_set(&alg->verify_cnt, 0);
266 atomic_set(&alg->cipher_err_cnt, 0);
267 atomic_set(&alg->sign_cnt, 0);
268
261out: 269out:
262 return larval; 270 return larval;
263 271
diff --git a/crypto/crypto_user.c b/crypto/crypto_user_base.c
index 0e89b5457cab..e41f6cc33fff 100644
--- a/crypto/crypto_user.c
+++ b/crypto/crypto_user_base.c
@@ -29,6 +29,7 @@
29#include <crypto/internal/rng.h> 29#include <crypto/internal/rng.h>
30#include <crypto/akcipher.h> 30#include <crypto/akcipher.h>
31#include <crypto/kpp.h> 31#include <crypto/kpp.h>
32#include <crypto/internal/cryptouser.h>
32 33
33#include "internal.h" 34#include "internal.h"
34 35
@@ -37,7 +38,7 @@
37static DEFINE_MUTEX(crypto_cfg_mutex); 38static DEFINE_MUTEX(crypto_cfg_mutex);
38 39
39/* The crypto netlink socket */ 40/* The crypto netlink socket */
40static struct sock *crypto_nlsk; 41struct sock *crypto_nlsk;
41 42
42struct crypto_dump_info { 43struct crypto_dump_info {
43 struct sk_buff *in_skb; 44 struct sk_buff *in_skb;
@@ -46,7 +47,7 @@ struct crypto_dump_info {
46 u16 nlmsg_flags; 47 u16 nlmsg_flags;
47}; 48};
48 49
49static struct crypto_alg *crypto_alg_match(struct crypto_user_alg *p, int exact) 50struct crypto_alg *crypto_alg_match(struct crypto_user_alg *p, int exact)
50{ 51{
51 struct crypto_alg *q, *alg = NULL; 52 struct crypto_alg *q, *alg = NULL;
52 53
@@ -461,6 +462,7 @@ static const int crypto_msg_min[CRYPTO_NR_MSGTYPES] = {
461 [CRYPTO_MSG_UPDATEALG - CRYPTO_MSG_BASE] = MSGSIZE(crypto_user_alg), 462 [CRYPTO_MSG_UPDATEALG - CRYPTO_MSG_BASE] = MSGSIZE(crypto_user_alg),
462 [CRYPTO_MSG_GETALG - CRYPTO_MSG_BASE] = MSGSIZE(crypto_user_alg), 463 [CRYPTO_MSG_GETALG - CRYPTO_MSG_BASE] = MSGSIZE(crypto_user_alg),
463 [CRYPTO_MSG_DELRNG - CRYPTO_MSG_BASE] = 0, 464 [CRYPTO_MSG_DELRNG - CRYPTO_MSG_BASE] = 0,
465 [CRYPTO_MSG_GETSTAT - CRYPTO_MSG_BASE] = MSGSIZE(crypto_user_alg),
464}; 466};
465 467
466static const struct nla_policy crypto_policy[CRYPTOCFGA_MAX+1] = { 468static const struct nla_policy crypto_policy[CRYPTOCFGA_MAX+1] = {
@@ -481,6 +483,9 @@ static const struct crypto_link {
481 .dump = crypto_dump_report, 483 .dump = crypto_dump_report,
482 .done = crypto_dump_report_done}, 484 .done = crypto_dump_report_done},
483 [CRYPTO_MSG_DELRNG - CRYPTO_MSG_BASE] = { .doit = crypto_del_rng }, 485 [CRYPTO_MSG_DELRNG - CRYPTO_MSG_BASE] = { .doit = crypto_del_rng },
486 [CRYPTO_MSG_GETSTAT - CRYPTO_MSG_BASE] = { .doit = crypto_reportstat,
487 .dump = crypto_dump_reportstat,
488 .done = crypto_dump_reportstat_done},
484}; 489};
485 490
486static int crypto_user_rcv_msg(struct sk_buff *skb, struct nlmsghdr *nlh, 491static int crypto_user_rcv_msg(struct sk_buff *skb, struct nlmsghdr *nlh,
diff --git a/crypto/crypto_user_stat.c b/crypto/crypto_user_stat.c
new file mode 100644
index 000000000000..021ad06bbb62
--- /dev/null
+++ b/crypto/crypto_user_stat.c
@@ -0,0 +1,463 @@
1// SPDX-License-Identifier: GPL-2.0
2/*
3 * Crypto user configuration API.
4 *
5 * Copyright (C) 2017-2018 Corentin Labbe <clabbe@baylibre.com>
6 *
7 */
8
9#include <linux/crypto.h>
10#include <linux/cryptouser.h>
11#include <linux/sched.h>
12#include <net/netlink.h>
13#include <crypto/internal/skcipher.h>
14#include <crypto/internal/rng.h>
15#include <crypto/akcipher.h>
16#include <crypto/kpp.h>
17#include <crypto/internal/cryptouser.h>
18
19#include "internal.h"
20
21#define null_terminated(x) (strnlen(x, sizeof(x)) < sizeof(x))
22
23static DEFINE_MUTEX(crypto_cfg_mutex);
24
25extern struct sock *crypto_nlsk;
26
27struct crypto_dump_info {
28 struct sk_buff *in_skb;
29 struct sk_buff *out_skb;
30 u32 nlmsg_seq;
31 u16 nlmsg_flags;
32};
33
34static int crypto_report_aead(struct sk_buff *skb, struct crypto_alg *alg)
35{
36 struct crypto_stat raead;
37 u64 v64;
38 u32 v32;
39
40 strncpy(raead.type, "aead", sizeof(raead.type));
41
42 v32 = atomic_read(&alg->encrypt_cnt);
43 raead.stat_encrypt_cnt = v32;
44 v64 = atomic64_read(&alg->encrypt_tlen);
45 raead.stat_encrypt_tlen = v64;
46 v32 = atomic_read(&alg->decrypt_cnt);
47 raead.stat_decrypt_cnt = v32;
48 v64 = atomic64_read(&alg->decrypt_tlen);
49 raead.stat_decrypt_tlen = v64;
50 v32 = atomic_read(&alg->aead_err_cnt);
51 raead.stat_aead_err_cnt = v32;
52
53 if (nla_put(skb, CRYPTOCFGA_STAT_AEAD,
54 sizeof(struct crypto_stat), &raead))
55 goto nla_put_failure;
56 return 0;
57
58nla_put_failure:
59 return -EMSGSIZE;
60}
61
62static int crypto_report_cipher(struct sk_buff *skb, struct crypto_alg *alg)
63{
64 struct crypto_stat rcipher;
65 u64 v64;
66 u32 v32;
67
68 strlcpy(rcipher.type, "cipher", sizeof(rcipher.type));
69
70 v32 = atomic_read(&alg->encrypt_cnt);
71 rcipher.stat_encrypt_cnt = v32;
72 v64 = atomic64_read(&alg->encrypt_tlen);
73 rcipher.stat_encrypt_tlen = v64;
74 v32 = atomic_read(&alg->decrypt_cnt);
75 rcipher.stat_decrypt_cnt = v32;
76 v64 = atomic64_read(&alg->decrypt_tlen);
77 rcipher.stat_decrypt_tlen = v64;
78 v32 = atomic_read(&alg->cipher_err_cnt);
79 rcipher.stat_cipher_err_cnt = v32;
80
81 if (nla_put(skb, CRYPTOCFGA_STAT_CIPHER,
82 sizeof(struct crypto_stat), &rcipher))
83 goto nla_put_failure;
84 return 0;
85
86nla_put_failure:
87 return -EMSGSIZE;
88}
89
90static int crypto_report_comp(struct sk_buff *skb, struct crypto_alg *alg)
91{
92 struct crypto_stat rcomp;
93 u64 v64;
94 u32 v32;
95
96 strlcpy(rcomp.type, "compression", sizeof(rcomp.type));
97 v32 = atomic_read(&alg->compress_cnt);
98 rcomp.stat_compress_cnt = v32;
99 v64 = atomic64_read(&alg->compress_tlen);
100 rcomp.stat_compress_tlen = v64;
101 v32 = atomic_read(&alg->decompress_cnt);
102 rcomp.stat_decompress_cnt = v32;
103 v64 = atomic64_read(&alg->decompress_tlen);
104 rcomp.stat_decompress_tlen = v64;
105 v32 = atomic_read(&alg->cipher_err_cnt);
106 rcomp.stat_compress_err_cnt = v32;
107
108 if (nla_put(skb, CRYPTOCFGA_STAT_COMPRESS,
109 sizeof(struct crypto_stat), &rcomp))
110 goto nla_put_failure;
111 return 0;
112
113nla_put_failure:
114 return -EMSGSIZE;
115}
116
117static int crypto_report_acomp(struct sk_buff *skb, struct crypto_alg *alg)
118{
119 struct crypto_stat racomp;
120 u64 v64;
121 u32 v32;
122
123 strlcpy(racomp.type, "acomp", sizeof(racomp.type));
124 v32 = atomic_read(&alg->compress_cnt);
125 racomp.stat_compress_cnt = v32;
126 v64 = atomic64_read(&alg->compress_tlen);
127 racomp.stat_compress_tlen = v64;
128 v32 = atomic_read(&alg->decompress_cnt);
129 racomp.stat_decompress_cnt = v32;
130 v64 = atomic64_read(&alg->decompress_tlen);
131 racomp.stat_decompress_tlen = v64;
132 v32 = atomic_read(&alg->cipher_err_cnt);
133 racomp.stat_compress_err_cnt = v32;
134
135 if (nla_put(skb, CRYPTOCFGA_STAT_ACOMP,
136 sizeof(struct crypto_stat), &racomp))
137 goto nla_put_failure;
138 return 0;
139
140nla_put_failure:
141 return -EMSGSIZE;
142}
143
144static int crypto_report_akcipher(struct sk_buff *skb, struct crypto_alg *alg)
145{
146 struct crypto_stat rakcipher;
147 u64 v64;
148 u32 v32;
149
150 strncpy(rakcipher.type, "akcipher", sizeof(rakcipher.type));
151 v32 = atomic_read(&alg->encrypt_cnt);
152 rakcipher.stat_encrypt_cnt = v32;
153 v64 = atomic64_read(&alg->encrypt_tlen);
154 rakcipher.stat_encrypt_tlen = v64;
155 v32 = atomic_read(&alg->decrypt_cnt);
156 rakcipher.stat_decrypt_cnt = v32;
157 v64 = atomic64_read(&alg->decrypt_tlen);
158 rakcipher.stat_decrypt_tlen = v64;
159 v32 = atomic_read(&alg->sign_cnt);
160 rakcipher.stat_sign_cnt = v32;
161 v32 = atomic_read(&alg->verify_cnt);
162 rakcipher.stat_verify_cnt = v32;
163 v32 = atomic_read(&alg->akcipher_err_cnt);
164 rakcipher.stat_akcipher_err_cnt = v32;
165
166 if (nla_put(skb, CRYPTOCFGA_STAT_AKCIPHER,
167 sizeof(struct crypto_stat), &rakcipher))
168 goto nla_put_failure;
169 return 0;
170
171nla_put_failure:
172 return -EMSGSIZE;
173}
174
175static int crypto_report_kpp(struct sk_buff *skb, struct crypto_alg *alg)
176{
177 struct crypto_stat rkpp;
178 u32 v;
179
180 strlcpy(rkpp.type, "kpp", sizeof(rkpp.type));
181
182 v = atomic_read(&alg->setsecret_cnt);
183 rkpp.stat_setsecret_cnt = v;
184 v = atomic_read(&alg->generate_public_key_cnt);
185 rkpp.stat_generate_public_key_cnt = v;
186 v = atomic_read(&alg->compute_shared_secret_cnt);
187 rkpp.stat_compute_shared_secret_cnt = v;
188 v = atomic_read(&alg->kpp_err_cnt);
189 rkpp.stat_kpp_err_cnt = v;
190
191 if (nla_put(skb, CRYPTOCFGA_STAT_KPP,
192 sizeof(struct crypto_stat), &rkpp))
193 goto nla_put_failure;
194 return 0;
195
196nla_put_failure:
197 return -EMSGSIZE;
198}
199
200static int crypto_report_ahash(struct sk_buff *skb, struct crypto_alg *alg)
201{
202 struct crypto_stat rhash;
203 u64 v64;
204 u32 v32;
205
206 strncpy(rhash.type, "ahash", sizeof(rhash.type));
207
208 v32 = atomic_read(&alg->hash_cnt);
209 rhash.stat_hash_cnt = v32;
210 v64 = atomic64_read(&alg->hash_tlen);
211 rhash.stat_hash_tlen = v64;
212 v32 = atomic_read(&alg->hash_err_cnt);
213 rhash.stat_hash_err_cnt = v32;
214
215 if (nla_put(skb, CRYPTOCFGA_STAT_HASH,
216 sizeof(struct crypto_stat), &rhash))
217 goto nla_put_failure;
218 return 0;
219
220nla_put_failure:
221 return -EMSGSIZE;
222}
223
224static int crypto_report_shash(struct sk_buff *skb, struct crypto_alg *alg)
225{
226 struct crypto_stat rhash;
227 u64 v64;
228 u32 v32;
229
230 strncpy(rhash.type, "shash", sizeof(rhash.type));
231
232 v32 = atomic_read(&alg->hash_cnt);
233 rhash.stat_hash_cnt = v32;
234 v64 = atomic64_read(&alg->hash_tlen);
235 rhash.stat_hash_tlen = v64;
236 v32 = atomic_read(&alg->hash_err_cnt);
237 rhash.stat_hash_err_cnt = v32;
238
239 if (nla_put(skb, CRYPTOCFGA_STAT_HASH,
240 sizeof(struct crypto_stat), &rhash))
241 goto nla_put_failure;
242 return 0;
243
244nla_put_failure:
245 return -EMSGSIZE;
246}
247
248static int crypto_report_rng(struct sk_buff *skb, struct crypto_alg *alg)
249{
250 struct crypto_stat rrng;
251 u64 v64;
252 u32 v32;
253
254 strncpy(rrng.type, "rng", sizeof(rrng.type));
255
256 v32 = atomic_read(&alg->generate_cnt);
257 rrng.stat_generate_cnt = v32;
258 v64 = atomic64_read(&alg->generate_tlen);
259 rrng.stat_generate_tlen = v64;
260 v32 = atomic_read(&alg->seed_cnt);
261 rrng.stat_seed_cnt = v32;
262 v32 = atomic_read(&alg->hash_err_cnt);
263 rrng.stat_rng_err_cnt = v32;
264
265 if (nla_put(skb, CRYPTOCFGA_STAT_RNG,
266 sizeof(struct crypto_stat), &rrng))
267 goto nla_put_failure;
268 return 0;
269
270nla_put_failure:
271 return -EMSGSIZE;
272}
273
274static int crypto_reportstat_one(struct crypto_alg *alg,
275 struct crypto_user_alg *ualg,
276 struct sk_buff *skb)
277{
278 strlcpy(ualg->cru_name, alg->cra_name, sizeof(ualg->cru_name));
279 strlcpy(ualg->cru_driver_name, alg->cra_driver_name,
280 sizeof(ualg->cru_driver_name));
281 strlcpy(ualg->cru_module_name, module_name(alg->cra_module),
282 sizeof(ualg->cru_module_name));
283
284 ualg->cru_type = 0;
285 ualg->cru_mask = 0;
286 ualg->cru_flags = alg->cra_flags;
287 ualg->cru_refcnt = refcount_read(&alg->cra_refcnt);
288
289 if (nla_put_u32(skb, CRYPTOCFGA_PRIORITY_VAL, alg->cra_priority))
290 goto nla_put_failure;
291 if (alg->cra_flags & CRYPTO_ALG_LARVAL) {
292 struct crypto_stat rl;
293
294 strlcpy(rl.type, "larval", sizeof(rl.type));
295 if (nla_put(skb, CRYPTOCFGA_STAT_LARVAL,
296 sizeof(struct crypto_stat), &rl))
297 goto nla_put_failure;
298 goto out;
299 }
300
301 switch (alg->cra_flags & (CRYPTO_ALG_TYPE_MASK | CRYPTO_ALG_LARVAL)) {
302 case CRYPTO_ALG_TYPE_AEAD:
303 if (crypto_report_aead(skb, alg))
304 goto nla_put_failure;
305 break;
306 case CRYPTO_ALG_TYPE_SKCIPHER:
307 if (crypto_report_cipher(skb, alg))
308 goto nla_put_failure;
309 break;
310 case CRYPTO_ALG_TYPE_BLKCIPHER:
311 if (crypto_report_cipher(skb, alg))
312 goto nla_put_failure;
313 break;
314 case CRYPTO_ALG_TYPE_CIPHER:
315 if (crypto_report_cipher(skb, alg))
316 goto nla_put_failure;
317 break;
318 case CRYPTO_ALG_TYPE_COMPRESS:
319 if (crypto_report_comp(skb, alg))
320 goto nla_put_failure;
321 break;
322 case CRYPTO_ALG_TYPE_ACOMPRESS:
323 if (crypto_report_acomp(skb, alg))
324 goto nla_put_failure;
325 break;
326 case CRYPTO_ALG_TYPE_SCOMPRESS:
327 if (crypto_report_acomp(skb, alg))
328 goto nla_put_failure;
329 break;
330 case CRYPTO_ALG_TYPE_AKCIPHER:
331 if (crypto_report_akcipher(skb, alg))
332 goto nla_put_failure;
333 break;
334 case CRYPTO_ALG_TYPE_KPP:
335 if (crypto_report_kpp(skb, alg))
336 goto nla_put_failure;
337 break;
338 case CRYPTO_ALG_TYPE_AHASH:
339 if (crypto_report_ahash(skb, alg))
340 goto nla_put_failure;
341 break;
342 case CRYPTO_ALG_TYPE_HASH:
343 if (crypto_report_shash(skb, alg))
344 goto nla_put_failure;
345 break;
346 case CRYPTO_ALG_TYPE_RNG:
347 if (crypto_report_rng(skb, alg))
348 goto nla_put_failure;
349 break;
350 default:
351 pr_err("ERROR: Unhandled alg %d in %s\n",
352 alg->cra_flags & (CRYPTO_ALG_TYPE_MASK | CRYPTO_ALG_LARVAL),
353 __func__);
354 }
355
356out:
357 return 0;
358
359nla_put_failure:
360 return -EMSGSIZE;
361}
362
363static int crypto_reportstat_alg(struct crypto_alg *alg,
364 struct crypto_dump_info *info)
365{
366 struct sk_buff *in_skb = info->in_skb;
367 struct sk_buff *skb = info->out_skb;
368 struct nlmsghdr *nlh;
369 struct crypto_user_alg *ualg;
370 int err = 0;
371
372 nlh = nlmsg_put(skb, NETLINK_CB(in_skb).portid, info->nlmsg_seq,
373 CRYPTO_MSG_GETSTAT, sizeof(*ualg), info->nlmsg_flags);
374 if (!nlh) {
375 err = -EMSGSIZE;
376 goto out;
377 }
378
379 ualg = nlmsg_data(nlh);
380
381 err = crypto_reportstat_one(alg, ualg, skb);
382 if (err) {
383 nlmsg_cancel(skb, nlh);
384 goto out;
385 }
386
387 nlmsg_end(skb, nlh);
388
389out:
390 return err;
391}
392
393int crypto_reportstat(struct sk_buff *in_skb, struct nlmsghdr *in_nlh,
394 struct nlattr **attrs)
395{
396 struct crypto_user_alg *p = nlmsg_data(in_nlh);
397 struct crypto_alg *alg;
398 struct sk_buff *skb;
399 struct crypto_dump_info info;
400 int err;
401
402 if (!null_terminated(p->cru_name) || !null_terminated(p->cru_driver_name))
403 return -EINVAL;
404
405 alg = crypto_alg_match(p, 0);
406 if (!alg)
407 return -ENOENT;
408
409 err = -ENOMEM;
410 skb = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_ATOMIC);
411 if (!skb)
412 goto drop_alg;
413
414 info.in_skb = in_skb;
415 info.out_skb = skb;
416 info.nlmsg_seq = in_nlh->nlmsg_seq;
417 info.nlmsg_flags = 0;
418
419 err = crypto_reportstat_alg(alg, &info);
420
421drop_alg:
422 crypto_mod_put(alg);
423
424 if (err)
425 return err;
426
427 return nlmsg_unicast(crypto_nlsk, skb, NETLINK_CB(in_skb).portid);
428}
429
430int crypto_dump_reportstat(struct sk_buff *skb, struct netlink_callback *cb)
431{
432 struct crypto_alg *alg;
433 struct crypto_dump_info info;
434 int err;
435
436 if (cb->args[0])
437 goto out;
438
439 cb->args[0] = 1;
440
441 info.in_skb = cb->skb;
442 info.out_skb = skb;
443 info.nlmsg_seq = cb->nlh->nlmsg_seq;
444 info.nlmsg_flags = NLM_F_MULTI;
445
446 list_for_each_entry(alg, &crypto_alg_list, cra_list) {
447 err = crypto_reportstat_alg(alg, &info);
448 if (err)
449 goto out_err;
450 }
451
452out:
453 return skb->len;
454out_err:
455 return err;
456}
457
458int crypto_dump_reportstat_done(struct netlink_callback *cb)
459{
460 return 0;
461}
462
463MODULE_LICENSE("GPL");
diff --git a/crypto/rng.c b/crypto/rng.c
index b4a618668161..547f16ecbfb0 100644
--- a/crypto/rng.c
+++ b/crypto/rng.c
@@ -50,6 +50,7 @@ int crypto_rng_reset(struct crypto_rng *tfm, const u8 *seed, unsigned int slen)
50 } 50 }
51 51
52 err = crypto_rng_alg(tfm)->seed(tfm, seed, slen); 52 err = crypto_rng_alg(tfm)->seed(tfm, seed, slen);
53 crypto_stat_rng_seed(tfm, err);
53out: 54out:
54 kzfree(buf); 55 kzfree(buf);
55 return err; 56 return err;
diff --git a/include/crypto/acompress.h b/include/crypto/acompress.h
index e328b52425a8..22e6f412c595 100644
--- a/include/crypto/acompress.h
+++ b/include/crypto/acompress.h
@@ -234,6 +234,34 @@ static inline void acomp_request_set_params(struct acomp_req *req,
234 req->flags |= CRYPTO_ACOMP_ALLOC_OUTPUT; 234 req->flags |= CRYPTO_ACOMP_ALLOC_OUTPUT;
235} 235}
236 236
237static inline void crypto_stat_compress(struct acomp_req *req, int ret)
238{
239#ifdef CONFIG_CRYPTO_STATS
240 struct crypto_acomp *tfm = crypto_acomp_reqtfm(req);
241
242 if (ret && ret != -EINPROGRESS && ret != -EBUSY) {
243 atomic_inc(&tfm->base.__crt_alg->compress_err_cnt);
244 } else {
245 atomic_inc(&tfm->base.__crt_alg->compress_cnt);
246 atomic64_add(req->slen, &tfm->base.__crt_alg->compress_tlen);
247 }
248#endif
249}
250
251static inline void crypto_stat_decompress(struct acomp_req *req, int ret)
252{
253#ifdef CONFIG_CRYPTO_STATS
254 struct crypto_acomp *tfm = crypto_acomp_reqtfm(req);
255
256 if (ret && ret != -EINPROGRESS && ret != -EBUSY) {
257 atomic_inc(&tfm->base.__crt_alg->compress_err_cnt);
258 } else {
259 atomic_inc(&tfm->base.__crt_alg->decompress_cnt);
260 atomic64_add(req->slen, &tfm->base.__crt_alg->decompress_tlen);
261 }
262#endif
263}
264
237/** 265/**
238 * crypto_acomp_compress() -- Invoke asynchronous compress operation 266 * crypto_acomp_compress() -- Invoke asynchronous compress operation
239 * 267 *
@@ -246,8 +274,11 @@ static inline void acomp_request_set_params(struct acomp_req *req,
246static inline int crypto_acomp_compress(struct acomp_req *req) 274static inline int crypto_acomp_compress(struct acomp_req *req)
247{ 275{
248 struct crypto_acomp *tfm = crypto_acomp_reqtfm(req); 276 struct crypto_acomp *tfm = crypto_acomp_reqtfm(req);
277 int ret;
249 278
250 return tfm->compress(req); 279 ret = tfm->compress(req);
280 crypto_stat_compress(req, ret);
281 return ret;
251} 282}
252 283
253/** 284/**
@@ -262,8 +293,11 @@ static inline int crypto_acomp_compress(struct acomp_req *req)
262static inline int crypto_acomp_decompress(struct acomp_req *req) 293static inline int crypto_acomp_decompress(struct acomp_req *req)
263{ 294{
264 struct crypto_acomp *tfm = crypto_acomp_reqtfm(req); 295 struct crypto_acomp *tfm = crypto_acomp_reqtfm(req);
296 int ret;
265 297
266 return tfm->decompress(req); 298 ret = tfm->decompress(req);
299 crypto_stat_decompress(req, ret);
300 return ret;
267} 301}
268 302
269#endif 303#endif
diff --git a/include/crypto/aead.h b/include/crypto/aead.h
index 1e26f790b03f..0d765d7bfb82 100644
--- a/include/crypto/aead.h
+++ b/include/crypto/aead.h
@@ -306,6 +306,34 @@ static inline struct crypto_aead *crypto_aead_reqtfm(struct aead_request *req)
306 return __crypto_aead_cast(req->base.tfm); 306 return __crypto_aead_cast(req->base.tfm);
307} 307}
308 308
309static inline void crypto_stat_aead_encrypt(struct aead_request *req, int ret)
310{
311#ifdef CONFIG_CRYPTO_STATS
312 struct crypto_aead *tfm = crypto_aead_reqtfm(req);
313
314 if (ret && ret != -EINPROGRESS && ret != -EBUSY) {
315 atomic_inc(&tfm->base.__crt_alg->aead_err_cnt);
316 } else {
317 atomic_inc(&tfm->base.__crt_alg->encrypt_cnt);
318 atomic64_add(req->cryptlen, &tfm->base.__crt_alg->encrypt_tlen);
319 }
320#endif
321}
322
323static inline void crypto_stat_aead_decrypt(struct aead_request *req, int ret)
324{
325#ifdef CONFIG_CRYPTO_STATS
326 struct crypto_aead *tfm = crypto_aead_reqtfm(req);
327
328 if (ret && ret != -EINPROGRESS && ret != -EBUSY) {
329 atomic_inc(&tfm->base.__crt_alg->aead_err_cnt);
330 } else {
331 atomic_inc(&tfm->base.__crt_alg->decrypt_cnt);
332 atomic64_add(req->cryptlen, &tfm->base.__crt_alg->decrypt_tlen);
333 }
334#endif
335}
336
309/** 337/**
310 * crypto_aead_encrypt() - encrypt plaintext 338 * crypto_aead_encrypt() - encrypt plaintext
311 * @req: reference to the aead_request handle that holds all information 339 * @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)
328static inline int crypto_aead_encrypt(struct aead_request *req) 356static inline int crypto_aead_encrypt(struct aead_request *req)
329{ 357{
330 struct crypto_aead *aead = crypto_aead_reqtfm(req); 358 struct crypto_aead *aead = crypto_aead_reqtfm(req);
359 int ret;
331 360
332 if (crypto_aead_get_flags(aead) & CRYPTO_TFM_NEED_KEY) 361 if (crypto_aead_get_flags(aead) & CRYPTO_TFM_NEED_KEY)
333 return -ENOKEY; 362 ret = -ENOKEY;
334 363 else
335 return crypto_aead_alg(aead)->encrypt(req); 364 ret = crypto_aead_alg(aead)->encrypt(req);
365 crypto_stat_aead_encrypt(req, ret);
366 return ret;
336} 367}
337 368
338/** 369/**
@@ -360,14 +391,16 @@ static inline int crypto_aead_encrypt(struct aead_request *req)
360static inline int crypto_aead_decrypt(struct aead_request *req) 391static inline int crypto_aead_decrypt(struct aead_request *req)
361{ 392{
362 struct crypto_aead *aead = crypto_aead_reqtfm(req); 393 struct crypto_aead *aead = crypto_aead_reqtfm(req);
394 int ret;
363 395
364 if (crypto_aead_get_flags(aead) & CRYPTO_TFM_NEED_KEY) 396 if (crypto_aead_get_flags(aead) & CRYPTO_TFM_NEED_KEY)
365 return -ENOKEY; 397 ret = -ENOKEY;
366 398 else if (req->cryptlen < crypto_aead_authsize(aead))
367 if (req->cryptlen < crypto_aead_authsize(aead)) 399 ret = -EINVAL;
368 return -EINVAL; 400 else
369 401 ret = crypto_aead_alg(aead)->decrypt(req);
370 return crypto_aead_alg(aead)->decrypt(req); 402 crypto_stat_aead_decrypt(req, ret);
403 return ret;
371} 404}
372 405
373/** 406/**
diff --git a/include/crypto/akcipher.h b/include/crypto/akcipher.h
index b5e11de4d497..afac71119396 100644
--- a/include/crypto/akcipher.h
+++ b/include/crypto/akcipher.h
@@ -271,6 +271,62 @@ static inline unsigned int crypto_akcipher_maxsize(struct crypto_akcipher *tfm)
271 return alg->max_size(tfm); 271 return alg->max_size(tfm);
272} 272}
273 273
274static inline void crypto_stat_akcipher_encrypt(struct akcipher_request *req,
275 int ret)
276{
277#ifdef CONFIG_CRYPTO_STATS
278 struct crypto_akcipher *tfm = crypto_akcipher_reqtfm(req);
279
280 if (ret && ret != -EINPROGRESS && ret != -EBUSY) {
281 atomic_inc(&tfm->base.__crt_alg->akcipher_err_cnt);
282 } else {
283 atomic_inc(&tfm->base.__crt_alg->encrypt_cnt);
284 atomic64_add(req->src_len, &tfm->base.__crt_alg->encrypt_tlen);
285 }
286#endif
287}
288
289static inline void crypto_stat_akcipher_decrypt(struct akcipher_request *req,
290 int ret)
291{
292#ifdef CONFIG_CRYPTO_STATS
293 struct crypto_akcipher *tfm = crypto_akcipher_reqtfm(req);
294
295 if (ret && ret != -EINPROGRESS && ret != -EBUSY) {
296 atomic_inc(&tfm->base.__crt_alg->akcipher_err_cnt);
297 } else {
298 atomic_inc(&tfm->base.__crt_alg->decrypt_cnt);
299 atomic64_add(req->src_len, &tfm->base.__crt_alg->decrypt_tlen);
300 }
301#endif
302}
303
304static inline void crypto_stat_akcipher_sign(struct akcipher_request *req,
305 int ret)
306{
307#ifdef CONFIG_CRYPTO_STATS
308 struct crypto_akcipher *tfm = crypto_akcipher_reqtfm(req);
309
310 if (ret && ret != -EINPROGRESS && ret != -EBUSY)
311 atomic_inc(&tfm->base.__crt_alg->akcipher_err_cnt);
312 else
313 atomic_inc(&tfm->base.__crt_alg->sign_cnt);
314#endif
315}
316
317static inline void crypto_stat_akcipher_verify(struct akcipher_request *req,
318 int ret)
319{
320#ifdef CONFIG_CRYPTO_STATS
321 struct crypto_akcipher *tfm = crypto_akcipher_reqtfm(req);
322
323 if (ret && ret != -EINPROGRESS && ret != -EBUSY)
324 atomic_inc(&tfm->base.__crt_alg->akcipher_err_cnt);
325 else
326 atomic_inc(&tfm->base.__crt_alg->verify_cnt);
327#endif
328}
329
274/** 330/**
275 * crypto_akcipher_encrypt() - Invoke public key encrypt operation 331 * crypto_akcipher_encrypt() - Invoke public key encrypt operation
276 * 332 *
@@ -285,8 +341,11 @@ static inline int crypto_akcipher_encrypt(struct akcipher_request *req)
285{ 341{
286 struct crypto_akcipher *tfm = crypto_akcipher_reqtfm(req); 342 struct crypto_akcipher *tfm = crypto_akcipher_reqtfm(req);
287 struct akcipher_alg *alg = crypto_akcipher_alg(tfm); 343 struct akcipher_alg *alg = crypto_akcipher_alg(tfm);
344 int ret;
288 345
289 return alg->encrypt(req); 346 ret = alg->encrypt(req);
347 crypto_stat_akcipher_encrypt(req, ret);
348 return ret;
290} 349}
291 350
292/** 351/**
@@ -303,8 +362,11 @@ static inline int crypto_akcipher_decrypt(struct akcipher_request *req)
303{ 362{
304 struct crypto_akcipher *tfm = crypto_akcipher_reqtfm(req); 363 struct crypto_akcipher *tfm = crypto_akcipher_reqtfm(req);
305 struct akcipher_alg *alg = crypto_akcipher_alg(tfm); 364 struct akcipher_alg *alg = crypto_akcipher_alg(tfm);
365 int ret;
306 366
307 return alg->decrypt(req); 367 ret = alg->decrypt(req);
368 crypto_stat_akcipher_decrypt(req, ret);
369 return ret;
308} 370}
309 371
310/** 372/**
@@ -321,8 +383,11 @@ static inline int crypto_akcipher_sign(struct akcipher_request *req)
321{ 383{
322 struct crypto_akcipher *tfm = crypto_akcipher_reqtfm(req); 384 struct crypto_akcipher *tfm = crypto_akcipher_reqtfm(req);
323 struct akcipher_alg *alg = crypto_akcipher_alg(tfm); 385 struct akcipher_alg *alg = crypto_akcipher_alg(tfm);
386 int ret;
324 387
325 return alg->sign(req); 388 ret = alg->sign(req);
389 crypto_stat_akcipher_sign(req, ret);
390 return ret;
326} 391}
327 392
328/** 393/**
@@ -339,8 +404,11 @@ static inline int crypto_akcipher_verify(struct akcipher_request *req)
339{ 404{
340 struct crypto_akcipher *tfm = crypto_akcipher_reqtfm(req); 405 struct crypto_akcipher *tfm = crypto_akcipher_reqtfm(req);
341 struct akcipher_alg *alg = crypto_akcipher_alg(tfm); 406 struct akcipher_alg *alg = crypto_akcipher_alg(tfm);
407 int ret;
342 408
343 return alg->verify(req); 409 ret = alg->verify(req);
410 crypto_stat_akcipher_verify(req, ret);
411 return ret;
344} 412}
345 413
346/** 414/**
diff --git a/include/crypto/hash.h b/include/crypto/hash.h
index 21587011ab0f..bc7796600338 100644
--- a/include/crypto/hash.h
+++ b/include/crypto/hash.h
@@ -412,6 +412,32 @@ static inline void *ahash_request_ctx(struct ahash_request *req)
412int crypto_ahash_setkey(struct crypto_ahash *tfm, const u8 *key, 412int crypto_ahash_setkey(struct crypto_ahash *tfm, const u8 *key,
413 unsigned int keylen); 413 unsigned int keylen);
414 414
415static inline void crypto_stat_ahash_update(struct ahash_request *req, int ret)
416{
417#ifdef CONFIG_CRYPTO_STATS
418 struct crypto_ahash *tfm = crypto_ahash_reqtfm(req);
419
420 if (ret && ret != -EINPROGRESS && ret != -EBUSY)
421 atomic_inc(&tfm->base.__crt_alg->hash_err_cnt);
422 else
423 atomic64_add(req->nbytes, &tfm->base.__crt_alg->hash_tlen);
424#endif
425}
426
427static inline void crypto_stat_ahash_final(struct ahash_request *req, int ret)
428{
429#ifdef CONFIG_CRYPTO_STATS
430 struct crypto_ahash *tfm = crypto_ahash_reqtfm(req);
431
432 if (ret && ret != -EINPROGRESS && ret != -EBUSY) {
433 atomic_inc(&tfm->base.__crt_alg->hash_err_cnt);
434 } else {
435 atomic_inc(&tfm->base.__crt_alg->hash_cnt);
436 atomic64_add(req->nbytes, &tfm->base.__crt_alg->hash_tlen);
437 }
438#endif
439}
440
415/** 441/**
416 * crypto_ahash_finup() - update and finalize message digest 442 * crypto_ahash_finup() - update and finalize message digest
417 * @req: reference to the ahash_request handle that holds all information 443 * @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 */ 552 */
527static inline int crypto_ahash_update(struct ahash_request *req) 553static inline int crypto_ahash_update(struct ahash_request *req)
528{ 554{
529 return crypto_ahash_reqtfm(req)->update(req); 555 int ret;
556
557 ret = crypto_ahash_reqtfm(req)->update(req);
558 crypto_stat_ahash_update(req, ret);
559 return ret;
530} 560}
531 561
532/** 562/**
diff --git a/include/crypto/internal/cryptouser.h b/include/crypto/internal/cryptouser.h
new file mode 100644
index 000000000000..8db299c25566
--- /dev/null
+++ b/include/crypto/internal/cryptouser.h
@@ -0,0 +1,8 @@
1/* SPDX-License-Identifier: GPL-2.0 */
2#include <net/netlink.h>
3
4struct crypto_alg *crypto_alg_match(struct crypto_user_alg *p, int exact);
5
6int crypto_dump_reportstat(struct sk_buff *skb, struct netlink_callback *cb);
7int crypto_reportstat(struct sk_buff *in_skb, struct nlmsghdr *in_nlh, struct nlattr **attrs);
8int crypto_dump_reportstat_done(struct netlink_callback *cb);
diff --git a/include/crypto/kpp.h b/include/crypto/kpp.h
index 1bde0a6514fa..f517ba6d3a27 100644
--- a/include/crypto/kpp.h
+++ b/include/crypto/kpp.h
@@ -268,6 +268,42 @@ struct kpp_secret {
268 unsigned short len; 268 unsigned short len;
269}; 269};
270 270
271static inline void crypto_stat_kpp_set_secret(struct crypto_kpp *tfm, int ret)
272{
273#ifdef CONFIG_CRYPTO_STATS
274 if (ret)
275 atomic_inc(&tfm->base.__crt_alg->kpp_err_cnt);
276 else
277 atomic_inc(&tfm->base.__crt_alg->setsecret_cnt);
278#endif
279}
280
281static inline void crypto_stat_kpp_generate_public_key(struct kpp_request *req,
282 int ret)
283{
284#ifdef CONFIG_CRYPTO_STATS
285 struct crypto_kpp *tfm = crypto_kpp_reqtfm(req);
286
287 if (ret)
288 atomic_inc(&tfm->base.__crt_alg->kpp_err_cnt);
289 else
290 atomic_inc(&tfm->base.__crt_alg->generate_public_key_cnt);
291#endif
292}
293
294static inline void crypto_stat_kpp_compute_shared_secret(struct kpp_request *req,
295 int ret)
296{
297#ifdef CONFIG_CRYPTO_STATS
298 struct crypto_kpp *tfm = crypto_kpp_reqtfm(req);
299
300 if (ret)
301 atomic_inc(&tfm->base.__crt_alg->kpp_err_cnt);
302 else
303 atomic_inc(&tfm->base.__crt_alg->compute_shared_secret_cnt);
304#endif
305}
306
271/** 307/**
272 * crypto_kpp_set_secret() - Invoke kpp operation 308 * crypto_kpp_set_secret() - Invoke kpp operation
273 * 309 *
@@ -287,8 +323,11 @@ static inline int crypto_kpp_set_secret(struct crypto_kpp *tfm,
287 const void *buffer, unsigned int len) 323 const void *buffer, unsigned int len)
288{ 324{
289 struct kpp_alg *alg = crypto_kpp_alg(tfm); 325 struct kpp_alg *alg = crypto_kpp_alg(tfm);
326 int ret;
290 327
291 return alg->set_secret(tfm, buffer, len); 328 ret = alg->set_secret(tfm, buffer, len);
329 crypto_stat_kpp_set_secret(tfm, ret);
330 return ret;
292} 331}
293 332
294/** 333/**
@@ -308,8 +347,11 @@ static inline int crypto_kpp_generate_public_key(struct kpp_request *req)
308{ 347{
309 struct crypto_kpp *tfm = crypto_kpp_reqtfm(req); 348 struct crypto_kpp *tfm = crypto_kpp_reqtfm(req);
310 struct kpp_alg *alg = crypto_kpp_alg(tfm); 349 struct kpp_alg *alg = crypto_kpp_alg(tfm);
350 int ret;
311 351
312 return alg->generate_public_key(req); 352 ret = alg->generate_public_key(req);
353 crypto_stat_kpp_generate_public_key(req, ret);
354 return ret;
313} 355}
314 356
315/** 357/**
@@ -326,8 +368,11 @@ static inline int crypto_kpp_compute_shared_secret(struct kpp_request *req)
326{ 368{
327 struct crypto_kpp *tfm = crypto_kpp_reqtfm(req); 369 struct crypto_kpp *tfm = crypto_kpp_reqtfm(req);
328 struct kpp_alg *alg = crypto_kpp_alg(tfm); 370 struct kpp_alg *alg = crypto_kpp_alg(tfm);
371 int ret;
329 372
330 return alg->compute_shared_secret(req); 373 ret = alg->compute_shared_secret(req);
374 crypto_stat_kpp_compute_shared_secret(req, ret);
375 return ret;
331} 376}
332 377
333/** 378/**
diff --git a/include/crypto/rng.h b/include/crypto/rng.h
index b95ede354a66..6d258f5b68f1 100644
--- a/include/crypto/rng.h
+++ b/include/crypto/rng.h
@@ -122,6 +122,29 @@ static inline void crypto_free_rng(struct crypto_rng *tfm)
122 crypto_destroy_tfm(tfm, crypto_rng_tfm(tfm)); 122 crypto_destroy_tfm(tfm, crypto_rng_tfm(tfm));
123} 123}
124 124
125static inline void crypto_stat_rng_seed(struct crypto_rng *tfm, int ret)
126{
127#ifdef CONFIG_CRYPTO_STATS
128 if (ret && ret != -EINPROGRESS && ret != -EBUSY)
129 atomic_inc(&tfm->base.__crt_alg->rng_err_cnt);
130 else
131 atomic_inc(&tfm->base.__crt_alg->seed_cnt);
132#endif
133}
134
135static inline void crypto_stat_rng_generate(struct crypto_rng *tfm,
136 unsigned int dlen, int ret)
137{
138#ifdef CONFIG_CRYPTO_STATS
139 if (ret && ret != -EINPROGRESS && ret != -EBUSY) {
140 atomic_inc(&tfm->base.__crt_alg->rng_err_cnt);
141 } else {
142 atomic_inc(&tfm->base.__crt_alg->generate_cnt);
143 atomic64_add(dlen, &tfm->base.__crt_alg->generate_tlen);
144 }
145#endif
146}
147
125/** 148/**
126 * crypto_rng_generate() - get random number 149 * crypto_rng_generate() - get random number
127 * @tfm: cipher handle 150 * @tfm: cipher handle
@@ -140,7 +163,11 @@ static inline int crypto_rng_generate(struct crypto_rng *tfm,
140 const u8 *src, unsigned int slen, 163 const u8 *src, unsigned int slen,
141 u8 *dst, unsigned int dlen) 164 u8 *dst, unsigned int dlen)
142{ 165{
143 return crypto_rng_alg(tfm)->generate(tfm, src, slen, dst, dlen); 166 int ret;
167
168 ret = crypto_rng_alg(tfm)->generate(tfm, src, slen, dst, dlen);
169 crypto_stat_rng_generate(tfm, dlen, ret);
170 return ret;
144} 171}
145 172
146/** 173/**
diff --git a/include/crypto/skcipher.h b/include/crypto/skcipher.h
index 45ae894fda32..925f547cdcfa 100644
--- a/include/crypto/skcipher.h
+++ b/include/crypto/skcipher.h
@@ -486,6 +486,32 @@ static inline struct crypto_sync_skcipher *crypto_sync_skcipher_reqtfm(
486 return container_of(tfm, struct crypto_sync_skcipher, base); 486 return container_of(tfm, struct crypto_sync_skcipher, base);
487} 487}
488 488
489static inline void crypto_stat_skcipher_encrypt(struct skcipher_request *req,
490 int ret, struct crypto_alg *alg)
491{
492#ifdef CONFIG_CRYPTO_STATS
493 if (ret && ret != -EINPROGRESS && ret != -EBUSY) {
494 atomic_inc(&alg->cipher_err_cnt);
495 } else {
496 atomic_inc(&alg->encrypt_cnt);
497 atomic64_add(req->cryptlen, &alg->encrypt_tlen);
498 }
499#endif
500}
501
502static inline void crypto_stat_skcipher_decrypt(struct skcipher_request *req,
503 int ret, struct crypto_alg *alg)
504{
505#ifdef CONFIG_CRYPTO_STATS
506 if (ret && ret != -EINPROGRESS && ret != -EBUSY) {
507 atomic_inc(&alg->cipher_err_cnt);
508 } else {
509 atomic_inc(&alg->decrypt_cnt);
510 atomic64_add(req->cryptlen, &alg->decrypt_tlen);
511 }
512#endif
513}
514
489/** 515/**
490 * crypto_skcipher_encrypt() - encrypt plaintext 516 * crypto_skcipher_encrypt() - encrypt plaintext
491 * @req: reference to the skcipher_request handle that holds all information 517 * @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(
500static inline int crypto_skcipher_encrypt(struct skcipher_request *req) 526static inline int crypto_skcipher_encrypt(struct skcipher_request *req)
501{ 527{
502 struct crypto_skcipher *tfm = crypto_skcipher_reqtfm(req); 528 struct crypto_skcipher *tfm = crypto_skcipher_reqtfm(req);
529 int ret;
503 530
504 if (crypto_skcipher_get_flags(tfm) & CRYPTO_TFM_NEED_KEY) 531 if (crypto_skcipher_get_flags(tfm) & CRYPTO_TFM_NEED_KEY)
505 return -ENOKEY; 532 ret = -ENOKEY;
506 533 else
507 return tfm->encrypt(req); 534 ret = tfm->encrypt(req);
535 crypto_stat_skcipher_encrypt(req, ret, tfm->base.__crt_alg);
536 return ret;
508} 537}
509 538
510/** 539/**
@@ -521,11 +550,14 @@ static inline int crypto_skcipher_encrypt(struct skcipher_request *req)
521static inline int crypto_skcipher_decrypt(struct skcipher_request *req) 550static inline int crypto_skcipher_decrypt(struct skcipher_request *req)
522{ 551{
523 struct crypto_skcipher *tfm = crypto_skcipher_reqtfm(req); 552 struct crypto_skcipher *tfm = crypto_skcipher_reqtfm(req);
553 int ret;
524 554
525 if (crypto_skcipher_get_flags(tfm) & CRYPTO_TFM_NEED_KEY) 555 if (crypto_skcipher_get_flags(tfm) & CRYPTO_TFM_NEED_KEY)
526 return -ENOKEY; 556 ret = -ENOKEY;
527 557 else
528 return tfm->decrypt(req); 558 ret = tfm->decrypt(req);
559 crypto_stat_skcipher_decrypt(req, ret, tfm->base.__crt_alg);
560 return ret;
529} 561}
530 562
531/** 563/**
diff --git a/include/linux/crypto.h b/include/linux/crypto.h
index e8839d3a7559..3634ad6fe202 100644
--- a/include/linux/crypto.h
+++ b/include/linux/crypto.h
@@ -454,6 +454,33 @@ struct compress_alg {
454 * @cra_refcnt: internally used 454 * @cra_refcnt: internally used
455 * @cra_destroy: internally used 455 * @cra_destroy: internally used
456 * 456 *
457 * All following statistics are for this crypto_alg
458 * @encrypt_cnt: number of encrypt requests
459 * @decrypt_cnt: number of decrypt requests
460 * @compress_cnt: number of compress requests
461 * @decompress_cnt: number of decompress requests
462 * @generate_cnt: number of RNG generate requests
463 * @seed_cnt: number of times the rng was seeded
464 * @hash_cnt: number of hash requests
465 * @sign_cnt: number of sign requests
466 * @setsecret_cnt: number of setsecrey operation
467 * @generate_public_key_cnt: number of generate_public_key operation
468 * @verify_cnt: number of verify operation
469 * @compute_shared_secret_cnt: number of compute_shared_secret operation
470 * @encrypt_tlen: total data size handled by encrypt requests
471 * @decrypt_tlen: total data size handled by decrypt requests
472 * @compress_tlen: total data size handled by compress requests
473 * @decompress_tlen: total data size handled by decompress requests
474 * @generate_tlen: total data size of generated data by the RNG
475 * @hash_tlen: total data size hashed
476 * @akcipher_err_cnt: number of error for akcipher requests
477 * @cipher_err_cnt: number of error for akcipher requests
478 * @compress_err_cnt: number of error for akcipher requests
479 * @aead_err_cnt: number of error for akcipher requests
480 * @hash_err_cnt: number of error for akcipher requests
481 * @rng_err_cnt: number of error for akcipher requests
482 * @kpp_err_cnt: number of error for akcipher requests
483 *
457 * The struct crypto_alg describes a generic Crypto API algorithm and is common 484 * The struct crypto_alg describes a generic Crypto API algorithm and is common
458 * for all of the transformations. Any variable not documented here shall not 485 * for all of the transformations. Any variable not documented here shall not
459 * be used by a cipher implementation as it is internal to the Crypto API. 486 * be used by a cipher implementation as it is internal to the Crypto API.
@@ -487,6 +514,45 @@ struct crypto_alg {
487 void (*cra_destroy)(struct crypto_alg *alg); 514 void (*cra_destroy)(struct crypto_alg *alg);
488 515
489 struct module *cra_module; 516 struct module *cra_module;
517
518 union {
519 atomic_t encrypt_cnt;
520 atomic_t compress_cnt;
521 atomic_t generate_cnt;
522 atomic_t hash_cnt;
523 atomic_t setsecret_cnt;
524 };
525 union {
526 atomic64_t encrypt_tlen;
527 atomic64_t compress_tlen;
528 atomic64_t generate_tlen;
529 atomic64_t hash_tlen;
530 };
531 union {
532 atomic_t akcipher_err_cnt;
533 atomic_t cipher_err_cnt;
534 atomic_t compress_err_cnt;
535 atomic_t aead_err_cnt;
536 atomic_t hash_err_cnt;
537 atomic_t rng_err_cnt;
538 atomic_t kpp_err_cnt;
539 };
540 union {
541 atomic_t decrypt_cnt;
542 atomic_t decompress_cnt;
543 atomic_t seed_cnt;
544 atomic_t generate_public_key_cnt;
545 };
546 union {
547 atomic64_t decrypt_tlen;
548 atomic64_t decompress_tlen;
549 };
550 union {
551 atomic_t verify_cnt;
552 atomic_t compute_shared_secret_cnt;
553 };
554 atomic_t sign_cnt;
555
490} CRYPTO_MINALIGN_ATTR; 556} CRYPTO_MINALIGN_ATTR;
491 557
492/* 558/*
@@ -907,6 +973,38 @@ static inline struct crypto_ablkcipher *crypto_ablkcipher_reqtfm(
907 return __crypto_ablkcipher_cast(req->base.tfm); 973 return __crypto_ablkcipher_cast(req->base.tfm);
908} 974}
909 975
976static inline void crypto_stat_ablkcipher_encrypt(struct ablkcipher_request *req,
977 int ret)
978{
979#ifdef CONFIG_CRYPTO_STATS
980 struct ablkcipher_tfm *crt =
981 crypto_ablkcipher_crt(crypto_ablkcipher_reqtfm(req));
982
983 if (ret && ret != -EINPROGRESS && ret != -EBUSY) {
984 atomic_inc(&crt->base->base.__crt_alg->cipher_err_cnt);
985 } else {
986 atomic_inc(&crt->base->base.__crt_alg->encrypt_cnt);
987 atomic64_add(req->nbytes, &crt->base->base.__crt_alg->encrypt_tlen);
988 }
989#endif
990}
991
992static inline void crypto_stat_ablkcipher_decrypt(struct ablkcipher_request *req,
993 int ret)
994{
995#ifdef CONFIG_CRYPTO_STATS
996 struct ablkcipher_tfm *crt =
997 crypto_ablkcipher_crt(crypto_ablkcipher_reqtfm(req));
998
999 if (ret && ret != -EINPROGRESS && ret != -EBUSY) {
1000 atomic_inc(&crt->base->base.__crt_alg->cipher_err_cnt);
1001 } else {
1002 atomic_inc(&crt->base->base.__crt_alg->decrypt_cnt);
1003 atomic64_add(req->nbytes, &crt->base->base.__crt_alg->decrypt_tlen);
1004 }
1005#endif
1006}
1007
910/** 1008/**
911 * crypto_ablkcipher_encrypt() - encrypt plaintext 1009 * crypto_ablkcipher_encrypt() - encrypt plaintext
912 * @req: reference to the ablkcipher_request handle that holds all information 1010 * @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{ 1020{
923 struct ablkcipher_tfm *crt = 1021 struct ablkcipher_tfm *crt =
924 crypto_ablkcipher_crt(crypto_ablkcipher_reqtfm(req)); 1022 crypto_ablkcipher_crt(crypto_ablkcipher_reqtfm(req));
925 return crt->encrypt(req); 1023 int ret;
1024
1025 ret = crt->encrypt(req);
1026 crypto_stat_ablkcipher_encrypt(req, ret);
1027 return ret;
926} 1028}
927 1029
928/** 1030/**
@@ -940,7 +1042,11 @@ static inline int crypto_ablkcipher_decrypt(struct ablkcipher_request *req)
940{ 1042{
941 struct ablkcipher_tfm *crt = 1043 struct ablkcipher_tfm *crt =
942 crypto_ablkcipher_crt(crypto_ablkcipher_reqtfm(req)); 1044 crypto_ablkcipher_crt(crypto_ablkcipher_reqtfm(req));
943 return crt->decrypt(req); 1045 int ret;
1046
1047 ret = crt->decrypt(req);
1048 crypto_stat_ablkcipher_decrypt(req, ret);
1049 return ret;
944} 1050}
945 1051
946/** 1052/**
diff --git a/include/uapi/linux/cryptouser.h b/include/uapi/linux/cryptouser.h
index 19bf0ca6d635..6dafbc3e4414 100644
--- a/include/uapi/linux/cryptouser.h
+++ b/include/uapi/linux/cryptouser.h
@@ -29,6 +29,7 @@ enum {
29 CRYPTO_MSG_UPDATEALG, 29 CRYPTO_MSG_UPDATEALG,
30 CRYPTO_MSG_GETALG, 30 CRYPTO_MSG_GETALG,
31 CRYPTO_MSG_DELRNG, 31 CRYPTO_MSG_DELRNG,
32 CRYPTO_MSG_GETSTAT,
32 __CRYPTO_MSG_MAX 33 __CRYPTO_MSG_MAX
33}; 34};
34#define CRYPTO_MSG_MAX (__CRYPTO_MSG_MAX - 1) 35#define CRYPTO_MSG_MAX (__CRYPTO_MSG_MAX - 1)
@@ -50,6 +51,16 @@ enum crypto_attr_type_t {
50 CRYPTOCFGA_REPORT_AKCIPHER, /* struct crypto_report_akcipher */ 51 CRYPTOCFGA_REPORT_AKCIPHER, /* struct crypto_report_akcipher */
51 CRYPTOCFGA_REPORT_KPP, /* struct crypto_report_kpp */ 52 CRYPTOCFGA_REPORT_KPP, /* struct crypto_report_kpp */
52 CRYPTOCFGA_REPORT_ACOMP, /* struct crypto_report_acomp */ 53 CRYPTOCFGA_REPORT_ACOMP, /* struct crypto_report_acomp */
54 CRYPTOCFGA_STAT_LARVAL, /* struct crypto_stat */
55 CRYPTOCFGA_STAT_HASH, /* struct crypto_stat */
56 CRYPTOCFGA_STAT_BLKCIPHER, /* struct crypto_stat */
57 CRYPTOCFGA_STAT_AEAD, /* struct crypto_stat */
58 CRYPTOCFGA_STAT_COMPRESS, /* struct crypto_stat */
59 CRYPTOCFGA_STAT_RNG, /* struct crypto_stat */
60 CRYPTOCFGA_STAT_CIPHER, /* struct crypto_stat */
61 CRYPTOCFGA_STAT_AKCIPHER, /* struct crypto_stat */
62 CRYPTOCFGA_STAT_KPP, /* struct crypto_stat */
63 CRYPTOCFGA_STAT_ACOMP, /* struct crypto_stat */
53 __CRYPTOCFGA_MAX 64 __CRYPTOCFGA_MAX
54 65
55#define CRYPTOCFGA_MAX (__CRYPTOCFGA_MAX - 1) 66#define CRYPTOCFGA_MAX (__CRYPTOCFGA_MAX - 1)
@@ -65,6 +76,47 @@ struct crypto_user_alg {
65 __u32 cru_flags; 76 __u32 cru_flags;
66}; 77};
67 78
79struct crypto_stat {
80 char type[CRYPTO_MAX_NAME];
81 union {
82 __u32 stat_encrypt_cnt;
83 __u32 stat_compress_cnt;
84 __u32 stat_generate_cnt;
85 __u32 stat_hash_cnt;
86 __u32 stat_setsecret_cnt;
87 };
88 union {
89 __u64 stat_encrypt_tlen;
90 __u64 stat_compress_tlen;
91 __u64 stat_generate_tlen;
92 __u64 stat_hash_tlen;
93 };
94 union {
95 __u32 stat_akcipher_err_cnt;
96 __u32 stat_cipher_err_cnt;
97 __u32 stat_compress_err_cnt;
98 __u32 stat_aead_err_cnt;
99 __u32 stat_hash_err_cnt;
100 __u32 stat_rng_err_cnt;
101 __u32 stat_kpp_err_cnt;
102 };
103 union {
104 __u32 stat_decrypt_cnt;
105 __u32 stat_decompress_cnt;
106 __u32 stat_seed_cnt;
107 __u32 stat_generate_public_key_cnt;
108 };
109 union {
110 __u64 stat_decrypt_tlen;
111 __u64 stat_decompress_tlen;
112 };
113 union {
114 __u32 stat_verify_cnt;
115 __u32 stat_compute_shared_secret_cnt;
116 };
117 __u32 stat_sign_cnt;
118};
119
68struct crypto_report_larval { 120struct crypto_report_larval {
69 char type[CRYPTO_MAX_NAME]; 121 char type[CRYPTO_MAX_NAME];
70}; 122};