+static int hash_async_setkey(struct crypto_ahash *tfm_async, const u8 *key,
+ unsigned int keylen)
+{
+ struct crypto_tfm *tfm = crypto_ahash_tfm(tfm_async);
+ struct crypto_hash *tfm_hash = __crypto_hash_cast(tfm);
+ struct hash_alg *alg = &tfm->__crt_alg->cra_hash;
+
+ return alg->setkey(tfm_hash, key, keylen);
+}
+
+static int hash_async_init(struct ahash_request *req)
+{
+ struct crypto_tfm *tfm = req->base.tfm;
+ struct hash_alg *alg = &tfm->__crt_alg->cra_hash;
+ struct hash_desc desc = {
+ .tfm = __crypto_hash_cast(tfm),
+ .flags = req->base.flags,
+ };
+
+ return alg->init(&desc);
+}
+
+static int hash_async_update(struct ahash_request *req)
+{
+ struct crypto_tfm *tfm = req->base.tfm;
+ struct hash_alg *alg = &tfm->__crt_alg->cra_hash;
+ struct hash_desc desc = {
+ .tfm = __crypto_hash_cast(tfm),
+ .flags = req->base.flags,
+ };
+
+ return alg->update(&desc, req->src, req->nbytes);
+}
+
+static int hash_async_final(struct ahash_request *req)
+{
+ struct crypto_tfm *tfm = req->base.tfm;
+ struct hash_alg *alg = &tfm->__crt_alg->cra_hash;
+ struct hash_desc desc = {
+ .tfm = __crypto_hash_cast(tfm),
+ .flags = req->base.flags,
+ };
+
+ return alg->final(&desc, req->result);
+}
+
+static int hash_async_digest(struct ahash_request *req)
+{
+ struct crypto_tfm *tfm = req->base.tfm;
+ struct hash_alg *alg = &tfm->__crt_alg->cra_hash;
+ struct hash_desc desc = {
+ .tfm = __crypto_hash_cast(tfm),
+ .flags = req->base.flags,
+ };
+
+ return alg->digest(&desc, req->src, req->nbytes, req->result);
+}
+
+static int crypto_init_hash_ops_async(struct crypto_tfm *tfm)
+{
+ struct ahash_tfm *crt = &tfm->crt_ahash;
+ struct hash_alg *alg = &tfm->__crt_alg->cra_hash;
+
+ crt->init = hash_async_init;
+ crt->update = hash_async_update;
+ crt->final = hash_async_final;
+ crt->digest = hash_async_digest;
+ crt->setkey = hash_async_setkey;
+ crt->digestsize = alg->digestsize;
+
+ return 0;
+}
+
+static int crypto_init_hash_ops_sync(struct crypto_tfm *tfm)