Branch data Line data Source code
1 : : /*
2 : : * Block chaining cipher operations.
3 : : *
4 : : * Generic encrypt/decrypt wrapper for ciphers, handles operations across
5 : : * multiple page boundaries by using temporary blocks. In user context,
6 : : * the kernel is given a chance to schedule us once per page.
7 : : *
8 : : * Copyright (c) 2006 Herbert Xu <herbert@gondor.apana.org.au>
9 : : *
10 : : * This program is free software; you can redistribute it and/or modify it
11 : : * under the terms of the GNU General Public License as published by the Free
12 : : * Software Foundation; either version 2 of the License, or (at your option)
13 : : * any later version.
14 : : *
15 : : */
16 : :
17 : : #include <crypto/internal/skcipher.h>
18 : : #include <crypto/scatterwalk.h>
19 : : #include <linux/errno.h>
20 : : #include <linux/hardirq.h>
21 : : #include <linux/kernel.h>
22 : : #include <linux/module.h>
23 : : #include <linux/scatterlist.h>
24 : : #include <linux/seq_file.h>
25 : : #include <linux/slab.h>
26 : : #include <linux/string.h>
27 : : #include <linux/cryptouser.h>
28 : : #include <net/netlink.h>
29 : :
30 : : #include "internal.h"
31 : :
32 : : enum {
33 : : BLKCIPHER_WALK_PHYS = 1 << 0,
34 : : BLKCIPHER_WALK_SLOW = 1 << 1,
35 : : BLKCIPHER_WALK_COPY = 1 << 2,
36 : : BLKCIPHER_WALK_DIFF = 1 << 3,
37 : : };
38 : :
39 : : static int blkcipher_walk_next(struct blkcipher_desc *desc,
40 : : struct blkcipher_walk *walk);
41 : : static int blkcipher_walk_first(struct blkcipher_desc *desc,
42 : : struct blkcipher_walk *walk);
43 : :
44 : : static inline void blkcipher_map_src(struct blkcipher_walk *walk)
45 : : {
46 : 0 : walk->src.virt.addr = scatterwalk_map(&walk->in);
47 : : }
48 : :
49 : : static inline void blkcipher_map_dst(struct blkcipher_walk *walk)
50 : : {
51 : 0 : walk->dst.virt.addr = scatterwalk_map(&walk->out);
52 : : }
53 : :
54 : : static inline void blkcipher_unmap_src(struct blkcipher_walk *walk)
55 : : {
56 : : scatterwalk_unmap(walk->src.virt.addr);
57 : : }
58 : :
59 : : static inline void blkcipher_unmap_dst(struct blkcipher_walk *walk)
60 : : {
61 : : scatterwalk_unmap(walk->dst.virt.addr);
62 : : }
63 : :
64 : : /* Get a spot of the specified length that does not straddle a page.
65 : : * The caller needs to ensure that there is enough space for this operation.
66 : : */
67 : : static inline u8 *blkcipher_get_spot(u8 *start, unsigned int len)
68 : : {
69 : 0 : u8 *end_page = (u8 *)(((unsigned long)(start + len - 1)) & PAGE_MASK);
70 : 0 : return max(start, end_page);
71 : : }
72 : :
73 : : static inline unsigned int blkcipher_done_slow(struct crypto_blkcipher *tfm,
74 : : struct blkcipher_walk *walk,
75 : : unsigned int bsize)
76 : : {
77 : : u8 *addr;
78 : : unsigned int alignmask = crypto_blkcipher_alignmask(tfm);
79 : :
80 : 0 : addr = (u8 *)ALIGN((unsigned long)walk->buffer, alignmask + 1);
81 : : addr = blkcipher_get_spot(addr, bsize);
82 : 0 : scatterwalk_copychunks(addr, &walk->out, bsize, 1);
83 : : return bsize;
84 : : }
85 : :
86 : 0 : static inline unsigned int blkcipher_done_fast(struct blkcipher_walk *walk,
87 : : unsigned int n)
88 : : {
89 [ # # ]: 0 : if (walk->flags & BLKCIPHER_WALK_COPY) {
90 : : blkcipher_map_dst(walk);
91 : 0 : memcpy(walk->dst.virt.addr, walk->page, n);
92 : : blkcipher_unmap_dst(walk);
93 [ # # ]: 0 : } else if (!(walk->flags & BLKCIPHER_WALK_PHYS)) {
94 [ # # ]: 0 : if (walk->flags & BLKCIPHER_WALK_DIFF)
95 : : blkcipher_unmap_dst(walk);
96 : : blkcipher_unmap_src(walk);
97 : : }
98 : :
99 : : scatterwalk_advance(&walk->in, n);
100 : : scatterwalk_advance(&walk->out, n);
101 : :
102 : : return n;
103 : : }
104 : :
105 : 0 : int blkcipher_walk_done(struct blkcipher_desc *desc,
106 : : struct blkcipher_walk *walk, int err)
107 : : {
108 : 0 : struct crypto_blkcipher *tfm = desc->tfm;
109 : : unsigned int nbytes = 0;
110 : :
111 [ # # ]: 0 : if (likely(err >= 0)) {
112 : 0 : unsigned int n = walk->nbytes - err;
113 : :
114 [ # # ]: 0 : if (likely(!(walk->flags & BLKCIPHER_WALK_SLOW)))
115 : : n = blkcipher_done_fast(walk, n);
116 [ # # ][ # # ]: 0 : else if (WARN_ON(err)) {
117 : : err = -EINVAL;
118 : : goto err;
119 : : } else
120 : : n = blkcipher_done_slow(tfm, walk, n);
121 : :
122 : 0 : nbytes = walk->total - n;
123 : : err = 0;
124 : : }
125 : :
126 : 0 : scatterwalk_done(&walk->in, 0, nbytes);
127 : 0 : scatterwalk_done(&walk->out, 1, nbytes);
128 : :
129 : : err:
130 : 0 : walk->total = nbytes;
131 : 0 : walk->nbytes = nbytes;
132 : :
133 [ # # ]: 0 : if (nbytes) {
134 : 0 : crypto_yield(desc->flags);
135 : 0 : return blkcipher_walk_next(desc, walk);
136 : : }
137 : :
138 [ # # ]: 0 : if (walk->iv != desc->info)
139 : 0 : memcpy(desc->info, walk->iv, crypto_blkcipher_ivsize(tfm));
140 [ # # ]: 0 : if (walk->buffer != walk->page)
141 : 0 : kfree(walk->buffer);
142 [ # # ]: 0 : if (walk->page)
143 : 0 : free_page((unsigned long)walk->page);
144 : :
145 : 0 : return err;
146 : : }
147 : : EXPORT_SYMBOL_GPL(blkcipher_walk_done);
148 : :
149 : : static inline int blkcipher_next_slow(struct blkcipher_desc *desc,
150 : : struct blkcipher_walk *walk,
151 : : unsigned int bsize,
152 : : unsigned int alignmask)
153 : : {
154 : : unsigned int n;
155 : 0 : unsigned aligned_bsize = ALIGN(bsize, alignmask + 1);
156 : :
157 [ # # ]: 0 : if (walk->buffer)
158 : : goto ok;
159 : :
160 : 0 : walk->buffer = walk->page;
161 [ # # ]: 0 : if (walk->buffer)
162 : : goto ok;
163 : :
164 : 0 : n = aligned_bsize * 3 - (alignmask + 1) +
165 : 0 : (alignmask & ~(crypto_tfm_ctx_alignment() - 1));
166 : 0 : walk->buffer = kmalloc(n, GFP_ATOMIC);
167 [ # # ]: 0 : if (!walk->buffer)
168 : 0 : return blkcipher_walk_done(desc, walk, -ENOMEM);
169 : :
170 : : ok:
171 : 0 : walk->dst.virt.addr = (u8 *)ALIGN((unsigned long)walk->buffer,
172 : : alignmask + 1);
173 : 0 : walk->dst.virt.addr = blkcipher_get_spot(walk->dst.virt.addr, bsize);
174 : 0 : walk->src.virt.addr = blkcipher_get_spot(walk->dst.virt.addr +
175 : : aligned_bsize, bsize);
176 : :
177 : 0 : scatterwalk_copychunks(walk->src.virt.addr, &walk->in, bsize, 0);
178 : :
179 : 0 : walk->nbytes = bsize;
180 : 0 : walk->flags |= BLKCIPHER_WALK_SLOW;
181 : :
182 : : return 0;
183 : : }
184 : :
185 : 0 : static inline int blkcipher_next_copy(struct blkcipher_walk *walk)
186 : : {
187 : 0 : u8 *tmp = walk->page;
188 : :
189 : : blkcipher_map_src(walk);
190 : 0 : memcpy(tmp, walk->src.virt.addr, walk->nbytes);
191 : : blkcipher_unmap_src(walk);
192 : :
193 : 0 : walk->src.virt.addr = tmp;
194 : 0 : walk->dst.virt.addr = tmp;
195 : :
196 : : return 0;
197 : : }
198 : :
199 : : static inline int blkcipher_next_fast(struct blkcipher_desc *desc,
200 : : struct blkcipher_walk *walk)
201 : : {
202 : : unsigned long diff;
203 : :
204 : 0 : walk->src.phys.page = scatterwalk_page(&walk->in);
205 : 0 : walk->src.phys.offset = offset_in_page(walk->in.offset);
206 : 0 : walk->dst.phys.page = scatterwalk_page(&walk->out);
207 : 0 : walk->dst.phys.offset = offset_in_page(walk->out.offset);
208 : :
209 [ # # ]: 0 : if (walk->flags & BLKCIPHER_WALK_PHYS)
210 : : return 0;
211 : :
212 : 0 : diff = walk->src.phys.offset - walk->dst.phys.offset;
213 : 0 : diff |= walk->src.virt.page - walk->dst.virt.page;
214 : :
215 : : blkcipher_map_src(walk);
216 : 0 : walk->dst.virt.addr = walk->src.virt.addr;
217 : :
218 [ # # ]: 0 : if (diff) {
219 : 0 : walk->flags |= BLKCIPHER_WALK_DIFF;
220 : : blkcipher_map_dst(walk);
221 : : }
222 : :
223 : : return 0;
224 : : }
225 : :
226 : 0 : static int blkcipher_walk_next(struct blkcipher_desc *desc,
227 : : struct blkcipher_walk *walk)
228 : : {
229 : 0 : struct crypto_blkcipher *tfm = desc->tfm;
230 : : unsigned int alignmask = crypto_blkcipher_alignmask(tfm);
231 : : unsigned int bsize;
232 : : unsigned int n;
233 : : int err;
234 : :
235 : 0 : n = walk->total;
236 [ # # ]: 0 : if (unlikely(n < crypto_blkcipher_blocksize(tfm))) {
237 : 0 : desc->flags |= CRYPTO_TFM_RES_BAD_BLOCK_LEN;
238 : 0 : return blkcipher_walk_done(desc, walk, -EINVAL);
239 : : }
240 : :
241 : 0 : walk->flags &= ~(BLKCIPHER_WALK_SLOW | BLKCIPHER_WALK_COPY |
242 : : BLKCIPHER_WALK_DIFF);
243 [ # # ][ # # ]: 0 : if (!scatterwalk_aligned(&walk->in, alignmask) ||
244 : 0 : !scatterwalk_aligned(&walk->out, alignmask)) {
245 : 0 : walk->flags |= BLKCIPHER_WALK_COPY;
246 [ # # ]: 0 : if (!walk->page) {
247 : 0 : walk->page = (void *)__get_free_page(GFP_ATOMIC);
248 [ # # ]: 0 : if (!walk->page)
249 : : n = 0;
250 : : }
251 : : }
252 : :
253 : 0 : bsize = min(walk->blocksize, n);
254 : : n = scatterwalk_clamp(&walk->in, n);
255 : : n = scatterwalk_clamp(&walk->out, n);
256 : :
257 [ # # ]: 0 : if (unlikely(n < bsize)) {
258 : : err = blkcipher_next_slow(desc, walk, bsize, alignmask);
259 : 0 : goto set_phys_lowmem;
260 : : }
261 : :
262 : 0 : walk->nbytes = n;
263 [ # # ]: 0 : if (walk->flags & BLKCIPHER_WALK_COPY) {
264 : : err = blkcipher_next_copy(walk);
265 : 0 : goto set_phys_lowmem;
266 : : }
267 : :
268 : : return blkcipher_next_fast(desc, walk);
269 : :
270 : : set_phys_lowmem:
271 [ # # ]: 0 : if (walk->flags & BLKCIPHER_WALK_PHYS) {
272 : 0 : walk->src.phys.page = virt_to_page(walk->src.virt.addr);
273 : 0 : walk->dst.phys.page = virt_to_page(walk->dst.virt.addr);
274 : 0 : walk->src.phys.offset &= PAGE_SIZE - 1;
275 : 0 : walk->dst.phys.offset &= PAGE_SIZE - 1;
276 : : }
277 : 0 : return err;
278 : : }
279 : :
280 : : static inline int blkcipher_copy_iv(struct blkcipher_walk *walk,
281 : : struct crypto_blkcipher *tfm,
282 : : unsigned int alignmask)
283 : : {
284 : 0 : unsigned bs = walk->blocksize;
285 : : unsigned int ivsize = crypto_blkcipher_ivsize(tfm);
286 : 0 : unsigned aligned_bs = ALIGN(bs, alignmask + 1);
287 : 0 : unsigned int size = aligned_bs * 2 + ivsize + max(aligned_bs, ivsize) -
288 : : (alignmask + 1);
289 : : u8 *iv;
290 : :
291 : 0 : size += alignmask & ~(crypto_tfm_ctx_alignment() - 1);
292 : 0 : walk->buffer = kmalloc(size, GFP_ATOMIC);
293 [ # # ]: 0 : if (!walk->buffer)
294 : : return -ENOMEM;
295 : :
296 : 0 : iv = (u8 *)ALIGN((unsigned long)walk->buffer, alignmask + 1);
297 : 0 : iv = blkcipher_get_spot(iv, bs) + aligned_bs;
298 : 0 : iv = blkcipher_get_spot(iv, bs) + aligned_bs;
299 : : iv = blkcipher_get_spot(iv, ivsize);
300 : :
301 : 0 : walk->iv = memcpy(iv, walk->iv, ivsize);
302 : : return 0;
303 : : }
304 : :
305 : 0 : int blkcipher_walk_virt(struct blkcipher_desc *desc,
306 : : struct blkcipher_walk *walk)
307 : : {
308 : 0 : walk->flags &= ~BLKCIPHER_WALK_PHYS;
309 : 0 : walk->blocksize = crypto_blkcipher_blocksize(desc->tfm);
310 : 0 : return blkcipher_walk_first(desc, walk);
311 : : }
312 : : EXPORT_SYMBOL_GPL(blkcipher_walk_virt);
313 : :
314 : 0 : int blkcipher_walk_phys(struct blkcipher_desc *desc,
315 : : struct blkcipher_walk *walk)
316 : : {
317 : 0 : walk->flags |= BLKCIPHER_WALK_PHYS;
318 : 0 : walk->blocksize = crypto_blkcipher_blocksize(desc->tfm);
319 : 0 : return blkcipher_walk_first(desc, walk);
320 : : }
321 : : EXPORT_SYMBOL_GPL(blkcipher_walk_phys);
322 : :
323 : 0 : static int blkcipher_walk_first(struct blkcipher_desc *desc,
324 : : struct blkcipher_walk *walk)
325 : : {
326 : 0 : struct crypto_blkcipher *tfm = desc->tfm;
327 : : unsigned int alignmask = crypto_blkcipher_alignmask(tfm);
328 : :
329 [ # # ][ # # ]: 0 : if (WARN_ON_ONCE(in_irq()))
[ # # ][ # # ]
330 : : return -EDEADLK;
331 : :
332 : 0 : walk->nbytes = walk->total;
333 [ # # ]: 0 : if (unlikely(!walk->total))
334 : : return 0;
335 : :
336 : 0 : walk->buffer = NULL;
337 : 0 : walk->iv = desc->info;
338 [ # # ]: 0 : if (unlikely(((unsigned long)walk->iv & alignmask))) {
339 : : int err = blkcipher_copy_iv(walk, tfm, alignmask);
340 [ # # ]: 0 : if (err)
341 : : return err;
342 : : }
343 : :
344 : 0 : scatterwalk_start(&walk->in, walk->in.sg);
345 : 0 : scatterwalk_start(&walk->out, walk->out.sg);
346 : 0 : walk->page = NULL;
347 : :
348 : 0 : return blkcipher_walk_next(desc, walk);
349 : : }
350 : :
351 : 0 : int blkcipher_walk_virt_block(struct blkcipher_desc *desc,
352 : : struct blkcipher_walk *walk,
353 : : unsigned int blocksize)
354 : : {
355 : 0 : walk->flags &= ~BLKCIPHER_WALK_PHYS;
356 : 0 : walk->blocksize = blocksize;
357 : 0 : return blkcipher_walk_first(desc, walk);
358 : : }
359 : : EXPORT_SYMBOL_GPL(blkcipher_walk_virt_block);
360 : :
361 : 0 : static int setkey_unaligned(struct crypto_tfm *tfm, const u8 *key,
362 : : unsigned int keylen)
363 : : {
364 : 0 : struct blkcipher_alg *cipher = &tfm->__crt_alg->cra_blkcipher;
365 : : unsigned long alignmask = crypto_tfm_alg_alignmask(tfm);
366 : : int ret;
367 : : u8 *buffer, *alignbuffer;
368 : : unsigned long absize;
369 : :
370 : 0 : absize = keylen + alignmask;
371 : : buffer = kmalloc(absize, GFP_ATOMIC);
372 [ # # ]: 0 : if (!buffer)
373 : : return -ENOMEM;
374 : :
375 : 0 : alignbuffer = (u8 *)ALIGN((unsigned long)buffer, alignmask + 1);
376 : 0 : memcpy(alignbuffer, key, keylen);
377 : 0 : ret = cipher->setkey(tfm, alignbuffer, keylen);
378 [ # # ]: 0 : memset(alignbuffer, 0, keylen);
379 : 0 : kfree(buffer);
380 : 0 : return ret;
381 : : }
382 : :
383 : 0 : static int setkey(struct crypto_tfm *tfm, const u8 *key, unsigned int keylen)
384 : : {
385 : 0 : struct blkcipher_alg *cipher = &tfm->__crt_alg->cra_blkcipher;
386 : : unsigned long alignmask = crypto_tfm_alg_alignmask(tfm);
387 : :
388 [ # # ][ # # ]: 0 : if (keylen < cipher->min_keysize || keylen > cipher->max_keysize) {
389 : 0 : tfm->crt_flags |= CRYPTO_TFM_RES_BAD_KEY_LEN;
390 : 0 : return -EINVAL;
391 : : }
392 : :
393 [ # # ]: 0 : if ((unsigned long)key & alignmask)
394 : 0 : return setkey_unaligned(tfm, key, keylen);
395 : :
396 : 0 : return cipher->setkey(tfm, key, keylen);
397 : : }
398 : :
399 : 0 : static int async_setkey(struct crypto_ablkcipher *tfm, const u8 *key,
400 : : unsigned int keylen)
401 : : {
402 : 0 : return setkey(crypto_ablkcipher_tfm(tfm), key, keylen);
403 : : }
404 : :
405 : 0 : static int async_encrypt(struct ablkcipher_request *req)
406 : : {
407 : 0 : struct crypto_tfm *tfm = req->base.tfm;
408 : 0 : struct blkcipher_alg *alg = &tfm->__crt_alg->cra_blkcipher;
409 : 0 : struct blkcipher_desc desc = {
410 : : .tfm = __crypto_blkcipher_cast(tfm),
411 : 0 : .info = req->info,
412 : 0 : .flags = req->base.flags,
413 : : };
414 : :
415 : :
416 : 0 : return alg->encrypt(&desc, req->dst, req->src, req->nbytes);
417 : : }
418 : :
419 : 0 : static int async_decrypt(struct ablkcipher_request *req)
420 : : {
421 : 0 : struct crypto_tfm *tfm = req->base.tfm;
422 : 0 : struct blkcipher_alg *alg = &tfm->__crt_alg->cra_blkcipher;
423 : 0 : struct blkcipher_desc desc = {
424 : : .tfm = __crypto_blkcipher_cast(tfm),
425 : 0 : .info = req->info,
426 : 0 : .flags = req->base.flags,
427 : : };
428 : :
429 : 0 : return alg->decrypt(&desc, req->dst, req->src, req->nbytes);
430 : : }
431 : :
432 : 0 : static unsigned int crypto_blkcipher_ctxsize(struct crypto_alg *alg, u32 type,
433 : : u32 mask)
434 : : {
435 : : struct blkcipher_alg *cipher = &alg->cra_blkcipher;
436 : 0 : unsigned int len = alg->cra_ctxsize;
437 : :
438 [ # # ][ # # ]: 0 : if ((mask & CRYPTO_ALG_TYPE_MASK) == CRYPTO_ALG_TYPE_MASK &&
439 : 0 : cipher->ivsize) {
440 : 0 : len = ALIGN(len, (unsigned long)alg->cra_alignmask + 1);
441 : 0 : len += cipher->ivsize;
442 : : }
443 : :
444 : 0 : return len;
445 : : }
446 : :
447 : : static int crypto_init_blkcipher_ops_async(struct crypto_tfm *tfm)
448 : : {
449 : : struct ablkcipher_tfm *crt = &tfm->crt_ablkcipher;
450 : : struct blkcipher_alg *alg = &tfm->__crt_alg->cra_blkcipher;
451 : :
452 : 0 : crt->setkey = async_setkey;
453 : 0 : crt->encrypt = async_encrypt;
454 : 0 : crt->decrypt = async_decrypt;
455 [ # # ]: 0 : if (!alg->ivsize) {
456 : 0 : crt->givencrypt = skcipher_null_givencrypt;
457 : 0 : crt->givdecrypt = skcipher_null_givdecrypt;
458 : : }
459 : 0 : crt->base = __crypto_ablkcipher_cast(tfm);
460 : 0 : crt->ivsize = alg->ivsize;
461 : :
462 : : return 0;
463 : : }
464 : :
465 : 0 : static int crypto_init_blkcipher_ops_sync(struct crypto_tfm *tfm)
466 : : {
467 : : struct blkcipher_tfm *crt = &tfm->crt_blkcipher;
468 : 0 : struct blkcipher_alg *alg = &tfm->__crt_alg->cra_blkcipher;
469 : 0 : unsigned long align = crypto_tfm_alg_alignmask(tfm) + 1;
470 : : unsigned long addr;
471 : :
472 : 0 : crt->setkey = setkey;
473 : 0 : crt->encrypt = alg->encrypt;
474 : 0 : crt->decrypt = alg->decrypt;
475 : :
476 : 0 : addr = (unsigned long)crypto_tfm_ctx(tfm);
477 : 0 : addr = ALIGN(addr, align);
478 : 0 : addr += ALIGN(tfm->__crt_alg->cra_ctxsize, align);
479 : 0 : crt->iv = (void *)addr;
480 : :
481 : 0 : return 0;
482 : : }
483 : :
484 : 0 : static int crypto_init_blkcipher_ops(struct crypto_tfm *tfm, u32 type, u32 mask)
485 : : {
486 : 0 : struct blkcipher_alg *alg = &tfm->__crt_alg->cra_blkcipher;
487 : :
488 [ # # ]: 0 : if (alg->ivsize > PAGE_SIZE / 8)
489 : : return -EINVAL;
490 : :
491 [ # # ]: 0 : if ((mask & CRYPTO_ALG_TYPE_MASK) == CRYPTO_ALG_TYPE_MASK)
492 : 0 : return crypto_init_blkcipher_ops_sync(tfm);
493 : : else
494 : 0 : return crypto_init_blkcipher_ops_async(tfm);
495 : : }
496 : :
497 : : #ifdef CONFIG_NET
498 : 0 : static int crypto_blkcipher_report(struct sk_buff *skb, struct crypto_alg *alg)
499 : : {
500 : : struct crypto_report_blkcipher rblkcipher;
501 : :
502 : 0 : strncpy(rblkcipher.type, "blkcipher", sizeof(rblkcipher.type));
503 [ # # ]: 0 : strncpy(rblkcipher.geniv, alg->cra_blkcipher.geniv ?: "<default>",
504 : : sizeof(rblkcipher.geniv));
505 : :
506 : 0 : rblkcipher.blocksize = alg->cra_blocksize;
507 : 0 : rblkcipher.min_keysize = alg->cra_blkcipher.min_keysize;
508 : 0 : rblkcipher.max_keysize = alg->cra_blkcipher.max_keysize;
509 : 0 : rblkcipher.ivsize = alg->cra_blkcipher.ivsize;
510 : :
511 [ # # ]: 0 : if (nla_put(skb, CRYPTOCFGA_REPORT_BLKCIPHER,
512 : : sizeof(struct crypto_report_blkcipher), &rblkcipher))
513 : : goto nla_put_failure;
514 : : return 0;
515 : :
516 : : nla_put_failure:
517 : 0 : return -EMSGSIZE;
518 : : }
519 : : #else
520 : : static int crypto_blkcipher_report(struct sk_buff *skb, struct crypto_alg *alg)
521 : : {
522 : : return -ENOSYS;
523 : : }
524 : : #endif
525 : :
526 : : static void crypto_blkcipher_show(struct seq_file *m, struct crypto_alg *alg)
527 : : __attribute__ ((unused));
528 : 0 : static void crypto_blkcipher_show(struct seq_file *m, struct crypto_alg *alg)
529 : : {
530 : 0 : seq_printf(m, "type : blkcipher\n");
531 : 0 : seq_printf(m, "blocksize : %u\n", alg->cra_blocksize);
532 : 0 : seq_printf(m, "min keysize : %u\n", alg->cra_blkcipher.min_keysize);
533 : 0 : seq_printf(m, "max keysize : %u\n", alg->cra_blkcipher.max_keysize);
534 : 0 : seq_printf(m, "ivsize : %u\n", alg->cra_blkcipher.ivsize);
535 [ # # ]: 0 : seq_printf(m, "geniv : %s\n", alg->cra_blkcipher.geniv ?:
536 : : "<default>");
537 : 0 : }
538 : :
539 : : const struct crypto_type crypto_blkcipher_type = {
540 : : .ctxsize = crypto_blkcipher_ctxsize,
541 : : .init = crypto_init_blkcipher_ops,
542 : : #ifdef CONFIG_PROC_FS
543 : : .show = crypto_blkcipher_show,
544 : : #endif
545 : : .report = crypto_blkcipher_report,
546 : : };
547 : : EXPORT_SYMBOL_GPL(crypto_blkcipher_type);
548 : :
549 : 0 : static int crypto_grab_nivcipher(struct crypto_skcipher_spawn *spawn,
550 : : const char *name, u32 type, u32 mask)
551 : : {
552 : : struct crypto_alg *alg;
553 : : int err;
554 : :
555 : : type = crypto_skcipher_type(type);
556 : 0 : mask = crypto_skcipher_mask(mask)| CRYPTO_ALG_GENIV;
557 : :
558 : 0 : alg = crypto_alg_mod_lookup(name, type, mask);
559 [ # # ]: 0 : if (IS_ERR(alg))
560 : 0 : return PTR_ERR(alg);
561 : :
562 : 0 : err = crypto_init_spawn(&spawn->base, alg, spawn->base.inst, mask);
563 : 0 : crypto_mod_put(alg);
564 : 0 : return err;
565 : : }
566 : :
567 : 0 : struct crypto_instance *skcipher_geniv_alloc(struct crypto_template *tmpl,
568 : : struct rtattr **tb, u32 type,
569 : : u32 mask)
570 : : {
571 : : struct {
572 : : int (*setkey)(struct crypto_ablkcipher *tfm, const u8 *key,
573 : : unsigned int keylen);
574 : : int (*encrypt)(struct ablkcipher_request *req);
575 : : int (*decrypt)(struct ablkcipher_request *req);
576 : :
577 : : unsigned int min_keysize;
578 : : unsigned int max_keysize;
579 : : unsigned int ivsize;
580 : :
581 : : const char *geniv;
582 : : } balg;
583 : : const char *name;
584 : 0 : struct crypto_skcipher_spawn *spawn;
585 : : struct crypto_attr_type *algt;
586 : : struct crypto_instance *inst;
587 : : struct crypto_alg *alg;
588 : : int err;
589 : :
590 : 0 : algt = crypto_get_attr_type(tb);
591 [ # # ]: 0 : if (IS_ERR(algt))
592 : : return ERR_CAST(algt);
593 : :
594 [ # # ]: 0 : if ((algt->type ^ (CRYPTO_ALG_TYPE_GIVCIPHER | CRYPTO_ALG_GENIV)) &
595 : 0 : algt->mask)
596 : : return ERR_PTR(-EINVAL);
597 : :
598 : 0 : name = crypto_attr_alg_name(tb[1]);
599 [ # # ]: 0 : if (IS_ERR(name))
600 : : return ERR_CAST(name);
601 : :
602 : : inst = kzalloc(sizeof(*inst) + sizeof(*spawn), GFP_KERNEL);
603 [ # # ]: 0 : if (!inst)
604 : : return ERR_PTR(-ENOMEM);
605 : :
606 : 0 : spawn = crypto_instance_ctx(inst);
607 : :
608 : : /* Ignore async algorithms if necessary. */
609 : 0 : mask |= crypto_requires_sync(algt->type, algt->mask);
610 : :
611 : : crypto_set_skcipher_spawn(spawn, inst);
612 : 0 : err = crypto_grab_nivcipher(spawn, name, type, mask);
613 [ # # ]: 0 : if (err)
614 : : goto err_free_inst;
615 : :
616 : : alg = crypto_skcipher_spawn_alg(spawn);
617 : :
618 [ # # ]: 0 : if ((alg->cra_flags & CRYPTO_ALG_TYPE_MASK) ==
619 : : CRYPTO_ALG_TYPE_BLKCIPHER) {
620 : 0 : balg.ivsize = alg->cra_blkcipher.ivsize;
621 : 0 : balg.min_keysize = alg->cra_blkcipher.min_keysize;
622 : 0 : balg.max_keysize = alg->cra_blkcipher.max_keysize;
623 : :
624 : : balg.setkey = async_setkey;
625 : : balg.encrypt = async_encrypt;
626 : : balg.decrypt = async_decrypt;
627 : :
628 : 0 : balg.geniv = alg->cra_blkcipher.geniv;
629 : : } else {
630 : 0 : balg.ivsize = alg->cra_ablkcipher.ivsize;
631 : 0 : balg.min_keysize = alg->cra_ablkcipher.min_keysize;
632 : 0 : balg.max_keysize = alg->cra_ablkcipher.max_keysize;
633 : :
634 : 0 : balg.setkey = alg->cra_ablkcipher.setkey;
635 : 0 : balg.encrypt = alg->cra_ablkcipher.encrypt;
636 : 0 : balg.decrypt = alg->cra_ablkcipher.decrypt;
637 : :
638 : 0 : balg.geniv = alg->cra_ablkcipher.geniv;
639 : : }
640 : :
641 : : err = -EINVAL;
642 [ # # ]: 0 : if (!balg.ivsize)
643 : : goto err_drop_alg;
644 : :
645 : : /*
646 : : * This is only true if we're constructing an algorithm with its
647 : : * default IV generator. For the default generator we elide the
648 : : * template name and double-check the IV generator.
649 : : */
650 [ # # ]: 0 : if (algt->mask & CRYPTO_ALG_GENIV) {
651 [ # # ]: 0 : if (!balg.geniv)
652 : 0 : balg.geniv = crypto_default_geniv(alg);
653 : : err = -EAGAIN;
654 [ # # ]: 0 : if (strcmp(tmpl->name, balg.geniv))
655 : : goto err_drop_alg;
656 : :
657 : 0 : memcpy(inst->alg.cra_name, alg->cra_name, CRYPTO_MAX_ALG_NAME);
658 : 0 : memcpy(inst->alg.cra_driver_name, alg->cra_driver_name,
659 : : CRYPTO_MAX_ALG_NAME);
660 : : } else {
661 : : err = -ENAMETOOLONG;
662 [ # # ]: 0 : if (snprintf(inst->alg.cra_name, CRYPTO_MAX_ALG_NAME,
663 : 0 : "%s(%s)", tmpl->name, alg->cra_name) >=
664 : : CRYPTO_MAX_ALG_NAME)
665 : : goto err_drop_alg;
666 [ # # ]: 0 : if (snprintf(inst->alg.cra_driver_name, CRYPTO_MAX_ALG_NAME,
667 : 0 : "%s(%s)", tmpl->name, alg->cra_driver_name) >=
668 : : CRYPTO_MAX_ALG_NAME)
669 : : goto err_drop_alg;
670 : : }
671 : :
672 : 0 : inst->alg.cra_flags = CRYPTO_ALG_TYPE_GIVCIPHER | CRYPTO_ALG_GENIV;
673 : 0 : inst->alg.cra_flags |= alg->cra_flags & CRYPTO_ALG_ASYNC;
674 : 0 : inst->alg.cra_priority = alg->cra_priority;
675 : 0 : inst->alg.cra_blocksize = alg->cra_blocksize;
676 : 0 : inst->alg.cra_alignmask = alg->cra_alignmask;
677 : 0 : inst->alg.cra_type = &crypto_givcipher_type;
678 : :
679 : 0 : inst->alg.cra_ablkcipher.ivsize = balg.ivsize;
680 : 0 : inst->alg.cra_ablkcipher.min_keysize = balg.min_keysize;
681 : 0 : inst->alg.cra_ablkcipher.max_keysize = balg.max_keysize;
682 : 0 : inst->alg.cra_ablkcipher.geniv = balg.geniv;
683 : :
684 : 0 : inst->alg.cra_ablkcipher.setkey = balg.setkey;
685 : 0 : inst->alg.cra_ablkcipher.encrypt = balg.encrypt;
686 : 0 : inst->alg.cra_ablkcipher.decrypt = balg.decrypt;
687 : :
688 : : out:
689 : 0 : return inst;
690 : :
691 : : err_drop_alg:
692 : : crypto_drop_skcipher(spawn);
693 : : err_free_inst:
694 : 0 : kfree(inst);
695 : : inst = ERR_PTR(err);
696 : 0 : goto out;
697 : : }
698 : : EXPORT_SYMBOL_GPL(skcipher_geniv_alloc);
699 : :
700 : 0 : void skcipher_geniv_free(struct crypto_instance *inst)
701 : : {
702 : : crypto_drop_skcipher(crypto_instance_ctx(inst));
703 : 0 : kfree(inst);
704 : 0 : }
705 : : EXPORT_SYMBOL_GPL(skcipher_geniv_free);
706 : :
707 : 0 : int skcipher_geniv_init(struct crypto_tfm *tfm)
708 : : {
709 : 0 : struct crypto_instance *inst = (void *)tfm->__crt_alg;
710 : : struct crypto_ablkcipher *cipher;
711 : :
712 : : cipher = crypto_spawn_skcipher(crypto_instance_ctx(inst));
713 [ # # ]: 0 : if (IS_ERR(cipher))
714 : 0 : return PTR_ERR(cipher);
715 : :
716 : 0 : tfm->crt_ablkcipher.base = cipher;
717 : 0 : tfm->crt_ablkcipher.reqsize += crypto_ablkcipher_reqsize(cipher);
718 : :
719 : 0 : return 0;
720 : : }
721 : : EXPORT_SYMBOL_GPL(skcipher_geniv_init);
722 : :
723 : 0 : void skcipher_geniv_exit(struct crypto_tfm *tfm)
724 : : {
725 : 0 : crypto_free_ablkcipher(tfm->crt_ablkcipher.base);
726 : 0 : }
727 : : EXPORT_SYMBOL_GPL(skcipher_geniv_exit);
728 : :
729 : : MODULE_LICENSE("GPL");
730 : : MODULE_DESCRIPTION("Generic block chaining cipher type");
|