Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

crypto: hash - Add request chaining API

This adds request chaining to the ahash interface. Request chaining
allows multiple requests to be submitted in one shot. An algorithm
can elect to receive chained requests by setting the flag
CRYPTO_ALG_REQ_CHAIN. If this bit is not set, the API will break
up chained requests and submit them one-by-one.

A new err field is added to struct crypto_async_request to record
the return value for each individual request.

Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>

+299 -37
+235 -26
crypto/ahash.c
··· 42 42 }; 43 43 44 44 struct ahash_save_req_state { 45 - struct ahash_request *req; 45 + struct list_head head; 46 + struct ahash_request *req0; 47 + struct ahash_request *cur; 48 + int (*op)(struct ahash_request *req); 46 49 crypto_completion_t compl; 47 50 void *data; 48 51 }; 52 + 53 + static void ahash_reqchain_done(void *data, int err); 54 + static int ahash_save_req(struct ahash_request *req, crypto_completion_t cplt); 55 + static void ahash_restore_req(struct ahash_request *req); 56 + static int ahash_def_finup(struct ahash_request *req); 49 57 50 58 static int hash_walk_next(struct crypto_hash_walk *walk) 51 59 { ··· 281 273 } 282 274 EXPORT_SYMBOL_GPL(crypto_ahash_setkey); 283 275 276 + static int ahash_reqchain_finish(struct ahash_save_req_state *state, 277 + int err, u32 mask) 278 + { 279 + struct ahash_request *req0 = state->req0; 280 + struct ahash_request *req = state->cur; 281 + struct ahash_request *n; 282 + 283 + req->base.err = err; 284 + 285 + if (req != req0) 286 + list_add_tail(&req->base.list, &req0->base.list); 287 + 288 + list_for_each_entry_safe(req, n, &state->head, base.list) { 289 + list_del_init(&req->base.list); 290 + 291 + req->base.flags &= mask; 292 + req->base.complete = ahash_reqchain_done; 293 + req->base.data = state; 294 + state->cur = req; 295 + err = state->op(req); 296 + 297 + if (err == -EINPROGRESS) { 298 + if (!list_empty(&state->head)) 299 + err = -EBUSY; 300 + goto out; 301 + } 302 + 303 + if (err == -EBUSY) 304 + goto out; 305 + 306 + req->base.err = err; 307 + list_add_tail(&req->base.list, &req0->base.list); 308 + } 309 + 310 + ahash_restore_req(req0); 311 + 312 + out: 313 + return err; 314 + } 315 + 316 + static void ahash_reqchain_done(void *data, int err) 317 + { 318 + struct ahash_save_req_state *state = data; 319 + crypto_completion_t compl = state->compl; 320 + 321 + data = state->data; 322 + 323 + if (err == -EINPROGRESS) { 324 + if (!list_empty(&state->head)) 325 + return; 326 + goto notify; 327 + } 328 + 329 + err = ahash_reqchain_finish(state, err, CRYPTO_TFM_REQ_MAY_BACKLOG); 330 + if (err == -EBUSY) 331 + return; 332 + 333 + notify: 334 + compl(data, err); 335 + } 336 + 337 + static int ahash_do_req_chain(struct ahash_request *req, 338 + int (*op)(struct ahash_request *req)) 339 + { 340 + struct crypto_ahash *tfm = crypto_ahash_reqtfm(req); 341 + struct ahash_save_req_state *state; 342 + struct ahash_save_req_state state0; 343 + int err; 344 + 345 + if (!ahash_request_chained(req) || crypto_ahash_req_chain(tfm)) 346 + return op(req); 347 + 348 + state = &state0; 349 + 350 + if (ahash_is_async(tfm)) { 351 + err = ahash_save_req(req, ahash_reqchain_done); 352 + if (err) { 353 + struct ahash_request *r2; 354 + 355 + req->base.err = err; 356 + list_for_each_entry(r2, &req->base.list, base.list) 357 + r2->base.err = err; 358 + 359 + return err; 360 + } 361 + 362 + state = req->base.data; 363 + } 364 + 365 + state->op = op; 366 + state->cur = req; 367 + INIT_LIST_HEAD(&state->head); 368 + list_splice_init(&req->base.list, &state->head); 369 + 370 + err = op(req); 371 + if (err == -EBUSY || err == -EINPROGRESS) 372 + return -EBUSY; 373 + 374 + return ahash_reqchain_finish(state, err, ~0); 375 + } 376 + 284 377 int crypto_ahash_init(struct ahash_request *req) 285 378 { 286 379 struct crypto_ahash *tfm = crypto_ahash_reqtfm(req); 287 380 288 - if (likely(tfm->using_shash)) 289 - return crypto_shash_init(prepare_shash_desc(req, tfm)); 381 + if (likely(tfm->using_shash)) { 382 + struct ahash_request *r2; 383 + int err; 384 + 385 + err = crypto_shash_init(prepare_shash_desc(req, tfm)); 386 + req->base.err = err; 387 + 388 + list_for_each_entry(r2, &req->base.list, base.list) { 389 + struct shash_desc *desc; 390 + 391 + desc = prepare_shash_desc(r2, tfm); 392 + r2->base.err = crypto_shash_init(desc); 393 + } 394 + 395 + return err; 396 + } 397 + 290 398 if (crypto_ahash_get_flags(tfm) & CRYPTO_TFM_NEED_KEY) 291 399 return -ENOKEY; 292 - return crypto_ahash_alg(tfm)->init(req); 400 + 401 + return ahash_do_req_chain(req, crypto_ahash_alg(tfm)->init); 293 402 } 294 403 EXPORT_SYMBOL_GPL(crypto_ahash_init); 295 404 296 405 static int ahash_save_req(struct ahash_request *req, crypto_completion_t cplt) 297 406 { 407 + struct crypto_ahash *tfm = crypto_ahash_reqtfm(req); 298 408 struct ahash_save_req_state *state; 299 409 gfp_t gfp; 300 410 u32 flags; 411 + 412 + if (!ahash_is_async(tfm)) 413 + return 0; 301 414 302 415 flags = ahash_request_flags(req); 303 416 gfp = (flags & CRYPTO_TFM_REQ_MAY_SLEEP) ? GFP_KERNEL : GFP_ATOMIC; ··· 430 301 state->data = req->base.data; 431 302 req->base.complete = cplt; 432 303 req->base.data = state; 433 - state->req = req; 304 + state->req0 = req; 434 305 435 306 return 0; 436 307 } 437 308 438 309 static void ahash_restore_req(struct ahash_request *req) 439 310 { 440 - struct ahash_save_req_state *state = req->base.data; 311 + struct crypto_ahash *tfm = crypto_ahash_reqtfm(req); 312 + struct ahash_save_req_state *state; 313 + 314 + if (!ahash_is_async(tfm)) 315 + return; 316 + 317 + state = req->base.data; 441 318 442 319 req->base.complete = state->compl; 443 320 req->base.data = state->data; ··· 454 319 { 455 320 struct crypto_ahash *tfm = crypto_ahash_reqtfm(req); 456 321 457 - if (likely(tfm->using_shash)) 458 - return shash_ahash_update(req, ahash_request_ctx(req)); 322 + if (likely(tfm->using_shash)) { 323 + struct ahash_request *r2; 324 + int err; 459 325 460 - return crypto_ahash_alg(tfm)->update(req); 326 + err = shash_ahash_update(req, ahash_request_ctx(req)); 327 + req->base.err = err; 328 + 329 + list_for_each_entry(r2, &req->base.list, base.list) { 330 + struct shash_desc *desc; 331 + 332 + desc = ahash_request_ctx(r2); 333 + r2->base.err = shash_ahash_update(r2, desc); 334 + } 335 + 336 + return err; 337 + } 338 + 339 + return ahash_do_req_chain(req, crypto_ahash_alg(tfm)->update); 461 340 } 462 341 EXPORT_SYMBOL_GPL(crypto_ahash_update); 463 342 ··· 479 330 { 480 331 struct crypto_ahash *tfm = crypto_ahash_reqtfm(req); 481 332 482 - if (likely(tfm->using_shash)) 483 - return crypto_shash_final(ahash_request_ctx(req), req->result); 333 + if (likely(tfm->using_shash)) { 334 + struct ahash_request *r2; 335 + int err; 484 336 485 - return crypto_ahash_alg(tfm)->final(req); 337 + err = crypto_shash_final(ahash_request_ctx(req), req->result); 338 + req->base.err = err; 339 + 340 + list_for_each_entry(r2, &req->base.list, base.list) { 341 + struct shash_desc *desc; 342 + 343 + desc = ahash_request_ctx(r2); 344 + r2->base.err = crypto_shash_final(desc, r2->result); 345 + } 346 + 347 + return err; 348 + } 349 + 350 + return ahash_do_req_chain(req, crypto_ahash_alg(tfm)->final); 486 351 } 487 352 EXPORT_SYMBOL_GPL(crypto_ahash_final); 488 353 ··· 504 341 { 505 342 struct crypto_ahash *tfm = crypto_ahash_reqtfm(req); 506 343 507 - if (likely(tfm->using_shash)) 508 - return shash_ahash_finup(req, ahash_request_ctx(req)); 344 + if (likely(tfm->using_shash)) { 345 + struct ahash_request *r2; 346 + int err; 509 347 510 - return crypto_ahash_alg(tfm)->finup(req); 348 + err = shash_ahash_finup(req, ahash_request_ctx(req)); 349 + req->base.err = err; 350 + 351 + list_for_each_entry(r2, &req->base.list, base.list) { 352 + struct shash_desc *desc; 353 + 354 + desc = ahash_request_ctx(r2); 355 + r2->base.err = shash_ahash_finup(r2, desc); 356 + } 357 + 358 + return err; 359 + } 360 + 361 + if (!crypto_ahash_alg(tfm)->finup) 362 + return ahash_def_finup(req); 363 + 364 + return ahash_do_req_chain(req, crypto_ahash_alg(tfm)->finup); 511 365 } 512 366 EXPORT_SYMBOL_GPL(crypto_ahash_finup); 513 367 ··· 532 352 { 533 353 struct crypto_ahash *tfm = crypto_ahash_reqtfm(req); 534 354 535 - if (likely(tfm->using_shash)) 536 - return shash_ahash_digest(req, prepare_shash_desc(req, tfm)); 355 + if (likely(tfm->using_shash)) { 356 + struct ahash_request *r2; 357 + int err; 358 + 359 + err = shash_ahash_digest(req, prepare_shash_desc(req, tfm)); 360 + req->base.err = err; 361 + 362 + list_for_each_entry(r2, &req->base.list, base.list) { 363 + struct shash_desc *desc; 364 + 365 + desc = prepare_shash_desc(r2, tfm); 366 + r2->base.err = shash_ahash_digest(r2, desc); 367 + } 368 + 369 + return err; 370 + } 537 371 538 372 if (crypto_ahash_get_flags(tfm) & CRYPTO_TFM_NEED_KEY) 539 373 return -ENOKEY; 540 374 541 - return crypto_ahash_alg(tfm)->digest(req); 375 + return ahash_do_req_chain(req, crypto_ahash_alg(tfm)->digest); 542 376 } 543 377 EXPORT_SYMBOL_GPL(crypto_ahash_digest); 544 378 545 379 static void ahash_def_finup_done2(void *data, int err) 546 380 { 547 381 struct ahash_save_req_state *state = data; 548 - struct ahash_request *areq = state->req; 382 + struct ahash_request *areq = state->req0; 549 383 550 384 if (err == -EINPROGRESS) 551 385 return; ··· 570 376 571 377 static int ahash_def_finup_finish1(struct ahash_request *req, int err) 572 378 { 379 + struct crypto_ahash *tfm = crypto_ahash_reqtfm(req); 380 + 573 381 if (err) 574 382 goto out; 575 383 576 - req->base.complete = ahash_def_finup_done2; 384 + if (ahash_is_async(tfm)) 385 + req->base.complete = ahash_def_finup_done2; 577 386 578 - err = crypto_ahash_alg(crypto_ahash_reqtfm(req))->final(req); 387 + err = crypto_ahash_final(req); 579 388 if (err == -EINPROGRESS || err == -EBUSY) 580 389 return err; 581 390 ··· 594 397 struct ahash_request *areq; 595 398 596 399 state = *state0; 597 - areq = state.req; 400 + areq = state.req0; 598 401 if (err == -EINPROGRESS) 599 402 goto out; 600 403 ··· 610 413 611 414 static int ahash_def_finup(struct ahash_request *req) 612 415 { 613 - struct crypto_ahash *tfm = crypto_ahash_reqtfm(req); 614 416 int err; 615 417 616 418 err = ahash_save_req(req, ahash_def_finup_done1); 617 419 if (err) 618 420 return err; 619 421 620 - err = crypto_ahash_alg(tfm)->update(req); 422 + err = crypto_ahash_update(req); 621 423 if (err == -EINPROGRESS || err == -EBUSY) 622 424 return err; 623 425 ··· 831 635 base->cra_type = &crypto_ahash_type; 832 636 base->cra_flags |= CRYPTO_ALG_TYPE_AHASH; 833 637 834 - if (!alg->finup) 835 - alg->finup = ahash_def_finup; 836 638 if (!alg->setkey) 837 639 alg->setkey = ahash_nosetkey; 838 640 ··· 900 706 return crypto_register_instance(tmpl, ahash_crypto_instance(inst)); 901 707 } 902 708 EXPORT_SYMBOL_GPL(ahash_register_instance); 709 + 710 + void ahash_request_free(struct ahash_request *req) 711 + { 712 + struct ahash_request *tmp; 713 + struct ahash_request *r2; 714 + 715 + if (unlikely(!req)) 716 + return; 717 + 718 + list_for_each_entry_safe(r2, tmp, &req->base.list, base.list) 719 + kfree_sensitive(r2); 720 + 721 + kfree_sensitive(req); 722 + } 723 + EXPORT_SYMBOL_GPL(ahash_request_free); 903 724 904 725 MODULE_LICENSE("GPL"); 905 726 MODULE_DESCRIPTION("Asynchronous cryptographic hash type");
+1 -1
crypto/algapi.c
··· 955 955 queue->backlog = queue->backlog->next; 956 956 957 957 request = queue->list.next; 958 - list_del(request); 958 + list_del_init(request); 959 959 960 960 return list_entry(request, struct crypto_async_request, list); 961 961 }
+11
include/crypto/algapi.h
··· 11 11 #include <linux/align.h> 12 12 #include <linux/cache.h> 13 13 #include <linux/crypto.h> 14 + #include <linux/list.h> 14 15 #include <linux/types.h> 15 16 #include <linux/workqueue.h> 16 17 ··· 270 269 static inline u32 crypto_tfm_alg_type(struct crypto_tfm *tfm) 271 270 { 272 271 return tfm->__crt_alg->cra_flags & CRYPTO_ALG_TYPE_MASK; 272 + } 273 + 274 + static inline bool crypto_request_chained(struct crypto_async_request *req) 275 + { 276 + return !list_empty(&req->list); 277 + } 278 + 279 + static inline bool crypto_tfm_req_chain(struct crypto_tfm *tfm) 280 + { 281 + return tfm->__crt_alg->cra_flags & CRYPTO_ALG_REQ_CHAIN; 273 282 } 274 283 275 284 #endif /* _CRYPTO_ALGAPI_H */
+18 -10
include/crypto/hash.h
··· 572 572 * ahash_request_free() - zeroize and free the request data structure 573 573 * @req: request data structure cipher handle to be freed 574 574 */ 575 - static inline void ahash_request_free(struct ahash_request *req) 576 - { 577 - kfree_sensitive(req); 578 - } 579 - 580 - static inline void ahash_request_zero(struct ahash_request *req) 581 - { 582 - memzero_explicit(req, sizeof(*req) + 583 - crypto_ahash_reqsize(crypto_ahash_reqtfm(req))); 584 - } 575 + void ahash_request_free(struct ahash_request *req); 585 576 586 577 static inline struct ahash_request *ahash_request_cast( 587 578 struct crypto_async_request *req) ··· 613 622 req->base.complete = compl; 614 623 req->base.data = data; 615 624 req->base.flags = flags; 625 + crypto_reqchain_init(&req->base); 616 626 } 617 627 618 628 /** ··· 636 644 req->src = src; 637 645 req->nbytes = nbytes; 638 646 req->result = result; 647 + } 648 + 649 + static inline void ahash_request_chain(struct ahash_request *req, 650 + struct ahash_request *head) 651 + { 652 + crypto_request_chain(&req->base, &head->base); 639 653 } 640 654 641 655 /** ··· 943 945 { 944 946 memzero_explicit(desc, 945 947 sizeof(*desc) + crypto_shash_descsize(desc->tfm)); 948 + } 949 + 950 + static inline int ahash_request_err(struct ahash_request *req) 951 + { 952 + return req->base.err; 953 + } 954 + 955 + static inline bool ahash_is_async(struct crypto_ahash *tfm) 956 + { 957 + return crypto_tfm_is_async(&tfm->base); 946 958 } 947 959 948 960 #endif /* _CRYPTO_HASH_H */
+10
include/crypto/internal/hash.h
··· 247 247 return container_of(tfm, struct crypto_shash, base); 248 248 } 249 249 250 + static inline bool ahash_request_chained(struct ahash_request *req) 251 + { 252 + return crypto_request_chained(&req->base); 253 + } 254 + 255 + static inline bool crypto_ahash_req_chain(struct crypto_ahash *tfm) 256 + { 257 + return crypto_tfm_req_chain(&tfm->base); 258 + } 259 + 250 260 #endif /* _CRYPTO_INTERNAL_HASH_H */ 251 261
+24
include/linux/crypto.h
··· 13 13 #define _LINUX_CRYPTO_H 14 14 15 15 #include <linux/completion.h> 16 + #include <linux/errno.h> 17 + #include <linux/list.h> 16 18 #include <linux/refcount.h> 17 19 #include <linux/slab.h> 18 20 #include <linux/types.h> ··· 126 124 */ 127 125 #define CRYPTO_ALG_FIPS_INTERNAL 0x00020000 128 126 127 + /* Set if the algorithm supports request chains. */ 128 + #define CRYPTO_ALG_REQ_CHAIN 0x00040000 129 + 129 130 /* 130 131 * Transform masks and values (for crt_flags). 131 132 */ ··· 179 174 struct crypto_tfm *tfm; 180 175 181 176 u32 flags; 177 + int err; 182 178 }; 183 179 184 180 /** ··· 545 539 int crypto_comp_decompress(struct crypto_comp *tfm, 546 540 const u8 *src, unsigned int slen, 547 541 u8 *dst, unsigned int *dlen); 542 + 543 + static inline void crypto_reqchain_init(struct crypto_async_request *req) 544 + { 545 + req->err = -EINPROGRESS; 546 + INIT_LIST_HEAD(&req->list); 547 + } 548 + 549 + static inline void crypto_request_chain(struct crypto_async_request *req, 550 + struct crypto_async_request *head) 551 + { 552 + req->err = -EINPROGRESS; 553 + list_add_tail(&req->list, &head->list); 554 + } 555 + 556 + static inline bool crypto_tfm_is_async(struct crypto_tfm *tfm) 557 + { 558 + return tfm->__crt_alg->cra_flags & CRYPTO_ALG_ASYNC; 559 + } 548 560 549 561 #endif /* _LINUX_CRYPTO_H */ 550 562