History

crypto: api - allow algs only in specific constructions in FIPS mode

Currently we do not distinguish between algorithms that fail on the self-test vs. those which are disabled in FIPS mode (not allowed). Both are marked as having failed the self-test. Recently the need arose to allow the usage of certain algorithms only as arguments to specific template instantiations in FIPS mode. For example, standalone "dh" must be blocked, but e.g. "ffdhe2048(dh)" is allowed. Other potential use cases include "cbcmac(aes)", which must only be used with ccm(), or "ghash", which must be used only for gcm(). This patch allows this scenario by adding a new flag FIPS_INTERNAL to indicate those algorithms that are not FIPS-allowed. They can then be used as template arguments only, i.e. when looked up via crypto_grab_spawn() to be more specific. The FIPS_INTERNAL bit gets propagated upwards recursively into the surrounding template instances, until the construction eventually matches an explicit testmgr entry with ->fips_allowed being set, if any. The behaviour to skip !->fips_allowed self-test executions in FIPS mode will be retained. Note that this effectively means that FIPS_INTERNAL algorithms are handled very similarly to the INTERNAL ones in this regard. It is expected that the FIPS_INTERNAL algorithms will receive sufficient testing when the larger constructions they're a part of, if any, get exercised by testmgr. Note that as a side-effect of this patch algorithms which are not FIPS-allowed will now return ENOENT instead of ELIBBAD. Hopefully this is not an issue as some people were relying on this already.

Nicolai Stange committed 4 years ago

Commit d6097b81 parent c8e82365 files · +63 −10Browse files

Unified · Split

5 files
  1. crypto/algapi.c +16 −2
  2. crypto/api.c +17 −2
  3. crypto/tcrypt.c +2 −2
  4. crypto/testmgr.c +19 −4
  5. include/linux/crypto.h +9 −0
crypto/algapi.c+16−2
@@ -328,8 +328,16 @@ void crypto_alg_tested(const char *name, int err) · 327 unmodified lines
328found:328found:
329 q->cra_flags |= CRYPTO_ALG_DEAD;329 q->cra_flags |= CRYPTO_ALG_DEAD;
330 alg = test->adult;330 alg = test->adult;
331 if (err || list_empty(&alg->cra_list))331
332 if (list_empty(&alg->cra_list))
333 goto complete;
334
335 if (err == -ECANCELED)
336 alg->cra_flags |= CRYPTO_ALG_FIPS_INTERNAL;
337 else if (err)
332 goto complete;338 goto complete;
339 else
340 alg->cra_flags &= ~CRYPTO_ALG_FIPS_INTERNAL;
333 341
334 alg->cra_flags |= CRYPTO_ALG_TESTED;342 alg->cra_flags |= CRYPTO_ALG_TESTED;
335 343
@@ -610,6 +618,7 @@ int crypto_register_instance(struct crypto_template *tmpl, · 274 unmodified lines
610{618{
611 struct crypto_larval *larval;619 struct crypto_larval *larval;
612 struct crypto_spawn *spawn;620 struct crypto_spawn *spawn;
621 u32 fips_internal = 0;
613 int err;622 int err;
614 623
615 err = crypto_check_alg(&inst->alg);624 err = crypto_check_alg(&inst->alg);
@@ -632,11 +641,15 @@ int crypto_register_instance(struct crypto_template *tmpl, · 16 unmodified lines
632 spawn->inst = inst;641 spawn->inst = inst;
633 spawn->registered = true;642 spawn->registered = true;
634 643
644 fips_internal |= spawn->alg->cra_flags;
645
635 crypto_mod_put(spawn->alg);646 crypto_mod_put(spawn->alg);
636 647
637 spawn = next;648 spawn = next;
638 }649 }
639 650
651 inst->alg.cra_flags |= (fips_internal & CRYPTO_ALG_FIPS_INTERNAL);
652
640 larval = __crypto_register_alg(&inst->alg);653 larval = __crypto_register_alg(&inst->alg);
641 if (IS_ERR(larval))654 if (IS_ERR(larval))
642 goto unlock;655 goto unlock;
@@ -689,7 +702,8 @@ int crypto_grab_spawn(struct crypto_spawn *spawn, struct crypto_instance *inst, · 46 unmodified lines
689 if (IS_ERR(name))702 if (IS_ERR(name))
690 return PTR_ERR(name);703 return PTR_ERR(name);
691 704
692 alg = crypto_find_alg(name, spawn->frontend, type, mask);705 alg = crypto_find_alg(name, spawn->frontend,
706 type | CRYPTO_ALG_FIPS_INTERNAL, mask);
693 if (IS_ERR(alg))707 if (IS_ERR(alg))
694 return PTR_ERR(alg);708 return PTR_ERR(alg);
695 709
crypto/api.c+17−2
@@ -223,6 +223,8 @@ static struct crypto_alg *crypto_larval_wait(struct crypto_alg *alg) · 222 unmodified lines
223 else if (crypto_is_test_larval(larval) &&223 else if (crypto_is_test_larval(larval) &&
224 !(alg->cra_flags & CRYPTO_ALG_TESTED))224 !(alg->cra_flags & CRYPTO_ALG_TESTED))
225 alg = ERR_PTR(-EAGAIN);225 alg = ERR_PTR(-EAGAIN);
226 else if (alg->cra_flags & CRYPTO_ALG_FIPS_INTERNAL)
227 alg = ERR_PTR(-EAGAIN);
226 else if (!crypto_mod_get(alg))228 else if (!crypto_mod_get(alg))
227 alg = ERR_PTR(-EAGAIN);229 alg = ERR_PTR(-EAGAIN);
228 crypto_mod_put(&larval->alg);230 crypto_mod_put(&larval->alg);
@@ -233,6 +235,7 @@ static struct crypto_alg *crypto_larval_wait(struct crypto_alg *alg) · 4 unmodified lines
233static struct crypto_alg *crypto_alg_lookup(const char *name, u32 type,235static struct crypto_alg *crypto_alg_lookup(const char *name, u32 type,
234 u32 mask)236 u32 mask)
235{237{
238 const u32 fips = CRYPTO_ALG_FIPS_INTERNAL;
236 struct crypto_alg *alg;239 struct crypto_alg *alg;
237 u32 test = 0;240 u32 test = 0;
238 241
@@ -240,8 +243,20 @@ static struct crypto_alg *crypto_alg_lookup(const char *name, u32 type, · 1 unmodified line
240 test |= CRYPTO_ALG_TESTED;243 test |= CRYPTO_ALG_TESTED;
241 244
242 down_read(&crypto_alg_sem);245 down_read(&crypto_alg_sem);
243 alg = __crypto_alg_lookup(name, type | test, mask | test);246 alg = __crypto_alg_lookup(name, (type | test) & ~fips,
244 if (!alg && test) {247 (mask | test) & ~fips);
248 if (alg) {
249 if (((type | mask) ^ fips) & fips)
250 mask |= fips;
251 mask &= fips;
252
253 if (!crypto_is_larval(alg) &&
254 ((type ^ alg->cra_flags) & mask)) {
255 /* Algorithm is disallowed in FIPS mode. */
256 crypto_mod_put(alg);
257 alg = ERR_PTR(-ENOENT);
258 }
259 } else if (test) {
245 alg = __crypto_alg_lookup(name, type, mask);260 alg = __crypto_alg_lookup(name, type, mask);
246 if (alg && !crypto_is_larval(alg)) {261 if (alg && !crypto_is_larval(alg)) {
247 /* Test failed */262 /* Test failed */
crypto/tcrypt.c+2−2
@@ -1473,8 +1473,8 @@ static inline int tcrypt_test(const char *alg) · 1472 unmodified lines
1473 pr_debug("testing %s\n", alg);1473 pr_debug("testing %s\n", alg);
1474 1474
1475 ret = alg_test(alg, alg, 0, 0);1475 ret = alg_test(alg, alg, 0, 0);
1476 /* non-fips algs return -EINVAL in fips mode */1476 /* non-fips algs return -EINVAL or -ECANCELED in fips mode */
1477 if (fips_enabled && ret == -EINVAL)1477 if (fips_enabled && (ret == -EINVAL || ret == -ECANCELED))
1478 ret = 0;1478 ret = 0;
1479 return ret;1479 return ret;
1480}1480}
crypto/testmgr.c+19−4
@@ -5650,6 +5650,13 @@ static int alg_find_test(const char *alg) · 5649 unmodified lines
5650 return -1;5650 return -1;
5651}5651}
5652 5652
5653static int alg_fips_disabled(const char *driver, const char *alg)
5654{
5655 pr_info("alg: %s (%s) is disabled due to FIPS\n", alg, driver);
5656
5657 return -ECANCELED;
5658}
5659
5653int alg_test(const char *driver, const char *alg, u32 type, u32 mask)5660int alg_test(const char *driver, const char *alg, u32 type, u32 mask)
5654{5661{
5655 int i;5662 int i;
@@ -5686,9 +5693,13 @@ int alg_test(const char *driver, const char *alg, u32 type, u32 mask) · 30 unmodified lines
5686 if (i < 0 && j < 0)5693 if (i < 0 && j < 0)
5687 goto notest;5694 goto notest;
5688 5695
5689 if (fips_enabled && ((i >= 0 && !alg_test_descs[i].fips_allowed) ||5696 if (fips_enabled) {
5690 (j >= 0 && !alg_test_descs[j].fips_allowed)))5697 if (j >= 0 && !alg_test_descs[j].fips_allowed)
5691 goto non_fips_alg;5698 return -EINVAL;
5699
5700 if (i >= 0 && !alg_test_descs[i].fips_allowed)
5701 goto non_fips_alg;
5702 }
5692 5703
5693 rc = 0;5704 rc = 0;
5694 if (i >= 0)5705 if (i >= 0)
@@ -5718,9 +5729,13 @@ test_done: · 23 unmodified lines
5718 5729
5719notest:5730notest:
5720 printk(KERN_INFO "alg: No test for %s (%s)\n", alg, driver);5731 printk(KERN_INFO "alg: No test for %s (%s)\n", alg, driver);
5732
5733 if (type & CRYPTO_ALG_FIPS_INTERNAL)
5734 return alg_fips_disabled(driver, alg);
5735
5721 return 0;5736 return 0;
5722non_fips_alg:5737non_fips_alg:
5723 return -EINVAL;5738 return alg_fips_disabled(driver, alg);
5724}5739}
5725 5740
5726#endif /* CONFIG_CRYPTO_MANAGER_DISABLE_TESTS */5741#endif /* CONFIG_CRYPTO_MANAGER_DISABLE_TESTS */
include/linux/crypto.h+9−0
@@ -132,6 +132,15 @@ · 131 unmodified lines
132 */132 */
133#define CRYPTO_ALG_ALLOCATES_MEMORY 0x00010000133#define CRYPTO_ALG_ALLOCATES_MEMORY 0x00010000
134 134
135/*
136 * Mark an algorithm as a service implementation only usable by a
137 * template and never by a normal user of the kernel crypto API.
138 * This is intended to be used by algorithms that are themselves
139 * not FIPS-approved but may instead be used to implement parts of
140 * a FIPS-approved algorithm (e.g., dh vs. ffdhe2048(dh)).
141 */
142#define CRYPTO_ALG_FIPS_INTERNAL 0x00020000
143
135/*144/*
136 * Transform masks and values (for crt_flags).145 * Transform masks and values (for crt_flags).
137 */146 */

Keyboard shortcuts

General

Show keyboard shortcuts
?
Focus the current search
/

Issues and pull requests

Open filters
f

Issues, pull requests and Inbox

Select next item
j↓
Select previous item
k↑
Open selected item
Enter
Dismiss filters or clear selection
Esc

Repository code

Go to file
t