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