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.
Showing the changes to crypto/algapi.c (1 of 5 files). Show all
Unified · Split
| @@ -328,8 +328,16 @@ void crypto_alg_tested(const char *name, int err) · 327 unmodified lines | ||
| 328 | 328 | found: |
| 329 | 329 | q->cra_flags |= CRYPTO_ALG_DEAD; |
| 330 | 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 | 338 | goto complete; |
| 339 | + else | |
| 340 | + alg->cra_flags &= ~CRYPTO_ALG_FIPS_INTERNAL; | |
| 333 | 341 | |
| 334 | 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 | 619 | struct crypto_larval *larval; |
| 612 | 620 | struct crypto_spawn *spawn; |
| 621 | + u32 fips_internal = 0; | |
| 613 | 622 | int err; |
| 614 | 623 | |
| 615 | 624 | err = crypto_check_alg(&inst->alg); |
| @@ -632,11 +641,15 @@ int crypto_register_instance(struct crypto_template *tmpl, · 16 unmodified lines | ||
| 632 | 641 | spawn->inst = inst; |
| 633 | 642 | spawn->registered = true; |
| 634 | 643 | |
| 644 | + fips_internal |= spawn->alg->cra_flags; | |
| 645 | + | |
| 635 | 646 | crypto_mod_put(spawn->alg); |
| 636 | 647 | |
| 637 | 648 | spawn = next; |
| 638 | 649 | } |
| 639 | 650 | |
| 651 | + inst->alg.cra_flags |= (fips_internal & CRYPTO_ALG_FIPS_INTERNAL); | |
| 652 | + | |
| 640 | 653 | larval = __crypto_register_alg(&inst->alg); |
| 641 | 654 | if (IS_ERR(larval)) |
| 642 | 655 | goto unlock; |
| @@ -689,7 +702,8 @@ int crypto_grab_spawn(struct crypto_spawn *spawn, struct crypto_instance *inst, · 46 unmodified lines | ||
| 689 | 702 | if (IS_ERR(name)) |
| 690 | 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 | 707 | if (IS_ERR(alg)) |
| 694 | 708 | return PTR_ERR(alg); |
| 695 | 709 | |