summaryrefslogtreecommitdiffstats
path: root/crypto/aead.c
diff options
context:
space:
mode:
authorHerbert Xu <herbert@gondor.apana.org.au>2015-05-21 03:11:01 -0400
committerHerbert Xu <herbert@gondor.apana.org.au>2015-05-21 23:25:51 -0400
commit996d98d85ccc27d9c592ad7dc1371c60cd6585cc (patch)
treea7f9c96dc0ec10e5761495fc2116d4d3364705bd /crypto/aead.c
parentfc42bcba97bae738f905b83741134a63af7e6c02 (diff)
crypto: aead - Add new interface with single SG list
The primary user of AEAD, IPsec includes the IV in the AD in most cases, except where it is implicitly authenticated by the underlying algorithm. The way it is currently implemented is a hack because we pass the data in piecemeal and the underlying algorithms try to stitch them back up into one piece. This is why this patch is adding a new interface that allows a single SG list to be passed in that contains everything so the algorithm implementors do not have to stitch. The new interface accepts a single source SG list and a single destination SG list. Both must be laid out as follows: AD, skipped data, plain/cipher text, ICV The ICV is not present from the source during encryption and from the destination during decryption. For the top-level IPsec AEAD algorithm the plain/cipher text will contain the generated (or received) IV. Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>
Diffstat (limited to 'crypto/aead.c')
-rw-r--r--crypto/aead.c58
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 @@
13 */ 13 */
14 14
15#include <crypto/internal/aead.h> 15#include <crypto/internal/aead.h>
16#include <crypto/scatterwalk.h>
16#include <linux/err.h> 17#include <linux/err.h>
17#include <linux/init.h> 18#include <linux/init.h>
18#include <linux/kernel.h> 19#include <linux/kernel.h>
@@ -85,6 +86,59 @@ int crypto_aead_setauthsize(struct crypto_aead *tfm, unsigned int authsize)
85} 86}
86EXPORT_SYMBOL_GPL(crypto_aead_setauthsize); 87EXPORT_SYMBOL_GPL(crypto_aead_setauthsize);
87 88
89struct aead_old_request {
90 struct scatterlist srcbuf[2];
91 struct scatterlist dstbuf[2];
92 struct aead_request subreq;
93};
94
95unsigned int crypto_aead_reqsize(struct crypto_aead *tfm)
96{
97 return tfm->reqsize + sizeof(struct aead_old_request);
98}
99EXPORT_SYMBOL_GPL(crypto_aead_reqsize);
100
101static int old_crypt(struct aead_request *req,
102 int (*crypt)(struct aead_request *req))
103{
104 struct aead_old_request *nreq = aead_request_ctx(req);
105 struct crypto_aead *aead = crypto_aead_reqtfm(req);
106 struct scatterlist *src, *dst;
107
108 if (req->old)
109 return crypt(req);
110
111 src = scatterwalk_ffwd(nreq->srcbuf, req->src,
112 req->assoclen + req->cryptoff);
113 dst = scatterwalk_ffwd(nreq->dstbuf, req->dst,
114 req->assoclen + req->cryptoff);
115
116 aead_request_set_tfm(&nreq->subreq, aead);
117 aead_request_set_callback(&nreq->subreq, aead_request_flags(req),
118 req->base.complete, req->base.data);
119 aead_request_set_crypt(&nreq->subreq, src, dst, req->cryptlen,
120 req->iv);
121 aead_request_set_assoc(&nreq->subreq, req->src, req->assoclen);
122
123 return crypt(&nreq->subreq);
124}
125
126static int old_encrypt(struct aead_request *req)
127{
128 struct crypto_aead *aead = crypto_aead_reqtfm(req);
129 struct aead_alg *alg = crypto_aead_alg(aead);
130
131 return old_crypt(req, alg->encrypt);
132}
133
134static int old_decrypt(struct aead_request *req)
135{
136 struct crypto_aead *aead = crypto_aead_reqtfm(req);
137 struct aead_alg *alg = crypto_aead_alg(aead);
138
139 return old_crypt(req, alg->decrypt);
140}
141
88static int no_givcrypt(struct aead_givcrypt_request *req) 142static int no_givcrypt(struct aead_givcrypt_request *req)
89{ 143{
90 return -ENOSYS; 144 return -ENOSYS;
@@ -98,8 +152,8 @@ static int crypto_aead_init_tfm(struct crypto_tfm *tfm)
98 if (max(alg->maxauthsize, alg->ivsize) > PAGE_SIZE / 8) 152 if (max(alg->maxauthsize, alg->ivsize) > PAGE_SIZE / 8)
99 return -EINVAL; 153 return -EINVAL;
100 154
101 crt->encrypt = alg->encrypt; 155 crt->encrypt = old_encrypt;
102 crt->decrypt = alg->decrypt; 156 crt->decrypt = old_decrypt;
103 if (alg->ivsize) { 157 if (alg->ivsize) {
104 crt->givencrypt = alg->givencrypt ?: no_givcrypt; 158 crt->givencrypt = alg->givencrypt ?: no_givcrypt;
105 crt->givdecrypt = alg->givdecrypt ?: no_givcrypt; 159 crt->givdecrypt = alg->givdecrypt ?: no_givcrypt;