.. | .. |
---|
98 | 98 | */ |
---|
99 | 99 | |
---|
100 | 100 | #include <crypto/drbg.h> |
---|
| 101 | +#include <crypto/internal/cipher.h> |
---|
101 | 102 | #include <linux/kernel.h> |
---|
102 | 103 | |
---|
103 | 104 | /*************************************************************** |
---|
.. | .. |
---|
217 | 218 | default: |
---|
218 | 219 | return 32; |
---|
219 | 220 | } |
---|
| 221 | +} |
---|
| 222 | + |
---|
| 223 | +/* |
---|
| 224 | + * FIPS 140-2 continuous self test for the noise source |
---|
| 225 | + * The test is performed on the noise source input data. Thus, the function |
---|
| 226 | + * implicitly knows the size of the buffer to be equal to the security |
---|
| 227 | + * strength. |
---|
| 228 | + * |
---|
| 229 | + * Note, this function disregards the nonce trailing the entropy data during |
---|
| 230 | + * initial seeding. |
---|
| 231 | + * |
---|
| 232 | + * drbg->drbg_mutex must have been taken. |
---|
| 233 | + * |
---|
| 234 | + * @drbg DRBG handle |
---|
| 235 | + * @entropy buffer of seed data to be checked |
---|
| 236 | + * |
---|
| 237 | + * return: |
---|
| 238 | + * 0 on success |
---|
| 239 | + * -EAGAIN on when the CTRNG is not yet primed |
---|
| 240 | + * < 0 on error |
---|
| 241 | + */ |
---|
| 242 | +static int drbg_fips_continuous_test(struct drbg_state *drbg, |
---|
| 243 | + const unsigned char *entropy) |
---|
| 244 | +{ |
---|
| 245 | + unsigned short entropylen = drbg_sec_strength(drbg->core->flags); |
---|
| 246 | + int ret = 0; |
---|
| 247 | + |
---|
| 248 | + if (!IS_ENABLED(CONFIG_CRYPTO_FIPS)) |
---|
| 249 | + return 0; |
---|
| 250 | + |
---|
| 251 | + /* skip test if we test the overall system */ |
---|
| 252 | + if (list_empty(&drbg->test_data.list)) |
---|
| 253 | + return 0; |
---|
| 254 | + /* only perform test in FIPS mode */ |
---|
| 255 | + if (!fips_enabled) |
---|
| 256 | + return 0; |
---|
| 257 | + |
---|
| 258 | + if (!drbg->fips_primed) { |
---|
| 259 | + /* Priming of FIPS test */ |
---|
| 260 | + memcpy(drbg->prev, entropy, entropylen); |
---|
| 261 | + drbg->fips_primed = true; |
---|
| 262 | + /* priming: another round is needed */ |
---|
| 263 | + return -EAGAIN; |
---|
| 264 | + } |
---|
| 265 | + ret = memcmp(drbg->prev, entropy, entropylen); |
---|
| 266 | + if (!ret) |
---|
| 267 | + panic("DRBG continuous self test failed\n"); |
---|
| 268 | + memcpy(drbg->prev, entropy, entropylen); |
---|
| 269 | + |
---|
| 270 | + /* the test shall pass when the two values are not equal */ |
---|
| 271 | + return 0; |
---|
220 | 272 | } |
---|
221 | 273 | |
---|
222 | 274 | /* |
---|
.. | .. |
---|
984 | 1036 | ******************************************************************/ |
---|
985 | 1037 | |
---|
986 | 1038 | static inline int __drbg_seed(struct drbg_state *drbg, struct list_head *seed, |
---|
987 | | - int reseed) |
---|
| 1039 | + int reseed, enum drbg_seed_state new_seed_state) |
---|
988 | 1040 | { |
---|
989 | 1041 | int ret = drbg->d_ops->update(drbg, seed, reseed); |
---|
990 | 1042 | |
---|
991 | 1043 | if (ret) |
---|
992 | 1044 | return ret; |
---|
993 | 1045 | |
---|
994 | | - drbg->seeded = true; |
---|
| 1046 | + drbg->seeded = new_seed_state; |
---|
995 | 1047 | /* 10.1.1.2 / 10.1.1.3 step 5 */ |
---|
996 | 1048 | drbg->reseed_ctr = 1; |
---|
| 1049 | + |
---|
| 1050 | + switch (drbg->seeded) { |
---|
| 1051 | + case DRBG_SEED_STATE_UNSEEDED: |
---|
| 1052 | + /* Impossible, but handle it to silence compiler warnings. */ |
---|
| 1053 | + fallthrough; |
---|
| 1054 | + case DRBG_SEED_STATE_PARTIAL: |
---|
| 1055 | + /* |
---|
| 1056 | + * Require frequent reseeds until the seed source is |
---|
| 1057 | + * fully initialized. |
---|
| 1058 | + */ |
---|
| 1059 | + drbg->reseed_threshold = 50; |
---|
| 1060 | + break; |
---|
| 1061 | + |
---|
| 1062 | + case DRBG_SEED_STATE_FULL: |
---|
| 1063 | + /* |
---|
| 1064 | + * Seed source has become fully initialized, frequent |
---|
| 1065 | + * reseeds no longer required. |
---|
| 1066 | + */ |
---|
| 1067 | + drbg->reseed_threshold = drbg_max_requests(drbg); |
---|
| 1068 | + break; |
---|
| 1069 | + } |
---|
997 | 1070 | |
---|
998 | 1071 | return ret; |
---|
999 | 1072 | } |
---|
1000 | 1073 | |
---|
1001 | | -static void drbg_async_seed(struct work_struct *work) |
---|
| 1074 | +static inline int drbg_get_random_bytes(struct drbg_state *drbg, |
---|
| 1075 | + unsigned char *entropy, |
---|
| 1076 | + unsigned int entropylen) |
---|
| 1077 | +{ |
---|
| 1078 | + int ret; |
---|
| 1079 | + |
---|
| 1080 | + do { |
---|
| 1081 | + get_random_bytes(entropy, entropylen); |
---|
| 1082 | + ret = drbg_fips_continuous_test(drbg, entropy); |
---|
| 1083 | + if (ret && ret != -EAGAIN) |
---|
| 1084 | + return ret; |
---|
| 1085 | + } while (ret); |
---|
| 1086 | + |
---|
| 1087 | + return 0; |
---|
| 1088 | +} |
---|
| 1089 | + |
---|
| 1090 | +static int drbg_seed_from_random(struct drbg_state *drbg) |
---|
1002 | 1091 | { |
---|
1003 | 1092 | struct drbg_string data; |
---|
1004 | 1093 | LIST_HEAD(seedlist); |
---|
1005 | | - struct drbg_state *drbg = container_of(work, struct drbg_state, |
---|
1006 | | - seed_work); |
---|
1007 | 1094 | unsigned int entropylen = drbg_sec_strength(drbg->core->flags); |
---|
1008 | 1095 | unsigned char entropy[32]; |
---|
| 1096 | + int ret; |
---|
1009 | 1097 | |
---|
1010 | 1098 | BUG_ON(!entropylen); |
---|
1011 | 1099 | BUG_ON(entropylen > sizeof(entropy)); |
---|
1012 | | - get_random_bytes(entropy, entropylen); |
---|
1013 | 1100 | |
---|
1014 | 1101 | drbg_string_fill(&data, entropy, entropylen); |
---|
1015 | 1102 | list_add_tail(&data.list, &seedlist); |
---|
1016 | 1103 | |
---|
1017 | | - mutex_lock(&drbg->drbg_mutex); |
---|
| 1104 | + ret = drbg_get_random_bytes(drbg, entropy, entropylen); |
---|
| 1105 | + if (ret) |
---|
| 1106 | + goto out; |
---|
1018 | 1107 | |
---|
1019 | | - /* If nonblocking pool is initialized, deactivate Jitter RNG */ |
---|
1020 | | - crypto_free_rng(drbg->jent); |
---|
1021 | | - drbg->jent = NULL; |
---|
| 1108 | + ret = __drbg_seed(drbg, &seedlist, true, DRBG_SEED_STATE_FULL); |
---|
1022 | 1109 | |
---|
1023 | | - /* Set seeded to false so that if __drbg_seed fails the |
---|
1024 | | - * next generate call will trigger a reseed. |
---|
1025 | | - */ |
---|
1026 | | - drbg->seeded = false; |
---|
1027 | | - |
---|
1028 | | - __drbg_seed(drbg, &seedlist, true); |
---|
1029 | | - |
---|
1030 | | - if (drbg->seeded) |
---|
1031 | | - drbg->reseed_threshold = drbg_max_requests(drbg); |
---|
1032 | | - |
---|
1033 | | - mutex_unlock(&drbg->drbg_mutex); |
---|
1034 | | - |
---|
| 1110 | +out: |
---|
1035 | 1111 | memzero_explicit(entropy, entropylen); |
---|
| 1112 | + return ret; |
---|
1036 | 1113 | } |
---|
1037 | 1114 | |
---|
1038 | 1115 | /* |
---|
.. | .. |
---|
1054 | 1131 | unsigned int entropylen = drbg_sec_strength(drbg->core->flags); |
---|
1055 | 1132 | struct drbg_string data1; |
---|
1056 | 1133 | LIST_HEAD(seedlist); |
---|
| 1134 | + enum drbg_seed_state new_seed_state = DRBG_SEED_STATE_FULL; |
---|
1057 | 1135 | |
---|
1058 | 1136 | /* 9.1 / 9.2 / 9.3.1 step 3 */ |
---|
1059 | 1137 | if (pers && pers->len > (drbg_max_addtl(drbg))) { |
---|
.. | .. |
---|
1081 | 1159 | BUG_ON((entropylen * 2) > sizeof(entropy)); |
---|
1082 | 1160 | |
---|
1083 | 1161 | /* Get seed from in-kernel /dev/urandom */ |
---|
1084 | | - get_random_bytes(entropy, entropylen); |
---|
| 1162 | + if (!rng_is_initialized()) |
---|
| 1163 | + new_seed_state = DRBG_SEED_STATE_PARTIAL; |
---|
| 1164 | + |
---|
| 1165 | + ret = drbg_get_random_bytes(drbg, entropy, entropylen); |
---|
| 1166 | + if (ret) |
---|
| 1167 | + goto out; |
---|
1085 | 1168 | |
---|
1086 | 1169 | if (!drbg->jent) { |
---|
1087 | 1170 | drbg_string_fill(&data1, entropy, entropylen); |
---|
.. | .. |
---|
1094 | 1177 | entropylen); |
---|
1095 | 1178 | if (ret) { |
---|
1096 | 1179 | pr_devel("DRBG: jent failed with %d\n", ret); |
---|
1097 | | - return ret; |
---|
| 1180 | + |
---|
| 1181 | + /* |
---|
| 1182 | + * Do not treat the transient failure of the |
---|
| 1183 | + * Jitter RNG as an error that needs to be |
---|
| 1184 | + * reported. The combined number of the |
---|
| 1185 | + * maximum reseed threshold times the maximum |
---|
| 1186 | + * number of Jitter RNG transient errors is |
---|
| 1187 | + * less than the reseed threshold required by |
---|
| 1188 | + * SP800-90A allowing us to treat the |
---|
| 1189 | + * transient errors as such. |
---|
| 1190 | + * |
---|
| 1191 | + * However, we mandate that at least the first |
---|
| 1192 | + * seeding operation must succeed with the |
---|
| 1193 | + * Jitter RNG. |
---|
| 1194 | + */ |
---|
| 1195 | + if (!reseed || ret != -EAGAIN) |
---|
| 1196 | + goto out; |
---|
1098 | 1197 | } |
---|
1099 | 1198 | |
---|
1100 | 1199 | drbg_string_fill(&data1, entropy, entropylen * 2); |
---|
.. | .. |
---|
1119 | 1218 | memset(drbg->C, 0, drbg_statelen(drbg)); |
---|
1120 | 1219 | } |
---|
1121 | 1220 | |
---|
1122 | | - ret = __drbg_seed(drbg, &seedlist, reseed); |
---|
| 1221 | + ret = __drbg_seed(drbg, &seedlist, reseed, new_seed_state); |
---|
1123 | 1222 | |
---|
| 1223 | +out: |
---|
1124 | 1224 | memzero_explicit(entropy, entropylen * 2); |
---|
1125 | 1225 | |
---|
1126 | 1226 | return ret; |
---|
.. | .. |
---|
1131 | 1231 | { |
---|
1132 | 1232 | if (!drbg) |
---|
1133 | 1233 | return; |
---|
1134 | | - kzfree(drbg->Vbuf); |
---|
| 1234 | + kfree_sensitive(drbg->Vbuf); |
---|
1135 | 1235 | drbg->Vbuf = NULL; |
---|
1136 | 1236 | drbg->V = NULL; |
---|
1137 | | - kzfree(drbg->Cbuf); |
---|
| 1237 | + kfree_sensitive(drbg->Cbuf); |
---|
1138 | 1238 | drbg->Cbuf = NULL; |
---|
1139 | 1239 | drbg->C = NULL; |
---|
1140 | | - kzfree(drbg->scratchpadbuf); |
---|
| 1240 | + kfree_sensitive(drbg->scratchpadbuf); |
---|
1141 | 1241 | drbg->scratchpadbuf = NULL; |
---|
1142 | 1242 | drbg->reseed_ctr = 0; |
---|
1143 | 1243 | drbg->d_ops = NULL; |
---|
1144 | 1244 | drbg->core = NULL; |
---|
| 1245 | + if (IS_ENABLED(CONFIG_CRYPTO_FIPS)) { |
---|
| 1246 | + kfree_sensitive(drbg->prev); |
---|
| 1247 | + drbg->prev = NULL; |
---|
| 1248 | + drbg->fips_primed = false; |
---|
| 1249 | + } |
---|
1145 | 1250 | } |
---|
1146 | 1251 | |
---|
1147 | 1252 | /* |
---|
.. | .. |
---|
1209 | 1314 | goto fini; |
---|
1210 | 1315 | } |
---|
1211 | 1316 | drbg->scratchpad = PTR_ALIGN(drbg->scratchpadbuf, ret + 1); |
---|
| 1317 | + } |
---|
| 1318 | + |
---|
| 1319 | + if (IS_ENABLED(CONFIG_CRYPTO_FIPS)) { |
---|
| 1320 | + drbg->prev = kzalloc(drbg_sec_strength(drbg->core->flags), |
---|
| 1321 | + GFP_KERNEL); |
---|
| 1322 | + if (!drbg->prev) { |
---|
| 1323 | + ret = -ENOMEM; |
---|
| 1324 | + goto fini; |
---|
| 1325 | + } |
---|
| 1326 | + drbg->fips_primed = false; |
---|
1212 | 1327 | } |
---|
1213 | 1328 | |
---|
1214 | 1329 | return 0; |
---|
.. | .. |
---|
1283 | 1398 | * here. The spec is a bit convoluted here, we make it simpler. |
---|
1284 | 1399 | */ |
---|
1285 | 1400 | if (drbg->reseed_threshold < drbg->reseed_ctr) |
---|
1286 | | - drbg->seeded = false; |
---|
| 1401 | + drbg->seeded = DRBG_SEED_STATE_UNSEEDED; |
---|
1287 | 1402 | |
---|
1288 | | - if (drbg->pr || !drbg->seeded) { |
---|
| 1403 | + if (drbg->pr || drbg->seeded == DRBG_SEED_STATE_UNSEEDED) { |
---|
1289 | 1404 | pr_devel("DRBG: reseeding before generation (prediction " |
---|
1290 | 1405 | "resistance: %s, state %s)\n", |
---|
1291 | 1406 | drbg->pr ? "true" : "false", |
---|
1292 | | - drbg->seeded ? "seeded" : "unseeded"); |
---|
| 1407 | + (drbg->seeded == DRBG_SEED_STATE_FULL ? |
---|
| 1408 | + "seeded" : "unseeded")); |
---|
1293 | 1409 | /* 9.3.1 steps 7.1 through 7.3 */ |
---|
1294 | 1410 | len = drbg_seed(drbg, addtl, true); |
---|
1295 | 1411 | if (len) |
---|
1296 | 1412 | goto err; |
---|
1297 | 1413 | /* 9.3.1 step 7.4 */ |
---|
1298 | 1414 | addtl = NULL; |
---|
| 1415 | + } else if (rng_is_initialized() && |
---|
| 1416 | + drbg->seeded == DRBG_SEED_STATE_PARTIAL) { |
---|
| 1417 | + len = drbg_seed_from_random(drbg); |
---|
| 1418 | + if (len) |
---|
| 1419 | + goto err; |
---|
1299 | 1420 | } |
---|
1300 | 1421 | |
---|
1301 | 1422 | if (addtl && 0 < addtl->len) |
---|
.. | .. |
---|
1388 | 1509 | return 0; |
---|
1389 | 1510 | } |
---|
1390 | 1511 | |
---|
1391 | | -static void drbg_schedule_async_seed(struct random_ready_callback *rdy) |
---|
1392 | | -{ |
---|
1393 | | - struct drbg_state *drbg = container_of(rdy, struct drbg_state, |
---|
1394 | | - random_ready); |
---|
1395 | | - |
---|
1396 | | - schedule_work(&drbg->seed_work); |
---|
1397 | | -} |
---|
1398 | | - |
---|
1399 | 1512 | static int drbg_prepare_hrng(struct drbg_state *drbg) |
---|
1400 | 1513 | { |
---|
1401 | | - int err; |
---|
1402 | | - |
---|
1403 | 1514 | /* We do not need an HRNG in test mode. */ |
---|
1404 | 1515 | if (list_empty(&drbg->test_data.list)) |
---|
1405 | 1516 | return 0; |
---|
1406 | 1517 | |
---|
1407 | | - INIT_WORK(&drbg->seed_work, drbg_async_seed); |
---|
1408 | | - |
---|
1409 | | - drbg->random_ready.owner = THIS_MODULE; |
---|
1410 | | - drbg->random_ready.func = drbg_schedule_async_seed; |
---|
1411 | | - |
---|
1412 | | - err = add_random_ready_callback(&drbg->random_ready); |
---|
1413 | | - |
---|
1414 | | - switch (err) { |
---|
1415 | | - case 0: |
---|
1416 | | - break; |
---|
1417 | | - |
---|
1418 | | - case -EALREADY: |
---|
1419 | | - err = 0; |
---|
1420 | | - /* fall through */ |
---|
1421 | | - |
---|
1422 | | - default: |
---|
1423 | | - drbg->random_ready.func = NULL; |
---|
1424 | | - return err; |
---|
1425 | | - } |
---|
1426 | | - |
---|
1427 | 1518 | drbg->jent = crypto_alloc_rng("jitterentropy_rng", 0, 0); |
---|
1428 | 1519 | |
---|
1429 | | - /* |
---|
1430 | | - * Require frequent reseeds until the seed source is fully |
---|
1431 | | - * initialized. |
---|
1432 | | - */ |
---|
1433 | | - drbg->reseed_threshold = 50; |
---|
1434 | | - |
---|
1435 | | - return err; |
---|
| 1520 | + return 0; |
---|
1436 | 1521 | } |
---|
1437 | 1522 | |
---|
1438 | 1523 | /* |
---|
.. | .. |
---|
1475 | 1560 | if (!drbg->core) { |
---|
1476 | 1561 | drbg->core = &drbg_cores[coreref]; |
---|
1477 | 1562 | drbg->pr = pr; |
---|
1478 | | - drbg->seeded = false; |
---|
| 1563 | + drbg->seeded = DRBG_SEED_STATE_UNSEEDED; |
---|
1479 | 1564 | drbg->reseed_threshold = drbg_max_requests(drbg); |
---|
1480 | 1565 | |
---|
1481 | 1566 | ret = drbg_alloc_state(drbg); |
---|
.. | .. |
---|
1526 | 1611 | */ |
---|
1527 | 1612 | static int drbg_uninstantiate(struct drbg_state *drbg) |
---|
1528 | 1613 | { |
---|
1529 | | - if (drbg->random_ready.func) { |
---|
1530 | | - del_random_ready_callback(&drbg->random_ready); |
---|
1531 | | - cancel_work_sync(&drbg->seed_work); |
---|
| 1614 | + if (!IS_ERR_OR_NULL(drbg->jent)) |
---|
1532 | 1615 | crypto_free_rng(drbg->jent); |
---|
1533 | | - drbg->jent = NULL; |
---|
1534 | | - } |
---|
| 1616 | + drbg->jent = NULL; |
---|
1535 | 1617 | |
---|
1536 | 1618 | if (drbg->d_ops) |
---|
1537 | 1619 | drbg->d_ops->crypto_fini(drbg); |
---|
.. | .. |
---|
1587 | 1669 | } |
---|
1588 | 1670 | |
---|
1589 | 1671 | sdesc->shash.tfm = tfm; |
---|
1590 | | - sdesc->shash.flags = 0; |
---|
1591 | 1672 | drbg->priv_data = sdesc; |
---|
1592 | 1673 | |
---|
1593 | 1674 | return crypto_shash_alignmask(tfm); |
---|
.. | .. |
---|
1598 | 1679 | struct sdesc *sdesc = (struct sdesc *)drbg->priv_data; |
---|
1599 | 1680 | if (sdesc) { |
---|
1600 | 1681 | crypto_free_shash(sdesc->shash.tfm); |
---|
1601 | | - kzfree(sdesc); |
---|
| 1682 | + kfree_sensitive(sdesc); |
---|
1602 | 1683 | } |
---|
1603 | 1684 | drbg->priv_data = NULL; |
---|
1604 | 1685 | return 0; |
---|
.. | .. |
---|
2039 | 2120 | crypto_unregister_rngs(drbg_algs, (ARRAY_SIZE(drbg_cores) * 2)); |
---|
2040 | 2121 | } |
---|
2041 | 2122 | |
---|
2042 | | -module_init(drbg_init); |
---|
| 2123 | +subsys_initcall(drbg_init); |
---|
2043 | 2124 | module_exit(drbg_exit); |
---|
2044 | 2125 | #ifndef CRYPTO_DRBG_HASH_STRING |
---|
2045 | 2126 | #define CRYPTO_DRBG_HASH_STRING "" |
---|
.. | .. |
---|
2058 | 2139 | CRYPTO_DRBG_HMAC_STRING |
---|
2059 | 2140 | CRYPTO_DRBG_CTR_STRING); |
---|
2060 | 2141 | MODULE_ALIAS_CRYPTO("stdrng"); |
---|
| 2142 | +MODULE_IMPORT_NS(CRYPTO_INTERNAL); |
---|