crypto/api.c

Source file repositories/reference/linux-study-clean/crypto/api.c

File Facts

System
Linux kernel
Corpus path
crypto/api.c
Extension
.c
Size
16240 bytes
Lines
688
Domain
Kernel Services
Bucket
crypto
Inferred role
Kernel Services: exported/initcall integration point
Status
integration implementation candidate

Why This File Exists

Shared kernel service surface used by multiple subsystems, including helpers, cryptography, virtualization support, and async I/O infrastructure.

Dependency Surface

Detected Declarations

Annotated Snippet

else if (!time_left) {
		if (crypto_is_test_larval(larval))
			crypto_larval_kill(larval);
		alg = ERR_PTR(-ETIMEDOUT);
	} else if (!alg || PTR_ERR(alg) == -EEXIST) {
		int err = alg ? -EEXIST : -EAGAIN;

		/*
		 * EEXIST is expected because two probes can be scheduled
		 * at the same time with one using alg_name and the other
		 * using driver_name.  Do a re-lookup but do not retry in
		 * case we hit a quirk like gcm_base(ctr(aes),...) which
		 * will never match.
		 */
		alg = &larval->alg;
		alg = crypto_alg_lookup(alg->cra_name, type, mask) ?:
		      ERR_PTR(err);
	} else if (IS_ERR(alg))
		;
	else if (crypto_is_test_larval(larval) &&
		 !(alg->cra_flags & CRYPTO_ALG_TESTED))
		alg = ERR_PTR(-EAGAIN);
	else if (alg->cra_flags & CRYPTO_ALG_FIPS_INTERNAL)
		alg = ERR_PTR(-EAGAIN);
	else if (!crypto_mod_get(alg))
		alg = ERR_PTR(-EAGAIN);
	crypto_mod_put(&larval->alg);

	if (!IS_ERR(alg) && crypto_is_larval(alg))
		goto again;

	return alg;
}

static struct crypto_alg *crypto_alg_lookup(const char *name, u32 type,
					    u32 mask)
{
	const u32 fips = CRYPTO_ALG_FIPS_INTERNAL;
	struct crypto_alg *alg;
	u32 test = 0;

	if (!((type | mask) & CRYPTO_ALG_TESTED))
		test |= CRYPTO_ALG_TESTED;

	down_read(&crypto_alg_sem);
	alg = __crypto_alg_lookup(name, (type | test) & ~fips,
				  (mask | test) & ~fips);
	if (alg) {
		if (((type | mask) ^ fips) & fips)
			mask |= fips;
		mask &= fips;

		if (!crypto_is_larval(alg) &&
		    ((type ^ alg->cra_flags) & mask)) {
			/* Algorithm is disallowed in FIPS mode. */
			crypto_mod_put(alg);
			alg = ERR_PTR(-ENOENT);
		}
	} else if (test) {
		alg = __crypto_alg_lookup(name, type, mask);
		if (alg && !crypto_is_larval(alg)) {
			/* Test failed */
			crypto_mod_put(alg);
			alg = ERR_PTR(-ELIBBAD);
		}
	}
	up_read(&crypto_alg_sem);

	return alg;
}

static struct crypto_alg *crypto_larval_lookup(const char *name, u32 type,
					       u32 mask)
{
	struct crypto_alg *alg;

	if (!name)
		return ERR_PTR(-ENOENT);

	type &= ~(CRYPTO_ALG_LARVAL | CRYPTO_ALG_DEAD);
	mask &= ~(CRYPTO_ALG_LARVAL | CRYPTO_ALG_DEAD);

	alg = crypto_alg_lookup(name, type, mask);
	if (!alg && !(mask & CRYPTO_NOLOAD)) {
		request_module("crypto-%s", name);

		if (!((type ^ CRYPTO_ALG_NEED_FALLBACK) & mask &
		      CRYPTO_ALG_NEED_FALLBACK))
			request_module("crypto-%s-all", name);

Annotation

Implementation Notes