Skip to content

Commit 9807e49

Browse files
committed
crypto: rng - Count error stats differently
Move all stat code specific to rng into the rng code. While we're at it, change the stats so that bytes and counts are always incremented even in case of error. This allows the reference counting to be removed as we can now increment the counters prior to the operation. After the operation we simply increase the error count if necessary. This is safe as errors can only occur synchronously (or rather, the existing code already ignored asynchronous errors which are only visible to the callback function). Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>
1 parent 1085680 commit 9807e49

5 files changed

Lines changed: 105 additions & 126 deletions

File tree

crypto/algapi.c

Lines changed: 0 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -339,8 +339,6 @@ __crypto_register_alg(struct crypto_alg *alg, struct list_head *algs_to_put)
339339

340340
list_add(&alg->cra_list, &crypto_alg_list);
341341

342-
crypto_stats_init(alg);
343-
344342
if (larval) {
345343
/* No cheating! */
346344
alg->cra_flags &= ~CRYPTO_ALG_TESTED;
@@ -1038,43 +1036,6 @@ int crypto_type_has_alg(const char *name, const struct crypto_type *frontend,
10381036
}
10391037
EXPORT_SYMBOL_GPL(crypto_type_has_alg);
10401038

1041-
#ifdef CONFIG_CRYPTO_STATS
1042-
void crypto_stats_init(struct crypto_alg *alg)
1043-
{
1044-
memset(&alg->stats, 0, sizeof(alg->stats));
1045-
}
1046-
EXPORT_SYMBOL_GPL(crypto_stats_init);
1047-
1048-
void crypto_stats_get(struct crypto_alg *alg)
1049-
{
1050-
crypto_alg_get(alg);
1051-
}
1052-
EXPORT_SYMBOL_GPL(crypto_stats_get);
1053-
1054-
void crypto_stats_rng_seed(struct crypto_alg *alg, int ret)
1055-
{
1056-
if (ret && ret != -EINPROGRESS && ret != -EBUSY)
1057-
atomic64_inc(&alg->stats.rng.err_cnt);
1058-
else
1059-
atomic64_inc(&alg->stats.rng.seed_cnt);
1060-
crypto_alg_put(alg);
1061-
}
1062-
EXPORT_SYMBOL_GPL(crypto_stats_rng_seed);
1063-
1064-
void crypto_stats_rng_generate(struct crypto_alg *alg, unsigned int dlen,
1065-
int ret)
1066-
{
1067-
if (ret && ret != -EINPROGRESS && ret != -EBUSY) {
1068-
atomic64_inc(&alg->stats.rng.err_cnt);
1069-
} else {
1070-
atomic64_inc(&alg->stats.rng.generate_cnt);
1071-
atomic64_add(dlen, &alg->stats.rng.generate_tlen);
1072-
}
1073-
crypto_alg_put(alg);
1074-
}
1075-
EXPORT_SYMBOL_GPL(crypto_stats_rng_generate);
1076-
#endif
1077-
10781039
static void __init crypto_start_tests(void)
10791040
{
10801041
if (IS_ENABLED(CONFIG_CRYPTO_MANAGER_DISABLE_TESTS))

crypto/crypto_user_stat.c

Lines changed: 6 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -6,15 +6,14 @@
66
*
77
*/
88

9-
#include <linux/crypto.h>
10-
#include <linux/cryptouser.h>
11-
#include <linux/sched.h>
9+
#include <crypto/algapi.h>
10+
#include <crypto/internal/cryptouser.h>
11+
#include <linux/errno.h>
12+
#include <linux/kernel.h>
13+
#include <linux/module.h>
14+
#include <linux/string.h>
1215
#include <net/netlink.h>
1316
#include <net/sock.h>
14-
#include <crypto/internal/rng.h>
15-
#include <crypto/internal/cryptouser.h>
16-
17-
#include "internal.h"
1817

1918
#define null_terminated(x) (strnlen(x, sizeof(x)) < sizeof(x))
2019

@@ -47,22 +46,6 @@ static int crypto_report_comp(struct sk_buff *skb, struct crypto_alg *alg)
4746
return nla_put(skb, CRYPTOCFGA_STAT_COMPRESS, sizeof(rcomp), &rcomp);
4847
}
4948

50-
static int crypto_report_rng(struct sk_buff *skb, struct crypto_alg *alg)
51-
{
52-
struct crypto_stat_rng rrng;
53-
54-
memset(&rrng, 0, sizeof(rrng));
55-
56-
strscpy(rrng.type, "rng", sizeof(rrng.type));
57-
58-
rrng.stat_generate_cnt = atomic64_read(&alg->stats.rng.generate_cnt);
59-
rrng.stat_generate_tlen = atomic64_read(&alg->stats.rng.generate_tlen);
60-
rrng.stat_seed_cnt = atomic64_read(&alg->stats.rng.seed_cnt);
61-
rrng.stat_err_cnt = atomic64_read(&alg->stats.rng.err_cnt);
62-
63-
return nla_put(skb, CRYPTOCFGA_STAT_RNG, sizeof(rrng), &rrng);
64-
}
65-
6649
static int crypto_reportstat_one(struct crypto_alg *alg,
6750
struct crypto_user_alg *ualg,
6851
struct sk_buff *skb)
@@ -107,10 +90,6 @@ static int crypto_reportstat_one(struct crypto_alg *alg,
10790
if (crypto_report_comp(skb, alg))
10891
goto nla_put_failure;
10992
break;
110-
case CRYPTO_ALG_TYPE_RNG:
111-
if (crypto_report_rng(skb, alg))
112-
goto nla_put_failure;
113-
break;
11493
default:
11594
pr_err("ERROR: Unhandled alg %d in %s\n",
11695
alg->cra_flags & (CRYPTO_ALG_TYPE_MASK | CRYPTO_ALG_LARVAL),

crypto/rng.c

Lines changed: 42 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -8,17 +8,17 @@
88
* Copyright (c) 2015 Herbert Xu <herbert@gondor.apana.org.au>
99
*/
1010

11-
#include <linux/atomic.h>
1211
#include <crypto/internal/rng.h>
12+
#include <linux/atomic.h>
13+
#include <linux/cryptouser.h>
1314
#include <linux/err.h>
15+
#include <linux/kernel.h>
1416
#include <linux/module.h>
1517
#include <linux/mutex.h>
1618
#include <linux/random.h>
1719
#include <linux/seq_file.h>
1820
#include <linux/slab.h>
1921
#include <linux/string.h>
20-
#include <linux/cryptouser.h>
21-
#include <linux/compiler.h>
2222
#include <net/netlink.h>
2323

2424
#include "internal.h"
@@ -30,27 +30,30 @@ static int crypto_default_rng_refcnt;
3030

3131
int crypto_rng_reset(struct crypto_rng *tfm, const u8 *seed, unsigned int slen)
3232
{
33-
struct crypto_alg *alg = tfm->base.__crt_alg;
33+
struct rng_alg *alg = crypto_rng_alg(tfm);
3434
u8 *buf = NULL;
3535
int err;
3636

37+
if (IS_ENABLED(CONFIG_CRYPTO_STATS))
38+
atomic64_inc(&rng_get_stat(alg)->seed_cnt);
39+
3740
if (!seed && slen) {
3841
buf = kmalloc(slen, GFP_KERNEL);
42+
err = -ENOMEM;
3943
if (!buf)
40-
return -ENOMEM;
44+
goto out;
4145

4246
err = get_random_bytes_wait(buf, slen);
4347
if (err)
44-
goto out;
48+
goto free_buf;
4549
seed = buf;
4650
}
4751

48-
crypto_stats_get(alg);
49-
err = crypto_rng_alg(tfm)->seed(tfm, seed, slen);
50-
crypto_stats_rng_seed(alg, err);
51-
out:
52+
err = alg->seed(tfm, seed, slen);
53+
free_buf:
5254
kfree_sensitive(buf);
53-
return err;
55+
out:
56+
return crypto_rng_errstat(alg, err);
5457
}
5558
EXPORT_SYMBOL_GPL(crypto_rng_reset);
5659

@@ -94,13 +97,37 @@ static void crypto_rng_show(struct seq_file *m, struct crypto_alg *alg)
9497
seq_printf(m, "seedsize : %u\n", seedsize(alg));
9598
}
9699

100+
static int __maybe_unused crypto_rng_report_stat(
101+
struct sk_buff *skb, struct crypto_alg *alg)
102+
{
103+
struct rng_alg *rng = __crypto_rng_alg(alg);
104+
struct crypto_istat_rng *istat;
105+
struct crypto_stat_rng rrng;
106+
107+
istat = rng_get_stat(rng);
108+
109+
memset(&rrng, 0, sizeof(rrng));
110+
111+
strscpy(rrng.type, "rng", sizeof(rrng.type));
112+
113+
rrng.stat_generate_cnt = atomic64_read(&istat->generate_cnt);
114+
rrng.stat_generate_tlen = atomic64_read(&istat->generate_tlen);
115+
rrng.stat_seed_cnt = atomic64_read(&istat->seed_cnt);
116+
rrng.stat_err_cnt = atomic64_read(&istat->err_cnt);
117+
118+
return nla_put(skb, CRYPTOCFGA_STAT_RNG, sizeof(rrng), &rrng);
119+
}
120+
97121
static const struct crypto_type crypto_rng_type = {
98122
.extsize = crypto_alg_extsize,
99123
.init_tfm = crypto_rng_init_tfm,
100124
#ifdef CONFIG_PROC_FS
101125
.show = crypto_rng_show,
102126
#endif
103127
.report = crypto_rng_report,
128+
#ifdef CONFIG_CRYPTO_STATS
129+
.report_stat = crypto_rng_report_stat,
130+
#endif
104131
.maskclear = ~CRYPTO_ALG_TYPE_MASK,
105132
.maskset = CRYPTO_ALG_TYPE_MASK,
106133
.type = CRYPTO_ALG_TYPE_RNG,
@@ -176,6 +203,7 @@ EXPORT_SYMBOL_GPL(crypto_del_default_rng);
176203

177204
int crypto_register_rng(struct rng_alg *alg)
178205
{
206+
struct crypto_istat_rng *istat = rng_get_stat(alg);
179207
struct crypto_alg *base = &alg->base;
180208

181209
if (alg->seedsize > PAGE_SIZE / 8)
@@ -185,6 +213,9 @@ int crypto_register_rng(struct rng_alg *alg)
185213
base->cra_flags &= ~CRYPTO_ALG_TYPE_MASK;
186214
base->cra_flags |= CRYPTO_ALG_TYPE_RNG;
187215

216+
if (IS_ENABLED(CONFIG_CRYPTO_STATS))
217+
memset(istat, 0, sizeof(*istat));
218+
188219
return crypto_register_alg(base);
189220
}
190221
EXPORT_SYMBOL_GPL(crypto_register_rng);

include/crypto/rng.h

Lines changed: 57 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -9,10 +9,26 @@
99
#ifndef _CRYPTO_RNG_H
1010
#define _CRYPTO_RNG_H
1111

12+
#include <linux/atomic.h>
13+
#include <linux/container_of.h>
1214
#include <linux/crypto.h>
1315

1416
struct crypto_rng;
1517

18+
/*
19+
* struct crypto_istat_rng: statistics for RNG algorithm
20+
* @generate_cnt: number of RNG generate requests
21+
* @generate_tlen: total data size of generated data by the RNG
22+
* @seed_cnt: number of times the RNG was seeded
23+
* @err_cnt: number of error for RNG requests
24+
*/
25+
struct crypto_istat_rng {
26+
atomic64_t generate_cnt;
27+
atomic64_t generate_tlen;
28+
atomic64_t seed_cnt;
29+
atomic64_t err_cnt;
30+
};
31+
1632
/**
1733
* struct rng_alg - random number generator definition
1834
*
@@ -30,6 +46,7 @@ struct crypto_rng;
3046
* size of the seed is defined with @seedsize .
3147
* @set_ent: Set entropy that would otherwise be obtained from
3248
* entropy source. Internal use only.
49+
* @stat: Statistics for rng algorithm
3350
* @seedsize: The seed size required for a random number generator
3451
* initialization defined with this variable. Some
3552
* random number generators does not require a seed
@@ -46,6 +63,10 @@ struct rng_alg {
4663
void (*set_ent)(struct crypto_rng *tfm, const u8 *data,
4764
unsigned int len);
4865

66+
#ifdef CONFIG_CRYPTO_STATS
67+
struct crypto_istat_rng stat;
68+
#endif
69+
4970
unsigned int seedsize;
5071

5172
struct crypto_alg base;
@@ -94,6 +115,11 @@ static inline struct crypto_tfm *crypto_rng_tfm(struct crypto_rng *tfm)
94115
return &tfm->base;
95116
}
96117

118+
static inline struct rng_alg *__crypto_rng_alg(struct crypto_alg *alg)
119+
{
120+
return container_of(alg, struct rng_alg, base);
121+
}
122+
97123
/**
98124
* crypto_rng_alg - obtain name of RNG
99125
* @tfm: cipher handle
@@ -104,8 +130,7 @@ static inline struct crypto_tfm *crypto_rng_tfm(struct crypto_rng *tfm)
104130
*/
105131
static inline struct rng_alg *crypto_rng_alg(struct crypto_rng *tfm)
106132
{
107-
return container_of(crypto_rng_tfm(tfm)->__crt_alg,
108-
struct rng_alg, base);
133+
return __crypto_rng_alg(crypto_rng_tfm(tfm)->__crt_alg);
109134
}
110135

111136
/**
@@ -119,6 +144,26 @@ static inline void crypto_free_rng(struct crypto_rng *tfm)
119144
crypto_destroy_tfm(tfm, crypto_rng_tfm(tfm));
120145
}
121146

147+
static inline struct crypto_istat_rng *rng_get_stat(struct rng_alg *alg)
148+
{
149+
#ifdef CONFIG_CRYPTO_STATS
150+
return &alg->stat;
151+
#else
152+
return NULL;
153+
#endif
154+
}
155+
156+
static inline int crypto_rng_errstat(struct rng_alg *alg, int err)
157+
{
158+
if (!IS_ENABLED(CONFIG_CRYPTO_STATS))
159+
return err;
160+
161+
if (err && err != -EINPROGRESS && err != -EBUSY)
162+
atomic64_inc(&rng_get_stat(alg)->err_cnt);
163+
164+
return err;
165+
}
166+
122167
/**
123168
* crypto_rng_generate() - get random number
124169
* @tfm: cipher handle
@@ -137,13 +182,17 @@ static inline int crypto_rng_generate(struct crypto_rng *tfm,
137182
const u8 *src, unsigned int slen,
138183
u8 *dst, unsigned int dlen)
139184
{
140-
struct crypto_alg *alg = tfm->base.__crt_alg;
141-
int ret;
185+
struct rng_alg *alg = crypto_rng_alg(tfm);
186+
187+
if (IS_ENABLED(CONFIG_CRYPTO_STATS)) {
188+
struct crypto_istat_rng *istat = rng_get_stat(alg);
189+
190+
atomic64_inc(&istat->generate_cnt);
191+
atomic64_add(dlen, &istat->generate_tlen);
192+
}
142193

143-
crypto_stats_get(alg);
144-
ret = crypto_rng_alg(tfm)->generate(tfm, src, slen, dst, dlen);
145-
crypto_stats_rng_generate(alg, dlen, ret);
146-
return ret;
194+
return crypto_rng_errstat(alg,
195+
alg->generate(tfm, src, slen, dst, dlen));
147196
}
148197

149198
/**

0 commit comments

Comments
 (0)