diff options
Diffstat (limited to 'crypto/authenc.c')
-rw-r--r-- | crypto/authenc.c | 334 |
1 files changed, 213 insertions, 121 deletions
diff --git a/crypto/authenc.c b/crypto/authenc.c index 126a529b496d..ed8ac5a6fa5f 100644 --- a/crypto/authenc.c +++ b/crypto/authenc.c | |||
@@ -10,22 +10,21 @@ | |||
10 | * | 10 | * |
11 | */ | 11 | */ |
12 | 12 | ||
13 | #include <crypto/algapi.h> | 13 | #include <crypto/aead.h> |
14 | #include <crypto/internal/skcipher.h> | ||
15 | #include <crypto/authenc.h> | ||
16 | #include <crypto/scatterwalk.h> | ||
14 | #include <linux/err.h> | 17 | #include <linux/err.h> |
15 | #include <linux/init.h> | 18 | #include <linux/init.h> |
16 | #include <linux/kernel.h> | 19 | #include <linux/kernel.h> |
17 | #include <linux/module.h> | 20 | #include <linux/module.h> |
21 | #include <linux/rtnetlink.h> | ||
18 | #include <linux/slab.h> | 22 | #include <linux/slab.h> |
19 | #include <linux/spinlock.h> | 23 | #include <linux/spinlock.h> |
20 | 24 | ||
21 | #include "scatterwalk.h" | ||
22 | |||
23 | struct authenc_instance_ctx { | 25 | struct authenc_instance_ctx { |
24 | struct crypto_spawn auth; | 26 | struct crypto_spawn auth; |
25 | struct crypto_spawn enc; | 27 | struct crypto_skcipher_spawn enc; |
26 | |||
27 | unsigned int authsize; | ||
28 | unsigned int enckeylen; | ||
29 | }; | 28 | }; |
30 | 29 | ||
31 | struct crypto_authenc_ctx { | 30 | struct crypto_authenc_ctx { |
@@ -37,19 +36,31 @@ struct crypto_authenc_ctx { | |||
37 | static int crypto_authenc_setkey(struct crypto_aead *authenc, const u8 *key, | 36 | static int crypto_authenc_setkey(struct crypto_aead *authenc, const u8 *key, |
38 | unsigned int keylen) | 37 | unsigned int keylen) |
39 | { | 38 | { |
40 | struct authenc_instance_ctx *ictx = | ||
41 | crypto_instance_ctx(crypto_aead_alg_instance(authenc)); | ||
42 | unsigned int enckeylen = ictx->enckeylen; | ||
43 | unsigned int authkeylen; | 39 | unsigned int authkeylen; |
40 | unsigned int enckeylen; | ||
44 | struct crypto_authenc_ctx *ctx = crypto_aead_ctx(authenc); | 41 | struct crypto_authenc_ctx *ctx = crypto_aead_ctx(authenc); |
45 | struct crypto_hash *auth = ctx->auth; | 42 | struct crypto_hash *auth = ctx->auth; |
46 | struct crypto_ablkcipher *enc = ctx->enc; | 43 | struct crypto_ablkcipher *enc = ctx->enc; |
44 | struct rtattr *rta = (void *)key; | ||
45 | struct crypto_authenc_key_param *param; | ||
47 | int err = -EINVAL; | 46 | int err = -EINVAL; |
48 | 47 | ||
49 | if (keylen < enckeylen) { | 48 | if (!RTA_OK(rta, keylen)) |
50 | crypto_aead_set_flags(authenc, CRYPTO_TFM_RES_BAD_KEY_LEN); | 49 | goto badkey; |
51 | goto out; | 50 | if (rta->rta_type != CRYPTO_AUTHENC_KEYA_PARAM) |
52 | } | 51 | goto badkey; |
52 | if (RTA_PAYLOAD(rta) < sizeof(*param)) | ||
53 | goto badkey; | ||
54 | |||
55 | param = RTA_DATA(rta); | ||
56 | enckeylen = be32_to_cpu(param->enckeylen); | ||
57 | |||
58 | key += RTA_ALIGN(rta->rta_len); | ||
59 | keylen -= RTA_ALIGN(rta->rta_len); | ||
60 | |||
61 | if (keylen < enckeylen) | ||
62 | goto badkey; | ||
63 | |||
53 | authkeylen = keylen - enckeylen; | 64 | authkeylen = keylen - enckeylen; |
54 | 65 | ||
55 | crypto_hash_clear_flags(auth, CRYPTO_TFM_REQ_MASK); | 66 | crypto_hash_clear_flags(auth, CRYPTO_TFM_REQ_MASK); |
@@ -71,21 +82,38 @@ static int crypto_authenc_setkey(struct crypto_aead *authenc, const u8 *key, | |||
71 | 82 | ||
72 | out: | 83 | out: |
73 | return err; | 84 | return err; |
85 | |||
86 | badkey: | ||
87 | crypto_aead_set_flags(authenc, CRYPTO_TFM_RES_BAD_KEY_LEN); | ||
88 | goto out; | ||
74 | } | 89 | } |
75 | 90 | ||
76 | static int crypto_authenc_hash(struct aead_request *req) | 91 | static void authenc_chain(struct scatterlist *head, struct scatterlist *sg, |
92 | int chain) | ||
93 | { | ||
94 | if (chain) { | ||
95 | head->length += sg->length; | ||
96 | sg = scatterwalk_sg_next(sg); | ||
97 | } | ||
98 | |||
99 | if (sg) | ||
100 | scatterwalk_sg_chain(head, 2, sg); | ||
101 | else | ||
102 | sg_mark_end(head); | ||
103 | } | ||
104 | |||
105 | static u8 *crypto_authenc_hash(struct aead_request *req, unsigned int flags, | ||
106 | struct scatterlist *cipher, | ||
107 | unsigned int cryptlen) | ||
77 | { | 108 | { |
78 | struct crypto_aead *authenc = crypto_aead_reqtfm(req); | 109 | struct crypto_aead *authenc = crypto_aead_reqtfm(req); |
79 | struct authenc_instance_ctx *ictx = | ||
80 | crypto_instance_ctx(crypto_aead_alg_instance(authenc)); | ||
81 | struct crypto_authenc_ctx *ctx = crypto_aead_ctx(authenc); | 110 | struct crypto_authenc_ctx *ctx = crypto_aead_ctx(authenc); |
82 | struct crypto_hash *auth = ctx->auth; | 111 | struct crypto_hash *auth = ctx->auth; |
83 | struct hash_desc desc = { | 112 | struct hash_desc desc = { |
84 | .tfm = auth, | 113 | .tfm = auth, |
114 | .flags = aead_request_flags(req) & flags, | ||
85 | }; | 115 | }; |
86 | u8 *hash = aead_request_ctx(req); | 116 | u8 *hash = aead_request_ctx(req); |
87 | struct scatterlist *dst = req->dst; | ||
88 | unsigned int cryptlen = req->cryptlen; | ||
89 | int err; | 117 | int err; |
90 | 118 | ||
91 | hash = (u8 *)ALIGN((unsigned long)hash + crypto_hash_alignmask(auth), | 119 | hash = (u8 *)ALIGN((unsigned long)hash + crypto_hash_alignmask(auth), |
@@ -100,7 +128,7 @@ static int crypto_authenc_hash(struct aead_request *req) | |||
100 | if (err) | 128 | if (err) |
101 | goto auth_unlock; | 129 | goto auth_unlock; |
102 | 130 | ||
103 | err = crypto_hash_update(&desc, dst, cryptlen); | 131 | err = crypto_hash_update(&desc, cipher, cryptlen); |
104 | if (err) | 132 | if (err) |
105 | goto auth_unlock; | 133 | goto auth_unlock; |
106 | 134 | ||
@@ -109,17 +137,53 @@ auth_unlock: | |||
109 | spin_unlock_bh(&ctx->auth_lock); | 137 | spin_unlock_bh(&ctx->auth_lock); |
110 | 138 | ||
111 | if (err) | 139 | if (err) |
112 | return err; | 140 | return ERR_PTR(err); |
141 | |||
142 | return hash; | ||
143 | } | ||
113 | 144 | ||
114 | scatterwalk_map_and_copy(hash, dst, cryptlen, ictx->authsize, 1); | 145 | static int crypto_authenc_genicv(struct aead_request *req, u8 *iv, |
146 | unsigned int flags) | ||
147 | { | ||
148 | struct crypto_aead *authenc = crypto_aead_reqtfm(req); | ||
149 | struct scatterlist *dst = req->dst; | ||
150 | struct scatterlist cipher[2]; | ||
151 | struct page *dstp; | ||
152 | unsigned int ivsize = crypto_aead_ivsize(authenc); | ||
153 | unsigned int cryptlen; | ||
154 | u8 *vdst; | ||
155 | u8 *hash; | ||
156 | |||
157 | dstp = sg_page(dst); | ||
158 | vdst = PageHighMem(dstp) ? NULL : page_address(dstp) + dst->offset; | ||
159 | |||
160 | sg_init_table(cipher, 2); | ||
161 | sg_set_buf(cipher, iv, ivsize); | ||
162 | authenc_chain(cipher, dst, vdst == iv + ivsize); | ||
163 | |||
164 | cryptlen = req->cryptlen + ivsize; | ||
165 | hash = crypto_authenc_hash(req, flags, cipher, cryptlen); | ||
166 | if (IS_ERR(hash)) | ||
167 | return PTR_ERR(hash); | ||
168 | |||
169 | scatterwalk_map_and_copy(hash, cipher, cryptlen, | ||
170 | crypto_aead_authsize(authenc), 1); | ||
115 | return 0; | 171 | return 0; |
116 | } | 172 | } |
117 | 173 | ||
118 | static void crypto_authenc_encrypt_done(struct crypto_async_request *req, | 174 | static void crypto_authenc_encrypt_done(struct crypto_async_request *req, |
119 | int err) | 175 | int err) |
120 | { | 176 | { |
121 | if (!err) | 177 | if (!err) { |
122 | err = crypto_authenc_hash(req->data); | 178 | struct aead_request *areq = req->data; |
179 | struct crypto_aead *authenc = crypto_aead_reqtfm(areq); | ||
180 | struct crypto_authenc_ctx *ctx = crypto_aead_ctx(authenc); | ||
181 | struct ablkcipher_request *abreq = aead_request_ctx(areq); | ||
182 | u8 *iv = (u8 *)(abreq + 1) + | ||
183 | crypto_ablkcipher_reqsize(ctx->enc); | ||
184 | |||
185 | err = crypto_authenc_genicv(areq, iv, 0); | ||
186 | } | ||
123 | 187 | ||
124 | aead_request_complete(req->data, err); | 188 | aead_request_complete(req->data, err); |
125 | } | 189 | } |
@@ -129,72 +193,99 @@ static int crypto_authenc_encrypt(struct aead_request *req) | |||
129 | struct crypto_aead *authenc = crypto_aead_reqtfm(req); | 193 | struct crypto_aead *authenc = crypto_aead_reqtfm(req); |
130 | struct crypto_authenc_ctx *ctx = crypto_aead_ctx(authenc); | 194 | struct crypto_authenc_ctx *ctx = crypto_aead_ctx(authenc); |
131 | struct ablkcipher_request *abreq = aead_request_ctx(req); | 195 | struct ablkcipher_request *abreq = aead_request_ctx(req); |
196 | struct crypto_ablkcipher *enc = ctx->enc; | ||
197 | struct scatterlist *dst = req->dst; | ||
198 | unsigned int cryptlen = req->cryptlen; | ||
199 | u8 *iv = (u8 *)(abreq + 1) + crypto_ablkcipher_reqsize(enc); | ||
132 | int err; | 200 | int err; |
133 | 201 | ||
134 | ablkcipher_request_set_tfm(abreq, ctx->enc); | 202 | ablkcipher_request_set_tfm(abreq, enc); |
135 | ablkcipher_request_set_callback(abreq, aead_request_flags(req), | 203 | ablkcipher_request_set_callback(abreq, aead_request_flags(req), |
136 | crypto_authenc_encrypt_done, req); | 204 | crypto_authenc_encrypt_done, req); |
137 | ablkcipher_request_set_crypt(abreq, req->src, req->dst, req->cryptlen, | 205 | ablkcipher_request_set_crypt(abreq, req->src, dst, cryptlen, req->iv); |
138 | req->iv); | 206 | |
207 | memcpy(iv, req->iv, crypto_aead_ivsize(authenc)); | ||
139 | 208 | ||
140 | err = crypto_ablkcipher_encrypt(abreq); | 209 | err = crypto_ablkcipher_encrypt(abreq); |
141 | if (err) | 210 | if (err) |
142 | return err; | 211 | return err; |
143 | 212 | ||
144 | return crypto_authenc_hash(req); | 213 | return crypto_authenc_genicv(req, iv, CRYPTO_TFM_REQ_MAY_SLEEP); |
145 | } | 214 | } |
146 | 215 | ||
147 | static int crypto_authenc_verify(struct aead_request *req) | 216 | static void crypto_authenc_givencrypt_done(struct crypto_async_request *req, |
217 | int err) | ||
148 | { | 218 | { |
149 | struct crypto_aead *authenc = crypto_aead_reqtfm(req); | 219 | if (!err) { |
150 | struct authenc_instance_ctx *ictx = | 220 | struct aead_givcrypt_request *greq = req->data; |
151 | crypto_instance_ctx(crypto_aead_alg_instance(authenc)); | 221 | |
222 | err = crypto_authenc_genicv(&greq->areq, greq->giv, 0); | ||
223 | } | ||
224 | |||
225 | aead_request_complete(req->data, err); | ||
226 | } | ||
227 | |||
228 | static int crypto_authenc_givencrypt(struct aead_givcrypt_request *req) | ||
229 | { | ||
230 | struct crypto_aead *authenc = aead_givcrypt_reqtfm(req); | ||
152 | struct crypto_authenc_ctx *ctx = crypto_aead_ctx(authenc); | 231 | struct crypto_authenc_ctx *ctx = crypto_aead_ctx(authenc); |
153 | struct crypto_hash *auth = ctx->auth; | 232 | struct aead_request *areq = &req->areq; |
154 | struct hash_desc desc = { | 233 | struct skcipher_givcrypt_request *greq = aead_request_ctx(areq); |
155 | .tfm = auth, | 234 | u8 *iv = req->giv; |
156 | .flags = aead_request_flags(req), | ||
157 | }; | ||
158 | u8 *ohash = aead_request_ctx(req); | ||
159 | u8 *ihash; | ||
160 | struct scatterlist *src = req->src; | ||
161 | unsigned int cryptlen = req->cryptlen; | ||
162 | unsigned int authsize; | ||
163 | int err; | 235 | int err; |
164 | 236 | ||
165 | ohash = (u8 *)ALIGN((unsigned long)ohash + crypto_hash_alignmask(auth), | 237 | skcipher_givcrypt_set_tfm(greq, ctx->enc); |
166 | crypto_hash_alignmask(auth) + 1); | 238 | skcipher_givcrypt_set_callback(greq, aead_request_flags(areq), |
167 | ihash = ohash + crypto_hash_digestsize(auth); | 239 | crypto_authenc_givencrypt_done, areq); |
168 | 240 | skcipher_givcrypt_set_crypt(greq, areq->src, areq->dst, areq->cryptlen, | |
169 | spin_lock_bh(&ctx->auth_lock); | 241 | areq->iv); |
170 | err = crypto_hash_init(&desc); | 242 | skcipher_givcrypt_set_giv(greq, iv, req->seq); |
171 | if (err) | ||
172 | goto auth_unlock; | ||
173 | 243 | ||
174 | err = crypto_hash_update(&desc, req->assoc, req->assoclen); | 244 | err = crypto_skcipher_givencrypt(greq); |
175 | if (err) | 245 | if (err) |
176 | goto auth_unlock; | 246 | return err; |
177 | 247 | ||
178 | err = crypto_hash_update(&desc, src, cryptlen); | 248 | return crypto_authenc_genicv(areq, iv, CRYPTO_TFM_REQ_MAY_SLEEP); |
179 | if (err) | 249 | } |
180 | goto auth_unlock; | ||
181 | 250 | ||
182 | err = crypto_hash_final(&desc, ohash); | 251 | static int crypto_authenc_verify(struct aead_request *req, |
183 | auth_unlock: | 252 | struct scatterlist *cipher, |
184 | spin_unlock_bh(&ctx->auth_lock); | 253 | unsigned int cryptlen) |
254 | { | ||
255 | struct crypto_aead *authenc = crypto_aead_reqtfm(req); | ||
256 | u8 *ohash; | ||
257 | u8 *ihash; | ||
258 | unsigned int authsize; | ||
185 | 259 | ||
186 | if (err) | 260 | ohash = crypto_authenc_hash(req, CRYPTO_TFM_REQ_MAY_SLEEP, cipher, |
187 | return err; | 261 | cryptlen); |
262 | if (IS_ERR(ohash)) | ||
263 | return PTR_ERR(ohash); | ||
188 | 264 | ||
189 | authsize = ictx->authsize; | 265 | authsize = crypto_aead_authsize(authenc); |
190 | scatterwalk_map_and_copy(ihash, src, cryptlen, authsize, 0); | 266 | ihash = ohash + authsize; |
191 | return memcmp(ihash, ohash, authsize) ? -EINVAL : 0; | 267 | scatterwalk_map_and_copy(ihash, cipher, cryptlen, authsize, 0); |
268 | return memcmp(ihash, ohash, authsize) ? -EBADMSG: 0; | ||
192 | } | 269 | } |
193 | 270 | ||
194 | static void crypto_authenc_decrypt_done(struct crypto_async_request *req, | 271 | static int crypto_authenc_iverify(struct aead_request *req, u8 *iv, |
195 | int err) | 272 | unsigned int cryptlen) |
196 | { | 273 | { |
197 | aead_request_complete(req->data, err); | 274 | struct crypto_aead *authenc = crypto_aead_reqtfm(req); |
275 | struct scatterlist *src = req->src; | ||
276 | struct scatterlist cipher[2]; | ||
277 | struct page *srcp; | ||
278 | unsigned int ivsize = crypto_aead_ivsize(authenc); | ||
279 | u8 *vsrc; | ||
280 | |||
281 | srcp = sg_page(src); | ||
282 | vsrc = PageHighMem(srcp) ? NULL : page_address(srcp) + src->offset; | ||
283 | |||
284 | sg_init_table(cipher, 2); | ||
285 | sg_set_buf(cipher, iv, ivsize); | ||
286 | authenc_chain(cipher, src, vsrc == iv + ivsize); | ||
287 | |||
288 | return crypto_authenc_verify(req, cipher, cryptlen + ivsize); | ||
198 | } | 289 | } |
199 | 290 | ||
200 | static int crypto_authenc_decrypt(struct aead_request *req) | 291 | static int crypto_authenc_decrypt(struct aead_request *req) |
@@ -202,17 +293,23 @@ static int crypto_authenc_decrypt(struct aead_request *req) | |||
202 | struct crypto_aead *authenc = crypto_aead_reqtfm(req); | 293 | struct crypto_aead *authenc = crypto_aead_reqtfm(req); |
203 | struct crypto_authenc_ctx *ctx = crypto_aead_ctx(authenc); | 294 | struct crypto_authenc_ctx *ctx = crypto_aead_ctx(authenc); |
204 | struct ablkcipher_request *abreq = aead_request_ctx(req); | 295 | struct ablkcipher_request *abreq = aead_request_ctx(req); |
296 | unsigned int cryptlen = req->cryptlen; | ||
297 | unsigned int authsize = crypto_aead_authsize(authenc); | ||
298 | u8 *iv = req->iv; | ||
205 | int err; | 299 | int err; |
206 | 300 | ||
207 | err = crypto_authenc_verify(req); | 301 | if (cryptlen < authsize) |
302 | return -EINVAL; | ||
303 | cryptlen -= authsize; | ||
304 | |||
305 | err = crypto_authenc_iverify(req, iv, cryptlen); | ||
208 | if (err) | 306 | if (err) |
209 | return err; | 307 | return err; |
210 | 308 | ||
211 | ablkcipher_request_set_tfm(abreq, ctx->enc); | 309 | ablkcipher_request_set_tfm(abreq, ctx->enc); |
212 | ablkcipher_request_set_callback(abreq, aead_request_flags(req), | 310 | ablkcipher_request_set_callback(abreq, aead_request_flags(req), |
213 | crypto_authenc_decrypt_done, req); | 311 | req->base.complete, req->base.data); |
214 | ablkcipher_request_set_crypt(abreq, req->src, req->dst, req->cryptlen, | 312 | ablkcipher_request_set_crypt(abreq, req->src, req->dst, cryptlen, iv); |
215 | req->iv); | ||
216 | 313 | ||
217 | return crypto_ablkcipher_decrypt(abreq); | 314 | return crypto_ablkcipher_decrypt(abreq); |
218 | } | 315 | } |
@@ -224,19 +321,13 @@ static int crypto_authenc_init_tfm(struct crypto_tfm *tfm) | |||
224 | struct crypto_authenc_ctx *ctx = crypto_tfm_ctx(tfm); | 321 | struct crypto_authenc_ctx *ctx = crypto_tfm_ctx(tfm); |
225 | struct crypto_hash *auth; | 322 | struct crypto_hash *auth; |
226 | struct crypto_ablkcipher *enc; | 323 | struct crypto_ablkcipher *enc; |
227 | unsigned int digestsize; | ||
228 | int err; | 324 | int err; |
229 | 325 | ||
230 | auth = crypto_spawn_hash(&ictx->auth); | 326 | auth = crypto_spawn_hash(&ictx->auth); |
231 | if (IS_ERR(auth)) | 327 | if (IS_ERR(auth)) |
232 | return PTR_ERR(auth); | 328 | return PTR_ERR(auth); |
233 | 329 | ||
234 | err = -EINVAL; | 330 | enc = crypto_spawn_skcipher(&ictx->enc); |
235 | digestsize = crypto_hash_digestsize(auth); | ||
236 | if (ictx->authsize > digestsize) | ||
237 | goto err_free_hash; | ||
238 | |||
239 | enc = crypto_spawn_ablkcipher(&ictx->enc); | ||
240 | err = PTR_ERR(enc); | 331 | err = PTR_ERR(enc); |
241 | if (IS_ERR(enc)) | 332 | if (IS_ERR(enc)) |
242 | goto err_free_hash; | 333 | goto err_free_hash; |
@@ -246,9 +337,10 @@ static int crypto_authenc_init_tfm(struct crypto_tfm *tfm) | |||
246 | tfm->crt_aead.reqsize = max_t(unsigned int, | 337 | tfm->crt_aead.reqsize = max_t(unsigned int, |
247 | (crypto_hash_alignmask(auth) & | 338 | (crypto_hash_alignmask(auth) & |
248 | ~(crypto_tfm_ctx_alignment() - 1)) + | 339 | ~(crypto_tfm_ctx_alignment() - 1)) + |
249 | digestsize * 2, | 340 | crypto_hash_digestsize(auth) * 2, |
250 | sizeof(struct ablkcipher_request) + | 341 | sizeof(struct skcipher_givcrypt_request) + |
251 | crypto_ablkcipher_reqsize(enc)); | 342 | crypto_ablkcipher_reqsize(enc) + |
343 | crypto_ablkcipher_ivsize(enc)); | ||
252 | 344 | ||
253 | spin_lock_init(&ctx->auth_lock); | 345 | spin_lock_init(&ctx->auth_lock); |
254 | 346 | ||
@@ -269,75 +361,74 @@ static void crypto_authenc_exit_tfm(struct crypto_tfm *tfm) | |||
269 | 361 | ||
270 | static struct crypto_instance *crypto_authenc_alloc(struct rtattr **tb) | 362 | static struct crypto_instance *crypto_authenc_alloc(struct rtattr **tb) |
271 | { | 363 | { |
364 | struct crypto_attr_type *algt; | ||
272 | struct crypto_instance *inst; | 365 | struct crypto_instance *inst; |
273 | struct crypto_alg *auth; | 366 | struct crypto_alg *auth; |
274 | struct crypto_alg *enc; | 367 | struct crypto_alg *enc; |
275 | struct authenc_instance_ctx *ctx; | 368 | struct authenc_instance_ctx *ctx; |
276 | unsigned int authsize; | 369 | const char *enc_name; |
277 | unsigned int enckeylen; | ||
278 | int err; | 370 | int err; |
279 | 371 | ||
280 | err = crypto_check_attr_type(tb, CRYPTO_ALG_TYPE_AEAD); | 372 | algt = crypto_get_attr_type(tb); |
281 | if (err) | 373 | err = PTR_ERR(algt); |
374 | if (IS_ERR(algt)) | ||
282 | return ERR_PTR(err); | 375 | return ERR_PTR(err); |
283 | 376 | ||
377 | if ((algt->type ^ CRYPTO_ALG_TYPE_AEAD) & algt->mask) | ||
378 | return ERR_PTR(-EINVAL); | ||
379 | |||
284 | auth = crypto_attr_alg(tb[1], CRYPTO_ALG_TYPE_HASH, | 380 | auth = crypto_attr_alg(tb[1], CRYPTO_ALG_TYPE_HASH, |
285 | CRYPTO_ALG_TYPE_HASH_MASK); | 381 | CRYPTO_ALG_TYPE_HASH_MASK); |
286 | if (IS_ERR(auth)) | 382 | if (IS_ERR(auth)) |
287 | return ERR_PTR(PTR_ERR(auth)); | 383 | return ERR_PTR(PTR_ERR(auth)); |
288 | 384 | ||
289 | err = crypto_attr_u32(tb[2], &authsize); | 385 | enc_name = crypto_attr_alg_name(tb[2]); |
290 | inst = ERR_PTR(err); | 386 | err = PTR_ERR(enc_name); |
291 | if (err) | 387 | if (IS_ERR(enc_name)) |
292 | goto out_put_auth; | ||
293 | |||
294 | enc = crypto_attr_alg(tb[3], CRYPTO_ALG_TYPE_BLKCIPHER, | ||
295 | CRYPTO_ALG_TYPE_MASK); | ||
296 | inst = ERR_PTR(PTR_ERR(enc)); | ||
297 | if (IS_ERR(enc)) | ||
298 | goto out_put_auth; | 388 | goto out_put_auth; |
299 | 389 | ||
300 | err = crypto_attr_u32(tb[4], &enckeylen); | ||
301 | if (err) | ||
302 | goto out_put_enc; | ||
303 | |||
304 | inst = kzalloc(sizeof(*inst) + sizeof(*ctx), GFP_KERNEL); | 390 | inst = kzalloc(sizeof(*inst) + sizeof(*ctx), GFP_KERNEL); |
305 | err = -ENOMEM; | 391 | err = -ENOMEM; |
306 | if (!inst) | 392 | if (!inst) |
307 | goto out_put_enc; | 393 | goto out_put_auth; |
308 | |||
309 | err = -ENAMETOOLONG; | ||
310 | if (snprintf(inst->alg.cra_name, CRYPTO_MAX_ALG_NAME, | ||
311 | "authenc(%s,%u,%s,%u)", auth->cra_name, authsize, | ||
312 | enc->cra_name, enckeylen) >= CRYPTO_MAX_ALG_NAME) | ||
313 | goto err_free_inst; | ||
314 | |||
315 | if (snprintf(inst->alg.cra_driver_name, CRYPTO_MAX_ALG_NAME, | ||
316 | "authenc(%s,%u,%s,%u)", auth->cra_driver_name, | ||
317 | authsize, enc->cra_driver_name, enckeylen) >= | ||
318 | CRYPTO_MAX_ALG_NAME) | ||
319 | goto err_free_inst; | ||
320 | 394 | ||
321 | ctx = crypto_instance_ctx(inst); | 395 | ctx = crypto_instance_ctx(inst); |
322 | ctx->authsize = authsize; | ||
323 | ctx->enckeylen = enckeylen; | ||
324 | 396 | ||
325 | err = crypto_init_spawn(&ctx->auth, auth, inst, CRYPTO_ALG_TYPE_MASK); | 397 | err = crypto_init_spawn(&ctx->auth, auth, inst, CRYPTO_ALG_TYPE_MASK); |
326 | if (err) | 398 | if (err) |
327 | goto err_free_inst; | 399 | goto err_free_inst; |
328 | 400 | ||
329 | err = crypto_init_spawn(&ctx->enc, enc, inst, CRYPTO_ALG_TYPE_MASK); | 401 | crypto_set_skcipher_spawn(&ctx->enc, inst); |
402 | err = crypto_grab_skcipher(&ctx->enc, enc_name, 0, | ||
403 | crypto_requires_sync(algt->type, | ||
404 | algt->mask)); | ||
330 | if (err) | 405 | if (err) |
331 | goto err_drop_auth; | 406 | goto err_drop_auth; |
332 | 407 | ||
333 | inst->alg.cra_flags = CRYPTO_ALG_TYPE_AEAD | CRYPTO_ALG_ASYNC; | 408 | enc = crypto_skcipher_spawn_alg(&ctx->enc); |
409 | |||
410 | err = -ENAMETOOLONG; | ||
411 | if (snprintf(inst->alg.cra_name, CRYPTO_MAX_ALG_NAME, | ||
412 | "authenc(%s,%s)", auth->cra_name, enc->cra_name) >= | ||
413 | CRYPTO_MAX_ALG_NAME) | ||
414 | goto err_drop_enc; | ||
415 | |||
416 | if (snprintf(inst->alg.cra_driver_name, CRYPTO_MAX_ALG_NAME, | ||
417 | "authenc(%s,%s)", auth->cra_driver_name, | ||
418 | enc->cra_driver_name) >= CRYPTO_MAX_ALG_NAME) | ||
419 | goto err_drop_enc; | ||
420 | |||
421 | inst->alg.cra_flags = CRYPTO_ALG_TYPE_AEAD; | ||
422 | inst->alg.cra_flags |= enc->cra_flags & CRYPTO_ALG_ASYNC; | ||
334 | inst->alg.cra_priority = enc->cra_priority * 10 + auth->cra_priority; | 423 | inst->alg.cra_priority = enc->cra_priority * 10 + auth->cra_priority; |
335 | inst->alg.cra_blocksize = enc->cra_blocksize; | 424 | inst->alg.cra_blocksize = enc->cra_blocksize; |
336 | inst->alg.cra_alignmask = max(auth->cra_alignmask, enc->cra_alignmask); | 425 | inst->alg.cra_alignmask = auth->cra_alignmask | enc->cra_alignmask; |
337 | inst->alg.cra_type = &crypto_aead_type; | 426 | inst->alg.cra_type = &crypto_aead_type; |
338 | 427 | ||
339 | inst->alg.cra_aead.ivsize = enc->cra_blkcipher.ivsize; | 428 | inst->alg.cra_aead.ivsize = enc->cra_ablkcipher.ivsize; |
340 | inst->alg.cra_aead.authsize = authsize; | 429 | inst->alg.cra_aead.maxauthsize = auth->cra_type == &crypto_hash_type ? |
430 | auth->cra_hash.digestsize : | ||
431 | auth->cra_digest.dia_digestsize; | ||
341 | 432 | ||
342 | inst->alg.cra_ctxsize = sizeof(struct crypto_authenc_ctx); | 433 | inst->alg.cra_ctxsize = sizeof(struct crypto_authenc_ctx); |
343 | 434 | ||
@@ -347,18 +438,19 @@ static struct crypto_instance *crypto_authenc_alloc(struct rtattr **tb) | |||
347 | inst->alg.cra_aead.setkey = crypto_authenc_setkey; | 438 | inst->alg.cra_aead.setkey = crypto_authenc_setkey; |
348 | inst->alg.cra_aead.encrypt = crypto_authenc_encrypt; | 439 | inst->alg.cra_aead.encrypt = crypto_authenc_encrypt; |
349 | inst->alg.cra_aead.decrypt = crypto_authenc_decrypt; | 440 | inst->alg.cra_aead.decrypt = crypto_authenc_decrypt; |
441 | inst->alg.cra_aead.givencrypt = crypto_authenc_givencrypt; | ||
350 | 442 | ||
351 | out: | 443 | out: |
352 | crypto_mod_put(enc); | ||
353 | out_put_auth: | ||
354 | crypto_mod_put(auth); | 444 | crypto_mod_put(auth); |
355 | return inst; | 445 | return inst; |
356 | 446 | ||
447 | err_drop_enc: | ||
448 | crypto_drop_skcipher(&ctx->enc); | ||
357 | err_drop_auth: | 449 | err_drop_auth: |
358 | crypto_drop_spawn(&ctx->auth); | 450 | crypto_drop_spawn(&ctx->auth); |
359 | err_free_inst: | 451 | err_free_inst: |
360 | kfree(inst); | 452 | kfree(inst); |
361 | out_put_enc: | 453 | out_put_auth: |
362 | inst = ERR_PTR(err); | 454 | inst = ERR_PTR(err); |
363 | goto out; | 455 | goto out; |
364 | } | 456 | } |
@@ -367,7 +459,7 @@ static void crypto_authenc_free(struct crypto_instance *inst) | |||
367 | { | 459 | { |
368 | struct authenc_instance_ctx *ctx = crypto_instance_ctx(inst); | 460 | struct authenc_instance_ctx *ctx = crypto_instance_ctx(inst); |
369 | 461 | ||
370 | crypto_drop_spawn(&ctx->enc); | 462 | crypto_drop_skcipher(&ctx->enc); |
371 | crypto_drop_spawn(&ctx->auth); | 463 | crypto_drop_spawn(&ctx->auth); |
372 | kfree(inst); | 464 | kfree(inst); |
373 | } | 465 | } |