diff options
Diffstat (limited to 'crypto/ccm.c')
-rw-r--r-- | crypto/ccm.c | 386 |
1 files changed, 247 insertions, 139 deletions
diff --git a/crypto/ccm.c b/crypto/ccm.c index 26b924d1e582..442848807a52 100644 --- a/crypto/ccm.c +++ b/crypto/ccm.c | |||
@@ -11,6 +11,7 @@ | |||
11 | */ | 11 | */ |
12 | 12 | ||
13 | #include <crypto/internal/aead.h> | 13 | #include <crypto/internal/aead.h> |
14 | #include <crypto/internal/hash.h> | ||
14 | #include <crypto/internal/skcipher.h> | 15 | #include <crypto/internal/skcipher.h> |
15 | #include <crypto/scatterwalk.h> | 16 | #include <crypto/scatterwalk.h> |
16 | #include <linux/err.h> | 17 | #include <linux/err.h> |
@@ -23,11 +24,11 @@ | |||
23 | 24 | ||
24 | struct ccm_instance_ctx { | 25 | struct ccm_instance_ctx { |
25 | struct crypto_skcipher_spawn ctr; | 26 | struct crypto_skcipher_spawn ctr; |
26 | struct crypto_spawn cipher; | 27 | struct crypto_ahash_spawn mac; |
27 | }; | 28 | }; |
28 | 29 | ||
29 | struct crypto_ccm_ctx { | 30 | struct crypto_ccm_ctx { |
30 | struct crypto_cipher *cipher; | 31 | struct crypto_ahash *mac; |
31 | struct crypto_skcipher *ctr; | 32 | struct crypto_skcipher *ctr; |
32 | }; | 33 | }; |
33 | 34 | ||
@@ -44,15 +45,21 @@ struct crypto_rfc4309_req_ctx { | |||
44 | 45 | ||
45 | struct crypto_ccm_req_priv_ctx { | 46 | struct crypto_ccm_req_priv_ctx { |
46 | u8 odata[16]; | 47 | u8 odata[16]; |
47 | u8 idata[16]; | ||
48 | u8 auth_tag[16]; | 48 | u8 auth_tag[16]; |
49 | u32 ilen; | ||
50 | u32 flags; | 49 | u32 flags; |
51 | struct scatterlist src[3]; | 50 | struct scatterlist src[3]; |
52 | struct scatterlist dst[3]; | 51 | struct scatterlist dst[3]; |
53 | struct skcipher_request skreq; | 52 | struct skcipher_request skreq; |
54 | }; | 53 | }; |
55 | 54 | ||
55 | struct cbcmac_tfm_ctx { | ||
56 | struct crypto_cipher *child; | ||
57 | }; | ||
58 | |||
59 | struct cbcmac_desc_ctx { | ||
60 | unsigned int len; | ||
61 | }; | ||
62 | |||
56 | static inline struct crypto_ccm_req_priv_ctx *crypto_ccm_reqctx( | 63 | static inline struct crypto_ccm_req_priv_ctx *crypto_ccm_reqctx( |
57 | struct aead_request *req) | 64 | struct aead_request *req) |
58 | { | 65 | { |
@@ -84,7 +91,7 @@ static int crypto_ccm_setkey(struct crypto_aead *aead, const u8 *key, | |||
84 | { | 91 | { |
85 | struct crypto_ccm_ctx *ctx = crypto_aead_ctx(aead); | 92 | struct crypto_ccm_ctx *ctx = crypto_aead_ctx(aead); |
86 | struct crypto_skcipher *ctr = ctx->ctr; | 93 | struct crypto_skcipher *ctr = ctx->ctr; |
87 | struct crypto_cipher *tfm = ctx->cipher; | 94 | struct crypto_ahash *mac = ctx->mac; |
88 | int err = 0; | 95 | int err = 0; |
89 | 96 | ||
90 | crypto_skcipher_clear_flags(ctr, CRYPTO_TFM_REQ_MASK); | 97 | crypto_skcipher_clear_flags(ctr, CRYPTO_TFM_REQ_MASK); |
@@ -96,11 +103,11 @@ static int crypto_ccm_setkey(struct crypto_aead *aead, const u8 *key, | |||
96 | if (err) | 103 | if (err) |
97 | goto out; | 104 | goto out; |
98 | 105 | ||
99 | crypto_cipher_clear_flags(tfm, CRYPTO_TFM_REQ_MASK); | 106 | crypto_ahash_clear_flags(mac, CRYPTO_TFM_REQ_MASK); |
100 | crypto_cipher_set_flags(tfm, crypto_aead_get_flags(aead) & | 107 | crypto_ahash_set_flags(mac, crypto_aead_get_flags(aead) & |
101 | CRYPTO_TFM_REQ_MASK); | 108 | CRYPTO_TFM_REQ_MASK); |
102 | err = crypto_cipher_setkey(tfm, key, keylen); | 109 | err = crypto_ahash_setkey(mac, key, keylen); |
103 | crypto_aead_set_flags(aead, crypto_cipher_get_flags(tfm) & | 110 | crypto_aead_set_flags(aead, crypto_ahash_get_flags(mac) & |
104 | CRYPTO_TFM_RES_MASK); | 111 | CRYPTO_TFM_RES_MASK); |
105 | 112 | ||
106 | out: | 113 | out: |
@@ -167,119 +174,61 @@ static int format_adata(u8 *adata, unsigned int a) | |||
167 | return len; | 174 | return len; |
168 | } | 175 | } |
169 | 176 | ||
170 | static void compute_mac(struct crypto_cipher *tfm, u8 *data, int n, | ||
171 | struct crypto_ccm_req_priv_ctx *pctx) | ||
172 | { | ||
173 | unsigned int bs = 16; | ||
174 | u8 *odata = pctx->odata; | ||
175 | u8 *idata = pctx->idata; | ||
176 | int datalen, getlen; | ||
177 | |||
178 | datalen = n; | ||
179 | |||
180 | /* first time in here, block may be partially filled. */ | ||
181 | getlen = bs - pctx->ilen; | ||
182 | if (datalen >= getlen) { | ||
183 | memcpy(idata + pctx->ilen, data, getlen); | ||
184 | crypto_xor(odata, idata, bs); | ||
185 | crypto_cipher_encrypt_one(tfm, odata, odata); | ||
186 | datalen -= getlen; | ||
187 | data += getlen; | ||
188 | pctx->ilen = 0; | ||
189 | } | ||
190 | |||
191 | /* now encrypt rest of data */ | ||
192 | while (datalen >= bs) { | ||
193 | crypto_xor(odata, data, bs); | ||
194 | crypto_cipher_encrypt_one(tfm, odata, odata); | ||
195 | |||
196 | datalen -= bs; | ||
197 | data += bs; | ||
198 | } | ||
199 | |||
200 | /* check and see if there's leftover data that wasn't | ||
201 | * enough to fill a block. | ||
202 | */ | ||
203 | if (datalen) { | ||
204 | memcpy(idata + pctx->ilen, data, datalen); | ||
205 | pctx->ilen += datalen; | ||
206 | } | ||
207 | } | ||
208 | |||
209 | static void get_data_to_compute(struct crypto_cipher *tfm, | ||
210 | struct crypto_ccm_req_priv_ctx *pctx, | ||
211 | struct scatterlist *sg, unsigned int len) | ||
212 | { | ||
213 | struct scatter_walk walk; | ||
214 | u8 *data_src; | ||
215 | int n; | ||
216 | |||
217 | scatterwalk_start(&walk, sg); | ||
218 | |||
219 | while (len) { | ||
220 | n = scatterwalk_clamp(&walk, len); | ||
221 | if (!n) { | ||
222 | scatterwalk_start(&walk, sg_next(walk.sg)); | ||
223 | n = scatterwalk_clamp(&walk, len); | ||
224 | } | ||
225 | data_src = scatterwalk_map(&walk); | ||
226 | |||
227 | compute_mac(tfm, data_src, n, pctx); | ||
228 | len -= n; | ||
229 | |||
230 | scatterwalk_unmap(data_src); | ||
231 | scatterwalk_advance(&walk, n); | ||
232 | scatterwalk_done(&walk, 0, len); | ||
233 | if (len) | ||
234 | crypto_yield(pctx->flags); | ||
235 | } | ||
236 | |||
237 | /* any leftover needs padding and then encrypted */ | ||
238 | if (pctx->ilen) { | ||
239 | int padlen; | ||
240 | u8 *odata = pctx->odata; | ||
241 | u8 *idata = pctx->idata; | ||
242 | |||
243 | padlen = 16 - pctx->ilen; | ||
244 | memset(idata + pctx->ilen, 0, padlen); | ||
245 | crypto_xor(odata, idata, 16); | ||
246 | crypto_cipher_encrypt_one(tfm, odata, odata); | ||
247 | pctx->ilen = 0; | ||
248 | } | ||
249 | } | ||
250 | |||
251 | static int crypto_ccm_auth(struct aead_request *req, struct scatterlist *plain, | 177 | static int crypto_ccm_auth(struct aead_request *req, struct scatterlist *plain, |
252 | unsigned int cryptlen) | 178 | unsigned int cryptlen) |
253 | { | 179 | { |
180 | struct crypto_ccm_req_priv_ctx *pctx = crypto_ccm_reqctx(req); | ||
254 | struct crypto_aead *aead = crypto_aead_reqtfm(req); | 181 | struct crypto_aead *aead = crypto_aead_reqtfm(req); |
255 | struct crypto_ccm_ctx *ctx = crypto_aead_ctx(aead); | 182 | struct crypto_ccm_ctx *ctx = crypto_aead_ctx(aead); |
256 | struct crypto_ccm_req_priv_ctx *pctx = crypto_ccm_reqctx(req); | 183 | AHASH_REQUEST_ON_STACK(ahreq, ctx->mac); |
257 | struct crypto_cipher *cipher = ctx->cipher; | ||
258 | unsigned int assoclen = req->assoclen; | 184 | unsigned int assoclen = req->assoclen; |
259 | u8 *odata = pctx->odata; | 185 | struct scatterlist sg[3]; |
260 | u8 *idata = pctx->idata; | 186 | u8 odata[16]; |
261 | int err; | 187 | u8 idata[16]; |
188 | int ilen, err; | ||
262 | 189 | ||
263 | /* format control data for input */ | 190 | /* format control data for input */ |
264 | err = format_input(odata, req, cryptlen); | 191 | err = format_input(odata, req, cryptlen); |
265 | if (err) | 192 | if (err) |
266 | goto out; | 193 | goto out; |
267 | 194 | ||
268 | /* encrypt first block to use as start in computing mac */ | 195 | sg_init_table(sg, 3); |
269 | crypto_cipher_encrypt_one(cipher, odata, odata); | 196 | sg_set_buf(&sg[0], odata, 16); |
270 | 197 | ||
271 | /* format associated data and compute into mac */ | 198 | /* format associated data and compute into mac */ |
272 | if (assoclen) { | 199 | if (assoclen) { |
273 | pctx->ilen = format_adata(idata, assoclen); | 200 | ilen = format_adata(idata, assoclen); |
274 | get_data_to_compute(cipher, pctx, req->src, req->assoclen); | 201 | sg_set_buf(&sg[1], idata, ilen); |
202 | sg_chain(sg, 3, req->src); | ||
275 | } else { | 203 | } else { |
276 | pctx->ilen = 0; | 204 | ilen = 0; |
205 | sg_chain(sg, 2, req->src); | ||
277 | } | 206 | } |
278 | 207 | ||
279 | /* compute plaintext into mac */ | 208 | ahash_request_set_tfm(ahreq, ctx->mac); |
280 | if (cryptlen) | 209 | ahash_request_set_callback(ahreq, pctx->flags, NULL, NULL); |
281 | get_data_to_compute(cipher, pctx, plain, cryptlen); | 210 | ahash_request_set_crypt(ahreq, sg, NULL, assoclen + ilen + 16); |
211 | err = crypto_ahash_init(ahreq); | ||
212 | if (err) | ||
213 | goto out; | ||
214 | err = crypto_ahash_update(ahreq); | ||
215 | if (err) | ||
216 | goto out; | ||
282 | 217 | ||
218 | /* we need to pad the MAC input to a round multiple of the block size */ | ||
219 | ilen = 16 - (assoclen + ilen) % 16; | ||
220 | if (ilen < 16) { | ||
221 | memset(idata, 0, ilen); | ||
222 | sg_init_table(sg, 2); | ||
223 | sg_set_buf(&sg[0], idata, ilen); | ||
224 | if (plain) | ||
225 | sg_chain(sg, 2, plain); | ||
226 | plain = sg; | ||
227 | cryptlen += ilen; | ||
228 | } | ||
229 | |||
230 | ahash_request_set_crypt(ahreq, plain, pctx->odata, cryptlen); | ||
231 | err = crypto_ahash_finup(ahreq); | ||
283 | out: | 232 | out: |
284 | return err; | 233 | return err; |
285 | } | 234 | } |
@@ -453,21 +402,21 @@ static int crypto_ccm_init_tfm(struct crypto_aead *tfm) | |||
453 | struct aead_instance *inst = aead_alg_instance(tfm); | 402 | struct aead_instance *inst = aead_alg_instance(tfm); |
454 | struct ccm_instance_ctx *ictx = aead_instance_ctx(inst); | 403 | struct ccm_instance_ctx *ictx = aead_instance_ctx(inst); |
455 | struct crypto_ccm_ctx *ctx = crypto_aead_ctx(tfm); | 404 | struct crypto_ccm_ctx *ctx = crypto_aead_ctx(tfm); |
456 | struct crypto_cipher *cipher; | 405 | struct crypto_ahash *mac; |
457 | struct crypto_skcipher *ctr; | 406 | struct crypto_skcipher *ctr; |
458 | unsigned long align; | 407 | unsigned long align; |
459 | int err; | 408 | int err; |
460 | 409 | ||
461 | cipher = crypto_spawn_cipher(&ictx->cipher); | 410 | mac = crypto_spawn_ahash(&ictx->mac); |
462 | if (IS_ERR(cipher)) | 411 | if (IS_ERR(mac)) |
463 | return PTR_ERR(cipher); | 412 | return PTR_ERR(mac); |
464 | 413 | ||
465 | ctr = crypto_spawn_skcipher(&ictx->ctr); | 414 | ctr = crypto_spawn_skcipher(&ictx->ctr); |
466 | err = PTR_ERR(ctr); | 415 | err = PTR_ERR(ctr); |
467 | if (IS_ERR(ctr)) | 416 | if (IS_ERR(ctr)) |
468 | goto err_free_cipher; | 417 | goto err_free_mac; |
469 | 418 | ||
470 | ctx->cipher = cipher; | 419 | ctx->mac = mac; |
471 | ctx->ctr = ctr; | 420 | ctx->ctr = ctr; |
472 | 421 | ||
473 | align = crypto_aead_alignmask(tfm); | 422 | align = crypto_aead_alignmask(tfm); |
@@ -479,8 +428,8 @@ static int crypto_ccm_init_tfm(struct crypto_aead *tfm) | |||
479 | 428 | ||
480 | return 0; | 429 | return 0; |
481 | 430 | ||
482 | err_free_cipher: | 431 | err_free_mac: |
483 | crypto_free_cipher(cipher); | 432 | crypto_free_ahash(mac); |
484 | return err; | 433 | return err; |
485 | } | 434 | } |
486 | 435 | ||
@@ -488,7 +437,7 @@ static void crypto_ccm_exit_tfm(struct crypto_aead *tfm) | |||
488 | { | 437 | { |
489 | struct crypto_ccm_ctx *ctx = crypto_aead_ctx(tfm); | 438 | struct crypto_ccm_ctx *ctx = crypto_aead_ctx(tfm); |
490 | 439 | ||
491 | crypto_free_cipher(ctx->cipher); | 440 | crypto_free_ahash(ctx->mac); |
492 | crypto_free_skcipher(ctx->ctr); | 441 | crypto_free_skcipher(ctx->ctr); |
493 | } | 442 | } |
494 | 443 | ||
@@ -496,7 +445,7 @@ static void crypto_ccm_free(struct aead_instance *inst) | |||
496 | { | 445 | { |
497 | struct ccm_instance_ctx *ctx = aead_instance_ctx(inst); | 446 | struct ccm_instance_ctx *ctx = aead_instance_ctx(inst); |
498 | 447 | ||
499 | crypto_drop_spawn(&ctx->cipher); | 448 | crypto_drop_ahash(&ctx->mac); |
500 | crypto_drop_skcipher(&ctx->ctr); | 449 | crypto_drop_skcipher(&ctx->ctr); |
501 | kfree(inst); | 450 | kfree(inst); |
502 | } | 451 | } |
@@ -505,12 +454,13 @@ static int crypto_ccm_create_common(struct crypto_template *tmpl, | |||
505 | struct rtattr **tb, | 454 | struct rtattr **tb, |
506 | const char *full_name, | 455 | const char *full_name, |
507 | const char *ctr_name, | 456 | const char *ctr_name, |
508 | const char *cipher_name) | 457 | const char *mac_name) |
509 | { | 458 | { |
510 | struct crypto_attr_type *algt; | 459 | struct crypto_attr_type *algt; |
511 | struct aead_instance *inst; | 460 | struct aead_instance *inst; |
512 | struct skcipher_alg *ctr; | 461 | struct skcipher_alg *ctr; |
513 | struct crypto_alg *cipher; | 462 | struct crypto_alg *mac_alg; |
463 | struct hash_alg_common *mac; | ||
514 | struct ccm_instance_ctx *ictx; | 464 | struct ccm_instance_ctx *ictx; |
515 | int err; | 465 | int err; |
516 | 466 | ||
@@ -521,25 +471,26 @@ static int crypto_ccm_create_common(struct crypto_template *tmpl, | |||
521 | if ((algt->type ^ CRYPTO_ALG_TYPE_AEAD) & algt->mask) | 471 | if ((algt->type ^ CRYPTO_ALG_TYPE_AEAD) & algt->mask) |
522 | return -EINVAL; | 472 | return -EINVAL; |
523 | 473 | ||
524 | cipher = crypto_alg_mod_lookup(cipher_name, CRYPTO_ALG_TYPE_CIPHER, | 474 | mac_alg = crypto_find_alg(mac_name, &crypto_ahash_type, |
525 | CRYPTO_ALG_TYPE_MASK); | 475 | CRYPTO_ALG_TYPE_HASH, |
526 | if (IS_ERR(cipher)) | 476 | CRYPTO_ALG_TYPE_AHASH_MASK | |
527 | return PTR_ERR(cipher); | 477 | CRYPTO_ALG_ASYNC); |
478 | if (IS_ERR(mac_alg)) | ||
479 | return PTR_ERR(mac_alg); | ||
528 | 480 | ||
481 | mac = __crypto_hash_alg_common(mac_alg); | ||
529 | err = -EINVAL; | 482 | err = -EINVAL; |
530 | if (cipher->cra_blocksize != 16) | 483 | if (mac->digestsize != 16) |
531 | goto out_put_cipher; | 484 | goto out_put_mac; |
532 | 485 | ||
533 | inst = kzalloc(sizeof(*inst) + sizeof(*ictx), GFP_KERNEL); | 486 | inst = kzalloc(sizeof(*inst) + sizeof(*ictx), GFP_KERNEL); |
534 | err = -ENOMEM; | 487 | err = -ENOMEM; |
535 | if (!inst) | 488 | if (!inst) |
536 | goto out_put_cipher; | 489 | goto out_put_mac; |
537 | 490 | ||
538 | ictx = aead_instance_ctx(inst); | 491 | ictx = aead_instance_ctx(inst); |
539 | 492 | err = crypto_init_ahash_spawn(&ictx->mac, mac, | |
540 | err = crypto_init_spawn(&ictx->cipher, cipher, | 493 | aead_crypto_instance(inst)); |
541 | aead_crypto_instance(inst), | ||
542 | CRYPTO_ALG_TYPE_MASK); | ||
543 | if (err) | 494 | if (err) |
544 | goto err_free_inst; | 495 | goto err_free_inst; |
545 | 496 | ||
@@ -548,7 +499,7 @@ static int crypto_ccm_create_common(struct crypto_template *tmpl, | |||
548 | crypto_requires_sync(algt->type, | 499 | crypto_requires_sync(algt->type, |
549 | algt->mask)); | 500 | algt->mask)); |
550 | if (err) | 501 | if (err) |
551 | goto err_drop_cipher; | 502 | goto err_drop_mac; |
552 | 503 | ||
553 | ctr = crypto_spawn_skcipher_alg(&ictx->ctr); | 504 | ctr = crypto_spawn_skcipher_alg(&ictx->ctr); |
554 | 505 | ||
@@ -564,18 +515,17 @@ static int crypto_ccm_create_common(struct crypto_template *tmpl, | |||
564 | err = -ENAMETOOLONG; | 515 | err = -ENAMETOOLONG; |
565 | if (snprintf(inst->alg.base.cra_driver_name, CRYPTO_MAX_ALG_NAME, | 516 | if (snprintf(inst->alg.base.cra_driver_name, CRYPTO_MAX_ALG_NAME, |
566 | "ccm_base(%s,%s)", ctr->base.cra_driver_name, | 517 | "ccm_base(%s,%s)", ctr->base.cra_driver_name, |
567 | cipher->cra_driver_name) >= CRYPTO_MAX_ALG_NAME) | 518 | mac->base.cra_driver_name) >= CRYPTO_MAX_ALG_NAME) |
568 | goto err_drop_ctr; | 519 | goto err_drop_ctr; |
569 | 520 | ||
570 | memcpy(inst->alg.base.cra_name, full_name, CRYPTO_MAX_ALG_NAME); | 521 | memcpy(inst->alg.base.cra_name, full_name, CRYPTO_MAX_ALG_NAME); |
571 | 522 | ||
572 | inst->alg.base.cra_flags = ctr->base.cra_flags & CRYPTO_ALG_ASYNC; | 523 | inst->alg.base.cra_flags = ctr->base.cra_flags & CRYPTO_ALG_ASYNC; |
573 | inst->alg.base.cra_priority = (cipher->cra_priority + | 524 | inst->alg.base.cra_priority = (mac->base.cra_priority + |
574 | ctr->base.cra_priority) / 2; | 525 | ctr->base.cra_priority) / 2; |
575 | inst->alg.base.cra_blocksize = 1; | 526 | inst->alg.base.cra_blocksize = 1; |
576 | inst->alg.base.cra_alignmask = cipher->cra_alignmask | | 527 | inst->alg.base.cra_alignmask = mac->base.cra_alignmask | |
577 | ctr->base.cra_alignmask | | 528 | ctr->base.cra_alignmask; |
578 | (__alignof__(u32) - 1); | ||
579 | inst->alg.ivsize = 16; | 529 | inst->alg.ivsize = 16; |
580 | inst->alg.chunksize = crypto_skcipher_alg_chunksize(ctr); | 530 | inst->alg.chunksize = crypto_skcipher_alg_chunksize(ctr); |
581 | inst->alg.maxauthsize = 16; | 531 | inst->alg.maxauthsize = 16; |
@@ -593,23 +543,24 @@ static int crypto_ccm_create_common(struct crypto_template *tmpl, | |||
593 | if (err) | 543 | if (err) |
594 | goto err_drop_ctr; | 544 | goto err_drop_ctr; |
595 | 545 | ||
596 | out_put_cipher: | 546 | out_put_mac: |
597 | crypto_mod_put(cipher); | 547 | crypto_mod_put(mac_alg); |
598 | return err; | 548 | return err; |
599 | 549 | ||
600 | err_drop_ctr: | 550 | err_drop_ctr: |
601 | crypto_drop_skcipher(&ictx->ctr); | 551 | crypto_drop_skcipher(&ictx->ctr); |
602 | err_drop_cipher: | 552 | err_drop_mac: |
603 | crypto_drop_spawn(&ictx->cipher); | 553 | crypto_drop_ahash(&ictx->mac); |
604 | err_free_inst: | 554 | err_free_inst: |
605 | kfree(inst); | 555 | kfree(inst); |
606 | goto out_put_cipher; | 556 | goto out_put_mac; |
607 | } | 557 | } |
608 | 558 | ||
609 | static int crypto_ccm_create(struct crypto_template *tmpl, struct rtattr **tb) | 559 | static int crypto_ccm_create(struct crypto_template *tmpl, struct rtattr **tb) |
610 | { | 560 | { |
611 | const char *cipher_name; | 561 | const char *cipher_name; |
612 | char ctr_name[CRYPTO_MAX_ALG_NAME]; | 562 | char ctr_name[CRYPTO_MAX_ALG_NAME]; |
563 | char mac_name[CRYPTO_MAX_ALG_NAME]; | ||
613 | char full_name[CRYPTO_MAX_ALG_NAME]; | 564 | char full_name[CRYPTO_MAX_ALG_NAME]; |
614 | 565 | ||
615 | cipher_name = crypto_attr_alg_name(tb[1]); | 566 | cipher_name = crypto_attr_alg_name(tb[1]); |
@@ -620,12 +571,16 @@ static int crypto_ccm_create(struct crypto_template *tmpl, struct rtattr **tb) | |||
620 | cipher_name) >= CRYPTO_MAX_ALG_NAME) | 571 | cipher_name) >= CRYPTO_MAX_ALG_NAME) |
621 | return -ENAMETOOLONG; | 572 | return -ENAMETOOLONG; |
622 | 573 | ||
574 | if (snprintf(mac_name, CRYPTO_MAX_ALG_NAME, "cbcmac(%s)", | ||
575 | cipher_name) >= CRYPTO_MAX_ALG_NAME) | ||
576 | return -ENAMETOOLONG; | ||
577 | |||
623 | if (snprintf(full_name, CRYPTO_MAX_ALG_NAME, "ccm(%s)", cipher_name) >= | 578 | if (snprintf(full_name, CRYPTO_MAX_ALG_NAME, "ccm(%s)", cipher_name) >= |
624 | CRYPTO_MAX_ALG_NAME) | 579 | CRYPTO_MAX_ALG_NAME) |
625 | return -ENAMETOOLONG; | 580 | return -ENAMETOOLONG; |
626 | 581 | ||
627 | return crypto_ccm_create_common(tmpl, tb, full_name, ctr_name, | 582 | return crypto_ccm_create_common(tmpl, tb, full_name, ctr_name, |
628 | cipher_name); | 583 | mac_name); |
629 | } | 584 | } |
630 | 585 | ||
631 | static struct crypto_template crypto_ccm_tmpl = { | 586 | static struct crypto_template crypto_ccm_tmpl = { |
@@ -899,14 +854,164 @@ static struct crypto_template crypto_rfc4309_tmpl = { | |||
899 | .module = THIS_MODULE, | 854 | .module = THIS_MODULE, |
900 | }; | 855 | }; |
901 | 856 | ||
857 | static int crypto_cbcmac_digest_setkey(struct crypto_shash *parent, | ||
858 | const u8 *inkey, unsigned int keylen) | ||
859 | { | ||
860 | struct cbcmac_tfm_ctx *ctx = crypto_shash_ctx(parent); | ||
861 | |||
862 | return crypto_cipher_setkey(ctx->child, inkey, keylen); | ||
863 | } | ||
864 | |||
865 | static int crypto_cbcmac_digest_init(struct shash_desc *pdesc) | ||
866 | { | ||
867 | struct cbcmac_desc_ctx *ctx = shash_desc_ctx(pdesc); | ||
868 | int bs = crypto_shash_digestsize(pdesc->tfm); | ||
869 | u8 *dg = (u8 *)ctx + crypto_shash_descsize(pdesc->tfm) - bs; | ||
870 | |||
871 | ctx->len = 0; | ||
872 | memset(dg, 0, bs); | ||
873 | |||
874 | return 0; | ||
875 | } | ||
876 | |||
877 | static int crypto_cbcmac_digest_update(struct shash_desc *pdesc, const u8 *p, | ||
878 | unsigned int len) | ||
879 | { | ||
880 | struct crypto_shash *parent = pdesc->tfm; | ||
881 | struct cbcmac_tfm_ctx *tctx = crypto_shash_ctx(parent); | ||
882 | struct cbcmac_desc_ctx *ctx = shash_desc_ctx(pdesc); | ||
883 | struct crypto_cipher *tfm = tctx->child; | ||
884 | int bs = crypto_shash_digestsize(parent); | ||
885 | u8 *dg = (u8 *)ctx + crypto_shash_descsize(parent) - bs; | ||
886 | |||
887 | while (len > 0) { | ||
888 | unsigned int l = min(len, bs - ctx->len); | ||
889 | |||
890 | crypto_xor(dg + ctx->len, p, l); | ||
891 | ctx->len +=l; | ||
892 | len -= l; | ||
893 | p += l; | ||
894 | |||
895 | if (ctx->len == bs) { | ||
896 | crypto_cipher_encrypt_one(tfm, dg, dg); | ||
897 | ctx->len = 0; | ||
898 | } | ||
899 | } | ||
900 | |||
901 | return 0; | ||
902 | } | ||
903 | |||
904 | static int crypto_cbcmac_digest_final(struct shash_desc *pdesc, u8 *out) | ||
905 | { | ||
906 | struct crypto_shash *parent = pdesc->tfm; | ||
907 | struct cbcmac_tfm_ctx *tctx = crypto_shash_ctx(parent); | ||
908 | struct cbcmac_desc_ctx *ctx = shash_desc_ctx(pdesc); | ||
909 | struct crypto_cipher *tfm = tctx->child; | ||
910 | int bs = crypto_shash_digestsize(parent); | ||
911 | u8 *dg = (u8 *)ctx + crypto_shash_descsize(parent) - bs; | ||
912 | |||
913 | if (ctx->len) | ||
914 | crypto_cipher_encrypt_one(tfm, dg, dg); | ||
915 | |||
916 | memcpy(out, dg, bs); | ||
917 | return 0; | ||
918 | } | ||
919 | |||
920 | static int cbcmac_init_tfm(struct crypto_tfm *tfm) | ||
921 | { | ||
922 | struct crypto_cipher *cipher; | ||
923 | struct crypto_instance *inst = (void *)tfm->__crt_alg; | ||
924 | struct crypto_spawn *spawn = crypto_instance_ctx(inst); | ||
925 | struct cbcmac_tfm_ctx *ctx = crypto_tfm_ctx(tfm); | ||
926 | |||
927 | cipher = crypto_spawn_cipher(spawn); | ||
928 | if (IS_ERR(cipher)) | ||
929 | return PTR_ERR(cipher); | ||
930 | |||
931 | ctx->child = cipher; | ||
932 | |||
933 | return 0; | ||
934 | }; | ||
935 | |||
936 | static void cbcmac_exit_tfm(struct crypto_tfm *tfm) | ||
937 | { | ||
938 | struct cbcmac_tfm_ctx *ctx = crypto_tfm_ctx(tfm); | ||
939 | crypto_free_cipher(ctx->child); | ||
940 | } | ||
941 | |||
942 | static int cbcmac_create(struct crypto_template *tmpl, struct rtattr **tb) | ||
943 | { | ||
944 | struct shash_instance *inst; | ||
945 | struct crypto_alg *alg; | ||
946 | int err; | ||
947 | |||
948 | err = crypto_check_attr_type(tb, CRYPTO_ALG_TYPE_SHASH); | ||
949 | if (err) | ||
950 | return err; | ||
951 | |||
952 | alg = crypto_get_attr_alg(tb, CRYPTO_ALG_TYPE_CIPHER, | ||
953 | CRYPTO_ALG_TYPE_MASK); | ||
954 | if (IS_ERR(alg)) | ||
955 | return PTR_ERR(alg); | ||
956 | |||
957 | inst = shash_alloc_instance("cbcmac", alg); | ||
958 | err = PTR_ERR(inst); | ||
959 | if (IS_ERR(inst)) | ||
960 | goto out_put_alg; | ||
961 | |||
962 | err = crypto_init_spawn(shash_instance_ctx(inst), alg, | ||
963 | shash_crypto_instance(inst), | ||
964 | CRYPTO_ALG_TYPE_MASK); | ||
965 | if (err) | ||
966 | goto out_free_inst; | ||
967 | |||
968 | inst->alg.base.cra_priority = alg->cra_priority; | ||
969 | inst->alg.base.cra_blocksize = 1; | ||
970 | |||
971 | inst->alg.digestsize = alg->cra_blocksize; | ||
972 | inst->alg.descsize = ALIGN(sizeof(struct cbcmac_desc_ctx), | ||
973 | alg->cra_alignmask + 1) + | ||
974 | alg->cra_blocksize; | ||
975 | |||
976 | inst->alg.base.cra_ctxsize = sizeof(struct cbcmac_tfm_ctx); | ||
977 | inst->alg.base.cra_init = cbcmac_init_tfm; | ||
978 | inst->alg.base.cra_exit = cbcmac_exit_tfm; | ||
979 | |||
980 | inst->alg.init = crypto_cbcmac_digest_init; | ||
981 | inst->alg.update = crypto_cbcmac_digest_update; | ||
982 | inst->alg.final = crypto_cbcmac_digest_final; | ||
983 | inst->alg.setkey = crypto_cbcmac_digest_setkey; | ||
984 | |||
985 | err = shash_register_instance(tmpl, inst); | ||
986 | |||
987 | out_free_inst: | ||
988 | if (err) | ||
989 | shash_free_instance(shash_crypto_instance(inst)); | ||
990 | |||
991 | out_put_alg: | ||
992 | crypto_mod_put(alg); | ||
993 | return err; | ||
994 | } | ||
995 | |||
996 | static struct crypto_template crypto_cbcmac_tmpl = { | ||
997 | .name = "cbcmac", | ||
998 | .create = cbcmac_create, | ||
999 | .free = shash_free_instance, | ||
1000 | .module = THIS_MODULE, | ||
1001 | }; | ||
1002 | |||
902 | static int __init crypto_ccm_module_init(void) | 1003 | static int __init crypto_ccm_module_init(void) |
903 | { | 1004 | { |
904 | int err; | 1005 | int err; |
905 | 1006 | ||
906 | err = crypto_register_template(&crypto_ccm_base_tmpl); | 1007 | err = crypto_register_template(&crypto_cbcmac_tmpl); |
907 | if (err) | 1008 | if (err) |
908 | goto out; | 1009 | goto out; |
909 | 1010 | ||
1011 | err = crypto_register_template(&crypto_ccm_base_tmpl); | ||
1012 | if (err) | ||
1013 | goto out_undo_cbcmac; | ||
1014 | |||
910 | err = crypto_register_template(&crypto_ccm_tmpl); | 1015 | err = crypto_register_template(&crypto_ccm_tmpl); |
911 | if (err) | 1016 | if (err) |
912 | goto out_undo_base; | 1017 | goto out_undo_base; |
@@ -922,6 +1027,8 @@ out_undo_ccm: | |||
922 | crypto_unregister_template(&crypto_ccm_tmpl); | 1027 | crypto_unregister_template(&crypto_ccm_tmpl); |
923 | out_undo_base: | 1028 | out_undo_base: |
924 | crypto_unregister_template(&crypto_ccm_base_tmpl); | 1029 | crypto_unregister_template(&crypto_ccm_base_tmpl); |
1030 | out_undo_cbcmac: | ||
1031 | crypto_register_template(&crypto_cbcmac_tmpl); | ||
925 | goto out; | 1032 | goto out; |
926 | } | 1033 | } |
927 | 1034 | ||
@@ -930,6 +1037,7 @@ static void __exit crypto_ccm_module_exit(void) | |||
930 | crypto_unregister_template(&crypto_rfc4309_tmpl); | 1037 | crypto_unregister_template(&crypto_rfc4309_tmpl); |
931 | crypto_unregister_template(&crypto_ccm_tmpl); | 1038 | crypto_unregister_template(&crypto_ccm_tmpl); |
932 | crypto_unregister_template(&crypto_ccm_base_tmpl); | 1039 | crypto_unregister_template(&crypto_ccm_base_tmpl); |
1040 | crypto_unregister_template(&crypto_cbcmac_tmpl); | ||
933 | } | 1041 | } |
934 | 1042 | ||
935 | module_init(crypto_ccm_module_init); | 1043 | module_init(crypto_ccm_module_init); |