diff options
-rw-r--r-- | crypto/Kconfig | 4 | ||||
-rw-r--r-- | crypto/Makefile | 1 | ||||
-rw-r--r-- | crypto/aead.c | 101 | ||||
-rw-r--r-- | include/crypto/algapi.h | 6 | ||||
-rw-r--r-- | include/linux/crypto.h | 200 |
5 files changed, 312 insertions, 0 deletions
diff --git a/crypto/Kconfig b/crypto/Kconfig index 981497c89752..f42bc7715f48 100644 --- a/crypto/Kconfig +++ b/crypto/Kconfig | |||
@@ -28,6 +28,10 @@ config CRYPTO_ABLKCIPHER | |||
28 | tristate | 28 | tristate |
29 | select CRYPTO_BLKCIPHER | 29 | select CRYPTO_BLKCIPHER |
30 | 30 | ||
31 | config CRYPTO_AEAD | ||
32 | tristate | ||
33 | select CRYPTO_ALGAPI | ||
34 | |||
31 | config CRYPTO_BLKCIPHER | 35 | config CRYPTO_BLKCIPHER |
32 | tristate | 36 | tristate |
33 | select CRYPTO_ALGAPI | 37 | select CRYPTO_ALGAPI |
diff --git a/crypto/Makefile b/crypto/Makefile index a070dcc074ff..9821c5ba054e 100644 --- a/crypto/Makefile +++ b/crypto/Makefile | |||
@@ -9,6 +9,7 @@ crypto_algapi-objs := algapi.o $(crypto_algapi-y) | |||
9 | obj-$(CONFIG_CRYPTO_ALGAPI) += crypto_algapi.o | 9 | obj-$(CONFIG_CRYPTO_ALGAPI) += crypto_algapi.o |
10 | 10 | ||
11 | obj-$(CONFIG_CRYPTO_ABLKCIPHER) += ablkcipher.o | 11 | obj-$(CONFIG_CRYPTO_ABLKCIPHER) += ablkcipher.o |
12 | obj-$(CONFIG_CRYPTO_AEAD) += aead.o | ||
12 | obj-$(CONFIG_CRYPTO_BLKCIPHER) += blkcipher.o | 13 | obj-$(CONFIG_CRYPTO_BLKCIPHER) += blkcipher.o |
13 | 14 | ||
14 | crypto_hash-objs := hash.o | 15 | crypto_hash-objs := hash.o |
diff --git a/crypto/aead.c b/crypto/aead.c new file mode 100644 index 000000000000..84a3501fb478 --- /dev/null +++ b/crypto/aead.c | |||
@@ -0,0 +1,101 @@ | |||
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)"); | ||
diff --git a/include/crypto/algapi.h b/include/crypto/algapi.h index 8081294e4328..290bce0c5bd5 100644 --- a/include/crypto/algapi.h +++ b/include/crypto/algapi.h | |||
@@ -94,6 +94,7 @@ struct blkcipher_walk { | |||
94 | }; | 94 | }; |
95 | 95 | ||
96 | extern const struct crypto_type crypto_ablkcipher_type; | 96 | extern const struct crypto_type crypto_ablkcipher_type; |
97 | extern const struct crypto_type crypto_aead_type; | ||
97 | extern const struct crypto_type crypto_blkcipher_type; | 98 | extern const struct crypto_type crypto_blkcipher_type; |
98 | extern const struct crypto_type crypto_hash_type; | 99 | extern const struct crypto_type crypto_hash_type; |
99 | 100 | ||
@@ -165,6 +166,11 @@ static inline void *crypto_ablkcipher_ctx_aligned(struct crypto_ablkcipher *tfm) | |||
165 | return crypto_tfm_ctx_aligned(&tfm->base); | 166 | return crypto_tfm_ctx_aligned(&tfm->base); |
166 | } | 167 | } |
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; | ||
172 | } | ||
173 | |||
168 | static inline struct crypto_blkcipher *crypto_spawn_blkcipher( | 174 | static inline struct crypto_blkcipher *crypto_spawn_blkcipher( |
169 | struct crypto_spawn *spawn) | 175 | struct crypto_spawn *spawn) |
170 | { | 176 | { |
diff --git a/include/linux/crypto.h b/include/linux/crypto.h index 357e8cfedc37..1072f9abaef6 100644 --- a/include/linux/crypto.h +++ b/include/linux/crypto.h | |||
@@ -34,6 +34,7 @@ | |||
34 | #define CRYPTO_ALG_TYPE_HASH 0x00000003 | 34 | #define CRYPTO_ALG_TYPE_HASH 0x00000003 |
35 | #define CRYPTO_ALG_TYPE_BLKCIPHER 0x00000004 | 35 | #define CRYPTO_ALG_TYPE_BLKCIPHER 0x00000004 |
36 | #define CRYPTO_ALG_TYPE_COMPRESS 0x00000005 | 36 | #define CRYPTO_ALG_TYPE_COMPRESS 0x00000005 |
37 | #define CRYPTO_ALG_TYPE_AEAD 0x00000006 | ||
37 | 38 | ||
38 | #define CRYPTO_ALG_TYPE_HASH_MASK 0x0000000e | 39 | #define CRYPTO_ALG_TYPE_HASH_MASK 0x0000000e |
39 | 40 | ||
@@ -91,6 +92,7 @@ | |||
91 | struct scatterlist; | 92 | struct scatterlist; |
92 | struct crypto_ablkcipher; | 93 | struct crypto_ablkcipher; |
93 | struct crypto_async_request; | 94 | struct crypto_async_request; |
95 | struct crypto_aead; | ||
94 | struct crypto_blkcipher; | 96 | struct crypto_blkcipher; |
95 | struct crypto_hash; | 97 | struct crypto_hash; |
96 | struct crypto_queue; | 98 | struct crypto_queue; |
@@ -121,6 +123,32 @@ struct ablkcipher_request { | |||
121 | void *__ctx[] CRYPTO_MINALIGN_ATTR; | 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 | struct blkcipher_desc { | 152 | struct blkcipher_desc { |
125 | struct crypto_blkcipher *tfm; | 153 | struct crypto_blkcipher *tfm; |
126 | void *info; | 154 | void *info; |
@@ -157,6 +185,16 @@ struct ablkcipher_alg { | |||
157 | unsigned int ivsize; | 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 | struct blkcipher_alg { | 198 | struct blkcipher_alg { |
161 | int (*setkey)(struct crypto_tfm *tfm, const u8 *key, | 199 | int (*setkey)(struct crypto_tfm *tfm, const u8 *key, |
162 | unsigned int keylen); | 200 | unsigned int keylen); |
@@ -212,6 +250,7 @@ struct compress_alg { | |||
212 | }; | 250 | }; |
213 | 251 | ||
214 | #define cra_ablkcipher cra_u.ablkcipher | 252 | #define cra_ablkcipher cra_u.ablkcipher |
253 | #define cra_aead cra_u.aead | ||
215 | #define cra_blkcipher cra_u.blkcipher | 254 | #define cra_blkcipher cra_u.blkcipher |
216 | #define cra_cipher cra_u.cipher | 255 | #define cra_cipher cra_u.cipher |
217 | #define cra_digest cra_u.digest | 256 | #define cra_digest cra_u.digest |
@@ -237,6 +276,7 @@ struct crypto_alg { | |||
237 | 276 | ||
238 | union { | 277 | union { |
239 | struct ablkcipher_alg ablkcipher; | 278 | struct ablkcipher_alg ablkcipher; |
279 | struct aead_alg aead; | ||
240 | struct blkcipher_alg blkcipher; | 280 | struct blkcipher_alg blkcipher; |
241 | struct cipher_alg cipher; | 281 | struct cipher_alg cipher; |
242 | struct digest_alg digest; | 282 | struct digest_alg digest; |
@@ -284,6 +324,16 @@ struct ablkcipher_tfm { | |||
284 | unsigned int reqsize; | 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 | struct blkcipher_tfm { | 337 | struct blkcipher_tfm { |
288 | void *iv; | 338 | void *iv; |
289 | int (*setkey)(struct crypto_tfm *tfm, const u8 *key, | 339 | int (*setkey)(struct crypto_tfm *tfm, const u8 *key, |
@@ -323,6 +373,7 @@ struct compress_tfm { | |||
323 | }; | 373 | }; |
324 | 374 | ||
325 | #define crt_ablkcipher crt_u.ablkcipher | 375 | #define crt_ablkcipher crt_u.ablkcipher |
376 | #define crt_aead crt_u.aead | ||
326 | #define crt_blkcipher crt_u.blkcipher | 377 | #define crt_blkcipher crt_u.blkcipher |
327 | #define crt_cipher crt_u.cipher | 378 | #define crt_cipher crt_u.cipher |
328 | #define crt_hash crt_u.hash | 379 | #define crt_hash crt_u.hash |
@@ -334,6 +385,7 @@ struct crypto_tfm { | |||
334 | 385 | ||
335 | union { | 386 | union { |
336 | struct ablkcipher_tfm ablkcipher; | 387 | struct ablkcipher_tfm ablkcipher; |
388 | struct aead_tfm aead; | ||
337 | struct blkcipher_tfm blkcipher; | 389 | struct blkcipher_tfm blkcipher; |
338 | struct cipher_tfm cipher; | 390 | struct cipher_tfm cipher; |
339 | struct hash_tfm hash; | 391 | struct hash_tfm hash; |
@@ -349,6 +401,10 @@ struct crypto_ablkcipher { | |||
349 | struct crypto_tfm base; | 401 | struct crypto_tfm base; |
350 | }; | 402 | }; |
351 | 403 | ||
404 | struct crypto_aead { | ||
405 | struct crypto_tfm base; | ||
406 | }; | ||
407 | |||
352 | struct crypto_blkcipher { | 408 | struct crypto_blkcipher { |
353 | struct crypto_tfm base; | 409 | struct crypto_tfm base; |
354 | }; | 410 | }; |
@@ -619,6 +675,150 @@ static inline void ablkcipher_request_set_crypt( | |||
619 | req->info = iv; | 675 | req->info = iv; |
620 | } | 676 | } |
621 | 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; | ||
820 | } | ||
821 | |||
622 | static inline struct crypto_blkcipher *__crypto_blkcipher_cast( | 822 | static inline struct crypto_blkcipher *__crypto_blkcipher_cast( |
623 | struct crypto_tfm *tfm) | 823 | struct crypto_tfm *tfm) |
624 | { | 824 | { |