summaryrefslogtreecommitdiffstats
path: root/crypto/skcipher.c
diff options
context:
space:
mode:
authorHerbert Xu <herbert@gondor.apana.org.au>2016-07-12 01:17:31 -0400
committerHerbert Xu <herbert@gondor.apana.org.au>2016-07-18 05:35:36 -0400
commit4e6c3df4d729f85997cbf276bfa8ffd8579b8e77 (patch)
tree3293b9ab0a019308724c8b44430cadc0a3b4488d /crypto/skcipher.c
parenteb9bc8e7afaa9f062105dad55ec1c0663d961bb3 (diff)
crypto: skcipher - Add low-level skcipher interface
This patch allows skcipher algorithms and instances to be created and registered with the crypto API. They are accessible through the top-level skcipher interface, along with ablkcipher/blkcipher algorithms and instances. This patch also introduces a new parameter called chunk size which is meant for ciphers such as CTR and CTS which ostensibly can handle arbitrary lengths, but still behave like block ciphers in that you can only process a partial block at the very end. For these ciphers the block size will continue to be set to 1 as it is now while the chunk size will be set to the underlying block size. Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>
Diffstat (limited to 'crypto/skcipher.c')
-rw-r--r--crypto/skcipher.c196
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
34static int skcipher_setkey_blkcipher(struct crypto_skcipher *tfm, 39static 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
224static 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
219static int crypto_skcipher_init_tfm(struct crypto_tfm *tfm) 232static 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
259static 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
267static void crypto_skcipher_show(struct seq_file *m, struct crypto_alg *alg)
268 __attribute__ ((unused));
269static 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
285static 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
304nla_put_failure:
305 return -EMSGSIZE;
306}
307#else
308static int crypto_skcipher_report(struct sk_buff *skb, struct crypto_alg *alg)
309{
310 return -ENOSYS;
311}
312#endif
313
230static const struct crypto_type crypto_skcipher_type2 = { 314static 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
328int 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}
334EXPORT_SYMBOL_GPL(crypto_grab_skcipher2);
335
239struct crypto_skcipher *crypto_alloc_skcipher(const char *alg_name, 336struct 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}
244EXPORT_SYMBOL_GPL(crypto_alloc_skcipher); 341EXPORT_SYMBOL_GPL(crypto_alloc_skcipher);
245 342
343int 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}
348EXPORT_SYMBOL_GPL(crypto_has_skcipher2);
349
350static 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
367int 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}
378EXPORT_SYMBOL_GPL(crypto_register_skcipher);
379
380void crypto_unregister_skcipher(struct skcipher_alg *alg)
381{
382 crypto_unregister_alg(&alg->base);
383}
384EXPORT_SYMBOL_GPL(crypto_unregister_skcipher);
385
386int 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
398err:
399 for (--i; i >= 0; --i)
400 crypto_unregister_skcipher(&algs[i]);
401
402 return ret;
403}
404EXPORT_SYMBOL_GPL(crypto_register_skciphers);
405
406void 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}
413EXPORT_SYMBOL_GPL(crypto_unregister_skciphers);
414
415int 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}
426EXPORT_SYMBOL_GPL(skcipher_register_instance);
427
246MODULE_LICENSE("GPL"); 428MODULE_LICENSE("GPL");
247MODULE_DESCRIPTION("Symmetric key cipher type"); 429MODULE_DESCRIPTION("Symmetric key cipher type");