crypto/ahash.c

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

File Facts

System
Linux kernel
Corpus path
crypto/ahash.c
Extension
.c
Size
25344 bytes
Lines
1024
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

if (unlikely(err)) {
			crypto_ahash_set_flags(tfm,
					       crypto_shash_get_flags(shash) &
					       CRYPTO_TFM_NEED_KEY);
			return err;
		}
	} else {
		struct ahash_alg *alg = crypto_ahash_alg(tfm);
		int err;

		err = alg->setkey(tfm, key, keylen);
		if (!err && crypto_ahash_need_fallback(tfm))
			err = crypto_ahash_setkey(crypto_ahash_fb(tfm),
						  key, keylen);
		if (unlikely(err)) {
			ahash_set_needkey(tfm, alg);
			return err;
		}
	}
	crypto_ahash_clear_flags(tfm, CRYPTO_TFM_NEED_KEY);
	return 0;
}
EXPORT_SYMBOL_GPL(crypto_ahash_setkey);

static int ahash_do_req_chain(struct ahash_request *req,
			      int (*const *op)(struct ahash_request *req))
{
	struct crypto_ahash *tfm = crypto_ahash_reqtfm(req);
	int err;

	if (crypto_ahash_req_virt(tfm) || !ahash_request_isvirt(req))
		return (*op)(req);

	if (crypto_ahash_statesize(tfm) > HASH_MAX_STATESIZE)
		return -ENOSYS;

	if (!crypto_ahash_need_fallback(tfm))
		return -ENOSYS;

	if (crypto_hash_no_export_core(tfm))
		return -ENOSYS;

	{
		u8 state[HASH_MAX_STATESIZE];

		if (op == &crypto_ahash_alg(tfm)->digest) {
			ahash_request_set_tfm(req, crypto_ahash_fb(tfm));
			err = crypto_ahash_digest(req);
			goto out_no_state;
		}

		err = crypto_ahash_export(req, state);
		ahash_request_set_tfm(req, crypto_ahash_fb(tfm));
		err = err ?: crypto_ahash_import(req, state);

		if (op == &crypto_ahash_alg(tfm)->finup) {
			err = err ?: crypto_ahash_finup(req);
			goto out_no_state;
		}

		err = err ?:
		      crypto_ahash_update(req) ?:
		      crypto_ahash_export(req, state);

		ahash_request_set_tfm(req, tfm);
		return err ?: crypto_ahash_import(req, state);

out_no_state:
		ahash_request_set_tfm(req, tfm);
		return err;
	}
}

int crypto_ahash_init(struct ahash_request *req)
{
	struct crypto_ahash *tfm = crypto_ahash_reqtfm(req);

	if (likely(tfm->using_shash))
		return crypto_shash_init(prepare_shash_desc(req, tfm));
	if (crypto_ahash_get_flags(tfm) & CRYPTO_TFM_NEED_KEY)
		return -ENOKEY;
	if (ahash_req_on_stack(req) && ahash_is_async(tfm))
		return -EAGAIN;
	if (crypto_ahash_block_only(tfm)) {
		u8 *buf = ahash_request_ctx(req);

		buf += crypto_ahash_reqsize(tfm) - 1;
		*buf = 0;
	}
	return crypto_ahash_alg(tfm)->init(req);

Annotation

Implementation Notes