aboutsummaryrefslogtreecommitdiffstats
path: root/crypto/hmac.c
diff options
context:
space:
mode:
authorHerbert Xu <herbert@gondor.apana.org.au>2009-07-09 00:43:37 -0400
committerHerbert Xu <herbert@gondor.apana.org.au>2009-07-14 00:58:04 -0400
commit8bd1209cfff246ce6dfae86837467a01236f9cb6 (patch)
tree1f6afaded943df5cfbfe6d5996ef6a022f066a6c /crypto/hmac.c
parentbbbee4679afd7c29a58087f133ffe241597f3144 (diff)
crypto: hmac - Switch to shash
This patch changes hmac to the new shash interface. Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>
Diffstat (limited to 'crypto/hmac.c')
-rw-r--r--crypto/hmac.c271
1 files changed, 114 insertions, 157 deletions
diff --git a/crypto/hmac.c b/crypto/hmac.c
index 0ad39c374963..e37342748f2f 100644
--- a/crypto/hmac.c
+++ b/crypto/hmac.c
@@ -27,7 +27,7 @@
27#include <linux/string.h> 27#include <linux/string.h>
28 28
29struct hmac_ctx { 29struct hmac_ctx {
30 struct crypto_hash *child; 30 struct shash_desc *desc;
31}; 31};
32 32
33static inline void *align_ptr(void *p, unsigned int align) 33static inline void *align_ptr(void *p, unsigned int align)
@@ -35,57 +35,33 @@ static inline void *align_ptr(void *p, unsigned int align)
35 return (void *)ALIGN((unsigned long)p, align); 35 return (void *)ALIGN((unsigned long)p, align);
36} 36}
37 37
38static inline struct hmac_ctx *hmac_ctx(struct crypto_hash *tfm) 38static inline struct hmac_ctx *hmac_ctx(struct crypto_shash *tfm)
39{ 39{
40 return align_ptr(crypto_hash_ctx_aligned(tfm) + 40 return align_ptr(crypto_shash_ctx_aligned(tfm) +
41 crypto_hash_blocksize(tfm) * 2 + 41 crypto_shash_blocksize(tfm) * 2 +
42 crypto_hash_digestsize(tfm), sizeof(void *)); 42 crypto_shash_digestsize(tfm),
43 crypto_tfm_ctx_alignment());
43} 44}
44 45
45static int hmac_setkey(struct crypto_hash *parent, 46static int hmac_setkey(struct crypto_shash *parent,
46 const u8 *inkey, unsigned int keylen) 47 const u8 *inkey, unsigned int keylen)
47{ 48{
48 int bs = crypto_hash_blocksize(parent); 49 int bs = crypto_shash_blocksize(parent);
49 int ds = crypto_hash_digestsize(parent); 50 int ds = crypto_shash_digestsize(parent);
50 char *ipad = crypto_hash_ctx_aligned(parent); 51 char *ipad = crypto_shash_ctx_aligned(parent);
51 char *opad = ipad + bs; 52 char *opad = ipad + bs;
52 char *digest = opad + bs; 53 char *digest = opad + bs;
53 struct hmac_ctx *ctx = align_ptr(digest + ds, sizeof(void *)); 54 struct hmac_ctx *ctx = align_ptr(digest + ds,
54 struct crypto_hash *tfm = ctx->child; 55 crypto_tfm_ctx_alignment());
55 unsigned int i; 56 unsigned int i;
56 57
57 if (keylen > bs) { 58 if (keylen > bs) {
58 struct hash_desc desc;
59 struct scatterlist tmp;
60 int tmplen;
61 int err; 59 int err;
62 60
63 desc.tfm = tfm; 61 ctx->desc->flags = crypto_shash_get_flags(parent) &
64 desc.flags = crypto_hash_get_flags(parent); 62 CRYPTO_TFM_REQ_MAY_SLEEP;
65 desc.flags &= CRYPTO_TFM_REQ_MAY_SLEEP;
66 63
67 err = crypto_hash_init(&desc); 64 err = crypto_shash_digest(ctx->desc, inkey, keylen, digest);
68 if (err)
69 return err;
70
71 tmplen = bs * 2 + ds;
72 sg_init_one(&tmp, ipad, tmplen);
73
74 for (; keylen > tmplen; inkey += tmplen, keylen -= tmplen) {
75 memcpy(ipad, inkey, tmplen);
76 err = crypto_hash_update(&desc, &tmp, tmplen);
77 if (err)
78 return err;
79 }
80
81 if (keylen) {
82 memcpy(ipad, inkey, keylen);
83 err = crypto_hash_update(&desc, &tmp, keylen);
84 if (err)
85 return err;
86 }
87
88 err = crypto_hash_final(&desc, digest);
89 if (err) 65 if (err)
90 return err; 66 return err;
91 67
@@ -105,181 +81,162 @@ static int hmac_setkey(struct crypto_hash *parent,
105 return 0; 81 return 0;
106} 82}
107 83
108static int hmac_init(struct hash_desc *pdesc) 84static int hmac_init(struct shash_desc *pdesc)
109{ 85{
110 struct crypto_hash *parent = pdesc->tfm; 86 struct crypto_shash *parent = pdesc->tfm;
111 int bs = crypto_hash_blocksize(parent); 87 int bs = crypto_shash_blocksize(parent);
112 int ds = crypto_hash_digestsize(parent); 88 int ds = crypto_shash_digestsize(parent);
113 char *ipad = crypto_hash_ctx_aligned(parent); 89 char *ipad = crypto_shash_ctx_aligned(parent);
114 struct hmac_ctx *ctx = align_ptr(ipad + bs * 2 + ds, sizeof(void *)); 90 struct hmac_ctx *ctx = align_ptr(ipad + bs * 2 + ds,
115 struct hash_desc desc; 91 crypto_tfm_ctx_alignment());
116 struct scatterlist tmp; 92 struct shash_desc *desc = shash_desc_ctx(pdesc);
117 int err; 93
118 94 desc->tfm = ctx->desc->tfm;
119 desc.tfm = ctx->child; 95 desc->flags = pdesc->flags & CRYPTO_TFM_REQ_MAY_SLEEP;
120 desc.flags = pdesc->flags & CRYPTO_TFM_REQ_MAY_SLEEP; 96
121 sg_init_one(&tmp, ipad, bs); 97 return crypto_shash_init(desc) ?:
122 98 crypto_shash_update(desc, ipad, bs);
123 err = crypto_hash_init(&desc);
124 if (unlikely(err))
125 return err;
126
127 return crypto_hash_update(&desc, &tmp, bs);
128} 99}
129 100
130static int hmac_update(struct hash_desc *pdesc, 101static int hmac_update(struct shash_desc *pdesc,
131 struct scatterlist *sg, unsigned int nbytes) 102 const u8 *data, unsigned int nbytes)
132{ 103{
133 struct hmac_ctx *ctx = hmac_ctx(pdesc->tfm); 104 struct shash_desc *desc = shash_desc_ctx(pdesc);
134 struct hash_desc desc;
135 105
136 desc.tfm = ctx->child; 106 desc->flags = pdesc->flags & CRYPTO_TFM_REQ_MAY_SLEEP;
137 desc.flags = pdesc->flags & CRYPTO_TFM_REQ_MAY_SLEEP;
138 107
139 return crypto_hash_update(&desc, sg, nbytes); 108 return crypto_shash_update(desc, data, nbytes);
140} 109}
141 110
142static int hmac_final(struct hash_desc *pdesc, u8 *out) 111static int hmac_final(struct shash_desc *pdesc, u8 *out)
143{ 112{
144 struct crypto_hash *parent = pdesc->tfm; 113 struct crypto_shash *parent = pdesc->tfm;
145 int bs = crypto_hash_blocksize(parent); 114 int bs = crypto_shash_blocksize(parent);
146 int ds = crypto_hash_digestsize(parent); 115 int ds = crypto_shash_digestsize(parent);
147 char *opad = crypto_hash_ctx_aligned(parent) + bs; 116 char *opad = crypto_shash_ctx_aligned(parent) + bs;
148 char *digest = opad + bs; 117 char *digest = opad + bs;
149 struct hmac_ctx *ctx = align_ptr(digest + ds, sizeof(void *)); 118 struct shash_desc *desc = shash_desc_ctx(pdesc);
150 struct hash_desc desc;
151 struct scatterlist tmp;
152 int err;
153
154 desc.tfm = ctx->child;
155 desc.flags = pdesc->flags & CRYPTO_TFM_REQ_MAY_SLEEP;
156 sg_init_one(&tmp, opad, bs + ds);
157 119
158 err = crypto_hash_final(&desc, digest); 120 desc->flags = pdesc->flags & CRYPTO_TFM_REQ_MAY_SLEEP;
159 if (unlikely(err))
160 return err;
161 121
162 return crypto_hash_digest(&desc, &tmp, bs + ds, out); 122 return crypto_shash_final(desc, digest) ?:
123 crypto_shash_digest(desc, opad, bs + ds, out);
163} 124}
164 125
165static int hmac_digest(struct hash_desc *pdesc, struct scatterlist *sg, 126static int hmac_finup(struct shash_desc *pdesc, const u8 *data,
166 unsigned int nbytes, u8 *out) 127 unsigned int nbytes, u8 *out)
167{ 128{
168 struct crypto_hash *parent = pdesc->tfm;
169 int bs = crypto_hash_blocksize(parent);
170 int ds = crypto_hash_digestsize(parent);
171 char *ipad = crypto_hash_ctx_aligned(parent);
172 char *opad = ipad + bs;
173 char *digest = opad + bs;
174 struct hmac_ctx *ctx = align_ptr(digest + ds, sizeof(void *));
175 struct hash_desc desc;
176 struct scatterlist sg1[2];
177 struct scatterlist sg2[1];
178 int err;
179 129
180 desc.tfm = ctx->child; 130 struct crypto_shash *parent = pdesc->tfm;
181 desc.flags = pdesc->flags & CRYPTO_TFM_REQ_MAY_SLEEP; 131 int bs = crypto_shash_blocksize(parent);
182 132 int ds = crypto_shash_digestsize(parent);
183 sg_init_table(sg1, 2); 133 char *opad = crypto_shash_ctx_aligned(parent) + bs;
184 sg_set_buf(sg1, ipad, bs); 134 char *digest = opad + bs;
185 scatterwalk_sg_chain(sg1, 2, sg); 135 struct shash_desc *desc = shash_desc_ctx(pdesc);
186 136
187 sg_init_table(sg2, 1); 137 desc->flags = pdesc->flags & CRYPTO_TFM_REQ_MAY_SLEEP;
188 sg_set_buf(sg2, opad, bs + ds);
189 138
190 err = crypto_hash_digest(&desc, sg1, nbytes + bs, digest); 139 return crypto_shash_finup(desc, data, nbytes, digest) ?:
191 if (unlikely(err)) 140 crypto_shash_digest(desc, opad, bs + ds, out);
192 return err;
193
194 return crypto_hash_digest(&desc, sg2, bs + ds, out);
195} 141}
196 142
197static int hmac_init_tfm(struct crypto_tfm *tfm) 143static int hmac_init_tfm(struct crypto_tfm *tfm)
198{ 144{
199 struct crypto_hash *hash; 145 struct crypto_shash *parent = __crypto_shash_cast(tfm);
146 struct crypto_shash *hash;
200 struct crypto_instance *inst = (void *)tfm->__crt_alg; 147 struct crypto_instance *inst = (void *)tfm->__crt_alg;
201 struct crypto_spawn *spawn = crypto_instance_ctx(inst); 148 struct crypto_shash_spawn *spawn = crypto_instance_ctx(inst);
202 struct hmac_ctx *ctx = hmac_ctx(__crypto_hash_cast(tfm)); 149 struct hmac_ctx *ctx = hmac_ctx(parent);
203 150
204 hash = crypto_spawn_hash(spawn); 151 hash = crypto_spawn_shash(spawn);
205 if (IS_ERR(hash)) 152 if (IS_ERR(hash))
206 return PTR_ERR(hash); 153 return PTR_ERR(hash);
207 154
208 ctx->child = hash; 155 parent->descsize = sizeof(struct shash_desc) +
156 crypto_shash_descsize(hash);
157
158 ctx->desc = kmalloc(parent->descsize, GFP_KERNEL);
159 if (!ctx->desc) {
160 crypto_free_shash(hash);
161 return -ENOMEM;
162 }
163
164 ctx->desc->tfm = hash;
209 return 0; 165 return 0;
210} 166}
211 167
212static void hmac_exit_tfm(struct crypto_tfm *tfm) 168static void hmac_exit_tfm(struct crypto_tfm *tfm)
213{ 169{
214 struct hmac_ctx *ctx = hmac_ctx(__crypto_hash_cast(tfm)); 170 struct hmac_ctx *ctx = hmac_ctx(__crypto_shash_cast(tfm));
215 crypto_free_hash(ctx->child); 171 crypto_free_shash(ctx->desc->tfm);
172 kzfree(ctx->desc);
216} 173}
217 174
218static void hmac_free(struct crypto_instance *inst) 175static int hmac_create(struct crypto_template *tmpl, struct rtattr **tb)
219{ 176{
220 crypto_drop_spawn(crypto_instance_ctx(inst)); 177 struct shash_instance *inst;
221 kfree(inst);
222}
223
224static struct crypto_instance *hmac_alloc(struct rtattr **tb)
225{
226 struct crypto_instance *inst;
227 struct crypto_alg *alg; 178 struct crypto_alg *alg;
179 struct shash_alg *salg;
228 int err; 180 int err;
229 int ds; 181 int ds;
230 182
231 err = crypto_check_attr_type(tb, CRYPTO_ALG_TYPE_HASH); 183 err = crypto_check_attr_type(tb, CRYPTO_ALG_TYPE_SHASH);
232 if (err) 184 if (err)
233 return ERR_PTR(err); 185 return err;
234 186
235 alg = crypto_get_attr_alg(tb, CRYPTO_ALG_TYPE_HASH, 187 salg = shash_attr_alg(tb[1], 0, 0);
236 CRYPTO_ALG_TYPE_HASH_MASK); 188 if (IS_ERR(salg))
237 if (IS_ERR(alg)) 189 return PTR_ERR(salg);
238 return ERR_CAST(alg); 190
239 191 err = -EINVAL;
240 inst = ERR_PTR(-EINVAL); 192 ds = salg->digestsize;
241 ds = alg->cra_type == &crypto_hash_type ? 193 alg = &salg->base;
242 alg->cra_hash.digestsize :
243 alg->cra_type ?
244 __crypto_shash_alg(alg)->digestsize :
245 alg->cra_digest.dia_digestsize;
246 if (ds > alg->cra_blocksize) 194 if (ds > alg->cra_blocksize)
247 goto out_put_alg; 195 goto out_put_alg;
248 196
249 inst = crypto_alloc_instance("hmac", alg); 197 inst = shash_alloc_instance("hmac", alg);
250 if (IS_ERR(inst)) 198 if (IS_ERR(inst))
251 goto out_put_alg; 199 goto out_put_alg;
252 200
253 inst->alg.cra_flags = CRYPTO_ALG_TYPE_HASH; 201 err = crypto_init_shash_spawn(shash_instance_ctx(inst), salg,
254 inst->alg.cra_priority = alg->cra_priority; 202 shash_crypto_instance(inst));
255 inst->alg.cra_blocksize = alg->cra_blocksize; 203 if (err)
256 inst->alg.cra_alignmask = alg->cra_alignmask; 204 goto out_free_inst;
257 inst->alg.cra_type = &crypto_hash_type; 205
206 inst->alg.base.cra_priority = alg->cra_priority;
207 inst->alg.base.cra_blocksize = alg->cra_blocksize;
208 inst->alg.base.cra_alignmask = alg->cra_alignmask;
258 209
259 inst->alg.cra_hash.digestsize = ds; 210 inst->alg.digestsize = ds;
260 211
261 inst->alg.cra_ctxsize = sizeof(struct hmac_ctx) + 212 inst->alg.base.cra_ctxsize = sizeof(struct hmac_ctx) +
262 ALIGN(inst->alg.cra_blocksize * 2 + ds, 213 ALIGN(alg->cra_blocksize * 2 + ds,
263 sizeof(void *)); 214 crypto_tfm_ctx_alignment());
264 215
265 inst->alg.cra_init = hmac_init_tfm; 216 inst->alg.base.cra_init = hmac_init_tfm;
266 inst->alg.cra_exit = hmac_exit_tfm; 217 inst->alg.base.cra_exit = hmac_exit_tfm;
267 218
268 inst->alg.cra_hash.init = hmac_init; 219 inst->alg.init = hmac_init;
269 inst->alg.cra_hash.update = hmac_update; 220 inst->alg.update = hmac_update;
270 inst->alg.cra_hash.final = hmac_final; 221 inst->alg.final = hmac_final;
271 inst->alg.cra_hash.digest = hmac_digest; 222 inst->alg.finup = hmac_finup;
272 inst->alg.cra_hash.setkey = hmac_setkey; 223 inst->alg.setkey = hmac_setkey;
224
225 err = shash_register_instance(tmpl, inst);
226 if (err) {
227out_free_inst:
228 shash_free_instance(shash_crypto_instance(inst));
229 }
273 230
274out_put_alg: 231out_put_alg:
275 crypto_mod_put(alg); 232 crypto_mod_put(alg);
276 return inst; 233 return err;
277} 234}
278 235
279static struct crypto_template hmac_tmpl = { 236static struct crypto_template hmac_tmpl = {
280 .name = "hmac", 237 .name = "hmac",
281 .alloc = hmac_alloc, 238 .create = hmac_create,
282 .free = hmac_free, 239 .free = shash_free_instance,
283 .module = THIS_MODULE, 240 .module = THIS_MODULE,
284}; 241};
285 242