diff options
Diffstat (limited to 'crypto')
-rw-r--r-- | crypto/Kconfig | 4 | ||||
-rw-r--r-- | crypto/Makefile | 3 | ||||
-rw-r--r-- | crypto/digest.c | 129 | ||||
-rw-r--r-- | crypto/hash.c | 61 | ||||
-rw-r--r-- | crypto/hmac.c | 12 | ||||
-rw-r--r-- | crypto/scatterwalk.h | 4 |
6 files changed, 177 insertions, 36 deletions
diff --git a/crypto/Kconfig b/crypto/Kconfig index be5eb0cb7c30..69c5f992bcd4 100644 --- a/crypto/Kconfig +++ b/crypto/Kconfig | |||
@@ -20,6 +20,10 @@ config CRYPTO_BLKCIPHER | |||
20 | tristate | 20 | tristate |
21 | select CRYPTO_ALGAPI | 21 | select CRYPTO_ALGAPI |
22 | 22 | ||
23 | config CRYPTO_HASH | ||
24 | tristate | ||
25 | select CRYPTO_ALGAPI | ||
26 | |||
23 | config CRYPTO_MANAGER | 27 | config CRYPTO_MANAGER |
24 | tristate "Cryptographic algorithm manager" | 28 | tristate "Cryptographic algorithm manager" |
25 | select CRYPTO_ALGAPI | 29 | select CRYPTO_ALGAPI |
diff --git a/crypto/Makefile b/crypto/Makefile index 5e1ff4e0b1fc..72366208e291 100644 --- a/crypto/Makefile +++ b/crypto/Makefile | |||
@@ -10,6 +10,9 @@ obj-$(CONFIG_CRYPTO_ALGAPI) += crypto_algapi.o | |||
10 | 10 | ||
11 | obj-$(CONFIG_CRYPTO_BLKCIPHER) += blkcipher.o | 11 | obj-$(CONFIG_CRYPTO_BLKCIPHER) += blkcipher.o |
12 | 12 | ||
13 | crypto_hash-objs := hash.o | ||
14 | obj-$(CONFIG_CRYPTO_HASH) += crypto_hash.o | ||
15 | |||
13 | obj-$(CONFIG_CRYPTO_MANAGER) += cryptomgr.o | 16 | obj-$(CONFIG_CRYPTO_MANAGER) += cryptomgr.o |
14 | obj-$(CONFIG_CRYPTO_HMAC) += hmac.o | 17 | obj-$(CONFIG_CRYPTO_HMAC) += hmac.o |
15 | obj-$(CONFIG_CRYPTO_NULL) += crypto_null.o | 18 | obj-$(CONFIG_CRYPTO_NULL) += crypto_null.o |
diff --git a/crypto/digest.c b/crypto/digest.c index 96244a528844..5873063db840 100644 --- a/crypto/digest.c +++ b/crypto/digest.c | |||
@@ -11,29 +11,89 @@ | |||
11 | * any later version. | 11 | * any later version. |
12 | * | 12 | * |
13 | */ | 13 | */ |
14 | #include <linux/crypto.h> | 14 | |
15 | #include <linux/mm.h> | 15 | #include <linux/mm.h> |
16 | #include <linux/errno.h> | 16 | #include <linux/errno.h> |
17 | #include <linux/highmem.h> | 17 | #include <linux/highmem.h> |
18 | #include <asm/scatterlist.h> | 18 | #include <linux/module.h> |
19 | #include <linux/scatterlist.h> | ||
20 | |||
19 | #include "internal.h" | 21 | #include "internal.h" |
22 | #include "scatterwalk.h" | ||
20 | 23 | ||
21 | static void init(struct crypto_tfm *tfm) | 24 | void crypto_digest_init(struct crypto_tfm *tfm) |
22 | { | 25 | { |
23 | tfm->__crt_alg->cra_digest.dia_init(tfm); | 26 | struct crypto_hash *hash = crypto_hash_cast(tfm); |
27 | struct hash_desc desc = { .tfm = hash, .flags = tfm->crt_flags }; | ||
28 | |||
29 | crypto_hash_init(&desc); | ||
24 | } | 30 | } |
31 | EXPORT_SYMBOL_GPL(crypto_digest_init); | ||
25 | 32 | ||
26 | static void update(struct crypto_tfm *tfm, | 33 | void crypto_digest_update(struct crypto_tfm *tfm, |
27 | struct scatterlist *sg, unsigned int nsg) | 34 | struct scatterlist *sg, unsigned int nsg) |
28 | { | 35 | { |
36 | struct crypto_hash *hash = crypto_hash_cast(tfm); | ||
37 | struct hash_desc desc = { .tfm = hash, .flags = tfm->crt_flags }; | ||
38 | unsigned int nbytes = 0; | ||
29 | unsigned int i; | 39 | unsigned int i; |
40 | |||
41 | for (i = 0; i < nsg; i++) | ||
42 | nbytes += sg[i].length; | ||
43 | |||
44 | crypto_hash_update(&desc, sg, nbytes); | ||
45 | } | ||
46 | EXPORT_SYMBOL_GPL(crypto_digest_update); | ||
47 | |||
48 | void crypto_digest_final(struct crypto_tfm *tfm, u8 *out) | ||
49 | { | ||
50 | struct crypto_hash *hash = crypto_hash_cast(tfm); | ||
51 | struct hash_desc desc = { .tfm = hash, .flags = tfm->crt_flags }; | ||
52 | |||
53 | crypto_hash_final(&desc, out); | ||
54 | } | ||
55 | EXPORT_SYMBOL_GPL(crypto_digest_final); | ||
56 | |||
57 | void crypto_digest_digest(struct crypto_tfm *tfm, | ||
58 | struct scatterlist *sg, unsigned int nsg, u8 *out) | ||
59 | { | ||
60 | struct crypto_hash *hash = crypto_hash_cast(tfm); | ||
61 | struct hash_desc desc = { .tfm = hash, .flags = tfm->crt_flags }; | ||
62 | unsigned int nbytes = 0; | ||
63 | unsigned int i; | ||
64 | |||
65 | for (i = 0; i < nsg; i++) | ||
66 | nbytes += sg[i].length; | ||
67 | |||
68 | crypto_hash_digest(&desc, sg, nbytes, out); | ||
69 | } | ||
70 | EXPORT_SYMBOL_GPL(crypto_digest_digest); | ||
71 | |||
72 | static int init(struct hash_desc *desc) | ||
73 | { | ||
74 | struct crypto_tfm *tfm = crypto_hash_tfm(desc->tfm); | ||
75 | |||
76 | tfm->__crt_alg->cra_digest.dia_init(tfm); | ||
77 | return 0; | ||
78 | } | ||
79 | |||
80 | static int update(struct hash_desc *desc, | ||
81 | struct scatterlist *sg, unsigned int nbytes) | ||
82 | { | ||
83 | struct crypto_tfm *tfm = crypto_hash_tfm(desc->tfm); | ||
30 | unsigned int alignmask = crypto_tfm_alg_alignmask(tfm); | 84 | unsigned int alignmask = crypto_tfm_alg_alignmask(tfm); |
31 | 85 | ||
32 | for (i = 0; i < nsg; i++) { | 86 | if (!nbytes) |
87 | return 0; | ||
88 | |||
89 | for (;;) { | ||
90 | struct page *pg = sg->page; | ||
91 | unsigned int offset = sg->offset; | ||
92 | unsigned int l = sg->length; | ||
33 | 93 | ||
34 | struct page *pg = sg[i].page; | 94 | if (unlikely(l > nbytes)) |
35 | unsigned int offset = sg[i].offset; | 95 | l = nbytes; |
36 | unsigned int l = sg[i].length; | 96 | nbytes -= l; |
37 | 97 | ||
38 | do { | 98 | do { |
39 | unsigned int bytes_from_page = min(l, ((unsigned int) | 99 | unsigned int bytes_from_page = min(l, ((unsigned int) |
@@ -55,16 +115,23 @@ static void update(struct crypto_tfm *tfm, | |||
55 | tfm->__crt_alg->cra_digest.dia_update(tfm, p, | 115 | tfm->__crt_alg->cra_digest.dia_update(tfm, p, |
56 | bytes_from_page); | 116 | bytes_from_page); |
57 | crypto_kunmap(src, 0); | 117 | crypto_kunmap(src, 0); |
58 | crypto_yield(tfm->crt_flags); | 118 | crypto_yield(desc->flags); |
59 | offset = 0; | 119 | offset = 0; |
60 | pg++; | 120 | pg++; |
61 | l -= bytes_from_page; | 121 | l -= bytes_from_page; |
62 | } while (l > 0); | 122 | } while (l > 0); |
123 | |||
124 | if (!nbytes) | ||
125 | break; | ||
126 | sg = sg_next(sg); | ||
63 | } | 127 | } |
128 | |||
129 | return 0; | ||
64 | } | 130 | } |
65 | 131 | ||
66 | static void final(struct crypto_tfm *tfm, u8 *out) | 132 | static int final(struct hash_desc *desc, u8 *out) |
67 | { | 133 | { |
134 | struct crypto_tfm *tfm = crypto_hash_tfm(desc->tfm); | ||
68 | unsigned long alignmask = crypto_tfm_alg_alignmask(tfm); | 135 | unsigned long alignmask = crypto_tfm_alg_alignmask(tfm); |
69 | struct digest_alg *digest = &tfm->__crt_alg->cra_digest; | 136 | struct digest_alg *digest = &tfm->__crt_alg->cra_digest; |
70 | 137 | ||
@@ -78,26 +145,30 @@ static void final(struct crypto_tfm *tfm, u8 *out) | |||
78 | memcpy(out, dst, digest->dia_digestsize); | 145 | memcpy(out, dst, digest->dia_digestsize); |
79 | } else | 146 | } else |
80 | digest->dia_final(tfm, out); | 147 | digest->dia_final(tfm, out); |
148 | |||
149 | return 0; | ||
81 | } | 150 | } |
82 | 151 | ||
83 | static int nosetkey(struct crypto_tfm *tfm, const u8 *key, unsigned int keylen) | 152 | static int nosetkey(struct crypto_hash *tfm, const u8 *key, unsigned int keylen) |
84 | { | 153 | { |
85 | tfm->crt_flags &= ~CRYPTO_TFM_RES_MASK; | 154 | crypto_hash_clear_flags(tfm, CRYPTO_TFM_RES_MASK); |
86 | return -ENOSYS; | 155 | return -ENOSYS; |
87 | } | 156 | } |
88 | 157 | ||
89 | static int setkey(struct crypto_tfm *tfm, const u8 *key, unsigned int keylen) | 158 | static int setkey(struct crypto_hash *hash, const u8 *key, unsigned int keylen) |
90 | { | 159 | { |
91 | tfm->crt_flags &= ~CRYPTO_TFM_RES_MASK; | 160 | struct crypto_tfm *tfm = crypto_hash_tfm(hash); |
161 | |||
162 | crypto_hash_clear_flags(hash, CRYPTO_TFM_RES_MASK); | ||
92 | return tfm->__crt_alg->cra_digest.dia_setkey(tfm, key, keylen); | 163 | return tfm->__crt_alg->cra_digest.dia_setkey(tfm, key, keylen); |
93 | } | 164 | } |
94 | 165 | ||
95 | static void digest(struct crypto_tfm *tfm, | 166 | static int digest(struct hash_desc *desc, |
96 | struct scatterlist *sg, unsigned int nsg, u8 *out) | 167 | struct scatterlist *sg, unsigned int nbytes, u8 *out) |
97 | { | 168 | { |
98 | init(tfm); | 169 | init(desc); |
99 | update(tfm, sg, nsg); | 170 | update(desc, sg, nbytes); |
100 | final(tfm, out); | 171 | return final(desc, out); |
101 | } | 172 | } |
102 | 173 | ||
103 | int crypto_init_digest_flags(struct crypto_tfm *tfm, u32 flags) | 174 | int crypto_init_digest_flags(struct crypto_tfm *tfm, u32 flags) |
@@ -107,14 +178,18 @@ int crypto_init_digest_flags(struct crypto_tfm *tfm, u32 flags) | |||
107 | 178 | ||
108 | int crypto_init_digest_ops(struct crypto_tfm *tfm) | 179 | int crypto_init_digest_ops(struct crypto_tfm *tfm) |
109 | { | 180 | { |
110 | struct digest_tfm *ops = &tfm->crt_digest; | 181 | struct hash_tfm *ops = &tfm->crt_hash; |
111 | struct digest_alg *dalg = &tfm->__crt_alg->cra_digest; | 182 | struct digest_alg *dalg = &tfm->__crt_alg->cra_digest; |
183 | |||
184 | if (dalg->dia_digestsize > crypto_tfm_alg_blocksize(tfm)) | ||
185 | return -EINVAL; | ||
112 | 186 | ||
113 | ops->dit_init = init; | 187 | ops->init = init; |
114 | ops->dit_update = update; | 188 | ops->update = update; |
115 | ops->dit_final = final; | 189 | ops->final = final; |
116 | ops->dit_digest = digest; | 190 | ops->digest = digest; |
117 | ops->dit_setkey = dalg->dia_setkey ? setkey : nosetkey; | 191 | ops->setkey = dalg->dia_setkey ? setkey : nosetkey; |
192 | ops->digestsize = dalg->dia_digestsize; | ||
118 | 193 | ||
119 | return crypto_alloc_hmac_block(tfm); | 194 | return crypto_alloc_hmac_block(tfm); |
120 | } | 195 | } |
diff --git a/crypto/hash.c b/crypto/hash.c new file mode 100644 index 000000000000..cdec23d885fe --- /dev/null +++ b/crypto/hash.c | |||
@@ -0,0 +1,61 @@ | |||
1 | /* | ||
2 | * Cryptographic Hash operations. | ||
3 | * | ||
4 | * Copyright (c) 2006 Herbert Xu <herbert@gondor.apana.org.au> | ||
5 | * | ||
6 | * This program is free software; you can redistribute it and/or modify it | ||
7 | * under the terms of the GNU General Public License as published by the Free | ||
8 | * Software Foundation; either version 2 of the License, or (at your option) | ||
9 | * any later version. | ||
10 | */ | ||
11 | |||
12 | #include <linux/errno.h> | ||
13 | #include <linux/kernel.h> | ||
14 | #include <linux/module.h> | ||
15 | #include <linux/seq_file.h> | ||
16 | |||
17 | #include "internal.h" | ||
18 | |||
19 | static unsigned int crypto_hash_ctxsize(struct crypto_alg *alg) | ||
20 | { | ||
21 | return alg->cra_ctxsize; | ||
22 | } | ||
23 | |||
24 | static int crypto_init_hash_ops(struct crypto_tfm *tfm) | ||
25 | { | ||
26 | struct hash_tfm *crt = &tfm->crt_hash; | ||
27 | struct hash_alg *alg = &tfm->__crt_alg->cra_hash; | ||
28 | |||
29 | if (alg->digestsize > crypto_tfm_alg_blocksize(tfm)) | ||
30 | return -EINVAL; | ||
31 | |||
32 | crt->init = alg->init; | ||
33 | crt->update = alg->update; | ||
34 | crt->final = alg->final; | ||
35 | crt->digest = alg->digest; | ||
36 | crt->setkey = alg->setkey; | ||
37 | crt->digestsize = alg->digestsize; | ||
38 | |||
39 | return 0; | ||
40 | } | ||
41 | |||
42 | static void crypto_hash_show(struct seq_file *m, struct crypto_alg *alg) | ||
43 | __attribute_used__; | ||
44 | static void crypto_hash_show(struct seq_file *m, struct crypto_alg *alg) | ||
45 | { | ||
46 | seq_printf(m, "type : hash\n"); | ||
47 | seq_printf(m, "blocksize : %u\n", alg->cra_blocksize); | ||
48 | seq_printf(m, "digestsize : %u\n", alg->cra_hash.digestsize); | ||
49 | } | ||
50 | |||
51 | const struct crypto_type crypto_hash_type = { | ||
52 | .ctxsize = crypto_hash_ctxsize, | ||
53 | .init = crypto_init_hash_ops, | ||
54 | #ifdef CONFIG_PROC_FS | ||
55 | .show = crypto_hash_show, | ||
56 | #endif | ||
57 | }; | ||
58 | EXPORT_SYMBOL_GPL(crypto_hash_type); | ||
59 | |||
60 | MODULE_LICENSE("GPL"); | ||
61 | MODULE_DESCRIPTION("Generic cryptographic hash type"); | ||
diff --git a/crypto/hmac.c b/crypto/hmac.c index 46120dee5ada..ecf7b0a95b56 100644 --- a/crypto/hmac.c +++ b/crypto/hmac.c | |||
@@ -35,9 +35,9 @@ int crypto_alloc_hmac_block(struct crypto_tfm *tfm) | |||
35 | 35 | ||
36 | BUG_ON(!crypto_tfm_alg_blocksize(tfm)); | 36 | BUG_ON(!crypto_tfm_alg_blocksize(tfm)); |
37 | 37 | ||
38 | tfm->crt_digest.dit_hmac_block = kmalloc(crypto_tfm_alg_blocksize(tfm), | 38 | tfm->crt_hash.hmac_block = kmalloc(crypto_tfm_alg_blocksize(tfm), |
39 | GFP_KERNEL); | 39 | GFP_KERNEL); |
40 | if (tfm->crt_digest.dit_hmac_block == NULL) | 40 | if (tfm->crt_hash.hmac_block == NULL) |
41 | ret = -ENOMEM; | 41 | ret = -ENOMEM; |
42 | 42 | ||
43 | return ret; | 43 | return ret; |
@@ -46,14 +46,14 @@ int crypto_alloc_hmac_block(struct crypto_tfm *tfm) | |||
46 | 46 | ||
47 | void crypto_free_hmac_block(struct crypto_tfm *tfm) | 47 | void crypto_free_hmac_block(struct crypto_tfm *tfm) |
48 | { | 48 | { |
49 | kfree(tfm->crt_digest.dit_hmac_block); | 49 | kfree(tfm->crt_hash.hmac_block); |
50 | } | 50 | } |
51 | 51 | ||
52 | void crypto_hmac_init(struct crypto_tfm *tfm, u8 *key, unsigned int *keylen) | 52 | void crypto_hmac_init(struct crypto_tfm *tfm, u8 *key, unsigned int *keylen) |
53 | { | 53 | { |
54 | unsigned int i; | 54 | unsigned int i; |
55 | struct scatterlist tmp; | 55 | struct scatterlist tmp; |
56 | char *ipad = tfm->crt_digest.dit_hmac_block; | 56 | char *ipad = tfm->crt_hash.hmac_block; |
57 | 57 | ||
58 | if (*keylen > crypto_tfm_alg_blocksize(tfm)) { | 58 | if (*keylen > crypto_tfm_alg_blocksize(tfm)) { |
59 | hash_key(tfm, key, *keylen); | 59 | hash_key(tfm, key, *keylen); |
@@ -83,7 +83,7 @@ void crypto_hmac_final(struct crypto_tfm *tfm, u8 *key, | |||
83 | { | 83 | { |
84 | unsigned int i; | 84 | unsigned int i; |
85 | struct scatterlist tmp; | 85 | struct scatterlist tmp; |
86 | char *opad = tfm->crt_digest.dit_hmac_block; | 86 | char *opad = tfm->crt_hash.hmac_block; |
87 | 87 | ||
88 | if (*keylen > crypto_tfm_alg_blocksize(tfm)) { | 88 | if (*keylen > crypto_tfm_alg_blocksize(tfm)) { |
89 | hash_key(tfm, key, *keylen); | 89 | hash_key(tfm, key, *keylen); |
diff --git a/crypto/scatterwalk.h b/crypto/scatterwalk.h index ace595a2e119..f1592cc2d0f4 100644 --- a/crypto/scatterwalk.h +++ b/crypto/scatterwalk.h | |||
@@ -20,11 +20,9 @@ | |||
20 | 20 | ||
21 | #include "internal.h" | 21 | #include "internal.h" |
22 | 22 | ||
23 | /* Define sg_next is an inline routine now in case we want to change | ||
24 | scatterlist to a linked list later. */ | ||
25 | static inline struct scatterlist *sg_next(struct scatterlist *sg) | 23 | static inline struct scatterlist *sg_next(struct scatterlist *sg) |
26 | { | 24 | { |
27 | return sg + 1; | 25 | return (++sg)->length ? sg : (void *)sg->page; |
28 | } | 26 | } |
29 | 27 | ||
30 | static inline unsigned long scatterwalk_samebuf(struct scatter_walk *walk_in, | 28 | static inline unsigned long scatterwalk_samebuf(struct scatter_walk *walk_in, |