Skip to content

Commit 57225e6

Browse files
smuellerDDherbertx
authored andcommitted
crypto: drbg - Use callback API for random readiness
The get_blocking_random_bytes API is broken because the wait can be arbitrarily long (potentially forever) so there is no safe way of calling it from within the kernel. This patch replaces it with the new callback API which does not have this problem. The patch also removes the entropy buffer registered with the DRBG handle in favor of stack variables to hold the seed data. Signed-off-by: Stephan Mueller <smueller@chronox.de> Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>
1 parent 205a525 commit 57225e6

2 files changed

Lines changed: 127 additions & 93 deletions

File tree

crypto/drbg.c

Lines changed: 126 additions & 91 deletions
Original file line numberDiff line numberDiff line change
@@ -98,6 +98,7 @@
9898
*/
9999

100100
#include <crypto/drbg.h>
101+
#include <linux/kernel.h>
101102

102103
/***************************************************************
103104
* Backend cipher definitions available to DRBG
@@ -190,6 +191,8 @@ static const struct drbg_core drbg_cores[] = {
190191
#endif /* CONFIG_CRYPTO_DRBG_HMAC */
191192
};
192193

194+
static int drbg_uninstantiate(struct drbg_state *drbg);
195+
193196
/******************************************************************
194197
* Generic helper functions
195198
******************************************************************/
@@ -1062,20 +1065,32 @@ static void drbg_async_seed(struct work_struct *work)
10621065
LIST_HEAD(seedlist);
10631066
struct drbg_state *drbg = container_of(work, struct drbg_state,
10641067
seed_work);
1065-
int ret;
1068+
unsigned int entropylen = drbg_sec_strength(drbg->core->flags);
1069+
unsigned char entropy[32];
10661070

1067-
get_blocking_random_bytes(drbg->seed_buf, drbg->seed_buf_len);
1071+
BUG_ON(!entropylen);
1072+
BUG_ON(entropylen > sizeof(entropy));
1073+
get_random_bytes(entropy, entropylen);
10681074

1069-
drbg_string_fill(&data, drbg->seed_buf, drbg->seed_buf_len);
1075+
drbg_string_fill(&data, entropy, entropylen);
10701076
list_add_tail(&data.list, &seedlist);
1077+
10711078
mutex_lock(&drbg->drbg_mutex);
1072-
ret = __drbg_seed(drbg, &seedlist, true);
1073-
if (!ret && drbg->jent) {
1074-
crypto_free_rng(drbg->jent);
1075-
drbg->jent = NULL;
1076-
}
1077-
memzero_explicit(drbg->seed_buf, drbg->seed_buf_len);
1079+
1080+
/* If nonblocking pool is initialized, deactivate Jitter RNG */
1081+
crypto_free_rng(drbg->jent);
1082+
drbg->jent = NULL;
1083+
1084+
/* Set seeded to false so that if __drbg_seed fails the
1085+
* next generate call will trigger a reseed.
1086+
*/
1087+
drbg->seeded = false;
1088+
1089+
__drbg_seed(drbg, &seedlist, true);
1090+
10781091
mutex_unlock(&drbg->drbg_mutex);
1092+
1093+
memzero_explicit(entropy, entropylen);
10791094
}
10801095

10811096
/*
@@ -1092,7 +1107,9 @@ static void drbg_async_seed(struct work_struct *work)
10921107
static int drbg_seed(struct drbg_state *drbg, struct drbg_string *pers,
10931108
bool reseed)
10941109
{
1095-
int ret = 0;
1110+
int ret;
1111+
unsigned char entropy[((32 + 16) * 2)];
1112+
unsigned int entropylen = drbg_sec_strength(drbg->core->flags);
10961113
struct drbg_string data1;
10971114
LIST_HEAD(seedlist);
10981115

@@ -1108,23 +1125,39 @@ static int drbg_seed(struct drbg_state *drbg, struct drbg_string *pers,
11081125
drbg->test_data.len);
11091126
pr_devel("DRBG: using test entropy\n");
11101127
} else {
1128+
/*
1129+
* Gather entropy equal to the security strength of the DRBG.
1130+
* With a derivation function, a nonce is required in addition
1131+
* to the entropy. A nonce must be at least 1/2 of the security
1132+
* strength of the DRBG in size. Thus, entropy + nonce is 3/2
1133+
* of the strength. The consideration of a nonce is only
1134+
* applicable during initial seeding.
1135+
*/
1136+
BUG_ON(!entropylen);
1137+
if (!reseed)
1138+
entropylen = ((entropylen + 1) / 2) * 3;
1139+
BUG_ON((entropylen * 2) > sizeof(entropy));
1140+
11111141
/* Get seed from in-kernel /dev/urandom */
1112-
get_random_bytes(drbg->seed_buf, drbg->seed_buf_len);
1113-
1114-
/* Get seed from Jitter RNG */
1115-
if (!drbg->jent ||
1116-
crypto_rng_get_bytes(drbg->jent,
1117-
drbg->seed_buf + drbg->seed_buf_len,
1118-
drbg->seed_buf_len)) {
1119-
drbg_string_fill(&data1, drbg->seed_buf,
1120-
drbg->seed_buf_len);
1121-
pr_devel("DRBG: (re)seeding with %zu bytes of entropy\n",
1122-
drbg->seed_buf_len);
1142+
get_random_bytes(entropy, entropylen);
1143+
1144+
if (!drbg->jent) {
1145+
drbg_string_fill(&data1, entropy, entropylen);
1146+
pr_devel("DRBG: (re)seeding with %u bytes of entropy\n",
1147+
entropylen);
11231148
} else {
1124-
drbg_string_fill(&data1, drbg->seed_buf,
1125-
drbg->seed_buf_len * 2);
1126-
pr_devel("DRBG: (re)seeding with %zu bytes of entropy\n",
1127-
drbg->seed_buf_len * 2);
1149+
/* Get seed from Jitter RNG */
1150+
ret = crypto_rng_get_bytes(drbg->jent,
1151+
entropy + entropylen,
1152+
entropylen);
1153+
if (ret) {
1154+
pr_devel("DRBG: jent failed with %d\n", ret);
1155+
return ret;
1156+
}
1157+
1158+
drbg_string_fill(&data1, entropy, entropylen * 2);
1159+
pr_devel("DRBG: (re)seeding with %u bytes of entropy\n",
1160+
entropylen * 2);
11281161
}
11291162
}
11301163
list_add_tail(&data1.list, &seedlist);
@@ -1146,26 +1179,8 @@ static int drbg_seed(struct drbg_state *drbg, struct drbg_string *pers,
11461179

11471180
ret = __drbg_seed(drbg, &seedlist, reseed);
11481181

1149-
/*
1150-
* Clear the initial entropy buffer as the async call may not overwrite
1151-
* that buffer for quite some time.
1152-
*/
1153-
memzero_explicit(drbg->seed_buf, drbg->seed_buf_len * 2);
1154-
if (ret)
1155-
goto out;
1156-
/*
1157-
* For all subsequent seeding calls, we only need the seed buffer
1158-
* equal to the security strength of the DRBG. We undo the calculation
1159-
* in drbg_alloc_state.
1160-
*/
1161-
if (!reseed)
1162-
drbg->seed_buf_len = drbg->seed_buf_len / 3 * 2;
1163-
1164-
/* Invoke asynchronous seeding unless DRBG is in test mode. */
1165-
if (!list_empty(&drbg->test_data.list) && !reseed)
1166-
schedule_work(&drbg->seed_work);
1182+
memzero_explicit(entropy, entropylen * 2);
11671183

1168-
out:
11691184
return ret;
11701185
}
11711186

@@ -1188,12 +1203,6 @@ static inline void drbg_dealloc_state(struct drbg_state *drbg)
11881203
drbg->prev = NULL;
11891204
drbg->fips_primed = false;
11901205
#endif
1191-
kzfree(drbg->seed_buf);
1192-
drbg->seed_buf = NULL;
1193-
if (drbg->jent) {
1194-
crypto_free_rng(drbg->jent);
1195-
drbg->jent = NULL;
1196-
}
11971206
}
11981207

11991208
/*
@@ -1256,42 +1265,6 @@ static inline int drbg_alloc_state(struct drbg_state *drbg)
12561265
goto err;
12571266
}
12581267

1259-
/*
1260-
* Gather entropy equal to the security strength of the DRBG.
1261-
* With a derivation function, a nonce is required in addition
1262-
* to the entropy. A nonce must be at least 1/2 of the security
1263-
* strength of the DRBG in size. Thus, entropy * nonce is 3/2
1264-
* of the strength. The consideration of a nonce is only
1265-
* applicable during initial seeding.
1266-
*/
1267-
drbg->seed_buf_len = drbg_sec_strength(drbg->core->flags);
1268-
if (!drbg->seed_buf_len) {
1269-
ret = -EFAULT;
1270-
goto err;
1271-
}
1272-
/*
1273-
* Ensure we have sufficient buffer space for initial seed which
1274-
* consists of the seed from get_random_bytes and the Jitter RNG.
1275-
*/
1276-
drbg->seed_buf_len = ((drbg->seed_buf_len + 1) / 2) * 3;
1277-
drbg->seed_buf = kzalloc(drbg->seed_buf_len * 2, GFP_KERNEL);
1278-
if (!drbg->seed_buf)
1279-
goto err;
1280-
1281-
INIT_WORK(&drbg->seed_work, drbg_async_seed);
1282-
1283-
drbg->jent = crypto_alloc_rng("jitterentropy_rng", 0, 0);
1284-
if(IS_ERR(drbg->jent))
1285-
{
1286-
pr_info("DRBG: could not allocate Jitter RNG handle for seeding\n");
1287-
/*
1288-
* As the Jitter RNG is a module that may not be present, we
1289-
* continue with the operation and do not fully tie the DRBG
1290-
* to the Jitter RNG.
1291-
*/
1292-
drbg->jent = NULL;
1293-
}
1294-
12951268
return 0;
12961269

12971270
err:
@@ -1467,6 +1440,47 @@ static int drbg_generate_long(struct drbg_state *drbg,
14671440
return 0;
14681441
}
14691442

1443+
static void drbg_schedule_async_seed(struct random_ready_callback *rdy)
1444+
{
1445+
struct drbg_state *drbg = container_of(rdy, struct drbg_state,
1446+
random_ready);
1447+
1448+
schedule_work(&drbg->seed_work);
1449+
}
1450+
1451+
static int drbg_prepare_hrng(struct drbg_state *drbg)
1452+
{
1453+
int err;
1454+
1455+
/* We do not need an HRNG in test mode. */
1456+
if (list_empty(&drbg->test_data.list))
1457+
return 0;
1458+
1459+
INIT_WORK(&drbg->seed_work, drbg_async_seed);
1460+
1461+
drbg->random_ready.owner = THIS_MODULE;
1462+
drbg->random_ready.func = drbg_schedule_async_seed;
1463+
1464+
err = add_random_ready_callback(&drbg->random_ready);
1465+
1466+
switch (err) {
1467+
case 0:
1468+
break;
1469+
1470+
case -EALREADY:
1471+
err = 0;
1472+
/* fall through */
1473+
1474+
default:
1475+
drbg->random_ready.func = NULL;
1476+
return err;
1477+
}
1478+
1479+
drbg->jent = crypto_alloc_rng("jitterentropy_rng", 0, 0);
1480+
1481+
return err;
1482+
}
1483+
14701484
/*
14711485
* DRBG instantiation function as required by SP800-90A - this function
14721486
* sets up the DRBG handle, performs the initial seeding and all sanity
@@ -1517,15 +1531,25 @@ static int drbg_instantiate(struct drbg_state *drbg, struct drbg_string *pers,
15171531
if (drbg->d_ops->crypto_init(drbg))
15181532
goto err;
15191533

1534+
ret = drbg_prepare_hrng(drbg);
1535+
if (ret)
1536+
goto free_everything;
1537+
1538+
if (IS_ERR(drbg->jent)) {
1539+
ret = PTR_ERR(drbg->jent);
1540+
drbg->jent = NULL;
1541+
if (fips_enabled || ret != -ENOENT)
1542+
goto free_everything;
1543+
pr_info("DRBG: Continuing without Jitter RNG\n");
1544+
}
1545+
15201546
reseed = false;
15211547
}
15221548

15231549
ret = drbg_seed(drbg, pers, reseed);
15241550

1525-
if (ret && !reseed) {
1526-
drbg->d_ops->crypto_fini(drbg);
1527-
goto err;
1528-
}
1551+
if (ret && !reseed)
1552+
goto free_everything;
15291553

15301554
mutex_unlock(&drbg->drbg_mutex);
15311555
return ret;
@@ -1535,6 +1559,11 @@ static int drbg_instantiate(struct drbg_state *drbg, struct drbg_string *pers,
15351559
unlock:
15361560
mutex_unlock(&drbg->drbg_mutex);
15371561
return ret;
1562+
1563+
free_everything:
1564+
mutex_unlock(&drbg->drbg_mutex);
1565+
drbg_uninstantiate(drbg);
1566+
return ret;
15381567
}
15391568

15401569
/*
@@ -1548,7 +1577,13 @@ static int drbg_instantiate(struct drbg_state *drbg, struct drbg_string *pers,
15481577
*/
15491578
static int drbg_uninstantiate(struct drbg_state *drbg)
15501579
{
1551-
cancel_work_sync(&drbg->seed_work);
1580+
if (drbg->random_ready.func) {
1581+
del_random_ready_callback(&drbg->random_ready);
1582+
cancel_work_sync(&drbg->seed_work);
1583+
crypto_free_rng(drbg->jent);
1584+
drbg->jent = NULL;
1585+
}
1586+
15521587
if (drbg->d_ops)
15531588
drbg->d_ops->crypto_fini(drbg);
15541589
drbg_dealloc_state(drbg);

include/crypto/drbg.h

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -121,12 +121,11 @@ struct drbg_state {
121121
unsigned char *prev; /* FIPS 140-2 continuous test value */
122122
#endif
123123
struct work_struct seed_work; /* asynchronous seeding support */
124-
u8 *seed_buf; /* buffer holding the seed */
125-
size_t seed_buf_len;
126124
struct crypto_rng *jent;
127125
const struct drbg_state_ops *d_ops;
128126
const struct drbg_core *core;
129127
struct drbg_string test_data;
128+
struct random_ready_callback random_ready;
130129
};
131130

132131
static inline __u8 drbg_statelen(struct drbg_state *drbg)

0 commit comments

Comments
 (0)