Commit 1ae978208e2ee9ba1b01d309164bc5e590cd242d

Authored by Herbert Xu
Committed by David S. Miller
1 parent e2ee95b8c6

[CRYPTO] api: Add aead crypto type

This patch adds crypto_aead which is the interface for AEAD
(Authenticated Encryption with Associated Data) algorithms.

AEAD algorithms perform authentication and encryption in one
step.  Traditionally users (such as IPsec) would use two
different crypto algorithms to perform these.  With AEAD
this comes down to one algorithm and one operation.

Of course if traditional algorithms were used we'd still
be doing two operations underneath.  However, real AEAD
algorithms may allow the underlying operations to be
optimised as well.

Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>

Showing 5 changed files with 312 additions and 0 deletions Side-by-side Diff

... ... @@ -28,6 +28,10 @@
28 28 tristate
29 29 select CRYPTO_BLKCIPHER
30 30  
  31 +config CRYPTO_AEAD
  32 + tristate
  33 + select CRYPTO_ALGAPI
  34 +
31 35 config CRYPTO_BLKCIPHER
32 36 tristate
33 37 select CRYPTO_ALGAPI
... ... @@ -9,6 +9,7 @@
9 9 obj-$(CONFIG_CRYPTO_ALGAPI) += crypto_algapi.o
10 10  
11 11 obj-$(CONFIG_CRYPTO_ABLKCIPHER) += ablkcipher.o
  12 +obj-$(CONFIG_CRYPTO_AEAD) += aead.o
12 13 obj-$(CONFIG_CRYPTO_BLKCIPHER) += blkcipher.o
13 14  
14 15 crypto_hash-objs := hash.o
  1 +/*
  2 + * AEAD: Authenticated Encryption with Associated Data
  3 + *
  4 + * This file provides API support for AEAD algorithms.
  5 + *
  6 + * Copyright (c) 2007 Herbert Xu <herbert@gondor.apana.org.au>
  7 + *
  8 + * This program is free software; you can redistribute it and/or modify it
  9 + * under the terms of the GNU General Public License as published by the Free
  10 + * Software Foundation; either version 2 of the License, or (at your option)
  11 + * any later version.
  12 + *
  13 + */
  14 +
  15 +#include <crypto/algapi.h>
  16 +#include <linux/errno.h>
  17 +#include <linux/init.h>
  18 +#include <linux/kernel.h>
  19 +#include <linux/module.h>
  20 +#include <linux/slab.h>
  21 +#include <linux/seq_file.h>
  22 +
  23 +static int setkey_unaligned(struct crypto_aead *tfm, const u8 *key,
  24 + unsigned int keylen)
  25 +{
  26 + struct aead_alg *aead = crypto_aead_alg(tfm);
  27 + unsigned long alignmask = crypto_aead_alignmask(tfm);
  28 + int ret;
  29 + u8 *buffer, *alignbuffer;
  30 + unsigned long absize;
  31 +
  32 + absize = keylen + alignmask;
  33 + buffer = kmalloc(absize, GFP_ATOMIC);
  34 + if (!buffer)
  35 + return -ENOMEM;
  36 +
  37 + alignbuffer = (u8 *)ALIGN((unsigned long)buffer, alignmask + 1);
  38 + memcpy(alignbuffer, key, keylen);
  39 + ret = aead->setkey(tfm, alignbuffer, keylen);
  40 + memset(alignbuffer, 0, keylen);
  41 + kfree(buffer);
  42 + return ret;
  43 +}
  44 +
  45 +static int setkey(struct crypto_aead *tfm, const u8 *key, unsigned int keylen)
  46 +{
  47 + struct aead_alg *aead = crypto_aead_alg(tfm);
  48 + unsigned long alignmask = crypto_aead_alignmask(tfm);
  49 +
  50 + if ((unsigned long)key & alignmask)
  51 + return setkey_unaligned(tfm, key, keylen);
  52 +
  53 + return aead->setkey(tfm, key, keylen);
  54 +}
  55 +
  56 +static unsigned int crypto_aead_ctxsize(struct crypto_alg *alg, u32 type,
  57 + u32 mask)
  58 +{
  59 + return alg->cra_ctxsize;
  60 +}
  61 +
  62 +static int crypto_init_aead_ops(struct crypto_tfm *tfm, u32 type, u32 mask)
  63 +{
  64 + struct aead_alg *alg = &tfm->__crt_alg->cra_aead;
  65 + struct aead_tfm *crt = &tfm->crt_aead;
  66 +
  67 + if (max(alg->authsize, alg->ivsize) > PAGE_SIZE / 8)
  68 + return -EINVAL;
  69 +
  70 + crt->setkey = setkey;
  71 + crt->encrypt = alg->encrypt;
  72 + crt->decrypt = alg->decrypt;
  73 + crt->ivsize = alg->ivsize;
  74 + crt->authsize = alg->authsize;
  75 +
  76 + return 0;
  77 +}
  78 +
  79 +static void crypto_aead_show(struct seq_file *m, struct crypto_alg *alg)
  80 + __attribute__ ((unused));
  81 +static void crypto_aead_show(struct seq_file *m, struct crypto_alg *alg)
  82 +{
  83 + struct aead_alg *aead = &alg->cra_aead;
  84 +
  85 + seq_printf(m, "type : aead\n");
  86 + seq_printf(m, "blocksize : %u\n", alg->cra_blocksize);
  87 + seq_printf(m, "ivsize : %u\n", aead->ivsize);
  88 + seq_printf(m, "authsize : %u\n", aead->authsize);
  89 +}
  90 +
  91 +const struct crypto_type crypto_aead_type = {
  92 + .ctxsize = crypto_aead_ctxsize,
  93 + .init = crypto_init_aead_ops,
  94 +#ifdef CONFIG_PROC_FS
  95 + .show = crypto_aead_show,
  96 +#endif
  97 +};
  98 +EXPORT_SYMBOL_GPL(crypto_aead_type);
  99 +
  100 +MODULE_LICENSE("GPL");
  101 +MODULE_DESCRIPTION("Authenticated Encryption with Associated Data (AEAD)");
include/crypto/algapi.h
... ... @@ -94,6 +94,7 @@
94 94 };
95 95  
96 96 extern const struct crypto_type crypto_ablkcipher_type;
  97 +extern const struct crypto_type crypto_aead_type;
97 98 extern const struct crypto_type crypto_blkcipher_type;
98 99 extern const struct crypto_type crypto_hash_type;
99 100  
... ... @@ -163,6 +164,11 @@
163 164 static inline void *crypto_ablkcipher_ctx_aligned(struct crypto_ablkcipher *tfm)
164 165 {
165 166 return crypto_tfm_ctx_aligned(&tfm->base);
  167 +}
  168 +
  169 +static inline struct aead_alg *crypto_aead_alg(struct crypto_aead *tfm)
  170 +{
  171 + return &crypto_aead_tfm(tfm)->__crt_alg->cra_aead;
166 172 }
167 173  
168 174 static inline struct crypto_blkcipher *crypto_spawn_blkcipher(
include/linux/crypto.h
... ... @@ -34,6 +34,7 @@
34 34 #define CRYPTO_ALG_TYPE_HASH 0x00000003
35 35 #define CRYPTO_ALG_TYPE_BLKCIPHER 0x00000004
36 36 #define CRYPTO_ALG_TYPE_COMPRESS 0x00000005
  37 +#define CRYPTO_ALG_TYPE_AEAD 0x00000006
37 38  
38 39 #define CRYPTO_ALG_TYPE_HASH_MASK 0x0000000e
39 40  
... ... @@ -91,6 +92,7 @@
91 92 struct scatterlist;
92 93 struct crypto_ablkcipher;
93 94 struct crypto_async_request;
  95 +struct crypto_aead;
94 96 struct crypto_blkcipher;
95 97 struct crypto_hash;
96 98 struct crypto_queue;
... ... @@ -121,6 +123,32 @@
121 123 void *__ctx[] CRYPTO_MINALIGN_ATTR;
122 124 };
123 125  
  126 +/**
  127 + * struct aead_request - AEAD request
  128 + * @base: Common attributes for async crypto requests
  129 + * @assoclen: Length in bytes of associated data for authentication
  130 + * @cryptlen: Length of data to be encrypted or decrypted
  131 + * @iv: Initialisation vector
  132 + * @assoc: Associated data
  133 + * @src: Source data
  134 + * @dst: Destination data
  135 + * @__ctx: Start of private context data
  136 + */
  137 +struct aead_request {
  138 + struct crypto_async_request base;
  139 +
  140 + unsigned int assoclen;
  141 + unsigned int cryptlen;
  142 +
  143 + u8 *iv;
  144 +
  145 + struct scatterlist *assoc;
  146 + struct scatterlist *src;
  147 + struct scatterlist *dst;
  148 +
  149 + void *__ctx[] CRYPTO_MINALIGN_ATTR;
  150 +};
  151 +
124 152 struct blkcipher_desc {
125 153 struct crypto_blkcipher *tfm;
126 154 void *info;
... ... @@ -157,6 +185,16 @@
157 185 unsigned int ivsize;
158 186 };
159 187  
  188 +struct aead_alg {
  189 + int (*setkey)(struct crypto_aead *tfm, const u8 *key,
  190 + unsigned int keylen);
  191 + int (*encrypt)(struct aead_request *req);
  192 + int (*decrypt)(struct aead_request *req);
  193 +
  194 + unsigned int ivsize;
  195 + unsigned int authsize;
  196 +};
  197 +
160 198 struct blkcipher_alg {
161 199 int (*setkey)(struct crypto_tfm *tfm, const u8 *key,
162 200 unsigned int keylen);
... ... @@ -212,6 +250,7 @@
212 250 };
213 251  
214 252 #define cra_ablkcipher cra_u.ablkcipher
  253 +#define cra_aead cra_u.aead
215 254 #define cra_blkcipher cra_u.blkcipher
216 255 #define cra_cipher cra_u.cipher
217 256 #define cra_digest cra_u.digest
... ... @@ -237,6 +276,7 @@
237 276  
238 277 union {
239 278 struct ablkcipher_alg ablkcipher;
  279 + struct aead_alg aead;
240 280 struct blkcipher_alg blkcipher;
241 281 struct cipher_alg cipher;
242 282 struct digest_alg digest;
... ... @@ -284,6 +324,16 @@
284 324 unsigned int reqsize;
285 325 };
286 326  
  327 +struct aead_tfm {
  328 + int (*setkey)(struct crypto_aead *tfm, const u8 *key,
  329 + unsigned int keylen);
  330 + int (*encrypt)(struct aead_request *req);
  331 + int (*decrypt)(struct aead_request *req);
  332 + unsigned int ivsize;
  333 + unsigned int authsize;
  334 + unsigned int reqsize;
  335 +};
  336 +
287 337 struct blkcipher_tfm {
288 338 void *iv;
289 339 int (*setkey)(struct crypto_tfm *tfm, const u8 *key,
... ... @@ -323,6 +373,7 @@
323 373 };
324 374  
325 375 #define crt_ablkcipher crt_u.ablkcipher
  376 +#define crt_aead crt_u.aead
326 377 #define crt_blkcipher crt_u.blkcipher
327 378 #define crt_cipher crt_u.cipher
328 379 #define crt_hash crt_u.hash
... ... @@ -334,6 +385,7 @@
334 385  
335 386 union {
336 387 struct ablkcipher_tfm ablkcipher;
  388 + struct aead_tfm aead;
337 389 struct blkcipher_tfm blkcipher;
338 390 struct cipher_tfm cipher;
339 391 struct hash_tfm hash;
... ... @@ -349,6 +401,10 @@
349 401 struct crypto_tfm base;
350 402 };
351 403  
  404 +struct crypto_aead {
  405 + struct crypto_tfm base;
  406 +};
  407 +
352 408 struct crypto_blkcipher {
353 409 struct crypto_tfm base;
354 410 };
... ... @@ -617,6 +673,150 @@
617 673 req->dst = dst;
618 674 req->nbytes = nbytes;
619 675 req->info = iv;
  676 +}
  677 +
  678 +static inline struct crypto_aead *__crypto_aead_cast(struct crypto_tfm *tfm)
  679 +{
  680 + return (struct crypto_aead *)tfm;
  681 +}
  682 +
  683 +static inline struct crypto_aead *crypto_alloc_aead(const char *alg_name,
  684 + u32 type, u32 mask)
  685 +{
  686 + type &= ~CRYPTO_ALG_TYPE_MASK;
  687 + type |= CRYPTO_ALG_TYPE_AEAD;
  688 + mask |= CRYPTO_ALG_TYPE_MASK;
  689 +
  690 + return __crypto_aead_cast(crypto_alloc_base(alg_name, type, mask));
  691 +}
  692 +
  693 +static inline struct crypto_tfm *crypto_aead_tfm(struct crypto_aead *tfm)
  694 +{
  695 + return &tfm->base;
  696 +}
  697 +
  698 +static inline void crypto_free_aead(struct crypto_aead *tfm)
  699 +{
  700 + crypto_free_tfm(crypto_aead_tfm(tfm));
  701 +}
  702 +
  703 +static inline struct aead_tfm *crypto_aead_crt(struct crypto_aead *tfm)
  704 +{
  705 + return &crypto_aead_tfm(tfm)->crt_aead;
  706 +}
  707 +
  708 +static inline unsigned int crypto_aead_ivsize(struct crypto_aead *tfm)
  709 +{
  710 + return crypto_aead_crt(tfm)->ivsize;
  711 +}
  712 +
  713 +static inline unsigned int crypto_aead_authsize(struct crypto_aead *tfm)
  714 +{
  715 + return crypto_aead_crt(tfm)->authsize;
  716 +}
  717 +
  718 +static inline unsigned int crypto_aead_blocksize(struct crypto_aead *tfm)
  719 +{
  720 + return crypto_tfm_alg_blocksize(crypto_aead_tfm(tfm));
  721 +}
  722 +
  723 +static inline unsigned int crypto_aead_alignmask(struct crypto_aead *tfm)
  724 +{
  725 + return crypto_tfm_alg_alignmask(crypto_aead_tfm(tfm));
  726 +}
  727 +
  728 +static inline u32 crypto_aead_get_flags(struct crypto_aead *tfm)
  729 +{
  730 + return crypto_tfm_get_flags(crypto_aead_tfm(tfm));
  731 +}
  732 +
  733 +static inline void crypto_aead_set_flags(struct crypto_aead *tfm, u32 flags)
  734 +{
  735 + crypto_tfm_set_flags(crypto_aead_tfm(tfm), flags);
  736 +}
  737 +
  738 +static inline void crypto_aead_clear_flags(struct crypto_aead *tfm, u32 flags)
  739 +{
  740 + crypto_tfm_clear_flags(crypto_aead_tfm(tfm), flags);
  741 +}
  742 +
  743 +static inline int crypto_aead_setkey(struct crypto_aead *tfm, const u8 *key,
  744 + unsigned int keylen)
  745 +{
  746 + return crypto_aead_crt(tfm)->setkey(tfm, key, keylen);
  747 +}
  748 +
  749 +static inline struct crypto_aead *crypto_aead_reqtfm(struct aead_request *req)
  750 +{
  751 + return __crypto_aead_cast(req->base.tfm);
  752 +}
  753 +
  754 +static inline int crypto_aead_encrypt(struct aead_request *req)
  755 +{
  756 + return crypto_aead_crt(crypto_aead_reqtfm(req))->encrypt(req);
  757 +}
  758 +
  759 +static inline int crypto_aead_decrypt(struct aead_request *req)
  760 +{
  761 + return crypto_aead_crt(crypto_aead_reqtfm(req))->decrypt(req);
  762 +}
  763 +
  764 +static inline int crypto_aead_reqsize(struct crypto_aead *tfm)
  765 +{
  766 + return crypto_aead_crt(tfm)->reqsize;
  767 +}
  768 +
  769 +static inline void aead_request_set_tfm(struct aead_request *req,
  770 + struct crypto_aead *tfm)
  771 +{
  772 + req->base.tfm = crypto_aead_tfm(tfm);
  773 +}
  774 +
  775 +static inline struct aead_request *aead_request_alloc(struct crypto_aead *tfm,
  776 + gfp_t gfp)
  777 +{
  778 + struct aead_request *req;
  779 +
  780 + req = kmalloc(sizeof(*req) + crypto_aead_reqsize(tfm), gfp);
  781 +
  782 + if (likely(req))
  783 + aead_request_set_tfm(req, tfm);
  784 +
  785 + return req;
  786 +}
  787 +
  788 +static inline void aead_request_free(struct aead_request *req)
  789 +{
  790 + kfree(req);
  791 +}
  792 +
  793 +static inline void aead_request_set_callback(struct aead_request *req,
  794 + u32 flags,
  795 + crypto_completion_t complete,
  796 + void *data)
  797 +{
  798 + req->base.complete = complete;
  799 + req->base.data = data;
  800 + req->base.flags = flags;
  801 +}
  802 +
  803 +static inline void aead_request_set_crypt(struct aead_request *req,
  804 + struct scatterlist *src,
  805 + struct scatterlist *dst,
  806 + unsigned int cryptlen, u8 *iv)
  807 +{
  808 + req->src = src;
  809 + req->dst = dst;
  810 + req->cryptlen = cryptlen;
  811 + req->iv = iv;
  812 +}
  813 +
  814 +static inline void aead_request_set_assoc(struct aead_request *req,
  815 + struct scatterlist *assoc,
  816 + unsigned int assoclen)
  817 +{
  818 + req->assoc = assoc;
  819 + req->assoclen = assoclen;
620 820 }
621 821  
622 822 static inline struct crypto_blkcipher *__crypto_blkcipher_cast(