aboutsummaryrefslogtreecommitdiffstats
path: root/crypto/authenc.c
diff options
context:
space:
mode:
authorHerbert Xu <herbert@gondor.apana.org.au>2007-12-10 03:20:24 -0500
committerHerbert Xu <herbert@gondor.apana.org.au>2008-01-10 16:16:50 -0500
commite56dd56418fcc024683d1638564a494d9e9aab85 (patch)
treee929dde9fa19510fc5418f9f967733cf9a7dd40f /crypto/authenc.c
parent743edf57272fd420348e148bf94f9e48ed6abb70 (diff)
[CRYPTO] authenc: Add givencrypt operation
This patch implements the givencrypt function for authenc. It simply calls the givencrypt operation on the underlying cipher instead of encrypt. Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>
Diffstat (limited to 'crypto/authenc.c')
-rw-r--r--crypto/authenc.c136
1 files changed, 114 insertions, 22 deletions
diff --git a/crypto/authenc.c b/crypto/authenc.c
index 2d609b72f5be..ed8ac5a6fa5f 100644
--- a/crypto/authenc.c
+++ b/crypto/authenc.c
@@ -10,6 +10,7 @@
10 * 10 *
11 */ 11 */
12 12
13#include <crypto/aead.h>
13#include <crypto/internal/skcipher.h> 14#include <crypto/internal/skcipher.h>
14#include <crypto/authenc.h> 15#include <crypto/authenc.h>
15#include <crypto/scatterwalk.h> 16#include <crypto/scatterwalk.h>
@@ -87,6 +88,20 @@ badkey:
87 goto out; 88 goto out;
88} 89}
89 90
91static void authenc_chain(struct scatterlist *head, struct scatterlist *sg,
92 int chain)
93{
94 if (chain) {
95 head->length += sg->length;
96 sg = scatterwalk_sg_next(sg);
97 }
98
99 if (sg)
100 scatterwalk_sg_chain(head, 2, sg);
101 else
102 sg_mark_end(head);
103}
104
90static u8 *crypto_authenc_hash(struct aead_request *req, unsigned int flags, 105static u8 *crypto_authenc_hash(struct aead_request *req, unsigned int flags,
91 struct scatterlist *cipher, 106 struct scatterlist *cipher,
92 unsigned int cryptlen) 107 unsigned int cryptlen)
@@ -127,18 +142,31 @@ auth_unlock:
127 return hash; 142 return hash;
128} 143}
129 144
130static int crypto_authenc_genicv(struct aead_request *req, unsigned int flags) 145static int crypto_authenc_genicv(struct aead_request *req, u8 *iv,
146 unsigned int flags)
131{ 147{
132 struct crypto_aead *authenc = crypto_aead_reqtfm(req); 148 struct crypto_aead *authenc = crypto_aead_reqtfm(req);
133 struct scatterlist *dst = req->dst; 149 struct scatterlist *dst = req->dst;
134 unsigned int cryptlen = req->cryptlen; 150 struct scatterlist cipher[2];
151 struct page *dstp;
152 unsigned int ivsize = crypto_aead_ivsize(authenc);
153 unsigned int cryptlen;
154 u8 *vdst;
135 u8 *hash; 155 u8 *hash;
136 156
137 hash = crypto_authenc_hash(req, flags, dst, cryptlen); 157 dstp = sg_page(dst);
158 vdst = PageHighMem(dstp) ? NULL : page_address(dstp) + dst->offset;
159
160 sg_init_table(cipher, 2);
161 sg_set_buf(cipher, iv, ivsize);
162 authenc_chain(cipher, dst, vdst == iv + ivsize);
163
164 cryptlen = req->cryptlen + ivsize;
165 hash = crypto_authenc_hash(req, flags, cipher, cryptlen);
138 if (IS_ERR(hash)) 166 if (IS_ERR(hash))
139 return PTR_ERR(hash); 167 return PTR_ERR(hash);
140 168
141 scatterwalk_map_and_copy(hash, dst, cryptlen, 169 scatterwalk_map_and_copy(hash, cipher, cryptlen,
142 crypto_aead_authsize(authenc), 1); 170 crypto_aead_authsize(authenc), 1);
143 return 0; 171 return 0;
144} 172}
@@ -146,8 +174,16 @@ static int crypto_authenc_genicv(struct aead_request *req, unsigned int flags)
146static void crypto_authenc_encrypt_done(struct crypto_async_request *req, 174static void crypto_authenc_encrypt_done(struct crypto_async_request *req,
147 int err) 175 int err)
148{ 176{
149 if (!err) 177 if (!err) {
150 err = crypto_authenc_genicv(req->data, 0); 178 struct aead_request *areq = req->data;
179 struct crypto_aead *authenc = crypto_aead_reqtfm(areq);
180 struct crypto_authenc_ctx *ctx = crypto_aead_ctx(authenc);
181 struct ablkcipher_request *abreq = aead_request_ctx(areq);
182 u8 *iv = (u8 *)(abreq + 1) +
183 crypto_ablkcipher_reqsize(ctx->enc);
184
185 err = crypto_authenc_genicv(areq, iv, 0);
186 }
151 187
152 aead_request_complete(req->data, err); 188 aead_request_complete(req->data, err);
153} 189}
@@ -157,45 +193,99 @@ static int crypto_authenc_encrypt(struct aead_request *req)
157 struct crypto_aead *authenc = crypto_aead_reqtfm(req); 193 struct crypto_aead *authenc = crypto_aead_reqtfm(req);
158 struct crypto_authenc_ctx *ctx = crypto_aead_ctx(authenc); 194 struct crypto_authenc_ctx *ctx = crypto_aead_ctx(authenc);
159 struct ablkcipher_request *abreq = aead_request_ctx(req); 195 struct ablkcipher_request *abreq = aead_request_ctx(req);
196 struct crypto_ablkcipher *enc = ctx->enc;
197 struct scatterlist *dst = req->dst;
198 unsigned int cryptlen = req->cryptlen;
199 u8 *iv = (u8 *)(abreq + 1) + crypto_ablkcipher_reqsize(enc);
160 int err; 200 int err;
161 201
162 ablkcipher_request_set_tfm(abreq, ctx->enc); 202 ablkcipher_request_set_tfm(abreq, enc);
163 ablkcipher_request_set_callback(abreq, aead_request_flags(req), 203 ablkcipher_request_set_callback(abreq, aead_request_flags(req),
164 crypto_authenc_encrypt_done, req); 204 crypto_authenc_encrypt_done, req);
165 ablkcipher_request_set_crypt(abreq, req->src, req->dst, req->cryptlen, 205 ablkcipher_request_set_crypt(abreq, req->src, dst, cryptlen, req->iv);
166 req->iv); 206
207 memcpy(iv, req->iv, crypto_aead_ivsize(authenc));
167 208
168 err = crypto_ablkcipher_encrypt(abreq); 209 err = crypto_ablkcipher_encrypt(abreq);
169 if (err) 210 if (err)
170 return err; 211 return err;
171 212
172 return crypto_authenc_genicv(req, CRYPTO_TFM_REQ_MAY_SLEEP); 213 return crypto_authenc_genicv(req, iv, CRYPTO_TFM_REQ_MAY_SLEEP);
214}
215
216static void crypto_authenc_givencrypt_done(struct crypto_async_request *req,
217 int err)
218{
219 if (!err) {
220 struct aead_givcrypt_request *greq = req->data;
221
222 err = crypto_authenc_genicv(&greq->areq, greq->giv, 0);
223 }
224
225 aead_request_complete(req->data, err);
226}
227
228static int crypto_authenc_givencrypt(struct aead_givcrypt_request *req)
229{
230 struct crypto_aead *authenc = aead_givcrypt_reqtfm(req);
231 struct crypto_authenc_ctx *ctx = crypto_aead_ctx(authenc);
232 struct aead_request *areq = &req->areq;
233 struct skcipher_givcrypt_request *greq = aead_request_ctx(areq);
234 u8 *iv = req->giv;
235 int err;
236
237 skcipher_givcrypt_set_tfm(greq, ctx->enc);
238 skcipher_givcrypt_set_callback(greq, aead_request_flags(areq),
239 crypto_authenc_givencrypt_done, areq);
240 skcipher_givcrypt_set_crypt(greq, areq->src, areq->dst, areq->cryptlen,
241 areq->iv);
242 skcipher_givcrypt_set_giv(greq, iv, req->seq);
243
244 err = crypto_skcipher_givencrypt(greq);
245 if (err)
246 return err;
247
248 return crypto_authenc_genicv(areq, iv, CRYPTO_TFM_REQ_MAY_SLEEP);
173} 249}
174 250
175static int crypto_authenc_verify(struct aead_request *req, 251static int crypto_authenc_verify(struct aead_request *req,
252 struct scatterlist *cipher,
176 unsigned int cryptlen) 253 unsigned int cryptlen)
177{ 254{
178 struct crypto_aead *authenc = crypto_aead_reqtfm(req); 255 struct crypto_aead *authenc = crypto_aead_reqtfm(req);
179 u8 *ohash; 256 u8 *ohash;
180 u8 *ihash; 257 u8 *ihash;
181 struct scatterlist *src = req->src;
182 unsigned int authsize; 258 unsigned int authsize;
183 259
184 ohash = crypto_authenc_hash(req, CRYPTO_TFM_REQ_MAY_SLEEP, src, 260 ohash = crypto_authenc_hash(req, CRYPTO_TFM_REQ_MAY_SLEEP, cipher,
185 cryptlen); 261 cryptlen);
186 if (IS_ERR(ohash)) 262 if (IS_ERR(ohash))
187 return PTR_ERR(ohash); 263 return PTR_ERR(ohash);
188 264
189 authsize = crypto_aead_authsize(authenc); 265 authsize = crypto_aead_authsize(authenc);
190 ihash = ohash + authsize; 266 ihash = ohash + authsize;
191 scatterwalk_map_and_copy(ihash, src, cryptlen, authsize, 0); 267 scatterwalk_map_and_copy(ihash, cipher, cryptlen, authsize, 0);
192 return memcmp(ihash, ohash, authsize) ? -EBADMSG: 0; 268 return memcmp(ihash, ohash, authsize) ? -EBADMSG: 0;
193} 269}
194 270
195static void crypto_authenc_decrypt_done(struct crypto_async_request *req, 271static int crypto_authenc_iverify(struct aead_request *req, u8 *iv,
196 int err) 272 unsigned int cryptlen)
197{ 273{
198 aead_request_complete(req->data, err); 274 struct crypto_aead *authenc = crypto_aead_reqtfm(req);
275 struct scatterlist *src = req->src;
276 struct scatterlist cipher[2];
277 struct page *srcp;
278 unsigned int ivsize = crypto_aead_ivsize(authenc);
279 u8 *vsrc;
280
281 srcp = sg_page(src);
282 vsrc = PageHighMem(srcp) ? NULL : page_address(srcp) + src->offset;
283
284 sg_init_table(cipher, 2);
285 sg_set_buf(cipher, iv, ivsize);
286 authenc_chain(cipher, src, vsrc == iv + ivsize);
287
288 return crypto_authenc_verify(req, cipher, cryptlen + ivsize);
199} 289}
200 290
201static int crypto_authenc_decrypt(struct aead_request *req) 291static int crypto_authenc_decrypt(struct aead_request *req)
@@ -205,21 +295,21 @@ static int crypto_authenc_decrypt(struct aead_request *req)
205 struct ablkcipher_request *abreq = aead_request_ctx(req); 295 struct ablkcipher_request *abreq = aead_request_ctx(req);
206 unsigned int cryptlen = req->cryptlen; 296 unsigned int cryptlen = req->cryptlen;
207 unsigned int authsize = crypto_aead_authsize(authenc); 297 unsigned int authsize = crypto_aead_authsize(authenc);
298 u8 *iv = req->iv;
208 int err; 299 int err;
209 300
210 if (cryptlen < authsize) 301 if (cryptlen < authsize)
211 return -EINVAL; 302 return -EINVAL;
212 cryptlen -= authsize; 303 cryptlen -= authsize;
213 304
214 err = crypto_authenc_verify(req, cryptlen); 305 err = crypto_authenc_iverify(req, iv, cryptlen);
215 if (err) 306 if (err)
216 return err; 307 return err;
217 308
218 ablkcipher_request_set_tfm(abreq, ctx->enc); 309 ablkcipher_request_set_tfm(abreq, ctx->enc);
219 ablkcipher_request_set_callback(abreq, aead_request_flags(req), 310 ablkcipher_request_set_callback(abreq, aead_request_flags(req),
220 crypto_authenc_decrypt_done, req); 311 req->base.complete, req->base.data);
221 ablkcipher_request_set_crypt(abreq, req->src, req->dst, cryptlen, 312 ablkcipher_request_set_crypt(abreq, req->src, req->dst, cryptlen, iv);
222 req->iv);
223 313
224 return crypto_ablkcipher_decrypt(abreq); 314 return crypto_ablkcipher_decrypt(abreq);
225} 315}
@@ -248,8 +338,9 @@ static int crypto_authenc_init_tfm(struct crypto_tfm *tfm)
248 (crypto_hash_alignmask(auth) & 338 (crypto_hash_alignmask(auth) &
249 ~(crypto_tfm_ctx_alignment() - 1)) + 339 ~(crypto_tfm_ctx_alignment() - 1)) +
250 crypto_hash_digestsize(auth) * 2, 340 crypto_hash_digestsize(auth) * 2,
251 sizeof(struct ablkcipher_request) + 341 sizeof(struct skcipher_givcrypt_request) +
252 crypto_ablkcipher_reqsize(enc)); 342 crypto_ablkcipher_reqsize(enc) +
343 crypto_ablkcipher_ivsize(enc));
253 344
254 spin_lock_init(&ctx->auth_lock); 345 spin_lock_init(&ctx->auth_lock);
255 346
@@ -347,6 +438,7 @@ static struct crypto_instance *crypto_authenc_alloc(struct rtattr **tb)
347 inst->alg.cra_aead.setkey = crypto_authenc_setkey; 438 inst->alg.cra_aead.setkey = crypto_authenc_setkey;
348 inst->alg.cra_aead.encrypt = crypto_authenc_encrypt; 439 inst->alg.cra_aead.encrypt = crypto_authenc_encrypt;
349 inst->alg.cra_aead.decrypt = crypto_authenc_decrypt; 440 inst->alg.cra_aead.decrypt = crypto_authenc_decrypt;
441 inst->alg.cra_aead.givencrypt = crypto_authenc_givencrypt;
350 442
351out: 443out:
352 crypto_mod_put(auth); 444 crypto_mod_put(auth);