~ubuntu-branches/ubuntu/precise/linux-ti-omap4/precise

« back to all changes in this revision

Viewing changes to crypto/authencesn.c

  • Committer: Bazaar Package Importer
  • Author(s): Paolo Pisati
  • Date: 2011-06-29 15:23:51 UTC
  • mfrom: (26.1.1 natty-proposed)
  • Revision ID: james.westby@ubuntu.com-20110629152351-xs96tm303d95rpbk
Tags: 3.0.0-1200.2
* Rebased against 3.0.0-6.7
* BSP from TI based on 3.0.0

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*
 
2
 * authencesn.c - AEAD wrapper for IPsec with extended sequence numbers,
 
3
 *                 derived from authenc.c
 
4
 *
 
5
 * Copyright (C) 2010 secunet Security Networks AG
 
6
 * Copyright (C) 2010 Steffen Klassert <steffen.klassert@secunet.com>
 
7
 *
 
8
 * This program is free software; you can redistribute it and/or modify it
 
9
 * under the terms of the GNU General Public License as published by the Free
 
10
 * Software Foundation; either version 2 of the License, or (at your option)
 
11
 * any later version.
 
12
 *
 
13
 */
 
14
 
 
15
#include <crypto/aead.h>
 
16
#include <crypto/internal/hash.h>
 
17
#include <crypto/internal/skcipher.h>
 
18
#include <crypto/authenc.h>
 
19
#include <crypto/scatterwalk.h>
 
20
#include <linux/err.h>
 
21
#include <linux/init.h>
 
22
#include <linux/kernel.h>
 
23
#include <linux/module.h>
 
24
#include <linux/rtnetlink.h>
 
25
#include <linux/slab.h>
 
26
#include <linux/spinlock.h>
 
27
 
 
28
struct authenc_esn_instance_ctx {
 
29
        struct crypto_ahash_spawn auth;
 
30
        struct crypto_skcipher_spawn enc;
 
31
};
 
32
 
 
33
struct crypto_authenc_esn_ctx {
 
34
        unsigned int reqoff;
 
35
        struct crypto_ahash *auth;
 
36
        struct crypto_ablkcipher *enc;
 
37
};
 
38
 
 
39
struct authenc_esn_request_ctx {
 
40
        unsigned int cryptlen;
 
41
        unsigned int headlen;
 
42
        unsigned int trailen;
 
43
        struct scatterlist *sg;
 
44
        struct scatterlist hsg[2];
 
45
        struct scatterlist tsg[1];
 
46
        struct scatterlist cipher[2];
 
47
        crypto_completion_t complete;
 
48
        crypto_completion_t update_complete;
 
49
        crypto_completion_t update_complete2;
 
50
        char tail[];
 
51
};
 
52
 
 
53
static void authenc_esn_request_complete(struct aead_request *req, int err)
 
54
{
 
55
        if (err != -EINPROGRESS)
 
56
                aead_request_complete(req, err);
 
57
}
 
58
 
 
59
static int crypto_authenc_esn_setkey(struct crypto_aead *authenc_esn, const u8 *key,
 
60
                                     unsigned int keylen)
 
61
{
 
62
        unsigned int authkeylen;
 
63
        unsigned int enckeylen;
 
64
        struct crypto_authenc_esn_ctx *ctx = crypto_aead_ctx(authenc_esn);
 
65
        struct crypto_ahash *auth = ctx->auth;
 
66
        struct crypto_ablkcipher *enc = ctx->enc;
 
67
        struct rtattr *rta = (void *)key;
 
68
        struct crypto_authenc_key_param *param;
 
69
        int err = -EINVAL;
 
70
 
 
71
        if (!RTA_OK(rta, keylen))
 
72
                goto badkey;
 
73
        if (rta->rta_type != CRYPTO_AUTHENC_KEYA_PARAM)
 
74
                goto badkey;
 
75
        if (RTA_PAYLOAD(rta) < sizeof(*param))
 
76
                goto badkey;
 
77
 
 
78
        param = RTA_DATA(rta);
 
79
        enckeylen = be32_to_cpu(param->enckeylen);
 
80
 
 
81
        key += RTA_ALIGN(rta->rta_len);
 
82
        keylen -= RTA_ALIGN(rta->rta_len);
 
83
 
 
84
        if (keylen < enckeylen)
 
85
                goto badkey;
 
86
 
 
87
        authkeylen = keylen - enckeylen;
 
88
 
 
89
        crypto_ahash_clear_flags(auth, CRYPTO_TFM_REQ_MASK);
 
90
        crypto_ahash_set_flags(auth, crypto_aead_get_flags(authenc_esn) &
 
91
                                     CRYPTO_TFM_REQ_MASK);
 
92
        err = crypto_ahash_setkey(auth, key, authkeylen);
 
93
        crypto_aead_set_flags(authenc_esn, crypto_ahash_get_flags(auth) &
 
94
                                           CRYPTO_TFM_RES_MASK);
 
95
 
 
96
        if (err)
 
97
                goto out;
 
98
 
 
99
        crypto_ablkcipher_clear_flags(enc, CRYPTO_TFM_REQ_MASK);
 
100
        crypto_ablkcipher_set_flags(enc, crypto_aead_get_flags(authenc_esn) &
 
101
                                         CRYPTO_TFM_REQ_MASK);
 
102
        err = crypto_ablkcipher_setkey(enc, key + authkeylen, enckeylen);
 
103
        crypto_aead_set_flags(authenc_esn, crypto_ablkcipher_get_flags(enc) &
 
104
                                           CRYPTO_TFM_RES_MASK);
 
105
 
 
106
out:
 
107
        return err;
 
108
 
 
109
badkey:
 
110
        crypto_aead_set_flags(authenc_esn, CRYPTO_TFM_RES_BAD_KEY_LEN);
 
111
        goto out;
 
112
}
 
113
 
 
114
static void authenc_esn_geniv_ahash_update_done(struct crypto_async_request *areq,
 
115
                                                int err)
 
116
{
 
117
        struct aead_request *req = areq->data;
 
118
        struct crypto_aead *authenc_esn = crypto_aead_reqtfm(req);
 
119
        struct crypto_authenc_esn_ctx *ctx = crypto_aead_ctx(authenc_esn);
 
120
        struct authenc_esn_request_ctx *areq_ctx = aead_request_ctx(req);
 
121
        struct ahash_request *ahreq = (void *)(areq_ctx->tail + ctx->reqoff);
 
122
 
 
123
        if (err)
 
124
                goto out;
 
125
 
 
126
        ahash_request_set_crypt(ahreq, areq_ctx->sg, ahreq->result,
 
127
                                areq_ctx->cryptlen);
 
128
        ahash_request_set_callback(ahreq, aead_request_flags(req) &
 
129
                                          CRYPTO_TFM_REQ_MAY_SLEEP,
 
130
                                   areq_ctx->update_complete2, req);
 
131
 
 
132
        err = crypto_ahash_update(ahreq);
 
133
        if (err)
 
134
                goto out;
 
135
 
 
136
        ahash_request_set_crypt(ahreq, areq_ctx->tsg, ahreq->result,
 
137
                                areq_ctx->trailen);
 
138
        ahash_request_set_callback(ahreq, aead_request_flags(req) &
 
139
                                          CRYPTO_TFM_REQ_MAY_SLEEP,
 
140
                                   areq_ctx->complete, req);
 
141
 
 
142
        err = crypto_ahash_finup(ahreq);
 
143
        if (err)
 
144
                goto out;
 
145
 
 
146
        scatterwalk_map_and_copy(ahreq->result, areq_ctx->sg,
 
147
                                 areq_ctx->cryptlen,
 
148
                                 crypto_aead_authsize(authenc_esn), 1);
 
149
 
 
150
out:
 
151
        authenc_esn_request_complete(req, err);
 
152
}
 
153
 
 
154
static void authenc_esn_geniv_ahash_update_done2(struct crypto_async_request *areq,
 
155
                                                 int err)
 
156
{
 
157
        struct aead_request *req = areq->data;
 
158
        struct crypto_aead *authenc_esn = crypto_aead_reqtfm(req);
 
159
        struct crypto_authenc_esn_ctx *ctx = crypto_aead_ctx(authenc_esn);
 
160
        struct authenc_esn_request_ctx *areq_ctx = aead_request_ctx(req);
 
161
        struct ahash_request *ahreq = (void *)(areq_ctx->tail + ctx->reqoff);
 
162
 
 
163
        if (err)
 
164
                goto out;
 
165
 
 
166
        ahash_request_set_crypt(ahreq, areq_ctx->tsg, ahreq->result,
 
167
                                areq_ctx->trailen);
 
168
        ahash_request_set_callback(ahreq, aead_request_flags(req) &
 
169
                                          CRYPTO_TFM_REQ_MAY_SLEEP,
 
170
                                   areq_ctx->complete, req);
 
171
 
 
172
        err = crypto_ahash_finup(ahreq);
 
173
        if (err)
 
174
                goto out;
 
175
 
 
176
        scatterwalk_map_and_copy(ahreq->result, areq_ctx->sg,
 
177
                                 areq_ctx->cryptlen,
 
178
                                 crypto_aead_authsize(authenc_esn), 1);
 
179
 
 
180
out:
 
181
        authenc_esn_request_complete(req, err);
 
182
}
 
183
 
 
184
 
 
185
static void authenc_esn_geniv_ahash_done(struct crypto_async_request *areq,
 
186
                                         int err)
 
187
{
 
188
        struct aead_request *req = areq->data;
 
189
        struct crypto_aead *authenc_esn = crypto_aead_reqtfm(req);
 
190
        struct crypto_authenc_esn_ctx *ctx = crypto_aead_ctx(authenc_esn);
 
191
        struct authenc_esn_request_ctx *areq_ctx = aead_request_ctx(req);
 
192
        struct ahash_request *ahreq = (void *)(areq_ctx->tail + ctx->reqoff);
 
193
 
 
194
        if (err)
 
195
                goto out;
 
196
 
 
197
        scatterwalk_map_and_copy(ahreq->result, areq_ctx->sg,
 
198
                                 areq_ctx->cryptlen,
 
199
                                 crypto_aead_authsize(authenc_esn), 1);
 
200
 
 
201
out:
 
202
        aead_request_complete(req, err);
 
203
}
 
204
 
 
205
 
 
206
static void authenc_esn_verify_ahash_update_done(struct crypto_async_request *areq,
 
207
                                                 int err)
 
208
{
 
209
        u8 *ihash;
 
210
        unsigned int authsize;
 
211
        struct ablkcipher_request *abreq;
 
212
        struct aead_request *req = areq->data;
 
213
        struct crypto_aead *authenc_esn = crypto_aead_reqtfm(req);
 
214
        struct crypto_authenc_esn_ctx *ctx = crypto_aead_ctx(authenc_esn);
 
215
        struct authenc_esn_request_ctx *areq_ctx = aead_request_ctx(req);
 
216
        struct ahash_request *ahreq = (void *)(areq_ctx->tail + ctx->reqoff);
 
217
        unsigned int cryptlen = req->cryptlen;
 
218
 
 
219
        if (err)
 
220
                goto out;
 
221
 
 
222
        ahash_request_set_crypt(ahreq, areq_ctx->sg, ahreq->result,
 
223
                                areq_ctx->cryptlen);
 
224
 
 
225
        ahash_request_set_callback(ahreq,
 
226
                                   aead_request_flags(req) &
 
227
                                   CRYPTO_TFM_REQ_MAY_SLEEP,
 
228
                                   areq_ctx->update_complete2, req);
 
229
 
 
230
        err = crypto_ahash_update(ahreq);
 
231
        if (err)
 
232
                goto out;
 
233
 
 
234
        ahash_request_set_crypt(ahreq, areq_ctx->tsg, ahreq->result,
 
235
                                areq_ctx->trailen);
 
236
        ahash_request_set_callback(ahreq, aead_request_flags(req) &
 
237
                                          CRYPTO_TFM_REQ_MAY_SLEEP,
 
238
                                   areq_ctx->complete, req);
 
239
 
 
240
        err = crypto_ahash_finup(ahreq);
 
241
        if (err)
 
242
                goto out;
 
243
 
 
244
        authsize = crypto_aead_authsize(authenc_esn);
 
245
        cryptlen -= authsize;
 
246
        ihash = ahreq->result + authsize;
 
247
        scatterwalk_map_and_copy(ihash, areq_ctx->sg, areq_ctx->cryptlen,
 
248
                                 authsize, 0);
 
249
 
 
250
        err = memcmp(ihash, ahreq->result, authsize) ? -EBADMSG : 0;
 
251
        if (err)
 
252
                goto out;
 
253
 
 
254
        abreq = aead_request_ctx(req);
 
255
        ablkcipher_request_set_tfm(abreq, ctx->enc);
 
256
        ablkcipher_request_set_callback(abreq, aead_request_flags(req),
 
257
                                        req->base.complete, req->base.data);
 
258
        ablkcipher_request_set_crypt(abreq, req->src, req->dst,
 
259
                                     cryptlen, req->iv);
 
260
 
 
261
        err = crypto_ablkcipher_decrypt(abreq);
 
262
 
 
263
out:
 
264
        authenc_esn_request_complete(req, err);
 
265
}
 
266
 
 
267
static void authenc_esn_verify_ahash_update_done2(struct crypto_async_request *areq,
 
268
                                                  int err)
 
269
{
 
270
        u8 *ihash;
 
271
        unsigned int authsize;
 
272
        struct ablkcipher_request *abreq;
 
273
        struct aead_request *req = areq->data;
 
274
        struct crypto_aead *authenc_esn = crypto_aead_reqtfm(req);
 
275
        struct crypto_authenc_esn_ctx *ctx = crypto_aead_ctx(authenc_esn);
 
276
        struct authenc_esn_request_ctx *areq_ctx = aead_request_ctx(req);
 
277
        struct ahash_request *ahreq = (void *)(areq_ctx->tail + ctx->reqoff);
 
278
        unsigned int cryptlen = req->cryptlen;
 
279
 
 
280
        if (err)
 
281
                goto out;
 
282
 
 
283
        ahash_request_set_crypt(ahreq, areq_ctx->tsg, ahreq->result,
 
284
                                areq_ctx->trailen);
 
285
        ahash_request_set_callback(ahreq, aead_request_flags(req) &
 
286
                                          CRYPTO_TFM_REQ_MAY_SLEEP,
 
287
                                   areq_ctx->complete, req);
 
288
 
 
289
        err = crypto_ahash_finup(ahreq);
 
290
        if (err)
 
291
                goto out;
 
292
 
 
293
        authsize = crypto_aead_authsize(authenc_esn);
 
294
        cryptlen -= authsize;
 
295
        ihash = ahreq->result + authsize;
 
296
        scatterwalk_map_and_copy(ihash, areq_ctx->sg, areq_ctx->cryptlen,
 
297
                                 authsize, 0);
 
298
 
 
299
        err = memcmp(ihash, ahreq->result, authsize) ? -EBADMSG : 0;
 
300
        if (err)
 
301
                goto out;
 
302
 
 
303
        abreq = aead_request_ctx(req);
 
304
        ablkcipher_request_set_tfm(abreq, ctx->enc);
 
305
        ablkcipher_request_set_callback(abreq, aead_request_flags(req),
 
306
                                        req->base.complete, req->base.data);
 
307
        ablkcipher_request_set_crypt(abreq, req->src, req->dst,
 
308
                                     cryptlen, req->iv);
 
309
 
 
310
        err = crypto_ablkcipher_decrypt(abreq);
 
311
 
 
312
out:
 
313
        authenc_esn_request_complete(req, err);
 
314
}
 
315
 
 
316
 
 
317
static void authenc_esn_verify_ahash_done(struct crypto_async_request *areq,
 
318
                                          int err)
 
319
{
 
320
        u8 *ihash;
 
321
        unsigned int authsize;
 
322
        struct ablkcipher_request *abreq;
 
323
        struct aead_request *req = areq->data;
 
324
        struct crypto_aead *authenc_esn = crypto_aead_reqtfm(req);
 
325
        struct crypto_authenc_esn_ctx *ctx = crypto_aead_ctx(authenc_esn);
 
326
        struct authenc_esn_request_ctx *areq_ctx = aead_request_ctx(req);
 
327
        struct ahash_request *ahreq = (void *)(areq_ctx->tail + ctx->reqoff);
 
328
        unsigned int cryptlen = req->cryptlen;
 
329
 
 
330
        if (err)
 
331
                goto out;
 
332
 
 
333
        authsize = crypto_aead_authsize(authenc_esn);
 
334
        cryptlen -= authsize;
 
335
        ihash = ahreq->result + authsize;
 
336
        scatterwalk_map_and_copy(ihash, areq_ctx->sg, areq_ctx->cryptlen,
 
337
                                 authsize, 0);
 
338
 
 
339
        err = memcmp(ihash, ahreq->result, authsize) ? -EBADMSG : 0;
 
340
        if (err)
 
341
                goto out;
 
342
 
 
343
        abreq = aead_request_ctx(req);
 
344
        ablkcipher_request_set_tfm(abreq, ctx->enc);
 
345
        ablkcipher_request_set_callback(abreq, aead_request_flags(req),
 
346
                                        req->base.complete, req->base.data);
 
347
        ablkcipher_request_set_crypt(abreq, req->src, req->dst,
 
348
                                     cryptlen, req->iv);
 
349
 
 
350
        err = crypto_ablkcipher_decrypt(abreq);
 
351
 
 
352
out:
 
353
        authenc_esn_request_complete(req, err);
 
354
}
 
355
 
 
356
static u8 *crypto_authenc_esn_ahash(struct aead_request *req,
 
357
                                    unsigned int flags)
 
358
{
 
359
        struct crypto_aead *authenc_esn = crypto_aead_reqtfm(req);
 
360
        struct crypto_authenc_esn_ctx *ctx = crypto_aead_ctx(authenc_esn);
 
361
        struct crypto_ahash *auth = ctx->auth;
 
362
        struct authenc_esn_request_ctx *areq_ctx = aead_request_ctx(req);
 
363
        struct ahash_request *ahreq = (void *)(areq_ctx->tail + ctx->reqoff);
 
364
        u8 *hash = areq_ctx->tail;
 
365
        int err;
 
366
 
 
367
        hash = (u8 *)ALIGN((unsigned long)hash + crypto_ahash_alignmask(auth),
 
368
                            crypto_ahash_alignmask(auth) + 1);
 
369
 
 
370
        ahash_request_set_tfm(ahreq, auth);
 
371
 
 
372
        err = crypto_ahash_init(ahreq);
 
373
        if (err)
 
374
                return ERR_PTR(err);
 
375
 
 
376
        ahash_request_set_crypt(ahreq, areq_ctx->hsg, hash, areq_ctx->headlen);
 
377
        ahash_request_set_callback(ahreq, aead_request_flags(req) & flags,
 
378
                                   areq_ctx->update_complete, req);
 
379
 
 
380
        err = crypto_ahash_update(ahreq);
 
381
        if (err)
 
382
                return ERR_PTR(err);
 
383
 
 
384
        ahash_request_set_crypt(ahreq, areq_ctx->sg, hash, areq_ctx->cryptlen);
 
385
        ahash_request_set_callback(ahreq, aead_request_flags(req) & flags,
 
386
                                   areq_ctx->update_complete2, req);
 
387
 
 
388
        err = crypto_ahash_update(ahreq);
 
389
        if (err)
 
390
                return ERR_PTR(err);
 
391
 
 
392
        ahash_request_set_crypt(ahreq, areq_ctx->tsg, hash,
 
393
                                areq_ctx->trailen);
 
394
        ahash_request_set_callback(ahreq, aead_request_flags(req) & flags,
 
395
                                   areq_ctx->complete, req);
 
396
 
 
397
        err = crypto_ahash_finup(ahreq);
 
398
        if (err)
 
399
                return ERR_PTR(err);
 
400
 
 
401
        return hash;
 
402
}
 
403
 
 
404
static int crypto_authenc_esn_genicv(struct aead_request *req, u8 *iv,
 
405
                                     unsigned int flags)
 
406
{
 
407
        struct crypto_aead *authenc_esn = crypto_aead_reqtfm(req);
 
408
        struct authenc_esn_request_ctx *areq_ctx = aead_request_ctx(req);
 
409
        struct scatterlist *dst = req->dst;
 
410
        struct scatterlist *assoc = req->assoc;
 
411
        struct scatterlist *cipher = areq_ctx->cipher;
 
412
        struct scatterlist *hsg = areq_ctx->hsg;
 
413
        struct scatterlist *tsg = areq_ctx->tsg;
 
414
        struct scatterlist *assoc1;
 
415
        struct scatterlist *assoc2;
 
416
        unsigned int ivsize = crypto_aead_ivsize(authenc_esn);
 
417
        unsigned int cryptlen = req->cryptlen;
 
418
        struct page *dstp;
 
419
        u8 *vdst;
 
420
        u8 *hash;
 
421
 
 
422
        dstp = sg_page(dst);
 
423
        vdst = PageHighMem(dstp) ? NULL : page_address(dstp) + dst->offset;
 
424
 
 
425
        if (ivsize) {
 
426
                sg_init_table(cipher, 2);
 
427
                sg_set_buf(cipher, iv, ivsize);
 
428
                scatterwalk_crypto_chain(cipher, dst, vdst == iv + ivsize, 2);
 
429
                dst = cipher;
 
430
                cryptlen += ivsize;
 
431
        }
 
432
 
 
433
        if (sg_is_last(assoc))
 
434
                return -EINVAL;
 
435
 
 
436
        assoc1 = assoc + 1;
 
437
        if (sg_is_last(assoc1))
 
438
                return -EINVAL;
 
439
 
 
440
        assoc2 = assoc + 2;
 
441
        if (!sg_is_last(assoc2))
 
442
                return -EINVAL;
 
443
 
 
444
        sg_init_table(hsg, 2);
 
445
        sg_set_page(hsg, sg_page(assoc), assoc->length, assoc->offset);
 
446
        sg_set_page(hsg + 1, sg_page(assoc2), assoc2->length, assoc2->offset);
 
447
 
 
448
        sg_init_table(tsg, 1);
 
449
        sg_set_page(tsg, sg_page(assoc1), assoc1->length, assoc1->offset);
 
450
 
 
451
        areq_ctx->cryptlen = cryptlen;
 
452
        areq_ctx->headlen = assoc->length + assoc2->length;
 
453
        areq_ctx->trailen = assoc1->length;
 
454
        areq_ctx->sg = dst;
 
455
 
 
456
        areq_ctx->complete = authenc_esn_geniv_ahash_done;
 
457
        areq_ctx->update_complete = authenc_esn_geniv_ahash_update_done;
 
458
        areq_ctx->update_complete2 = authenc_esn_geniv_ahash_update_done2;
 
459
 
 
460
        hash = crypto_authenc_esn_ahash(req, flags);
 
461
        if (IS_ERR(hash))
 
462
                return PTR_ERR(hash);
 
463
 
 
464
        scatterwalk_map_and_copy(hash, dst, cryptlen,
 
465
                                 crypto_aead_authsize(authenc_esn), 1);
 
466
        return 0;
 
467
}
 
468
 
 
469
 
 
470
static void crypto_authenc_esn_encrypt_done(struct crypto_async_request *req,
 
471
                                            int err)
 
472
{
 
473
        struct aead_request *areq = req->data;
 
474
 
 
475
        if (!err) {
 
476
                struct crypto_aead *authenc_esn = crypto_aead_reqtfm(areq);
 
477
                struct crypto_authenc_esn_ctx *ctx = crypto_aead_ctx(authenc_esn);
 
478
                struct ablkcipher_request *abreq = aead_request_ctx(areq);
 
479
                u8 *iv = (u8 *)(abreq + 1) +
 
480
                         crypto_ablkcipher_reqsize(ctx->enc);
 
481
 
 
482
                err = crypto_authenc_esn_genicv(areq, iv, 0);
 
483
        }
 
484
 
 
485
        authenc_esn_request_complete(areq, err);
 
486
}
 
487
 
 
488
static int crypto_authenc_esn_encrypt(struct aead_request *req)
 
489
{
 
490
        struct crypto_aead *authenc_esn = crypto_aead_reqtfm(req);
 
491
        struct crypto_authenc_esn_ctx *ctx = crypto_aead_ctx(authenc_esn);
 
492
        struct authenc_esn_request_ctx *areq_ctx = aead_request_ctx(req);
 
493
        struct crypto_ablkcipher *enc = ctx->enc;
 
494
        struct scatterlist *dst = req->dst;
 
495
        unsigned int cryptlen = req->cryptlen;
 
496
        struct ablkcipher_request *abreq = (void *)(areq_ctx->tail
 
497
                                                    + ctx->reqoff);
 
498
        u8 *iv = (u8 *)abreq - crypto_ablkcipher_ivsize(enc);
 
499
        int err;
 
500
 
 
501
        ablkcipher_request_set_tfm(abreq, enc);
 
502
        ablkcipher_request_set_callback(abreq, aead_request_flags(req),
 
503
                                        crypto_authenc_esn_encrypt_done, req);
 
504
        ablkcipher_request_set_crypt(abreq, req->src, dst, cryptlen, req->iv);
 
505
 
 
506
        memcpy(iv, req->iv, crypto_aead_ivsize(authenc_esn));
 
507
 
 
508
        err = crypto_ablkcipher_encrypt(abreq);
 
509
        if (err)
 
510
                return err;
 
511
 
 
512
        return crypto_authenc_esn_genicv(req, iv, CRYPTO_TFM_REQ_MAY_SLEEP);
 
513
}
 
514
 
 
515
static void crypto_authenc_esn_givencrypt_done(struct crypto_async_request *req,
 
516
                                               int err)
 
517
{
 
518
        struct aead_request *areq = req->data;
 
519
 
 
520
        if (!err) {
 
521
                struct skcipher_givcrypt_request *greq = aead_request_ctx(areq);
 
522
 
 
523
                err = crypto_authenc_esn_genicv(areq, greq->giv, 0);
 
524
        }
 
525
 
 
526
        authenc_esn_request_complete(areq, err);
 
527
}
 
528
 
 
529
static int crypto_authenc_esn_givencrypt(struct aead_givcrypt_request *req)
 
530
{
 
531
        struct crypto_aead *authenc_esn = aead_givcrypt_reqtfm(req);
 
532
        struct crypto_authenc_esn_ctx *ctx = crypto_aead_ctx(authenc_esn);
 
533
        struct aead_request *areq = &req->areq;
 
534
        struct skcipher_givcrypt_request *greq = aead_request_ctx(areq);
 
535
        u8 *iv = req->giv;
 
536
        int err;
 
537
 
 
538
        skcipher_givcrypt_set_tfm(greq, ctx->enc);
 
539
        skcipher_givcrypt_set_callback(greq, aead_request_flags(areq),
 
540
                                       crypto_authenc_esn_givencrypt_done, areq);
 
541
        skcipher_givcrypt_set_crypt(greq, areq->src, areq->dst, areq->cryptlen,
 
542
                                    areq->iv);
 
543
        skcipher_givcrypt_set_giv(greq, iv, req->seq);
 
544
 
 
545
        err = crypto_skcipher_givencrypt(greq);
 
546
        if (err)
 
547
                return err;
 
548
 
 
549
        return crypto_authenc_esn_genicv(areq, iv, CRYPTO_TFM_REQ_MAY_SLEEP);
 
550
}
 
551
 
 
552
static int crypto_authenc_esn_verify(struct aead_request *req)
 
553
{
 
554
        struct crypto_aead *authenc_esn = crypto_aead_reqtfm(req);
 
555
        struct authenc_esn_request_ctx *areq_ctx = aead_request_ctx(req);
 
556
        u8 *ohash;
 
557
        u8 *ihash;
 
558
        unsigned int authsize;
 
559
 
 
560
        areq_ctx->complete = authenc_esn_verify_ahash_done;
 
561
        areq_ctx->update_complete = authenc_esn_verify_ahash_update_done;
 
562
 
 
563
        ohash = crypto_authenc_esn_ahash(req, CRYPTO_TFM_REQ_MAY_SLEEP);
 
564
        if (IS_ERR(ohash))
 
565
                return PTR_ERR(ohash);
 
566
 
 
567
        authsize = crypto_aead_authsize(authenc_esn);
 
568
        ihash = ohash + authsize;
 
569
        scatterwalk_map_and_copy(ihash, areq_ctx->sg, areq_ctx->cryptlen,
 
570
                                 authsize, 0);
 
571
        return memcmp(ihash, ohash, authsize) ? -EBADMSG : 0;
 
572
}
 
573
 
 
574
static int crypto_authenc_esn_iverify(struct aead_request *req, u8 *iv,
 
575
                                      unsigned int cryptlen)
 
576
{
 
577
        struct crypto_aead *authenc_esn = crypto_aead_reqtfm(req);
 
578
        struct authenc_esn_request_ctx *areq_ctx = aead_request_ctx(req);
 
579
        struct scatterlist *src = req->src;
 
580
        struct scatterlist *assoc = req->assoc;
 
581
        struct scatterlist *cipher = areq_ctx->cipher;
 
582
        struct scatterlist *hsg = areq_ctx->hsg;
 
583
        struct scatterlist *tsg = areq_ctx->tsg;
 
584
        struct scatterlist *assoc1;
 
585
        struct scatterlist *assoc2;
 
586
        unsigned int ivsize = crypto_aead_ivsize(authenc_esn);
 
587
        struct page *srcp;
 
588
        u8 *vsrc;
 
589
 
 
590
        srcp = sg_page(src);
 
591
        vsrc = PageHighMem(srcp) ? NULL : page_address(srcp) + src->offset;
 
592
 
 
593
        if (ivsize) {
 
594
                sg_init_table(cipher, 2);
 
595
                sg_set_buf(cipher, iv, ivsize);
 
596
                scatterwalk_crypto_chain(cipher, src, vsrc == iv + ivsize, 2);
 
597
                src = cipher;
 
598
                cryptlen += ivsize;
 
599
        }
 
600
 
 
601
        if (sg_is_last(assoc))
 
602
                return -EINVAL;
 
603
 
 
604
        assoc1 = assoc + 1;
 
605
        if (sg_is_last(assoc1))
 
606
                return -EINVAL;
 
607
 
 
608
        assoc2 = assoc + 2;
 
609
        if (!sg_is_last(assoc2))
 
610
                return -EINVAL;
 
611
 
 
612
        sg_init_table(hsg, 2);
 
613
        sg_set_page(hsg, sg_page(assoc), assoc->length, assoc->offset);
 
614
        sg_set_page(hsg + 1, sg_page(assoc2), assoc2->length, assoc2->offset);
 
615
 
 
616
        sg_init_table(tsg, 1);
 
617
        sg_set_page(tsg, sg_page(assoc1), assoc1->length, assoc1->offset);
 
618
 
 
619
        areq_ctx->cryptlen = cryptlen;
 
620
        areq_ctx->headlen = assoc->length + assoc2->length;
 
621
        areq_ctx->trailen = assoc1->length;
 
622
        areq_ctx->sg = src;
 
623
 
 
624
        areq_ctx->complete = authenc_esn_verify_ahash_done;
 
625
        areq_ctx->update_complete = authenc_esn_verify_ahash_update_done;
 
626
        areq_ctx->update_complete2 = authenc_esn_verify_ahash_update_done2;
 
627
 
 
628
        return crypto_authenc_esn_verify(req);
 
629
}
 
630
 
 
631
static int crypto_authenc_esn_decrypt(struct aead_request *req)
 
632
{
 
633
        struct crypto_aead *authenc_esn = crypto_aead_reqtfm(req);
 
634
        struct crypto_authenc_esn_ctx *ctx = crypto_aead_ctx(authenc_esn);
 
635
        struct ablkcipher_request *abreq = aead_request_ctx(req);
 
636
        unsigned int cryptlen = req->cryptlen;
 
637
        unsigned int authsize = crypto_aead_authsize(authenc_esn);
 
638
        u8 *iv = req->iv;
 
639
        int err;
 
640
 
 
641
        if (cryptlen < authsize)
 
642
                return -EINVAL;
 
643
        cryptlen -= authsize;
 
644
 
 
645
        err = crypto_authenc_esn_iverify(req, iv, cryptlen);
 
646
        if (err)
 
647
                return err;
 
648
 
 
649
        ablkcipher_request_set_tfm(abreq, ctx->enc);
 
650
        ablkcipher_request_set_callback(abreq, aead_request_flags(req),
 
651
                                        req->base.complete, req->base.data);
 
652
        ablkcipher_request_set_crypt(abreq, req->src, req->dst, cryptlen, iv);
 
653
 
 
654
        return crypto_ablkcipher_decrypt(abreq);
 
655
}
 
656
 
 
657
static int crypto_authenc_esn_init_tfm(struct crypto_tfm *tfm)
 
658
{
 
659
        struct crypto_instance *inst = crypto_tfm_alg_instance(tfm);
 
660
        struct authenc_esn_instance_ctx *ictx = crypto_instance_ctx(inst);
 
661
        struct crypto_authenc_esn_ctx *ctx = crypto_tfm_ctx(tfm);
 
662
        struct crypto_ahash *auth;
 
663
        struct crypto_ablkcipher *enc;
 
664
        int err;
 
665
 
 
666
        auth = crypto_spawn_ahash(&ictx->auth);
 
667
        if (IS_ERR(auth))
 
668
                return PTR_ERR(auth);
 
669
 
 
670
        enc = crypto_spawn_skcipher(&ictx->enc);
 
671
        err = PTR_ERR(enc);
 
672
        if (IS_ERR(enc))
 
673
                goto err_free_ahash;
 
674
 
 
675
        ctx->auth = auth;
 
676
        ctx->enc = enc;
 
677
 
 
678
        ctx->reqoff = ALIGN(2 * crypto_ahash_digestsize(auth) +
 
679
                            crypto_ahash_alignmask(auth),
 
680
                            crypto_ahash_alignmask(auth) + 1) +
 
681
                      crypto_ablkcipher_ivsize(enc);
 
682
 
 
683
        tfm->crt_aead.reqsize = sizeof(struct authenc_esn_request_ctx) +
 
684
                                ctx->reqoff +
 
685
                                max_t(unsigned int,
 
686
                                crypto_ahash_reqsize(auth) +
 
687
                                sizeof(struct ahash_request),
 
688
                                sizeof(struct skcipher_givcrypt_request) +
 
689
                                crypto_ablkcipher_reqsize(enc));
 
690
 
 
691
        return 0;
 
692
 
 
693
err_free_ahash:
 
694
        crypto_free_ahash(auth);
 
695
        return err;
 
696
}
 
697
 
 
698
static void crypto_authenc_esn_exit_tfm(struct crypto_tfm *tfm)
 
699
{
 
700
        struct crypto_authenc_esn_ctx *ctx = crypto_tfm_ctx(tfm);
 
701
 
 
702
        crypto_free_ahash(ctx->auth);
 
703
        crypto_free_ablkcipher(ctx->enc);
 
704
}
 
705
 
 
706
static struct crypto_instance *crypto_authenc_esn_alloc(struct rtattr **tb)
 
707
{
 
708
        struct crypto_attr_type *algt;
 
709
        struct crypto_instance *inst;
 
710
        struct hash_alg_common *auth;
 
711
        struct crypto_alg *auth_base;
 
712
        struct crypto_alg *enc;
 
713
        struct authenc_esn_instance_ctx *ctx;
 
714
        const char *enc_name;
 
715
        int err;
 
716
 
 
717
        algt = crypto_get_attr_type(tb);
 
718
        err = PTR_ERR(algt);
 
719
        if (IS_ERR(algt))
 
720
                return ERR_PTR(err);
 
721
 
 
722
        if ((algt->type ^ CRYPTO_ALG_TYPE_AEAD) & algt->mask)
 
723
                return ERR_PTR(-EINVAL);
 
724
 
 
725
        auth = ahash_attr_alg(tb[1], CRYPTO_ALG_TYPE_HASH,
 
726
                               CRYPTO_ALG_TYPE_AHASH_MASK);
 
727
        if (IS_ERR(auth))
 
728
                return ERR_CAST(auth);
 
729
 
 
730
        auth_base = &auth->base;
 
731
 
 
732
        enc_name = crypto_attr_alg_name(tb[2]);
 
733
        err = PTR_ERR(enc_name);
 
734
        if (IS_ERR(enc_name))
 
735
                goto out_put_auth;
 
736
 
 
737
        inst = kzalloc(sizeof(*inst) + sizeof(*ctx), GFP_KERNEL);
 
738
        err = -ENOMEM;
 
739
        if (!inst)
 
740
                goto out_put_auth;
 
741
 
 
742
        ctx = crypto_instance_ctx(inst);
 
743
 
 
744
        err = crypto_init_ahash_spawn(&ctx->auth, auth, inst);
 
745
        if (err)
 
746
                goto err_free_inst;
 
747
 
 
748
        crypto_set_skcipher_spawn(&ctx->enc, inst);
 
749
        err = crypto_grab_skcipher(&ctx->enc, enc_name, 0,
 
750
                                   crypto_requires_sync(algt->type,
 
751
                                                        algt->mask));
 
752
        if (err)
 
753
                goto err_drop_auth;
 
754
 
 
755
        enc = crypto_skcipher_spawn_alg(&ctx->enc);
 
756
 
 
757
        err = -ENAMETOOLONG;
 
758
        if (snprintf(inst->alg.cra_name, CRYPTO_MAX_ALG_NAME,
 
759
                     "authencesn(%s,%s)", auth_base->cra_name, enc->cra_name) >=
 
760
            CRYPTO_MAX_ALG_NAME)
 
761
                goto err_drop_enc;
 
762
 
 
763
        if (snprintf(inst->alg.cra_driver_name, CRYPTO_MAX_ALG_NAME,
 
764
                     "authencesn(%s,%s)", auth_base->cra_driver_name,
 
765
                     enc->cra_driver_name) >= CRYPTO_MAX_ALG_NAME)
 
766
                goto err_drop_enc;
 
767
 
 
768
        inst->alg.cra_flags = CRYPTO_ALG_TYPE_AEAD;
 
769
        inst->alg.cra_flags |= enc->cra_flags & CRYPTO_ALG_ASYNC;
 
770
        inst->alg.cra_priority = enc->cra_priority *
 
771
                                 10 + auth_base->cra_priority;
 
772
        inst->alg.cra_blocksize = enc->cra_blocksize;
 
773
        inst->alg.cra_alignmask = auth_base->cra_alignmask | enc->cra_alignmask;
 
774
        inst->alg.cra_type = &crypto_aead_type;
 
775
 
 
776
        inst->alg.cra_aead.ivsize = enc->cra_ablkcipher.ivsize;
 
777
        inst->alg.cra_aead.maxauthsize = auth->digestsize;
 
778
 
 
779
        inst->alg.cra_ctxsize = sizeof(struct crypto_authenc_esn_ctx);
 
780
 
 
781
        inst->alg.cra_init = crypto_authenc_esn_init_tfm;
 
782
        inst->alg.cra_exit = crypto_authenc_esn_exit_tfm;
 
783
 
 
784
        inst->alg.cra_aead.setkey = crypto_authenc_esn_setkey;
 
785
        inst->alg.cra_aead.encrypt = crypto_authenc_esn_encrypt;
 
786
        inst->alg.cra_aead.decrypt = crypto_authenc_esn_decrypt;
 
787
        inst->alg.cra_aead.givencrypt = crypto_authenc_esn_givencrypt;
 
788
 
 
789
out:
 
790
        crypto_mod_put(auth_base);
 
791
        return inst;
 
792
 
 
793
err_drop_enc:
 
794
        crypto_drop_skcipher(&ctx->enc);
 
795
err_drop_auth:
 
796
        crypto_drop_ahash(&ctx->auth);
 
797
err_free_inst:
 
798
        kfree(inst);
 
799
out_put_auth:
 
800
        inst = ERR_PTR(err);
 
801
        goto out;
 
802
}
 
803
 
 
804
static void crypto_authenc_esn_free(struct crypto_instance *inst)
 
805
{
 
806
        struct authenc_esn_instance_ctx *ctx = crypto_instance_ctx(inst);
 
807
 
 
808
        crypto_drop_skcipher(&ctx->enc);
 
809
        crypto_drop_ahash(&ctx->auth);
 
810
        kfree(inst);
 
811
}
 
812
 
 
813
static struct crypto_template crypto_authenc_esn_tmpl = {
 
814
        .name = "authencesn",
 
815
        .alloc = crypto_authenc_esn_alloc,
 
816
        .free = crypto_authenc_esn_free,
 
817
        .module = THIS_MODULE,
 
818
};
 
819
 
 
820
static int __init crypto_authenc_esn_module_init(void)
 
821
{
 
822
        return crypto_register_template(&crypto_authenc_esn_tmpl);
 
823
}
 
824
 
 
825
static void __exit crypto_authenc_esn_module_exit(void)
 
826
{
 
827
        crypto_unregister_template(&crypto_authenc_esn_tmpl);
 
828
}
 
829
 
 
830
module_init(crypto_authenc_esn_module_init);
 
831
module_exit(crypto_authenc_esn_module_exit);
 
832
 
 
833
MODULE_LICENSE("GPL");
 
834
MODULE_AUTHOR("Steffen Klassert <steffen.klassert@secunet.com>");
 
835
MODULE_DESCRIPTION("AEAD wrapper for IPsec with extended sequence numbers");