diff options
Diffstat (limited to 'crypto/skcipher.c')
-rw-r--r-- | crypto/skcipher.c | 196 |
1 files changed, 189 insertions, 7 deletions
diff --git a/crypto/skcipher.c b/crypto/skcipher.c index 69230e9d4ac9..d248008e7f7b 100644 --- a/crypto/skcipher.c +++ b/crypto/skcipher.c | |||
@@ -16,7 +16,11 @@ | |||
16 | 16 | ||
17 | #include <crypto/internal/skcipher.h> | 17 | #include <crypto/internal/skcipher.h> |
18 | #include <linux/bug.h> | 18 | #include <linux/bug.h> |
19 | #include <linux/cryptouser.h> | ||
19 | #include <linux/module.h> | 20 | #include <linux/module.h> |
21 | #include <linux/rtnetlink.h> | ||
22 | #include <linux/seq_file.h> | ||
23 | #include <net/netlink.h> | ||
20 | 24 | ||
21 | #include "internal.h" | 25 | #include "internal.h" |
22 | 26 | ||
@@ -25,10 +29,11 @@ static unsigned int crypto_skcipher_extsize(struct crypto_alg *alg) | |||
25 | if (alg->cra_type == &crypto_blkcipher_type) | 29 | if (alg->cra_type == &crypto_blkcipher_type) |
26 | return sizeof(struct crypto_blkcipher *); | 30 | return sizeof(struct crypto_blkcipher *); |
27 | 31 | ||
28 | BUG_ON(alg->cra_type != &crypto_ablkcipher_type && | 32 | if (alg->cra_type == &crypto_ablkcipher_type || |
29 | alg->cra_type != &crypto_givcipher_type); | 33 | alg->cra_type == &crypto_givcipher_type) |
34 | return sizeof(struct crypto_ablkcipher *); | ||
30 | 35 | ||
31 | return sizeof(struct crypto_ablkcipher *); | 36 | return crypto_alg_extsize(alg); |
32 | } | 37 | } |
33 | 38 | ||
34 | static int skcipher_setkey_blkcipher(struct crypto_skcipher *tfm, | 39 | static int skcipher_setkey_blkcipher(struct crypto_skcipher *tfm, |
@@ -216,26 +221,118 @@ static int crypto_init_skcipher_ops_ablkcipher(struct crypto_tfm *tfm) | |||
216 | return 0; | 221 | return 0; |
217 | } | 222 | } |
218 | 223 | ||
224 | static void crypto_skcipher_exit_tfm(struct crypto_tfm *tfm) | ||
225 | { | ||
226 | struct crypto_skcipher *skcipher = __crypto_skcipher_cast(tfm); | ||
227 | struct skcipher_alg *alg = crypto_skcipher_alg(skcipher); | ||
228 | |||
229 | alg->exit(skcipher); | ||
230 | } | ||
231 | |||
219 | static int crypto_skcipher_init_tfm(struct crypto_tfm *tfm) | 232 | static int crypto_skcipher_init_tfm(struct crypto_tfm *tfm) |
220 | { | 233 | { |
234 | struct crypto_skcipher *skcipher = __crypto_skcipher_cast(tfm); | ||
235 | struct skcipher_alg *alg = crypto_skcipher_alg(skcipher); | ||
236 | |||
221 | if (tfm->__crt_alg->cra_type == &crypto_blkcipher_type) | 237 | if (tfm->__crt_alg->cra_type == &crypto_blkcipher_type) |
222 | return crypto_init_skcipher_ops_blkcipher(tfm); | 238 | return crypto_init_skcipher_ops_blkcipher(tfm); |
223 | 239 | ||
224 | BUG_ON(tfm->__crt_alg->cra_type != &crypto_ablkcipher_type && | 240 | if (tfm->__crt_alg->cra_type == &crypto_ablkcipher_type || |
225 | tfm->__crt_alg->cra_type != &crypto_givcipher_type); | 241 | tfm->__crt_alg->cra_type == &crypto_givcipher_type) |
242 | return crypto_init_skcipher_ops_ablkcipher(tfm); | ||
243 | |||
244 | skcipher->setkey = alg->setkey; | ||
245 | skcipher->encrypt = alg->encrypt; | ||
246 | skcipher->decrypt = alg->decrypt; | ||
247 | skcipher->ivsize = alg->ivsize; | ||
248 | skcipher->keysize = alg->max_keysize; | ||
249 | |||
250 | if (alg->exit) | ||
251 | skcipher->base.exit = crypto_skcipher_exit_tfm; | ||
226 | 252 | ||
227 | return crypto_init_skcipher_ops_ablkcipher(tfm); | 253 | if (alg->init) |
254 | return alg->init(skcipher); | ||
255 | |||
256 | return 0; | ||
257 | } | ||
258 | |||
259 | static void crypto_skcipher_free_instance(struct crypto_instance *inst) | ||
260 | { | ||
261 | struct skcipher_instance *skcipher = | ||
262 | container_of(inst, struct skcipher_instance, s.base); | ||
263 | |||
264 | skcipher->free(skcipher); | ||
265 | } | ||
266 | |||
267 | static void crypto_skcipher_show(struct seq_file *m, struct crypto_alg *alg) | ||
268 | __attribute__ ((unused)); | ||
269 | static void crypto_skcipher_show(struct seq_file *m, struct crypto_alg *alg) | ||
270 | { | ||
271 | struct skcipher_alg *skcipher = container_of(alg, struct skcipher_alg, | ||
272 | base); | ||
273 | |||
274 | seq_printf(m, "type : skcipher\n"); | ||
275 | seq_printf(m, "async : %s\n", | ||
276 | alg->cra_flags & CRYPTO_ALG_ASYNC ? "yes" : "no"); | ||
277 | seq_printf(m, "blocksize : %u\n", alg->cra_blocksize); | ||
278 | seq_printf(m, "min keysize : %u\n", skcipher->min_keysize); | ||
279 | seq_printf(m, "max keysize : %u\n", skcipher->max_keysize); | ||
280 | seq_printf(m, "ivsize : %u\n", skcipher->ivsize); | ||
281 | seq_printf(m, "chunksize : %u\n", skcipher->chunksize); | ||
228 | } | 282 | } |
229 | 283 | ||
284 | #ifdef CONFIG_NET | ||
285 | static int crypto_skcipher_report(struct sk_buff *skb, struct crypto_alg *alg) | ||
286 | { | ||
287 | struct crypto_report_blkcipher rblkcipher; | ||
288 | struct skcipher_alg *skcipher = container_of(alg, struct skcipher_alg, | ||
289 | base); | ||
290 | |||
291 | strncpy(rblkcipher.type, "skcipher", sizeof(rblkcipher.type)); | ||
292 | strncpy(rblkcipher.geniv, "<none>", sizeof(rblkcipher.geniv)); | ||
293 | |||
294 | rblkcipher.blocksize = alg->cra_blocksize; | ||
295 | rblkcipher.min_keysize = skcipher->min_keysize; | ||
296 | rblkcipher.max_keysize = skcipher->max_keysize; | ||
297 | rblkcipher.ivsize = skcipher->ivsize; | ||
298 | |||
299 | if (nla_put(skb, CRYPTOCFGA_REPORT_BLKCIPHER, | ||
300 | sizeof(struct crypto_report_blkcipher), &rblkcipher)) | ||
301 | goto nla_put_failure; | ||
302 | return 0; | ||
303 | |||
304 | nla_put_failure: | ||
305 | return -EMSGSIZE; | ||
306 | } | ||
307 | #else | ||
308 | static int crypto_skcipher_report(struct sk_buff *skb, struct crypto_alg *alg) | ||
309 | { | ||
310 | return -ENOSYS; | ||
311 | } | ||
312 | #endif | ||
313 | |||
230 | static const struct crypto_type crypto_skcipher_type2 = { | 314 | static const struct crypto_type crypto_skcipher_type2 = { |
231 | .extsize = crypto_skcipher_extsize, | 315 | .extsize = crypto_skcipher_extsize, |
232 | .init_tfm = crypto_skcipher_init_tfm, | 316 | .init_tfm = crypto_skcipher_init_tfm, |
317 | .free = crypto_skcipher_free_instance, | ||
318 | #ifdef CONFIG_PROC_FS | ||
319 | .show = crypto_skcipher_show, | ||
320 | #endif | ||
321 | .report = crypto_skcipher_report, | ||
233 | .maskclear = ~CRYPTO_ALG_TYPE_MASK, | 322 | .maskclear = ~CRYPTO_ALG_TYPE_MASK, |
234 | .maskset = CRYPTO_ALG_TYPE_BLKCIPHER_MASK, | 323 | .maskset = CRYPTO_ALG_TYPE_BLKCIPHER_MASK, |
235 | .type = CRYPTO_ALG_TYPE_BLKCIPHER, | 324 | .type = CRYPTO_ALG_TYPE_SKCIPHER, |
236 | .tfmsize = offsetof(struct crypto_skcipher, base), | 325 | .tfmsize = offsetof(struct crypto_skcipher, base), |
237 | }; | 326 | }; |
238 | 327 | ||
328 | int crypto_grab_skcipher2(struct crypto_skcipher_spawn *spawn, | ||
329 | const char *name, u32 type, u32 mask) | ||
330 | { | ||
331 | spawn->base.frontend = &crypto_skcipher_type2; | ||
332 | return crypto_grab_spawn(&spawn->base, name, type, mask); | ||
333 | } | ||
334 | EXPORT_SYMBOL_GPL(crypto_grab_skcipher2); | ||
335 | |||
239 | struct crypto_skcipher *crypto_alloc_skcipher(const char *alg_name, | 336 | struct crypto_skcipher *crypto_alloc_skcipher(const char *alg_name, |
240 | u32 type, u32 mask) | 337 | u32 type, u32 mask) |
241 | { | 338 | { |
@@ -243,5 +340,90 @@ struct crypto_skcipher *crypto_alloc_skcipher(const char *alg_name, | |||
243 | } | 340 | } |
244 | EXPORT_SYMBOL_GPL(crypto_alloc_skcipher); | 341 | EXPORT_SYMBOL_GPL(crypto_alloc_skcipher); |
245 | 342 | ||
343 | int crypto_has_skcipher2(const char *alg_name, u32 type, u32 mask) | ||
344 | { | ||
345 | return crypto_type_has_alg(alg_name, &crypto_skcipher_type2, | ||
346 | type, mask); | ||
347 | } | ||
348 | EXPORT_SYMBOL_GPL(crypto_has_skcipher2); | ||
349 | |||
350 | static int skcipher_prepare_alg(struct skcipher_alg *alg) | ||
351 | { | ||
352 | struct crypto_alg *base = &alg->base; | ||
353 | |||
354 | if (alg->ivsize > PAGE_SIZE / 8 || alg->chunksize > PAGE_SIZE / 8) | ||
355 | return -EINVAL; | ||
356 | |||
357 | if (!alg->chunksize) | ||
358 | alg->chunksize = base->cra_blocksize; | ||
359 | |||
360 | base->cra_type = &crypto_skcipher_type2; | ||
361 | base->cra_flags &= ~CRYPTO_ALG_TYPE_MASK; | ||
362 | base->cra_flags |= CRYPTO_ALG_TYPE_SKCIPHER; | ||
363 | |||
364 | return 0; | ||
365 | } | ||
366 | |||
367 | int crypto_register_skcipher(struct skcipher_alg *alg) | ||
368 | { | ||
369 | struct crypto_alg *base = &alg->base; | ||
370 | int err; | ||
371 | |||
372 | err = skcipher_prepare_alg(alg); | ||
373 | if (err) | ||
374 | return err; | ||
375 | |||
376 | return crypto_register_alg(base); | ||
377 | } | ||
378 | EXPORT_SYMBOL_GPL(crypto_register_skcipher); | ||
379 | |||
380 | void crypto_unregister_skcipher(struct skcipher_alg *alg) | ||
381 | { | ||
382 | crypto_unregister_alg(&alg->base); | ||
383 | } | ||
384 | EXPORT_SYMBOL_GPL(crypto_unregister_skcipher); | ||
385 | |||
386 | int crypto_register_skciphers(struct skcipher_alg *algs, int count) | ||
387 | { | ||
388 | int i, ret; | ||
389 | |||
390 | for (i = 0; i < count; i++) { | ||
391 | ret = crypto_register_skcipher(&algs[i]); | ||
392 | if (ret) | ||
393 | goto err; | ||
394 | } | ||
395 | |||
396 | return 0; | ||
397 | |||
398 | err: | ||
399 | for (--i; i >= 0; --i) | ||
400 | crypto_unregister_skcipher(&algs[i]); | ||
401 | |||
402 | return ret; | ||
403 | } | ||
404 | EXPORT_SYMBOL_GPL(crypto_register_skciphers); | ||
405 | |||
406 | void crypto_unregister_skciphers(struct skcipher_alg *algs, int count) | ||
407 | { | ||
408 | int i; | ||
409 | |||
410 | for (i = count - 1; i >= 0; --i) | ||
411 | crypto_unregister_skcipher(&algs[i]); | ||
412 | } | ||
413 | EXPORT_SYMBOL_GPL(crypto_unregister_skciphers); | ||
414 | |||
415 | int skcipher_register_instance(struct crypto_template *tmpl, | ||
416 | struct skcipher_instance *inst) | ||
417 | { | ||
418 | int err; | ||
419 | |||
420 | err = skcipher_prepare_alg(&inst->alg); | ||
421 | if (err) | ||
422 | return err; | ||
423 | |||
424 | return crypto_register_instance(tmpl, skcipher_crypto_instance(inst)); | ||
425 | } | ||
426 | EXPORT_SYMBOL_GPL(skcipher_register_instance); | ||
427 | |||
246 | MODULE_LICENSE("GPL"); | 428 | MODULE_LICENSE("GPL"); |
247 | MODULE_DESCRIPTION("Symmetric key cipher type"); | 429 | MODULE_DESCRIPTION("Symmetric key cipher type"); |