diff options
Diffstat (limited to 'crypto/aead.c')
-rw-r--r-- | crypto/aead.c | 58 |
1 files changed, 56 insertions, 2 deletions
diff --git a/crypto/aead.c b/crypto/aead.c index 717b2f6ec9bb..c2bf3b313354 100644 --- a/crypto/aead.c +++ b/crypto/aead.c @@ -13,6 +13,7 @@ */ #include <crypto/internal/aead.h> +#include <crypto/scatterwalk.h> #include <linux/err.h> #include <linux/init.h> #include <linux/kernel.h> @@ -85,6 +86,59 @@ int crypto_aead_setauthsize(struct crypto_aead *tfm, unsigned int authsize) } EXPORT_SYMBOL_GPL(crypto_aead_setauthsize); +struct aead_old_request { + struct scatterlist srcbuf[2]; + struct scatterlist dstbuf[2]; + struct aead_request subreq; +}; + +unsigned int crypto_aead_reqsize(struct crypto_aead *tfm) +{ + return tfm->reqsize + sizeof(struct aead_old_request); +} +EXPORT_SYMBOL_GPL(crypto_aead_reqsize); + +static int old_crypt(struct aead_request *req, + int (*crypt)(struct aead_request *req)) +{ + struct aead_old_request *nreq = aead_request_ctx(req); + struct crypto_aead *aead = crypto_aead_reqtfm(req); + struct scatterlist *src, *dst; + + if (req->old) + return crypt(req); + + src = scatterwalk_ffwd(nreq->srcbuf, req->src, + req->assoclen + req->cryptoff); + dst = scatterwalk_ffwd(nreq->dstbuf, req->dst, + req->assoclen + req->cryptoff); + + aead_request_set_tfm(&nreq->subreq, aead); + aead_request_set_callback(&nreq->subreq, aead_request_flags(req), + req->base.complete, req->base.data); + aead_request_set_crypt(&nreq->subreq, src, dst, req->cryptlen, + req->iv); + aead_request_set_assoc(&nreq->subreq, req->src, req->assoclen); + + return crypt(&nreq->subreq); +} + +static int old_encrypt(struct aead_request *req) +{ + struct crypto_aead *aead = crypto_aead_reqtfm(req); + struct aead_alg *alg = crypto_aead_alg(aead); + + return old_crypt(req, alg->encrypt); +} + +static int old_decrypt(struct aead_request *req) +{ + struct crypto_aead *aead = crypto_aead_reqtfm(req); + struct aead_alg *alg = crypto_aead_alg(aead); + + return old_crypt(req, alg->decrypt); +} + static int no_givcrypt(struct aead_givcrypt_request *req) { return -ENOSYS; @@ -98,8 +152,8 @@ static int crypto_aead_init_tfm(struct crypto_tfm *tfm) if (max(alg->maxauthsize, alg->ivsize) > PAGE_SIZE / 8) return -EINVAL; - crt->encrypt = alg->encrypt; - crt->decrypt = alg->decrypt; + crt->encrypt = old_encrypt; + crt->decrypt = old_decrypt; if (alg->ivsize) { crt->givencrypt = alg->givencrypt ?: no_givcrypt; crt->givdecrypt = alg->givdecrypt ?: no_givcrypt; |