blob: 2680e94b00f598698dd63c63602470fa905ca15c [file] [log] [blame]
Herbert Xu0a270322007-11-30 21:38:37 +11001/*
2 * seqiv: Sequence Number IV Generator
3 *
4 * This generator generates an IV based on a sequence number by xoring it
5 * with a salt. This algorithm is mainly useful for CTR and similar modes.
6 *
7 * Copyright (c) 2007 Herbert Xu <herbert@gondor.apana.org.au>
8 *
9 * This program is free software; you can redistribute it and/or modify it
10 * under the terms of the GNU General Public License as published by the Free
11 * Software Foundation; either version 2 of the License, or (at your option)
12 * any later version.
13 *
14 */
15
Herbert Xu14df4d82007-12-12 12:27:26 +080016#include <crypto/internal/aead.h>
Herbert Xu0a270322007-11-30 21:38:37 +110017#include <crypto/internal/skcipher.h>
Herbert Xu856e3f402015-05-21 15:11:13 +080018#include <crypto/null.h>
Herbert Xua0f000e2008-08-14 22:21:31 +100019#include <crypto/rng.h>
Herbert Xu856e3f402015-05-21 15:11:13 +080020#include <crypto/scatterwalk.h>
Herbert Xu0a270322007-11-30 21:38:37 +110021#include <linux/err.h>
22#include <linux/init.h>
23#include <linux/kernel.h>
24#include <linux/module.h>
Tejun Heo5a0e3ad2010-03-24 17:04:11 +090025#include <linux/slab.h>
Herbert Xu0a270322007-11-30 21:38:37 +110026#include <linux/spinlock.h>
27#include <linux/string.h>
28
29struct seqiv_ctx {
30 spinlock_t lock;
31 u8 salt[] __attribute__ ((aligned(__alignof__(u32))));
32};
33
Herbert Xu856e3f402015-05-21 15:11:13 +080034struct seqiv_aead_ctx {
35 struct crypto_aead *child;
36 spinlock_t lock;
37 struct crypto_blkcipher *null;
38 u8 salt[] __attribute__ ((aligned(__alignof__(u32))));
39};
40
Herbert Xu06771572015-05-23 15:41:51 +080041static void seqiv_free(struct crypto_instance *inst);
42
Herbert Xu856e3f402015-05-21 15:11:13 +080043static int seqiv_aead_setkey(struct crypto_aead *tfm,
44 const u8 *key, unsigned int keylen)
45{
46 struct seqiv_aead_ctx *ctx = crypto_aead_ctx(tfm);
47
48 return crypto_aead_setkey(ctx->child, key, keylen);
49}
50
51static int seqiv_aead_setauthsize(struct crypto_aead *tfm,
52 unsigned int authsize)
53{
54 struct seqiv_aead_ctx *ctx = crypto_aead_ctx(tfm);
55
56 return crypto_aead_setauthsize(ctx->child, authsize);
57}
58
Herbert Xu0a270322007-11-30 21:38:37 +110059static void seqiv_complete2(struct skcipher_givcrypt_request *req, int err)
60{
61 struct ablkcipher_request *subreq = skcipher_givcrypt_reqctx(req);
62 struct crypto_ablkcipher *geniv;
63
64 if (err == -EINPROGRESS)
65 return;
66
67 if (err)
68 goto out;
69
70 geniv = skcipher_givcrypt_reqtfm(req);
71 memcpy(req->creq.info, subreq->info, crypto_ablkcipher_ivsize(geniv));
72
73out:
74 kfree(subreq->info);
75}
76
77static void seqiv_complete(struct crypto_async_request *base, int err)
78{
79 struct skcipher_givcrypt_request *req = base->data;
80
81 seqiv_complete2(req, err);
82 skcipher_givcrypt_complete(req, err);
83}
84
Herbert Xu14df4d82007-12-12 12:27:26 +080085static void seqiv_aead_complete2(struct aead_givcrypt_request *req, int err)
86{
87 struct aead_request *subreq = aead_givcrypt_reqctx(req);
88 struct crypto_aead *geniv;
89
90 if (err == -EINPROGRESS)
91 return;
92
93 if (err)
94 goto out;
95
96 geniv = aead_givcrypt_reqtfm(req);
97 memcpy(req->areq.iv, subreq->iv, crypto_aead_ivsize(geniv));
98
99out:
100 kfree(subreq->iv);
101}
102
103static void seqiv_aead_complete(struct crypto_async_request *base, int err)
104{
105 struct aead_givcrypt_request *req = base->data;
106
107 seqiv_aead_complete2(req, err);
108 aead_givcrypt_complete(req, err);
109}
110
Herbert Xu856e3f402015-05-21 15:11:13 +0800111static void seqiv_aead_encrypt_complete2(struct aead_request *req, int err)
112{
113 struct aead_request *subreq = aead_request_ctx(req);
114 struct crypto_aead *geniv;
115
116 if (err == -EINPROGRESS)
117 return;
118
119 if (err)
120 goto out;
121
122 geniv = crypto_aead_reqtfm(req);
123 memcpy(req->iv, subreq->iv, crypto_aead_ivsize(geniv));
124
125out:
126 kzfree(subreq->iv);
127}
128
129static void seqiv_aead_encrypt_complete(struct crypto_async_request *base,
130 int err)
131{
132 struct aead_request *req = base->data;
133
134 seqiv_aead_encrypt_complete2(req, err);
135 aead_request_complete(req, err);
136}
137
Herbert Xu14df4d82007-12-12 12:27:26 +0800138static void seqiv_geniv(struct seqiv_ctx *ctx, u8 *info, u64 seq,
139 unsigned int ivsize)
140{
141 unsigned int len = ivsize;
142
143 if (ivsize > sizeof(u64)) {
144 memset(info, 0, ivsize - sizeof(u64));
145 len = sizeof(u64);
146 }
147 seq = cpu_to_be64(seq);
148 memcpy(info + ivsize - len, &seq, len);
149 crypto_xor(info, ctx->salt, ivsize);
150}
151
Herbert Xu0a270322007-11-30 21:38:37 +1100152static int seqiv_givencrypt(struct skcipher_givcrypt_request *req)
153{
154 struct crypto_ablkcipher *geniv = skcipher_givcrypt_reqtfm(req);
155 struct seqiv_ctx *ctx = crypto_ablkcipher_ctx(geniv);
156 struct ablkcipher_request *subreq = skcipher_givcrypt_reqctx(req);
Mark Rustad3e3dc252014-07-25 02:53:38 -0700157 crypto_completion_t compl;
Herbert Xu0a270322007-11-30 21:38:37 +1100158 void *data;
159 u8 *info;
Herbert Xu0a270322007-11-30 21:38:37 +1100160 unsigned int ivsize;
Herbert Xu0a270322007-11-30 21:38:37 +1100161 int err;
162
163 ablkcipher_request_set_tfm(subreq, skcipher_geniv_cipher(geniv));
164
Mark Rustad3e3dc252014-07-25 02:53:38 -0700165 compl = req->creq.base.complete;
Herbert Xu0a270322007-11-30 21:38:37 +1100166 data = req->creq.base.data;
167 info = req->creq.info;
168
169 ivsize = crypto_ablkcipher_ivsize(geniv);
170
171 if (unlikely(!IS_ALIGNED((unsigned long)info,
172 crypto_ablkcipher_alignmask(geniv) + 1))) {
173 info = kmalloc(ivsize, req->creq.base.flags &
174 CRYPTO_TFM_REQ_MAY_SLEEP ? GFP_KERNEL:
175 GFP_ATOMIC);
176 if (!info)
177 return -ENOMEM;
178
Mark Rustad3e3dc252014-07-25 02:53:38 -0700179 compl = seqiv_complete;
Herbert Xu0a270322007-11-30 21:38:37 +1100180 data = req;
181 }
182
Mark Rustad3e3dc252014-07-25 02:53:38 -0700183 ablkcipher_request_set_callback(subreq, req->creq.base.flags, compl,
Herbert Xu0a270322007-11-30 21:38:37 +1100184 data);
185 ablkcipher_request_set_crypt(subreq, req->creq.src, req->creq.dst,
186 req->creq.nbytes, info);
187
Herbert Xu14df4d82007-12-12 12:27:26 +0800188 seqiv_geniv(ctx, info, req->seq, ivsize);
Herbert Xu0a270322007-11-30 21:38:37 +1100189 memcpy(req->giv, info, ivsize);
190
191 err = crypto_ablkcipher_encrypt(subreq);
192 if (unlikely(info != req->creq.info))
193 seqiv_complete2(req, err);
194 return err;
195}
196
Herbert Xu14df4d82007-12-12 12:27:26 +0800197static int seqiv_aead_givencrypt(struct aead_givcrypt_request *req)
198{
199 struct crypto_aead *geniv = aead_givcrypt_reqtfm(req);
200 struct seqiv_ctx *ctx = crypto_aead_ctx(geniv);
201 struct aead_request *areq = &req->areq;
202 struct aead_request *subreq = aead_givcrypt_reqctx(req);
Mark Rustad3e3dc252014-07-25 02:53:38 -0700203 crypto_completion_t compl;
Herbert Xu14df4d82007-12-12 12:27:26 +0800204 void *data;
205 u8 *info;
206 unsigned int ivsize;
207 int err;
208
209 aead_request_set_tfm(subreq, aead_geniv_base(geniv));
210
Mark Rustad3e3dc252014-07-25 02:53:38 -0700211 compl = areq->base.complete;
Herbert Xu14df4d82007-12-12 12:27:26 +0800212 data = areq->base.data;
213 info = areq->iv;
214
215 ivsize = crypto_aead_ivsize(geniv);
216
217 if (unlikely(!IS_ALIGNED((unsigned long)info,
218 crypto_aead_alignmask(geniv) + 1))) {
219 info = kmalloc(ivsize, areq->base.flags &
220 CRYPTO_TFM_REQ_MAY_SLEEP ? GFP_KERNEL:
221 GFP_ATOMIC);
222 if (!info)
223 return -ENOMEM;
224
Mark Rustad3e3dc252014-07-25 02:53:38 -0700225 compl = seqiv_aead_complete;
Herbert Xu14df4d82007-12-12 12:27:26 +0800226 data = req;
227 }
228
Mark Rustad3e3dc252014-07-25 02:53:38 -0700229 aead_request_set_callback(subreq, areq->base.flags, compl, data);
Herbert Xu14df4d82007-12-12 12:27:26 +0800230 aead_request_set_crypt(subreq, areq->src, areq->dst, areq->cryptlen,
231 info);
232 aead_request_set_assoc(subreq, areq->assoc, areq->assoclen);
233
234 seqiv_geniv(ctx, info, req->seq, ivsize);
235 memcpy(req->giv, info, ivsize);
236
237 err = crypto_aead_encrypt(subreq);
238 if (unlikely(info != areq->iv))
239 seqiv_aead_complete2(req, err);
240 return err;
241}
242
Herbert Xu856e3f402015-05-21 15:11:13 +0800243static int seqiv_aead_encrypt_compat(struct aead_request *req)
244{
245 struct crypto_aead *geniv = crypto_aead_reqtfm(req);
246 struct seqiv_aead_ctx *ctx = crypto_aead_ctx(geniv);
247 struct aead_request *subreq = aead_request_ctx(req);
248 crypto_completion_t compl;
249 void *data;
250 u8 *info;
251 unsigned int ivsize;
252 int err;
253
254 aead_request_set_tfm(subreq, ctx->child);
255
256 compl = req->base.complete;
257 data = req->base.data;
258 info = req->iv;
259
260 ivsize = crypto_aead_ivsize(geniv);
261
262 if (unlikely(!IS_ALIGNED((unsigned long)info,
263 crypto_aead_alignmask(geniv) + 1))) {
264 info = kmalloc(ivsize, req->base.flags &
265 CRYPTO_TFM_REQ_MAY_SLEEP ? GFP_KERNEL:
266 GFP_ATOMIC);
267 if (!info)
268 return -ENOMEM;
269
270 memcpy(info, req->iv, ivsize);
271 compl = seqiv_aead_encrypt_complete;
272 data = req;
273 }
274
275 aead_request_set_callback(subreq, req->base.flags, compl, data);
276 aead_request_set_crypt(subreq, req->src, req->dst,
277 req->cryptlen - ivsize, info);
278 aead_request_set_ad(subreq, req->assoclen, ivsize);
279
280 crypto_xor(info, ctx->salt, ivsize);
281 scatterwalk_map_and_copy(info, req->dst, req->assoclen, ivsize, 1);
282
283 err = crypto_aead_encrypt(subreq);
284 if (unlikely(info != req->iv))
285 seqiv_aead_encrypt_complete2(req, err);
286 return err;
287}
288
289static int seqiv_aead_encrypt(struct aead_request *req)
290{
291 struct crypto_aead *geniv = crypto_aead_reqtfm(req);
292 struct seqiv_aead_ctx *ctx = crypto_aead_ctx(geniv);
293 struct aead_request *subreq = aead_request_ctx(req);
294 crypto_completion_t compl;
295 void *data;
296 u8 *info;
297 unsigned int ivsize;
298 int err;
299
300 aead_request_set_tfm(subreq, ctx->child);
301
302 compl = req->base.complete;
303 data = req->base.data;
304 info = req->iv;
305
306 ivsize = crypto_aead_ivsize(geniv);
307
308 if (req->src != req->dst) {
309 struct scatterlist src[2];
310 struct scatterlist dst[2];
311 struct blkcipher_desc desc = {
312 .tfm = ctx->null,
313 };
314
315 err = crypto_blkcipher_encrypt(
316 &desc,
317 scatterwalk_ffwd(dst, req->dst,
318 req->assoclen + ivsize),
319 scatterwalk_ffwd(src, req->src,
320 req->assoclen + ivsize),
321 req->cryptlen - ivsize);
322 if (err)
323 return err;
324 }
325
326 if (unlikely(!IS_ALIGNED((unsigned long)info,
327 crypto_aead_alignmask(geniv) + 1))) {
328 info = kmalloc(ivsize, req->base.flags &
329 CRYPTO_TFM_REQ_MAY_SLEEP ? GFP_KERNEL:
330 GFP_ATOMIC);
331 if (!info)
332 return -ENOMEM;
333
334 memcpy(info, req->iv, ivsize);
335 compl = seqiv_aead_encrypt_complete;
336 data = req;
337 }
338
339 aead_request_set_callback(subreq, req->base.flags, compl, data);
340 aead_request_set_crypt(subreq, req->dst, req->dst,
341 req->cryptlen - ivsize, info);
342 aead_request_set_ad(subreq, req->assoclen + ivsize, 0);
343
344 crypto_xor(info, ctx->salt, ivsize);
345 scatterwalk_map_and_copy(info, req->dst, req->assoclen, ivsize, 1);
346
347 err = crypto_aead_encrypt(subreq);
348 if (unlikely(info != req->iv))
349 seqiv_aead_encrypt_complete2(req, err);
350 return err;
351}
352
353static int seqiv_aead_decrypt_compat(struct aead_request *req)
354{
355 struct crypto_aead *geniv = crypto_aead_reqtfm(req);
356 struct seqiv_aead_ctx *ctx = crypto_aead_ctx(geniv);
357 struct aead_request *subreq = aead_request_ctx(req);
358 crypto_completion_t compl;
359 void *data;
360 unsigned int ivsize;
361
362 aead_request_set_tfm(subreq, ctx->child);
363
364 compl = req->base.complete;
365 data = req->base.data;
366
367 ivsize = crypto_aead_ivsize(geniv);
368
369 aead_request_set_callback(subreq, req->base.flags, compl, data);
370 aead_request_set_crypt(subreq, req->src, req->dst,
371 req->cryptlen - ivsize, req->iv);
372 aead_request_set_ad(subreq, req->assoclen, ivsize);
373
374 scatterwalk_map_and_copy(req->iv, req->src, req->assoclen, ivsize, 0);
375
376 return crypto_aead_decrypt(subreq);
377}
378
379static int seqiv_aead_decrypt(struct aead_request *req)
380{
381 struct crypto_aead *geniv = crypto_aead_reqtfm(req);
382 struct seqiv_aead_ctx *ctx = crypto_aead_ctx(geniv);
383 struct aead_request *subreq = aead_request_ctx(req);
384 crypto_completion_t compl;
385 void *data;
386 unsigned int ivsize;
387
388 aead_request_set_tfm(subreq, ctx->child);
389
390 compl = req->base.complete;
391 data = req->base.data;
392
393 ivsize = crypto_aead_ivsize(geniv);
394
395 aead_request_set_callback(subreq, req->base.flags, compl, data);
396 aead_request_set_crypt(subreq, req->src, req->dst,
397 req->cryptlen - ivsize, req->iv);
398 aead_request_set_ad(subreq, req->assoclen + ivsize, 0);
399
400 scatterwalk_map_and_copy(req->iv, req->src, req->assoclen, ivsize, 0);
401 if (req->src != req->dst)
402 scatterwalk_map_and_copy(req->iv, req->dst,
403 req->assoclen, ivsize, 1);
404
405 return crypto_aead_decrypt(subreq);
406}
407
Herbert Xu0a270322007-11-30 21:38:37 +1100408static int seqiv_givencrypt_first(struct skcipher_givcrypt_request *req)
409{
410 struct crypto_ablkcipher *geniv = skcipher_givcrypt_reqtfm(req);
411 struct seqiv_ctx *ctx = crypto_ablkcipher_ctx(geniv);
Herbert Xua0f000e2008-08-14 22:21:31 +1000412 int err = 0;
Herbert Xu0a270322007-11-30 21:38:37 +1100413
414 spin_lock_bh(&ctx->lock);
415 if (crypto_ablkcipher_crt(geniv)->givencrypt != seqiv_givencrypt_first)
416 goto unlock;
417
418 crypto_ablkcipher_crt(geniv)->givencrypt = seqiv_givencrypt;
Herbert Xua0f000e2008-08-14 22:21:31 +1000419 err = crypto_rng_get_bytes(crypto_default_rng, ctx->salt,
420 crypto_ablkcipher_ivsize(geniv));
Herbert Xu0a270322007-11-30 21:38:37 +1100421
422unlock:
423 spin_unlock_bh(&ctx->lock);
424
Herbert Xua0f000e2008-08-14 22:21:31 +1000425 if (err)
426 return err;
427
Herbert Xu0a270322007-11-30 21:38:37 +1100428 return seqiv_givencrypt(req);
429}
430
Herbert Xu14df4d82007-12-12 12:27:26 +0800431static int seqiv_aead_givencrypt_first(struct aead_givcrypt_request *req)
432{
433 struct crypto_aead *geniv = aead_givcrypt_reqtfm(req);
434 struct seqiv_ctx *ctx = crypto_aead_ctx(geniv);
Herbert Xua0f000e2008-08-14 22:21:31 +1000435 int err = 0;
Herbert Xu14df4d82007-12-12 12:27:26 +0800436
437 spin_lock_bh(&ctx->lock);
438 if (crypto_aead_crt(geniv)->givencrypt != seqiv_aead_givencrypt_first)
439 goto unlock;
440
441 crypto_aead_crt(geniv)->givencrypt = seqiv_aead_givencrypt;
Herbert Xua0f000e2008-08-14 22:21:31 +1000442 err = crypto_rng_get_bytes(crypto_default_rng, ctx->salt,
443 crypto_aead_ivsize(geniv));
Herbert Xu14df4d82007-12-12 12:27:26 +0800444
445unlock:
446 spin_unlock_bh(&ctx->lock);
447
Herbert Xua0f000e2008-08-14 22:21:31 +1000448 if (err)
449 return err;
450
Herbert Xu14df4d82007-12-12 12:27:26 +0800451 return seqiv_aead_givencrypt(req);
452}
453
Herbert Xu856e3f402015-05-21 15:11:13 +0800454static int seqiv_aead_encrypt_compat_first(struct aead_request *req)
455{
456 struct crypto_aead *geniv = crypto_aead_reqtfm(req);
457 struct seqiv_aead_ctx *ctx = crypto_aead_ctx(geniv);
458 int err = 0;
459
460 spin_lock_bh(&ctx->lock);
461 if (geniv->encrypt != seqiv_aead_encrypt_compat_first)
462 goto unlock;
463
464 geniv->encrypt = seqiv_aead_encrypt_compat;
465 err = crypto_rng_get_bytes(crypto_default_rng, ctx->salt,
466 crypto_aead_ivsize(geniv));
467
468unlock:
469 spin_unlock_bh(&ctx->lock);
470
471 if (err)
472 return err;
473
474 return seqiv_aead_encrypt_compat(req);
475}
476
477static int seqiv_aead_encrypt_first(struct aead_request *req)
478{
479 struct crypto_aead *geniv = crypto_aead_reqtfm(req);
480 struct seqiv_aead_ctx *ctx = crypto_aead_ctx(geniv);
481 int err = 0;
482
483 spin_lock_bh(&ctx->lock);
484 if (geniv->encrypt != seqiv_aead_encrypt_first)
485 goto unlock;
486
487 geniv->encrypt = seqiv_aead_encrypt;
488 err = crypto_rng_get_bytes(crypto_default_rng, ctx->salt,
489 crypto_aead_ivsize(geniv));
490
491unlock:
492 spin_unlock_bh(&ctx->lock);
493
494 if (err)
495 return err;
496
497 return seqiv_aead_encrypt(req);
498}
499
Herbert Xu0a270322007-11-30 21:38:37 +1100500static int seqiv_init(struct crypto_tfm *tfm)
501{
502 struct crypto_ablkcipher *geniv = __crypto_ablkcipher_cast(tfm);
503 struct seqiv_ctx *ctx = crypto_ablkcipher_ctx(geniv);
504
505 spin_lock_init(&ctx->lock);
506
507 tfm->crt_ablkcipher.reqsize = sizeof(struct ablkcipher_request);
508
509 return skcipher_geniv_init(tfm);
510}
511
Herbert Xu856e3f402015-05-21 15:11:13 +0800512static int seqiv_old_aead_init(struct crypto_tfm *tfm)
Herbert Xu14df4d82007-12-12 12:27:26 +0800513{
514 struct crypto_aead *geniv = __crypto_aead_cast(tfm);
515 struct seqiv_ctx *ctx = crypto_aead_ctx(geniv);
516
517 spin_lock_init(&ctx->lock);
518
Herbert Xuba6d8e32015-05-11 17:48:03 +0800519 crypto_aead_set_reqsize(__crypto_aead_cast(tfm),
520 sizeof(struct aead_request));
Herbert Xu14df4d82007-12-12 12:27:26 +0800521
522 return aead_geniv_init(tfm);
523}
524
Herbert Xu856e3f402015-05-21 15:11:13 +0800525static int seqiv_aead_compat_init(struct crypto_tfm *tfm)
526{
527 struct crypto_aead *geniv = __crypto_aead_cast(tfm);
528 struct seqiv_aead_ctx *ctx = crypto_aead_ctx(geniv);
529 int err;
530
531 spin_lock_init(&ctx->lock);
532
533 crypto_aead_set_reqsize(geniv, sizeof(struct aead_request));
534
535 err = aead_geniv_init(tfm);
536
537 ctx->child = geniv->child;
538 geniv->child = geniv;
539
540 return err;
541}
542
543static int seqiv_aead_init(struct crypto_tfm *tfm)
544{
545 struct crypto_aead *geniv = __crypto_aead_cast(tfm);
546 struct seqiv_aead_ctx *ctx = crypto_aead_ctx(geniv);
547 int err;
548
549 spin_lock_init(&ctx->lock);
550
551 crypto_aead_set_reqsize(geniv, sizeof(struct aead_request));
552
553 ctx->null = crypto_get_default_null_skcipher();
554 err = PTR_ERR(ctx->null);
555 if (IS_ERR(ctx->null))
556 goto out;
557
558 err = aead_geniv_init(tfm);
559 if (err)
560 goto drop_null;
561
562 ctx->child = geniv->child;
563 geniv->child = geniv;
564
565out:
566 return err;
567
568drop_null:
569 crypto_put_default_null_skcipher();
570 goto out;
571}
572
573static void seqiv_aead_compat_exit(struct crypto_tfm *tfm)
574{
575 struct seqiv_aead_ctx *ctx = crypto_tfm_ctx(tfm);
576
577 crypto_free_aead(ctx->child);
578}
579
580static void seqiv_aead_exit(struct crypto_tfm *tfm)
581{
582 struct seqiv_aead_ctx *ctx = crypto_tfm_ctx(tfm);
583
584 crypto_free_aead(ctx->child);
585 crypto_put_default_null_skcipher();
586}
587
Herbert Xu06771572015-05-23 15:41:51 +0800588static int seqiv_ablkcipher_create(struct crypto_template *tmpl,
589 struct rtattr **tb)
Herbert Xu0a270322007-11-30 21:38:37 +1100590{
591 struct crypto_instance *inst;
Herbert Xu06771572015-05-23 15:41:51 +0800592 int err;
Herbert Xu0a270322007-11-30 21:38:37 +1100593
Herbert Xu06771572015-05-23 15:41:51 +0800594 inst = skcipher_geniv_alloc(tmpl, tb, 0, 0);
Herbert Xu14df4d82007-12-12 12:27:26 +0800595
Herbert Xu0a270322007-11-30 21:38:37 +1100596 if (IS_ERR(inst))
Herbert Xu06771572015-05-23 15:41:51 +0800597 return PTR_ERR(inst);
Herbert Xu0a270322007-11-30 21:38:37 +1100598
Herbert Xu06771572015-05-23 15:41:51 +0800599 err = -EINVAL;
600 if (inst->alg.cra_ablkcipher.ivsize < sizeof(u64))
601 goto free_inst;
Herbert Xuc0ecf892015-01-16 19:51:20 +1100602
Herbert Xu0a270322007-11-30 21:38:37 +1100603 inst->alg.cra_ablkcipher.givencrypt = seqiv_givencrypt_first;
604
605 inst->alg.cra_init = seqiv_init;
606 inst->alg.cra_exit = skcipher_geniv_exit;
607
Herbert Xu0a270322007-11-30 21:38:37 +1100608 inst->alg.cra_ctxsize += inst->alg.cra_ablkcipher.ivsize;
Herbert Xu856e3f402015-05-21 15:11:13 +0800609 inst->alg.cra_ctxsize += sizeof(struct seqiv_ctx);
Herbert Xu0a270322007-11-30 21:38:37 +1100610
Herbert Xu06771572015-05-23 15:41:51 +0800611 inst->alg.cra_alignmask |= __alignof__(u32) - 1;
612
613 err = crypto_register_instance(tmpl, inst);
614 if (err)
615 goto free_inst;
616
Herbert Xu0a270322007-11-30 21:38:37 +1100617out:
Herbert Xu06771572015-05-23 15:41:51 +0800618 return err;
619
620free_inst:
621 skcipher_geniv_free(inst);
622 goto out;
Herbert Xu0a270322007-11-30 21:38:37 +1100623}
624
Herbert Xu06771572015-05-23 15:41:51 +0800625static int seqiv_old_aead_create(struct crypto_template *tmpl,
626 struct aead_instance *aead)
Herbert Xu856e3f402015-05-21 15:11:13 +0800627{
628 struct crypto_instance *inst = aead_crypto_instance(aead);
Herbert Xu06771572015-05-23 15:41:51 +0800629 int err = -EINVAL;
Herbert Xu856e3f402015-05-21 15:11:13 +0800630
Herbert Xu06771572015-05-23 15:41:51 +0800631 if (inst->alg.cra_aead.ivsize < sizeof(u64))
632 goto free_inst;
Herbert Xu856e3f402015-05-21 15:11:13 +0800633
634 inst->alg.cra_aead.givencrypt = seqiv_aead_givencrypt_first;
635
636 inst->alg.cra_init = seqiv_old_aead_init;
637 inst->alg.cra_exit = aead_geniv_exit;
638
639 inst->alg.cra_ctxsize = inst->alg.cra_aead.ivsize;
640 inst->alg.cra_ctxsize += sizeof(struct seqiv_ctx);
641
Herbert Xu06771572015-05-23 15:41:51 +0800642 err = crypto_register_instance(tmpl, inst);
643 if (err)
644 goto free_inst;
645
646out:
647 return err;
648
649free_inst:
650 aead_geniv_free(aead);
651 goto out;
Herbert Xu856e3f402015-05-21 15:11:13 +0800652}
653
Herbert Xu06771572015-05-23 15:41:51 +0800654static int seqiv_aead_create(struct crypto_template *tmpl, struct rtattr **tb)
Herbert Xu14df4d82007-12-12 12:27:26 +0800655{
Herbert Xu856e3f402015-05-21 15:11:13 +0800656 struct aead_instance *inst;
657 struct crypto_aead_spawn *spawn;
658 struct aead_alg *alg;
Herbert Xu06771572015-05-23 15:41:51 +0800659 int err;
Herbert Xu14df4d82007-12-12 12:27:26 +0800660
Herbert Xu06771572015-05-23 15:41:51 +0800661 inst = aead_geniv_alloc(tmpl, tb, 0, 0);
Herbert Xu14df4d82007-12-12 12:27:26 +0800662
663 if (IS_ERR(inst))
Herbert Xu06771572015-05-23 15:41:51 +0800664 return PTR_ERR(inst);
665
666 inst->alg.base.cra_alignmask |= __alignof__(u32) - 1;
Herbert Xu14df4d82007-12-12 12:27:26 +0800667
Herbert Xu856e3f402015-05-21 15:11:13 +0800668 if (inst->alg.base.cra_aead.encrypt)
Herbert Xu06771572015-05-23 15:41:51 +0800669 return seqiv_old_aead_create(tmpl, inst);
Herbert Xu856e3f402015-05-21 15:11:13 +0800670
Herbert Xu06771572015-05-23 15:41:51 +0800671 err = -EINVAL;
672 if (inst->alg.ivsize < sizeof(u64))
673 goto free_inst;
Herbert Xuc0ecf892015-01-16 19:51:20 +1100674
Herbert Xu856e3f402015-05-21 15:11:13 +0800675 spawn = aead_instance_ctx(inst);
676 alg = crypto_spawn_aead_alg(spawn);
Herbert Xu14df4d82007-12-12 12:27:26 +0800677
Herbert Xu856e3f402015-05-21 15:11:13 +0800678 inst->alg.setkey = seqiv_aead_setkey;
679 inst->alg.setauthsize = seqiv_aead_setauthsize;
680 inst->alg.encrypt = seqiv_aead_encrypt_first;
681 inst->alg.decrypt = seqiv_aead_decrypt;
Herbert Xu14df4d82007-12-12 12:27:26 +0800682
Herbert Xu856e3f402015-05-21 15:11:13 +0800683 inst->alg.base.cra_init = seqiv_aead_init;
684 inst->alg.base.cra_exit = seqiv_aead_exit;
685
686 inst->alg.base.cra_ctxsize = sizeof(struct seqiv_aead_ctx);
687 inst->alg.base.cra_ctxsize += inst->alg.base.cra_aead.ivsize;
688
689 if (alg->base.cra_aead.encrypt) {
690 inst->alg.encrypt = seqiv_aead_encrypt_compat_first;
691 inst->alg.decrypt = seqiv_aead_decrypt_compat;
692
693 inst->alg.base.cra_init = seqiv_aead_compat_init;
694 inst->alg.base.cra_exit = seqiv_aead_compat_exit;
695 }
Herbert Xu14df4d82007-12-12 12:27:26 +0800696
Herbert Xu06771572015-05-23 15:41:51 +0800697 err = aead_register_instance(tmpl, inst);
698 if (err)
699 goto free_inst;
700
Herbert Xu14df4d82007-12-12 12:27:26 +0800701out:
Herbert Xu06771572015-05-23 15:41:51 +0800702 return err;
703
704free_inst:
705 aead_geniv_free(inst);
706 goto out;
Herbert Xu14df4d82007-12-12 12:27:26 +0800707}
708
Herbert Xu06771572015-05-23 15:41:51 +0800709static int seqiv_create(struct crypto_template *tmpl, struct rtattr **tb)
Herbert Xu14df4d82007-12-12 12:27:26 +0800710{
711 struct crypto_attr_type *algt;
Herbert Xu14df4d82007-12-12 12:27:26 +0800712 int err;
713
714 algt = crypto_get_attr_type(tb);
Herbert Xu14df4d82007-12-12 12:27:26 +0800715 if (IS_ERR(algt))
Herbert Xu06771572015-05-23 15:41:51 +0800716 return PTR_ERR(algt);
Herbert Xu14df4d82007-12-12 12:27:26 +0800717
Herbert Xua0f000e2008-08-14 22:21:31 +1000718 err = crypto_get_default_rng();
719 if (err)
Herbert Xu06771572015-05-23 15:41:51 +0800720 return err;
Herbert Xua0f000e2008-08-14 22:21:31 +1000721
Herbert Xu14df4d82007-12-12 12:27:26 +0800722 if ((algt->type ^ CRYPTO_ALG_TYPE_AEAD) & CRYPTO_ALG_TYPE_MASK)
Herbert Xu06771572015-05-23 15:41:51 +0800723 err = seqiv_ablkcipher_create(tmpl, tb);
Herbert Xu14df4d82007-12-12 12:27:26 +0800724 else
Herbert Xu06771572015-05-23 15:41:51 +0800725 err = seqiv_aead_create(tmpl, tb);
Herbert Xu14df4d82007-12-12 12:27:26 +0800726
Herbert Xu06771572015-05-23 15:41:51 +0800727 if (err)
728 crypto_put_default_rng();
Herbert Xu14df4d82007-12-12 12:27:26 +0800729
Herbert Xu06771572015-05-23 15:41:51 +0800730 return err;
Herbert Xu14df4d82007-12-12 12:27:26 +0800731}
732
Herbert Xu06771572015-05-23 15:41:51 +0800733static int seqniv_create(struct crypto_template *tmpl, struct rtattr **tb)
Herbert Xu3c08fee2015-05-21 15:11:14 +0800734{
735 struct aead_instance *inst;
736 struct crypto_aead_spawn *spawn;
737 struct aead_alg *alg;
738 int err;
739
740 err = crypto_get_default_rng();
741 if (err)
Herbert Xu06771572015-05-23 15:41:51 +0800742 return err;
Herbert Xu3c08fee2015-05-21 15:11:14 +0800743
Herbert Xu06771572015-05-23 15:41:51 +0800744 inst = aead_geniv_alloc(tmpl, tb, 0, 0);
745 err = PTR_ERR(inst);
Herbert Xu3c08fee2015-05-21 15:11:14 +0800746 if (IS_ERR(inst))
747 goto put_rng;
748
Herbert Xu06771572015-05-23 15:41:51 +0800749 err = -EINVAL;
750 if (inst->alg.ivsize < sizeof(u64))
751 goto free_inst;
Herbert Xu3c08fee2015-05-21 15:11:14 +0800752
753 spawn = aead_instance_ctx(inst);
754 alg = crypto_spawn_aead_alg(spawn);
755
756 inst->alg.setkey = seqiv_aead_setkey;
757 inst->alg.setauthsize = seqiv_aead_setauthsize;
758 inst->alg.encrypt = seqiv_aead_encrypt_compat_first;
759 inst->alg.decrypt = seqiv_aead_decrypt_compat;
760
761 inst->alg.base.cra_init = seqiv_aead_compat_init;
762 inst->alg.base.cra_exit = seqiv_aead_compat_exit;
763
764 inst->alg.base.cra_alignmask |= __alignof__(u32) - 1;
765 inst->alg.base.cra_ctxsize = sizeof(struct seqiv_aead_ctx);
766 inst->alg.base.cra_ctxsize += inst->alg.base.cra_aead.ivsize;
767
Herbert Xu06771572015-05-23 15:41:51 +0800768 err = aead_register_instance(tmpl, inst);
769 if (err)
770 goto free_inst;
Herbert Xu3c08fee2015-05-21 15:11:14 +0800771
Herbert Xu06771572015-05-23 15:41:51 +0800772out:
773 return err;
774
775free_inst:
776 aead_geniv_free(inst);
Herbert Xu3c08fee2015-05-21 15:11:14 +0800777put_rng:
778 crypto_put_default_rng();
779 goto out;
780}
781
Herbert Xu14df4d82007-12-12 12:27:26 +0800782static void seqiv_free(struct crypto_instance *inst)
783{
784 if ((inst->alg.cra_flags ^ CRYPTO_ALG_TYPE_AEAD) & CRYPTO_ALG_TYPE_MASK)
785 skcipher_geniv_free(inst);
786 else
Herbert Xu856e3f402015-05-21 15:11:13 +0800787 aead_geniv_free(aead_instance(inst));
Herbert Xua0f000e2008-08-14 22:21:31 +1000788 crypto_put_default_rng();
Herbert Xu14df4d82007-12-12 12:27:26 +0800789}
790
Herbert Xu0a270322007-11-30 21:38:37 +1100791static struct crypto_template seqiv_tmpl = {
792 .name = "seqiv",
Herbert Xu06771572015-05-23 15:41:51 +0800793 .create = seqiv_create,
Herbert Xu14df4d82007-12-12 12:27:26 +0800794 .free = seqiv_free,
Herbert Xu0a270322007-11-30 21:38:37 +1100795 .module = THIS_MODULE,
796};
797
Herbert Xu3c08fee2015-05-21 15:11:14 +0800798static struct crypto_template seqniv_tmpl = {
799 .name = "seqniv",
Herbert Xu06771572015-05-23 15:41:51 +0800800 .create = seqniv_create,
Herbert Xu3c08fee2015-05-21 15:11:14 +0800801 .free = seqiv_free,
802 .module = THIS_MODULE,
803};
804
Herbert Xu0a270322007-11-30 21:38:37 +1100805static int __init seqiv_module_init(void)
806{
Herbert Xu3c08fee2015-05-21 15:11:14 +0800807 int err;
808
809 err = crypto_register_template(&seqiv_tmpl);
810 if (err)
811 goto out;
812
813 err = crypto_register_template(&seqniv_tmpl);
814 if (err)
815 goto out_undo_niv;
816
817out:
818 return err;
819
820out_undo_niv:
821 crypto_unregister_template(&seqiv_tmpl);
822 goto out;
Herbert Xu0a270322007-11-30 21:38:37 +1100823}
824
825static void __exit seqiv_module_exit(void)
826{
827 crypto_unregister_template(&seqiv_tmpl);
828}
829
830module_init(seqiv_module_init);
831module_exit(seqiv_module_exit);
832
833MODULE_LICENSE("GPL");
834MODULE_DESCRIPTION("Sequence Number IV Generator");
Kees Cook4943ba12014-11-24 16:32:38 -0800835MODULE_ALIAS_CRYPTO("seqiv");
Herbert Xu3c08fee2015-05-21 15:11:14 +0800836MODULE_ALIAS_CRYPTO("seqniv");