aboutsummaryrefslogtreecommitdiffstats
path: root/crypto/hmac.c
diff options
context:
space:
mode:
Diffstat (limited to 'crypto/hmac.c')
-rw-r--r--crypto/hmac.c108
1 files changed, 62 insertions, 46 deletions
diff --git a/crypto/hmac.c b/crypto/hmac.c
index 02aa53ea14aa..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 shash_desc *desc; 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)
@@ -38,8 +38,7 @@ static inline void *align_ptr(void *p, unsigned int align)
38static inline struct hmac_ctx *hmac_ctx(struct crypto_shash *tfm) 38static inline struct hmac_ctx *hmac_ctx(struct crypto_shash *tfm)
39{ 39{
40 return align_ptr(crypto_shash_ctx_aligned(tfm) + 40 return align_ptr(crypto_shash_ctx_aligned(tfm) +
41 crypto_shash_blocksize(tfm) * 2 + 41 crypto_shash_statesize(tfm) * 2,
42 crypto_shash_digestsize(tfm),
43 crypto_tfm_ctx_alignment()); 42 crypto_tfm_ctx_alignment());
44} 43}
45 44
@@ -48,28 +47,33 @@ static int hmac_setkey(struct crypto_shash *parent,
48{ 47{
49 int bs = crypto_shash_blocksize(parent); 48 int bs = crypto_shash_blocksize(parent);
50 int ds = crypto_shash_digestsize(parent); 49 int ds = crypto_shash_digestsize(parent);
50 int ss = crypto_shash_statesize(parent);
51 char *ipad = crypto_shash_ctx_aligned(parent); 51 char *ipad = crypto_shash_ctx_aligned(parent);
52 char *opad = ipad + bs; 52 char *opad = ipad + ss;
53 char *digest = opad + bs; 53 struct hmac_ctx *ctx = align_ptr(opad + ss,
54 struct hmac_ctx *ctx = align_ptr(digest + ds,
55 crypto_tfm_ctx_alignment()); 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;
56 unsigned int i; 60 unsigned int i;
57 61
62 desc.shash.tfm = hash;
63 desc.shash.flags = crypto_shash_get_flags(parent) &
64 CRYPTO_TFM_REQ_MAY_SLEEP;
65
58 if (keylen > bs) { 66 if (keylen > bs) {
59 int err; 67 int err;
60 68
61 ctx->desc->flags = crypto_shash_get_flags(parent) & 69 err = crypto_shash_digest(&desc.shash, inkey, keylen, ipad);
62 CRYPTO_TFM_REQ_MAY_SLEEP;
63
64 err = crypto_shash_digest(ctx->desc, inkey, keylen, digest);
65 if (err) 70 if (err)
66 return err; 71 return err;
67 72
68 inkey = digest;
69 keylen = ds; 73 keylen = ds;
70 } 74 } else
75 memcpy(ipad, inkey, keylen);
71 76
72 memcpy(ipad, inkey, keylen);
73 memset(ipad + keylen, 0, bs - keylen); 77 memset(ipad + keylen, 0, bs - keylen);
74 memcpy(opad, ipad, bs); 78 memcpy(opad, ipad, bs);
75 79
@@ -78,24 +82,37 @@ static int hmac_setkey(struct crypto_shash *parent,
78 opad[i] ^= 0x5c; 82 opad[i] ^= 0x5c;
79 } 83 }
80 84
81 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);
82} 91}
83 92
84static int hmac_init(struct shash_desc *pdesc) 93static int hmac_export(struct shash_desc *pdesc, void *out)
94{
95 struct shash_desc *desc = shash_desc_ctx(pdesc);
96
97 desc->flags = pdesc->flags & CRYPTO_TFM_REQ_MAY_SLEEP;
98
99 return crypto_shash_export(desc, out);
100}
101
102static int hmac_import(struct shash_desc *pdesc, const void *in)
85{ 103{
86 struct crypto_shash *parent = pdesc->tfm;
87 int bs = crypto_shash_blocksize(parent);
88 int ds = crypto_shash_digestsize(parent);
89 char *ipad = crypto_shash_ctx_aligned(parent);
90 struct hmac_ctx *ctx = align_ptr(ipad + bs * 2 + ds,
91 crypto_tfm_ctx_alignment());
92 struct shash_desc *desc = shash_desc_ctx(pdesc); 104 struct shash_desc *desc = shash_desc_ctx(pdesc);
105 struct hmac_ctx *ctx = hmac_ctx(pdesc->tfm);
93 106
94 desc->tfm = ctx->desc->tfm; 107 desc->tfm = ctx->hash;
95 desc->flags = pdesc->flags & CRYPTO_TFM_REQ_MAY_SLEEP; 108 desc->flags = pdesc->flags & CRYPTO_TFM_REQ_MAY_SLEEP;
96 109
97 return crypto_shash_init(desc) ?: 110 return crypto_shash_import(desc, in);
98 crypto_shash_update(desc, ipad, bs); 111}
112
113static int hmac_init(struct shash_desc *pdesc)
114{
115 return hmac_import(pdesc, crypto_shash_ctx_aligned(pdesc->tfm));
99} 116}
100 117
101static int hmac_update(struct shash_desc *pdesc, 118static int hmac_update(struct shash_desc *pdesc,
@@ -111,16 +128,16 @@ static int hmac_update(struct shash_desc *pdesc,
111static int hmac_final(struct shash_desc *pdesc, u8 *out) 128static int hmac_final(struct shash_desc *pdesc, u8 *out)
112{ 129{
113 struct crypto_shash *parent = pdesc->tfm; 130 struct crypto_shash *parent = pdesc->tfm;
114 int bs = crypto_shash_blocksize(parent);
115 int ds = crypto_shash_digestsize(parent); 131 int ds = crypto_shash_digestsize(parent);
116 char *opad = crypto_shash_ctx_aligned(parent) + bs; 132 int ss = crypto_shash_statesize(parent);
117 char *digest = opad + bs; 133 char *opad = crypto_shash_ctx_aligned(parent) + ss;
118 struct shash_desc *desc = shash_desc_ctx(pdesc); 134 struct shash_desc *desc = shash_desc_ctx(pdesc);
119 135
120 desc->flags = pdesc->flags & CRYPTO_TFM_REQ_MAY_SLEEP; 136 desc->flags = pdesc->flags & CRYPTO_TFM_REQ_MAY_SLEEP;
121 137
122 return crypto_shash_final(desc, digest) ?: 138 return crypto_shash_final(desc, out) ?:
123 crypto_shash_digest(desc, opad, bs + ds, out); 139 crypto_shash_import(desc, opad) ?:
140 crypto_shash_finup(desc, out, ds, out);
124} 141}
125 142
126static int hmac_finup(struct shash_desc *pdesc, const u8 *data, 143static int hmac_finup(struct shash_desc *pdesc, const u8 *data,
@@ -128,16 +145,16 @@ static int hmac_finup(struct shash_desc *pdesc, const u8 *data,
128{ 145{
129 146
130 struct crypto_shash *parent = pdesc->tfm; 147 struct crypto_shash *parent = pdesc->tfm;
131 int bs = crypto_shash_blocksize(parent);
132 int ds = crypto_shash_digestsize(parent); 148 int ds = crypto_shash_digestsize(parent);
133 char *opad = crypto_shash_ctx_aligned(parent) + bs; 149 int ss = crypto_shash_statesize(parent);
134 char *digest = opad + bs; 150 char *opad = crypto_shash_ctx_aligned(parent) + ss;
135 struct shash_desc *desc = shash_desc_ctx(pdesc); 151 struct shash_desc *desc = shash_desc_ctx(pdesc);
136 152
137 desc->flags = pdesc->flags & CRYPTO_TFM_REQ_MAY_SLEEP; 153 desc->flags = pdesc->flags & CRYPTO_TFM_REQ_MAY_SLEEP;
138 154
139 return crypto_shash_finup(desc, data, nbytes, digest) ?: 155 return crypto_shash_finup(desc, data, nbytes, out) ?:
140 crypto_shash_digest(desc, opad, bs + ds, out); 156 crypto_shash_import(desc, opad) ?:
157 crypto_shash_finup(desc, out, ds, out);
141} 158}
142 159
143static int hmac_init_tfm(struct crypto_tfm *tfm) 160static int hmac_init_tfm(struct crypto_tfm *tfm)
@@ -155,21 +172,14 @@ static int hmac_init_tfm(struct crypto_tfm *tfm)
155 parent->descsize = sizeof(struct shash_desc) + 172 parent->descsize = sizeof(struct shash_desc) +
156 crypto_shash_descsize(hash); 173 crypto_shash_descsize(hash);
157 174
158 ctx->desc = kmalloc(parent->descsize, GFP_KERNEL); 175 ctx->hash = hash;
159 if (!ctx->desc) {
160 crypto_free_shash(hash);
161 return -ENOMEM;
162 }
163
164 ctx->desc->tfm = hash;
165 return 0; 176 return 0;
166} 177}
167 178
168static void hmac_exit_tfm(struct crypto_tfm *tfm) 179static void hmac_exit_tfm(struct crypto_tfm *tfm)
169{ 180{
170 struct hmac_ctx *ctx = hmac_ctx(__crypto_shash_cast(tfm)); 181 struct hmac_ctx *ctx = hmac_ctx(__crypto_shash_cast(tfm));
171 crypto_free_shash(ctx->desc->tfm); 182 crypto_free_shash(ctx->hash);
172 kzfree(ctx->desc);
173} 183}
174 184
175static int hmac_create(struct crypto_template *tmpl, struct rtattr **tb) 185static int hmac_create(struct crypto_template *tmpl, struct rtattr **tb)
@@ -179,6 +189,7 @@ static int hmac_create(struct crypto_template *tmpl, struct rtattr **tb)
179 struct shash_alg *salg; 189 struct shash_alg *salg;
180 int err; 190 int err;
181 int ds; 191 int ds;
192 int ss;
182 193
183 err = crypto_check_attr_type(tb, CRYPTO_ALG_TYPE_SHASH); 194 err = crypto_check_attr_type(tb, CRYPTO_ALG_TYPE_SHASH);
184 if (err) 195 if (err)
@@ -190,8 +201,10 @@ static int hmac_create(struct crypto_template *tmpl, struct rtattr **tb)
190 201
191 err = -EINVAL; 202 err = -EINVAL;
192 ds = salg->digestsize; 203 ds = salg->digestsize;
204 ss = salg->statesize;
193 alg = &salg->base; 205 alg = &salg->base;
194 if (ds > alg->cra_blocksize) 206 if (ds > alg->cra_blocksize ||
207 ss < alg->cra_blocksize)
195 goto out_put_alg; 208 goto out_put_alg;
196 209
197 inst = shash_alloc_instance("hmac", alg); 210 inst = shash_alloc_instance("hmac", alg);
@@ -208,11 +221,12 @@ static int hmac_create(struct crypto_template *tmpl, struct rtattr **tb)
208 inst->alg.base.cra_blocksize = alg->cra_blocksize; 221 inst->alg.base.cra_blocksize = alg->cra_blocksize;
209 inst->alg.base.cra_alignmask = alg->cra_alignmask; 222 inst->alg.base.cra_alignmask = alg->cra_alignmask;
210 223
224 ss = ALIGN(ss, alg->cra_alignmask + 1);
211 inst->alg.digestsize = ds; 225 inst->alg.digestsize = ds;
226 inst->alg.statesize = ss;
212 227
213 inst->alg.base.cra_ctxsize = sizeof(struct hmac_ctx) + 228 inst->alg.base.cra_ctxsize = sizeof(struct hmac_ctx) +
214 ALIGN(alg->cra_blocksize * 2 + ds, 229 ALIGN(ss * 2, crypto_tfm_ctx_alignment());
215 crypto_tfm_ctx_alignment());
216 230
217 inst->alg.base.cra_init = hmac_init_tfm; 231 inst->alg.base.cra_init = hmac_init_tfm;
218 inst->alg.base.cra_exit = hmac_exit_tfm; 232 inst->alg.base.cra_exit = hmac_exit_tfm;
@@ -221,6 +235,8 @@ static int hmac_create(struct crypto_template *tmpl, struct rtattr **tb)
221 inst->alg.update = hmac_update; 235 inst->alg.update = hmac_update;
222 inst->alg.final = hmac_final; 236 inst->alg.final = hmac_final;
223 inst->alg.finup = hmac_finup; 237 inst->alg.finup = hmac_finup;
238 inst->alg.export = hmac_export;
239 inst->alg.import = hmac_import;
224 inst->alg.setkey = hmac_setkey; 240 inst->alg.setkey = hmac_setkey;
225 241
226 err = shash_register_instance(tmpl, inst); 242 err = shash_register_instance(tmpl, inst);