diff options
author | Martin Willi <martin@strongswan.org> | 2015-07-16 13:14:05 -0400 |
---|---|---|
committer | Herbert Xu <herbert@gondor.apana.org.au> | 2015-07-17 09:20:26 -0400 |
commit | 2546f811ef45fc47fcb65531bea98beeed0c97cc (patch) | |
tree | 953ec34e28547cb648f131bde32cb842d7348920 | |
parent | 6692cbc28e88b4cbffaab84b82bfff888c03ed3a (diff) |
crypto: poly1305 - Export common Poly1305 helpers
As architecture specific drivers need a software fallback, export Poly1305
init/update/final functions together with some helpers in a header file.
Signed-off-by: Martin Willi <martin@strongswan.org>
Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>
-rw-r--r-- | crypto/chacha20poly1305.c | 4 | ||||
-rw-r--r-- | crypto/poly1305_generic.c | 73 | ||||
-rw-r--r-- | include/crypto/poly1305.h | 41 |
3 files changed, 77 insertions, 41 deletions
diff --git a/crypto/chacha20poly1305.c b/crypto/chacha20poly1305.c index 410554d3a1ff..b71445f282ad 100644 --- a/crypto/chacha20poly1305.c +++ b/crypto/chacha20poly1305.c | |||
@@ -14,6 +14,7 @@ | |||
14 | #include <crypto/internal/skcipher.h> | 14 | #include <crypto/internal/skcipher.h> |
15 | #include <crypto/scatterwalk.h> | 15 | #include <crypto/scatterwalk.h> |
16 | #include <crypto/chacha20.h> | 16 | #include <crypto/chacha20.h> |
17 | #include <crypto/poly1305.h> | ||
17 | #include <linux/err.h> | 18 | #include <linux/err.h> |
18 | #include <linux/init.h> | 19 | #include <linux/init.h> |
19 | #include <linux/kernel.h> | 20 | #include <linux/kernel.h> |
@@ -21,9 +22,6 @@ | |||
21 | 22 | ||
22 | #include "internal.h" | 23 | #include "internal.h" |
23 | 24 | ||
24 | #define POLY1305_BLOCK_SIZE 16 | ||
25 | #define POLY1305_DIGEST_SIZE 16 | ||
26 | #define POLY1305_KEY_SIZE 32 | ||
27 | #define CHACHAPOLY_IV_SIZE 12 | 25 | #define CHACHAPOLY_IV_SIZE 12 |
28 | 26 | ||
29 | struct chachapoly_instance_ctx { | 27 | struct chachapoly_instance_ctx { |
diff --git a/crypto/poly1305_generic.c b/crypto/poly1305_generic.c index 387b5c887a80..2df9835dfbc0 100644 --- a/crypto/poly1305_generic.c +++ b/crypto/poly1305_generic.c | |||
@@ -13,31 +13,11 @@ | |||
13 | 13 | ||
14 | #include <crypto/algapi.h> | 14 | #include <crypto/algapi.h> |
15 | #include <crypto/internal/hash.h> | 15 | #include <crypto/internal/hash.h> |
16 | #include <crypto/poly1305.h> | ||
16 | #include <linux/crypto.h> | 17 | #include <linux/crypto.h> |
17 | #include <linux/kernel.h> | 18 | #include <linux/kernel.h> |
18 | #include <linux/module.h> | 19 | #include <linux/module.h> |
19 | 20 | ||
20 | #define POLY1305_BLOCK_SIZE 16 | ||
21 | #define POLY1305_KEY_SIZE 32 | ||
22 | #define POLY1305_DIGEST_SIZE 16 | ||
23 | |||
24 | struct poly1305_desc_ctx { | ||
25 | /* key */ | ||
26 | u32 r[5]; | ||
27 | /* finalize key */ | ||
28 | u32 s[4]; | ||
29 | /* accumulator */ | ||
30 | u32 h[5]; | ||
31 | /* partial buffer */ | ||
32 | u8 buf[POLY1305_BLOCK_SIZE]; | ||
33 | /* bytes used in partial buffer */ | ||
34 | unsigned int buflen; | ||
35 | /* r key has been set */ | ||
36 | bool rset; | ||
37 | /* s key has been set */ | ||
38 | bool sset; | ||
39 | }; | ||
40 | |||
41 | static inline u64 mlt(u64 a, u64 b) | 21 | static inline u64 mlt(u64 a, u64 b) |
42 | { | 22 | { |
43 | return a * b; | 23 | return a * b; |
@@ -58,7 +38,7 @@ static inline u32 le32_to_cpuvp(const void *p) | |||
58 | return le32_to_cpup(p); | 38 | return le32_to_cpup(p); |
59 | } | 39 | } |
60 | 40 | ||
61 | static int poly1305_init(struct shash_desc *desc) | 41 | int crypto_poly1305_init(struct shash_desc *desc) |
62 | { | 42 | { |
63 | struct poly1305_desc_ctx *dctx = shash_desc_ctx(desc); | 43 | struct poly1305_desc_ctx *dctx = shash_desc_ctx(desc); |
64 | 44 | ||
@@ -69,8 +49,9 @@ static int poly1305_init(struct shash_desc *desc) | |||
69 | 49 | ||
70 | return 0; | 50 | return 0; |
71 | } | 51 | } |
52 | EXPORT_SYMBOL_GPL(crypto_poly1305_init); | ||
72 | 53 | ||
73 | static int poly1305_setkey(struct crypto_shash *tfm, | 54 | int crypto_poly1305_setkey(struct crypto_shash *tfm, |
74 | const u8 *key, unsigned int keylen) | 55 | const u8 *key, unsigned int keylen) |
75 | { | 56 | { |
76 | /* Poly1305 requires a unique key for each tag, which implies that | 57 | /* Poly1305 requires a unique key for each tag, which implies that |
@@ -79,6 +60,7 @@ static int poly1305_setkey(struct crypto_shash *tfm, | |||
79 | * the update() call. */ | 60 | * the update() call. */ |
80 | return -ENOTSUPP; | 61 | return -ENOTSUPP; |
81 | } | 62 | } |
63 | EXPORT_SYMBOL_GPL(crypto_poly1305_setkey); | ||
82 | 64 | ||
83 | static void poly1305_setrkey(struct poly1305_desc_ctx *dctx, const u8 *key) | 65 | static void poly1305_setrkey(struct poly1305_desc_ctx *dctx, const u8 *key) |
84 | { | 66 | { |
@@ -98,16 +80,10 @@ static void poly1305_setskey(struct poly1305_desc_ctx *dctx, const u8 *key) | |||
98 | dctx->s[3] = le32_to_cpuvp(key + 12); | 80 | dctx->s[3] = le32_to_cpuvp(key + 12); |
99 | } | 81 | } |
100 | 82 | ||
101 | static unsigned int poly1305_blocks(struct poly1305_desc_ctx *dctx, | 83 | unsigned int crypto_poly1305_setdesckey(struct poly1305_desc_ctx *dctx, |
102 | const u8 *src, unsigned int srclen, | 84 | const u8 *src, unsigned int srclen) |
103 | u32 hibit) | ||
104 | { | 85 | { |
105 | u32 r0, r1, r2, r3, r4; | 86 | if (!dctx->sset) { |
106 | u32 s1, s2, s3, s4; | ||
107 | u32 h0, h1, h2, h3, h4; | ||
108 | u64 d0, d1, d2, d3, d4; | ||
109 | |||
110 | if (unlikely(!dctx->sset)) { | ||
111 | if (!dctx->rset && srclen >= POLY1305_BLOCK_SIZE) { | 87 | if (!dctx->rset && srclen >= POLY1305_BLOCK_SIZE) { |
112 | poly1305_setrkey(dctx, src); | 88 | poly1305_setrkey(dctx, src); |
113 | src += POLY1305_BLOCK_SIZE; | 89 | src += POLY1305_BLOCK_SIZE; |
@@ -121,6 +97,25 @@ static unsigned int poly1305_blocks(struct poly1305_desc_ctx *dctx, | |||
121 | dctx->sset = true; | 97 | dctx->sset = true; |
122 | } | 98 | } |
123 | } | 99 | } |
100 | return srclen; | ||
101 | } | ||
102 | EXPORT_SYMBOL_GPL(crypto_poly1305_setdesckey); | ||
103 | |||
104 | static unsigned int poly1305_blocks(struct poly1305_desc_ctx *dctx, | ||
105 | const u8 *src, unsigned int srclen, | ||
106 | u32 hibit) | ||
107 | { | ||
108 | u32 r0, r1, r2, r3, r4; | ||
109 | u32 s1, s2, s3, s4; | ||
110 | u32 h0, h1, h2, h3, h4; | ||
111 | u64 d0, d1, d2, d3, d4; | ||
112 | unsigned int datalen; | ||
113 | |||
114 | if (unlikely(!dctx->sset)) { | ||
115 | datalen = crypto_poly1305_setdesckey(dctx, src, srclen); | ||
116 | src += srclen - datalen; | ||
117 | srclen = datalen; | ||
118 | } | ||
124 | 119 | ||
125 | r0 = dctx->r[0]; | 120 | r0 = dctx->r[0]; |
126 | r1 = dctx->r[1]; | 121 | r1 = dctx->r[1]; |
@@ -181,7 +176,7 @@ static unsigned int poly1305_blocks(struct poly1305_desc_ctx *dctx, | |||
181 | return srclen; | 176 | return srclen; |
182 | } | 177 | } |
183 | 178 | ||
184 | static int poly1305_update(struct shash_desc *desc, | 179 | int crypto_poly1305_update(struct shash_desc *desc, |
185 | const u8 *src, unsigned int srclen) | 180 | const u8 *src, unsigned int srclen) |
186 | { | 181 | { |
187 | struct poly1305_desc_ctx *dctx = shash_desc_ctx(desc); | 182 | struct poly1305_desc_ctx *dctx = shash_desc_ctx(desc); |
@@ -214,8 +209,9 @@ static int poly1305_update(struct shash_desc *desc, | |||
214 | 209 | ||
215 | return 0; | 210 | return 0; |
216 | } | 211 | } |
212 | EXPORT_SYMBOL_GPL(crypto_poly1305_update); | ||
217 | 213 | ||
218 | static int poly1305_final(struct shash_desc *desc, u8 *dst) | 214 | int crypto_poly1305_final(struct shash_desc *desc, u8 *dst) |
219 | { | 215 | { |
220 | struct poly1305_desc_ctx *dctx = shash_desc_ctx(desc); | 216 | struct poly1305_desc_ctx *dctx = shash_desc_ctx(desc); |
221 | __le32 *mac = (__le32 *)dst; | 217 | __le32 *mac = (__le32 *)dst; |
@@ -282,13 +278,14 @@ static int poly1305_final(struct shash_desc *desc, u8 *dst) | |||
282 | 278 | ||
283 | return 0; | 279 | return 0; |
284 | } | 280 | } |
281 | EXPORT_SYMBOL_GPL(crypto_poly1305_final); | ||
285 | 282 | ||
286 | static struct shash_alg poly1305_alg = { | 283 | static struct shash_alg poly1305_alg = { |
287 | .digestsize = POLY1305_DIGEST_SIZE, | 284 | .digestsize = POLY1305_DIGEST_SIZE, |
288 | .init = poly1305_init, | 285 | .init = crypto_poly1305_init, |
289 | .update = poly1305_update, | 286 | .update = crypto_poly1305_update, |
290 | .final = poly1305_final, | 287 | .final = crypto_poly1305_final, |
291 | .setkey = poly1305_setkey, | 288 | .setkey = crypto_poly1305_setkey, |
292 | .descsize = sizeof(struct poly1305_desc_ctx), | 289 | .descsize = sizeof(struct poly1305_desc_ctx), |
293 | .base = { | 290 | .base = { |
294 | .cra_name = "poly1305", | 291 | .cra_name = "poly1305", |
diff --git a/include/crypto/poly1305.h b/include/crypto/poly1305.h new file mode 100644 index 000000000000..894df59b74e4 --- /dev/null +++ b/include/crypto/poly1305.h | |||
@@ -0,0 +1,41 @@ | |||
1 | /* | ||
2 | * Common values for the Poly1305 algorithm | ||
3 | */ | ||
4 | |||
5 | #ifndef _CRYPTO_POLY1305_H | ||
6 | #define _CRYPTO_POLY1305_H | ||
7 | |||
8 | #include <linux/types.h> | ||
9 | #include <linux/crypto.h> | ||
10 | |||
11 | #define POLY1305_BLOCK_SIZE 16 | ||
12 | #define POLY1305_KEY_SIZE 32 | ||
13 | #define POLY1305_DIGEST_SIZE 16 | ||
14 | |||
15 | struct poly1305_desc_ctx { | ||
16 | /* key */ | ||
17 | u32 r[5]; | ||
18 | /* finalize key */ | ||
19 | u32 s[4]; | ||
20 | /* accumulator */ | ||
21 | u32 h[5]; | ||
22 | /* partial buffer */ | ||
23 | u8 buf[POLY1305_BLOCK_SIZE]; | ||
24 | /* bytes used in partial buffer */ | ||
25 | unsigned int buflen; | ||
26 | /* r key has been set */ | ||
27 | bool rset; | ||
28 | /* s key has been set */ | ||
29 | bool sset; | ||
30 | }; | ||
31 | |||
32 | int crypto_poly1305_init(struct shash_desc *desc); | ||
33 | int crypto_poly1305_setkey(struct crypto_shash *tfm, | ||
34 | const u8 *key, unsigned int keylen); | ||
35 | unsigned int crypto_poly1305_setdesckey(struct poly1305_desc_ctx *dctx, | ||
36 | const u8 *src, unsigned int srclen); | ||
37 | int crypto_poly1305_update(struct shash_desc *desc, | ||
38 | const u8 *src, unsigned int srclen); | ||
39 | int crypto_poly1305_final(struct shash_desc *desc, u8 *dst); | ||
40 | |||
41 | #endif | ||