aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorHerbert Xu <herbert@gondor.apana.org.au>2007-03-23 23:35:34 -0400
committerHerbert Xu <herbert@gondor.apana.org.au>2007-05-02 00:38:30 -0400
commit32e3983fe590ac4cd70c7728eb330d43cef031a7 (patch)
tree9e239c4d2f208578fd400c2abb31e8ae7788de4b
parent03f5d8cedb31deb558cd97095730cbc8bc54b12a (diff)
[CRYPTO] api: Add async block cipher interface
This patch adds the frontend interface for asynchronous block ciphers. In addition to the usual block cipher parameters, there is a callback function pointer and a data pointer. The callback will be invoked only if the encrypt/decrypt handlers return -EINPROGRESS. In other words, if the return value of zero the completion handler (or the equivalent code) needs to be invoked by the caller. The request structure is allocated and freed by the caller. Its size is determined by calling crypto_ablkcipher_reqsize(). The helpers ablkcipher_request_alloc/ablkcipher_request_free can be used to manage the memory for a request. Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>
-rw-r--r--crypto/blkcipher.c70
-rw-r--r--include/linux/crypto.h199
2 files changed, 260 insertions, 9 deletions
diff --git a/crypto/blkcipher.c b/crypto/blkcipher.c
index bf459179efe..8edf40c835a 100644
--- a/crypto/blkcipher.c
+++ b/crypto/blkcipher.c
@@ -349,13 +349,48 @@ static int setkey(struct crypto_tfm *tfm, const u8 *key,
349 return cipher->setkey(tfm, key, keylen); 349 return cipher->setkey(tfm, key, keylen);
350} 350}
351 351
352static int async_setkey(struct crypto_ablkcipher *tfm, const u8 *key,
353 unsigned int keylen)
354{
355 return setkey(crypto_ablkcipher_tfm(tfm), key, keylen);
356}
357
358static int async_encrypt(struct ablkcipher_request *req)
359{
360 struct crypto_tfm *tfm = req->base.tfm;
361 struct blkcipher_alg *alg = &tfm->__crt_alg->cra_blkcipher;
362 struct blkcipher_desc desc = {
363 .tfm = __crypto_blkcipher_cast(tfm),
364 .info = req->info,
365 .flags = req->base.flags,
366 };
367
368
369 return alg->encrypt(&desc, req->dst, req->src, req->nbytes);
370}
371
372static int async_decrypt(struct ablkcipher_request *req)
373{
374 struct crypto_tfm *tfm = req->base.tfm;
375 struct blkcipher_alg *alg = &tfm->__crt_alg->cra_blkcipher;
376 struct blkcipher_desc desc = {
377 .tfm = __crypto_blkcipher_cast(tfm),
378 .info = req->info,
379 .flags = req->base.flags,
380 };
381
382 return alg->decrypt(&desc, req->dst, req->src, req->nbytes);
383}
384
352static unsigned int crypto_blkcipher_ctxsize(struct crypto_alg *alg, u32 type, 385static unsigned int crypto_blkcipher_ctxsize(struct crypto_alg *alg, u32 type,
353 u32 mask) 386 u32 mask)
354{ 387{
355 struct blkcipher_alg *cipher = &alg->cra_blkcipher; 388 struct blkcipher_alg *cipher = &alg->cra_blkcipher;
356 unsigned int len = alg->cra_ctxsize; 389 unsigned int len = alg->cra_ctxsize;
357 390
358 if (cipher->ivsize) { 391 type ^= CRYPTO_ALG_ASYNC;
392 mask &= CRYPTO_ALG_ASYNC;
393 if ((type & mask) && cipher->ivsize) {
359 len = ALIGN(len, (unsigned long)alg->cra_alignmask + 1); 394 len = ALIGN(len, (unsigned long)alg->cra_alignmask + 1);
360 len += cipher->ivsize; 395 len += cipher->ivsize;
361 } 396 }
@@ -363,16 +398,26 @@ static unsigned int crypto_blkcipher_ctxsize(struct crypto_alg *alg, u32 type,
363 return len; 398 return len;
364} 399}
365 400
366static int crypto_init_blkcipher_ops(struct crypto_tfm *tfm, u32 type, u32 mask) 401static int crypto_init_blkcipher_ops_async(struct crypto_tfm *tfm)
402{
403 struct ablkcipher_tfm *crt = &tfm->crt_ablkcipher;
404 struct blkcipher_alg *alg = &tfm->__crt_alg->cra_blkcipher;
405
406 crt->setkey = async_setkey;
407 crt->encrypt = async_encrypt;
408 crt->decrypt = async_decrypt;
409 crt->ivsize = alg->ivsize;
410
411 return 0;
412}
413
414static int crypto_init_blkcipher_ops_sync(struct crypto_tfm *tfm)
367{ 415{
368 struct blkcipher_tfm *crt = &tfm->crt_blkcipher; 416 struct blkcipher_tfm *crt = &tfm->crt_blkcipher;
369 struct blkcipher_alg *alg = &tfm->__crt_alg->cra_blkcipher; 417 struct blkcipher_alg *alg = &tfm->__crt_alg->cra_blkcipher;
370 unsigned long align = crypto_tfm_alg_alignmask(tfm) + 1; 418 unsigned long align = crypto_tfm_alg_alignmask(tfm) + 1;
371 unsigned long addr; 419 unsigned long addr;
372 420
373 if (alg->ivsize > PAGE_SIZE / 8)
374 return -EINVAL;
375
376 crt->setkey = setkey; 421 crt->setkey = setkey;
377 crt->encrypt = alg->encrypt; 422 crt->encrypt = alg->encrypt;
378 crt->decrypt = alg->decrypt; 423 crt->decrypt = alg->decrypt;
@@ -385,6 +430,21 @@ static int crypto_init_blkcipher_ops(struct crypto_tfm *tfm, u32 type, u32 mask)
385 return 0; 430 return 0;
386} 431}
387 432
433static int crypto_init_blkcipher_ops(struct crypto_tfm *tfm, u32 type, u32 mask)
434{
435 struct blkcipher_alg *alg = &tfm->__crt_alg->cra_blkcipher;
436
437 if (alg->ivsize > PAGE_SIZE / 8)
438 return -EINVAL;
439
440 type ^= CRYPTO_ALG_ASYNC;
441 mask &= CRYPTO_ALG_ASYNC;
442 if (type & mask)
443 return crypto_init_blkcipher_ops_sync(tfm);
444 else
445 return crypto_init_blkcipher_ops_async(tfm);
446}
447
388static void crypto_blkcipher_show(struct seq_file *m, struct crypto_alg *alg) 448static void crypto_blkcipher_show(struct seq_file *m, struct crypto_alg *alg)
389 __attribute__ ((unused)); 449 __attribute__ ((unused));
390static void crypto_blkcipher_show(struct seq_file *m, struct crypto_alg *alg) 450static void crypto_blkcipher_show(struct seq_file *m, struct crypto_alg *alg)
diff --git a/include/linux/crypto.h b/include/linux/crypto.h
index 779aa78ee64..d4d05313280 100644
--- a/include/linux/crypto.h
+++ b/include/linux/crypto.h
@@ -56,6 +56,7 @@
56 56
57#define CRYPTO_TFM_REQ_WEAK_KEY 0x00000100 57#define CRYPTO_TFM_REQ_WEAK_KEY 0x00000100
58#define CRYPTO_TFM_REQ_MAY_SLEEP 0x00000200 58#define CRYPTO_TFM_REQ_MAY_SLEEP 0x00000200
59#define CRYPTO_TFM_REQ_MAY_BACKLOG 0x00000400
59#define CRYPTO_TFM_RES_WEAK_KEY 0x00100000 60#define CRYPTO_TFM_RES_WEAK_KEY 0x00100000
60#define CRYPTO_TFM_RES_BAD_KEY_LEN 0x00200000 61#define CRYPTO_TFM_RES_BAD_KEY_LEN 0x00200000
61#define CRYPTO_TFM_RES_BAD_KEY_SCHED 0x00400000 62#define CRYPTO_TFM_RES_BAD_KEY_SCHED 0x00400000
@@ -88,11 +89,37 @@
88#endif 89#endif
89 90
90struct scatterlist; 91struct scatterlist;
92struct crypto_ablkcipher;
93struct crypto_async_request;
91struct crypto_blkcipher; 94struct crypto_blkcipher;
92struct crypto_hash; 95struct crypto_hash;
93struct crypto_tfm; 96struct crypto_tfm;
94struct crypto_type; 97struct crypto_type;
95 98
99typedef void (*crypto_completion_t)(struct crypto_async_request *req, int err);
100
101struct crypto_async_request {
102 struct list_head list;
103 crypto_completion_t complete;
104 void *data;
105 struct crypto_tfm *tfm;
106
107 u32 flags;
108};
109
110struct ablkcipher_request {
111 struct crypto_async_request base;
112
113 unsigned int nbytes;
114
115 void *info;
116
117 struct scatterlist *src;
118 struct scatterlist *dst;
119
120 void *__ctx[] CRYPTO_MINALIGN_ATTR;
121};
122
96struct blkcipher_desc { 123struct blkcipher_desc {
97 struct crypto_blkcipher *tfm; 124 struct crypto_blkcipher *tfm;
98 void *info; 125 void *info;
@@ -232,6 +259,15 @@ static inline int crypto_has_alg(const char *name, u32 type, u32 mask)
232 * crypto_free_*(), as well as the various helpers below. 259 * crypto_free_*(), as well as the various helpers below.
233 */ 260 */
234 261
262struct ablkcipher_tfm {
263 int (*setkey)(struct crypto_ablkcipher *tfm, const u8 *key,
264 unsigned int keylen);
265 int (*encrypt)(struct ablkcipher_request *req);
266 int (*decrypt)(struct ablkcipher_request *req);
267 unsigned int ivsize;
268 unsigned int reqsize;
269};
270
235struct blkcipher_tfm { 271struct blkcipher_tfm {
236 void *iv; 272 void *iv;
237 int (*setkey)(struct crypto_tfm *tfm, const u8 *key, 273 int (*setkey)(struct crypto_tfm *tfm, const u8 *key,
@@ -290,6 +326,7 @@ struct compress_tfm {
290 u8 *dst, unsigned int *dlen); 326 u8 *dst, unsigned int *dlen);
291}; 327};
292 328
329#define crt_ablkcipher crt_u.ablkcipher
293#define crt_blkcipher crt_u.blkcipher 330#define crt_blkcipher crt_u.blkcipher
294#define crt_cipher crt_u.cipher 331#define crt_cipher crt_u.cipher
295#define crt_hash crt_u.hash 332#define crt_hash crt_u.hash
@@ -300,6 +337,7 @@ struct crypto_tfm {
300 u32 crt_flags; 337 u32 crt_flags;
301 338
302 union { 339 union {
340 struct ablkcipher_tfm ablkcipher;
303 struct blkcipher_tfm blkcipher; 341 struct blkcipher_tfm blkcipher;
304 struct cipher_tfm cipher; 342 struct cipher_tfm cipher;
305 struct hash_tfm hash; 343 struct hash_tfm hash;
@@ -311,6 +349,10 @@ struct crypto_tfm {
311 void *__crt_ctx[] CRYPTO_MINALIGN_ATTR; 349 void *__crt_ctx[] CRYPTO_MINALIGN_ATTR;
312}; 350};
313 351
352struct crypto_ablkcipher {
353 struct crypto_tfm base;
354};
355
314struct crypto_blkcipher { 356struct crypto_blkcipher {
315 struct crypto_tfm base; 357 struct crypto_tfm base;
316}; 358};
@@ -411,6 +453,155 @@ static inline unsigned int crypto_tfm_ctx_alignment(void)
411/* 453/*
412 * API wrappers. 454 * API wrappers.
413 */ 455 */
456static inline struct crypto_ablkcipher *__crypto_ablkcipher_cast(
457 struct crypto_tfm *tfm)
458{
459 return (struct crypto_ablkcipher *)tfm;
460}
461
462static inline struct crypto_ablkcipher *crypto_alloc_ablkcipher(
463 const char *alg_name, u32 type, u32 mask)
464{
465 type &= ~CRYPTO_ALG_TYPE_MASK;
466 type |= CRYPTO_ALG_TYPE_BLKCIPHER;
467 mask |= CRYPTO_ALG_TYPE_MASK;
468
469 return __crypto_ablkcipher_cast(
470 crypto_alloc_base(alg_name, type, mask));
471}
472
473static inline struct crypto_tfm *crypto_ablkcipher_tfm(
474 struct crypto_ablkcipher *tfm)
475{
476 return &tfm->base;
477}
478
479static inline void crypto_free_ablkcipher(struct crypto_ablkcipher *tfm)
480{
481 crypto_free_tfm(crypto_ablkcipher_tfm(tfm));
482}
483
484static inline int crypto_has_ablkcipher(const char *alg_name, u32 type,
485 u32 mask)
486{
487 type &= ~CRYPTO_ALG_TYPE_MASK;
488 type |= CRYPTO_ALG_TYPE_BLKCIPHER;
489 mask |= CRYPTO_ALG_TYPE_MASK;
490
491 return crypto_has_alg(alg_name, type, mask);
492}
493
494static inline struct ablkcipher_tfm *crypto_ablkcipher_crt(
495 struct crypto_ablkcipher *tfm)
496{
497 return &crypto_ablkcipher_tfm(tfm)->crt_ablkcipher;
498}
499
500static inline unsigned int crypto_ablkcipher_ivsize(
501 struct crypto_ablkcipher *tfm)
502{
503 return crypto_ablkcipher_crt(tfm)->ivsize;
504}
505
506static inline unsigned int crypto_ablkcipher_blocksize(
507 struct crypto_ablkcipher *tfm)
508{
509 return crypto_tfm_alg_blocksize(crypto_ablkcipher_tfm(tfm));
510}
511
512static inline unsigned int crypto_ablkcipher_alignmask(
513 struct crypto_ablkcipher *tfm)
514{
515 return crypto_tfm_alg_alignmask(crypto_ablkcipher_tfm(tfm));
516}
517
518static inline u32 crypto_ablkcipher_get_flags(struct crypto_ablkcipher *tfm)
519{
520 return crypto_tfm_get_flags(crypto_ablkcipher_tfm(tfm));
521}
522
523static inline void crypto_ablkcipher_set_flags(struct crypto_ablkcipher *tfm,
524 u32 flags)
525{
526 crypto_tfm_set_flags(crypto_ablkcipher_tfm(tfm), flags);
527}
528
529static inline void crypto_ablkcipher_clear_flags(struct crypto_ablkcipher *tfm,
530 u32 flags)
531{
532 crypto_tfm_clear_flags(crypto_ablkcipher_tfm(tfm), flags);
533}
534
535static inline int crypto_ablkcipher_setkey(struct crypto_ablkcipher *tfm,
536 const u8 *key, unsigned int keylen)
537{
538 return crypto_ablkcipher_crt(tfm)->setkey(tfm, key, keylen);
539}
540
541static inline struct crypto_ablkcipher *crypto_ablkcipher_reqtfm(
542 struct ablkcipher_request *req)
543{
544 return __crypto_ablkcipher_cast(req->base.tfm);
545}
546
547static inline int crypto_ablkcipher_encrypt(struct ablkcipher_request *req)
548{
549 struct ablkcipher_tfm *crt =
550 crypto_ablkcipher_crt(crypto_ablkcipher_reqtfm(req));
551 return crt->encrypt(req);
552}
553
554static inline int crypto_ablkcipher_decrypt(struct ablkcipher_request *req)
555{
556 struct ablkcipher_tfm *crt =
557 crypto_ablkcipher_crt(crypto_ablkcipher_reqtfm(req));
558 return crt->decrypt(req);
559}
560
561static inline int crypto_ablkcipher_reqsize(struct crypto_ablkcipher *tfm)
562{
563 return crypto_ablkcipher_crt(tfm)->reqsize;
564}
565
566static inline struct ablkcipher_request *ablkcipher_request_alloc(
567 struct crypto_ablkcipher *tfm, gfp_t gfp)
568{
569 struct ablkcipher_request *req;
570
571 req = kmalloc(sizeof(struct ablkcipher_request) +
572 crypto_ablkcipher_reqsize(tfm), gfp);
573
574 if (likely(req))
575 req->base.tfm = crypto_ablkcipher_tfm(tfm);
576
577 return req;
578}
579
580static inline void ablkcipher_request_free(struct ablkcipher_request *req)
581{
582 kfree(req);
583}
584
585static inline void ablkcipher_request_set_callback(
586 struct ablkcipher_request *req,
587 u32 flags, crypto_completion_t complete, void *data)
588{
589 req->base.complete = complete;
590 req->base.data = data;
591 req->base.flags = flags;
592}
593
594static inline void ablkcipher_request_set_crypt(
595 struct ablkcipher_request *req,
596 struct scatterlist *src, struct scatterlist *dst,
597 unsigned int nbytes, void *iv)
598{
599 req->src = src;
600 req->dst = dst;
601 req->nbytes = nbytes;
602 req->info = iv;
603}
604
414static inline struct crypto_blkcipher *__crypto_blkcipher_cast( 605static inline struct crypto_blkcipher *__crypto_blkcipher_cast(
415 struct crypto_tfm *tfm) 606 struct crypto_tfm *tfm)
416{ 607{
@@ -427,9 +618,9 @@ static inline struct crypto_blkcipher *crypto_blkcipher_cast(
427static inline struct crypto_blkcipher *crypto_alloc_blkcipher( 618static inline struct crypto_blkcipher *crypto_alloc_blkcipher(
428 const char *alg_name, u32 type, u32 mask) 619 const char *alg_name, u32 type, u32 mask)
429{ 620{
430 type &= ~CRYPTO_ALG_TYPE_MASK; 621 type &= ~(CRYPTO_ALG_TYPE_MASK | CRYPTO_ALG_ASYNC);
431 type |= CRYPTO_ALG_TYPE_BLKCIPHER; 622 type |= CRYPTO_ALG_TYPE_BLKCIPHER;
432 mask |= CRYPTO_ALG_TYPE_MASK; 623 mask |= CRYPTO_ALG_TYPE_MASK | CRYPTO_ALG_ASYNC;
433 624
434 return __crypto_blkcipher_cast(crypto_alloc_base(alg_name, type, mask)); 625 return __crypto_blkcipher_cast(crypto_alloc_base(alg_name, type, mask));
435} 626}
@@ -447,9 +638,9 @@ static inline void crypto_free_blkcipher(struct crypto_blkcipher *tfm)
447 638
448static inline int crypto_has_blkcipher(const char *alg_name, u32 type, u32 mask) 639static inline int crypto_has_blkcipher(const char *alg_name, u32 type, u32 mask)
449{ 640{
450 type &= ~CRYPTO_ALG_TYPE_MASK; 641 type &= ~(CRYPTO_ALG_TYPE_MASK | CRYPTO_ALG_ASYNC);
451 type |= CRYPTO_ALG_TYPE_BLKCIPHER; 642 type |= CRYPTO_ALG_TYPE_BLKCIPHER;
452 mask |= CRYPTO_ALG_TYPE_MASK; 643 mask |= CRYPTO_ALG_TYPE_MASK | CRYPTO_ALG_ASYNC;
453 644
454 return crypto_has_alg(alg_name, type, mask); 645 return crypto_has_alg(alg_name, type, mask);
455} 646}