mirror of
https://github.com/nxp-imx/linux-imx.git
synced 2025-07-10 11:25:18 +02:00
ANDROID: fips140: add service indicators
To satisfy the FIPS 140-3 "service indicators" requirement, add a function which checks whether the given algorithm is "approved" or not. Note that this function is a bit different from the module's other APIs in that it is an exported symbol rather than a registration-based API. This avoids needing to make kernel/KMI changes, so I think we should do it this way if possible, given that it's unlikely this function will be used in practice outside of the lab test. Built-in code can still call this function via symbol_get() if it really wants to. Bug: 188620248 Change-Id: I26c976258fa9446b34eb189bba7154142d85da16 Signed-off-by: Eric Biggers <ebiggers@google.com> (cherry picked from commit fe4b8d3c687efcf27064e472730291edbd81dad6)
This commit is contained in:
parent
b9066e59a5
commit
64d769e53f
|
@ -14,6 +14,8 @@
|
|||
* don't need to meet these requirements.
|
||||
*/
|
||||
|
||||
#undef __DISABLE_EXPORTS
|
||||
|
||||
#include <linux/ctype.h>
|
||||
#include <linux/module.h>
|
||||
#include <crypto/aead.h>
|
||||
|
@ -86,34 +88,37 @@ const u8 *__rodata_start = &__fips140_rodata_start;
|
|||
* When adding a new algorithm here, make sure to consider whether it needs a
|
||||
* self-test added to fips140_selftests[] as well.
|
||||
*/
|
||||
static const char * const fips140_algorithms[] __initconst = {
|
||||
"aes",
|
||||
static const struct {
|
||||
const char *name;
|
||||
bool approved;
|
||||
} fips140_algs_to_replace[] = {
|
||||
{"aes", true},
|
||||
|
||||
"cmac(aes)",
|
||||
"ecb(aes)",
|
||||
{"cmac(aes)", true},
|
||||
{"ecb(aes)", true},
|
||||
|
||||
"cbc(aes)",
|
||||
"cts(cbc(aes))",
|
||||
"ctr(aes)",
|
||||
"xts(aes)",
|
||||
"gcm(aes)",
|
||||
{"cbc(aes)", true},
|
||||
{"cts(cbc(aes))", true},
|
||||
{"ctr(aes)", true},
|
||||
{"xts(aes)", true},
|
||||
{"gcm(aes)", false},
|
||||
|
||||
"hmac(sha1)",
|
||||
"hmac(sha224)",
|
||||
"hmac(sha256)",
|
||||
"hmac(sha384)",
|
||||
"hmac(sha512)",
|
||||
"sha1",
|
||||
"sha224",
|
||||
"sha256",
|
||||
"sha384",
|
||||
"sha512",
|
||||
{"hmac(sha1)", true},
|
||||
{"hmac(sha224)", true},
|
||||
{"hmac(sha256)", true},
|
||||
{"hmac(sha384)", true},
|
||||
{"hmac(sha512)", true},
|
||||
{"sha1", true},
|
||||
{"sha224", true},
|
||||
{"sha256", true},
|
||||
{"sha384", true},
|
||||
{"sha512", true},
|
||||
|
||||
"stdrng",
|
||||
"jitterentropy_rng",
|
||||
{"stdrng", true},
|
||||
{"jitterentropy_rng", false},
|
||||
};
|
||||
|
||||
static bool __init is_fips140_algo(struct crypto_alg *alg)
|
||||
static bool __init fips140_should_unregister_alg(struct crypto_alg *alg)
|
||||
{
|
||||
int i;
|
||||
|
||||
|
@ -124,12 +129,48 @@ static bool __init is_fips140_algo(struct crypto_alg *alg)
|
|||
if (alg->cra_flags & CRYPTO_ALG_ASYNC)
|
||||
return false;
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(fips140_algorithms); i++)
|
||||
if (!strcmp(alg->cra_name, fips140_algorithms[i]))
|
||||
for (i = 0; i < ARRAY_SIZE(fips140_algs_to_replace); i++) {
|
||||
if (!strcmp(alg->cra_name, fips140_algs_to_replace[i].name))
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/*
|
||||
* FIPS 140-3 service indicators. FIPS 140-3 requires that all services
|
||||
* "provide an indicator when the service utilises an approved cryptographic
|
||||
* algorithm, security function or process in an approved manner". What this
|
||||
* means is very debatable, even with the help of the FIPS 140-3 Implementation
|
||||
* Guidance document. However, it was decided that a function that takes in an
|
||||
* algorithm name and returns whether that algorithm is approved or not will
|
||||
* meet this requirement. Note, this relies on some properties of the module:
|
||||
*
|
||||
* - The module doesn't distinguish between "services" and "algorithms"; its
|
||||
* services are simply its algorithms.
|
||||
*
|
||||
* - The status of an approved algorithm is never non-approved, since (a) the
|
||||
* module doesn't support operating in a non-approved mode, such as a mode
|
||||
* where the self-tests are skipped; (b) there are no cases where the module
|
||||
* supports non-approved settings for approved algorithms, e.g.
|
||||
* non-approved key sizes; and (c) this function isn't available to be
|
||||
* called until the module_init function has completed, so it's guaranteed
|
||||
* that the self-tests and integrity check have already passed.
|
||||
*
|
||||
* - The module does support some non-approved algorithms, so a single static
|
||||
* indicator ("return true;") would not be acceptable.
|
||||
*/
|
||||
bool fips140_is_approved_service(const char *name)
|
||||
{
|
||||
size_t i;
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(fips140_algs_to_replace); i++) {
|
||||
if (!strcmp(name, fips140_algs_to_replace[i].name))
|
||||
return fips140_algs_to_replace[i].approved;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(fips140_is_approved_service);
|
||||
|
||||
static LIST_HEAD(existing_live_algos);
|
||||
|
||||
/*
|
||||
|
@ -180,7 +221,7 @@ static void __init unregister_existing_fips140_algos(void)
|
|||
* that new users won't use them.
|
||||
*/
|
||||
list_for_each_entry_safe(alg, tmp, &crypto_alg_list, cra_list) {
|
||||
if (!is_fips140_algo(alg))
|
||||
if (!fips140_should_unregister_alg(alg))
|
||||
continue;
|
||||
if (refcount_read(&alg->cra_refcnt) == 1) {
|
||||
/*
|
||||
|
|
|
@ -21,4 +21,6 @@ extern struct task_struct *fips140_init_thread;
|
|||
|
||||
bool __init __must_check fips140_run_selftests(void);
|
||||
|
||||
bool fips140_is_approved_service(const char *name);
|
||||
|
||||
#endif /* _CRYPTO_FIPS140_MODULE_H */
|
||||
|
|
Loading…
Reference in New Issue
Block a user