static int gcm_hash(struct aead_request *req, struct crypto_gcm_req_priv_ctx *pctx) { struct ahash_request *ahreq = &pctx->u.ahreq; struct crypto_gcm_ghash_ctx *gctx = &pctx->ghash_ctx; struct crypto_gcm_ctx *ctx = crypto_tfm_ctx(req->base.tfm); unsigned int remain; crypto_completion_t compl; int err; ahash_request_set_tfm(ahreq, ctx->ghash); ahash_request_set_callback(ahreq, aead_request_flags(req), gcm_hash_init_done, req); err = crypto_ahash_init(ahreq); if (err) return err; remain = gcm_remain(req->assoclen); compl = remain ? gcm_hash_assoc_done : gcm_hash_assoc_remain_done; err = gcm_hash_update(req, pctx, compl, req->assoc, req->assoclen); if (err) return err; if (remain) { err = gcm_hash_remain(req, pctx, remain, gcm_hash_assoc_remain_done); if (err) return err; } remain = gcm_remain(gctx->cryptlen); compl = remain ? gcm_hash_crypt_done : gcm_hash_crypt_remain_done; err = gcm_hash_update(req, pctx, compl, gctx->src, gctx->cryptlen); if (err) return err; if (remain) { err = gcm_hash_remain(req, pctx, remain, gcm_hash_crypt_remain_done); if (err) return err; } err = gcm_hash_len(req, pctx); if (err) return err; err = gcm_hash_final(req, pctx); if (err) return err; return 0; }
static void __gcm_hash_assoc_done(struct aead_request *req, int err) { struct crypto_gcm_req_priv_ctx *pctx = crypto_gcm_reqctx(req); unsigned int remain; if (!err) { remain = gcm_remain(req->assoclen); BUG_ON(!remain); err = gcm_hash_remain(req, pctx, remain, gcm_hash_assoc_remain_done); if (err == -EINPROGRESS || err == -EBUSY) return; } __gcm_hash_assoc_remain_done(req, err); }
static void gcm_hash_crypt_done(struct crypto_async_request *areq, int err) { struct aead_request *req = areq->data; struct crypto_gcm_req_priv_ctx *pctx = crypto_gcm_reqctx(req); struct crypto_gcm_ghash_ctx *gctx = &pctx->ghash_ctx; unsigned int remain; if (!err) { remain = gcm_remain(gctx->cryptlen); BUG_ON(!remain); err = gcm_hash_remain(req, pctx, remain, gcm_hash_crypt_remain_done); if (err == -EINPROGRESS || err == -EBUSY) return; } gcm_hash_crypt_remain_done(areq, err); }
static void __gcm_hash_init_done(struct aead_request *req, int err) { struct crypto_gcm_req_priv_ctx *pctx = crypto_gcm_reqctx(req); crypto_completion_t compl; unsigned int remain = 0; if (!err && req->assoclen) { remain = gcm_remain(req->assoclen); compl = remain ? gcm_hash_assoc_done : gcm_hash_assoc_remain_done; err = gcm_hash_update(req, pctx, compl, req->assoc, req->assoclen); if (err == -EINPROGRESS || err == -EBUSY) return; } if (remain) __gcm_hash_assoc_done(req, err); else __gcm_hash_assoc_remain_done(req, err); }
static void __gcm_hash_assoc_remain_done(struct aead_request *req, int err) { struct crypto_gcm_req_priv_ctx *pctx = crypto_gcm_reqctx(req); struct crypto_gcm_ghash_ctx *gctx = &pctx->ghash_ctx; crypto_completion_t complete; unsigned int remain = 0; if (!err && gctx->cryptlen) { remain = gcm_remain(gctx->cryptlen); complete = remain ? gcm_hash_crypt_done : gcm_hash_crypt_remain_done; err = gcm_hash_update(req, pctx, complete, gctx->src, gctx->cryptlen); if (err == -EINPROGRESS || err == -EBUSY) return; } if (remain) __gcm_hash_crypt_done(req, err); else __gcm_hash_crypt_remain_done(req, err); }