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: s390/phmac - Do not modify the req->nbytes value

The phmac implementation used the req->nbytes field on combined
operations (finup, digest) to track the state:
with req->nbytes > 0 the update needs to be processed,
while req->nbytes == 0 means to do the final operation. For
this purpose the req->nbytes field was set to 0 after successful
update operation. However, aead uses the req->nbytes field after a
successful hash operation to determine the amount of data to
en/decrypt. So an implementation must not modify the nbytes field.

Fixed by a slight rework on the phmac implementation. There is
now a new field async_op in the request context which tracks
the (asynch) operation to process. So the 'state' via req->nbytes
is not needed any more and now this field is untouched and may
be evaluated even after a request is processed by the phmac
implementation.

Fixes: cbbc675506cc ("crypto: s390 - New s390 specific protected key hash phmac")
Reported-by: Ingo Franzki <ifranzki@linux.ibm.com>
Signed-off-by: Harald Freudenberger <freude@linux.ibm.com>
Tested-by: Ingo Franzki <ifranzki@linux.ibm.com>
Reviewed-by: Ingo Franzki <ifranzki@linux.ibm.com>
Reviewed-by: Holger Dengler <dengler@linux.ibm.com>
Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>

authored by

Harald Freudenberger and committed by
Herbert Xu
3ac2939b 3a866087

+34 -18
+34 -18
arch/s390/crypto/phmac_s390.c
··· 169 169 u64 buflen[2]; 170 170 }; 171 171 172 + enum async_op { 173 + OP_NOP = 0, 174 + OP_UPDATE, 175 + OP_FINAL, 176 + OP_FINUP, 177 + }; 178 + 172 179 /* phmac request context */ 173 180 struct phmac_req_ctx { 174 181 struct hash_walk_helper hwh; 175 182 struct kmac_sha2_ctx kmac_ctx; 176 - bool final; 183 + enum async_op async_op; 177 184 }; 178 185 179 186 /* ··· 617 610 * using engine to serialize requests. 618 611 */ 619 612 if (rc == 0 || rc == -EKEYEXPIRED) { 613 + req_ctx->async_op = OP_UPDATE; 620 614 atomic_inc(&tfm_ctx->via_engine_ctr); 621 615 rc = crypto_transfer_hash_request_to_engine(phmac_crypto_engine, req); 622 616 if (rc != -EINPROGRESS) ··· 655 647 * using engine to serialize requests. 656 648 */ 657 649 if (rc == 0 || rc == -EKEYEXPIRED) { 658 - req->nbytes = 0; 659 - req_ctx->final = true; 650 + req_ctx->async_op = OP_FINAL; 660 651 atomic_inc(&tfm_ctx->via_engine_ctr); 661 652 rc = crypto_transfer_hash_request_to_engine(phmac_crypto_engine, req); 662 653 if (rc != -EINPROGRESS) ··· 683 676 if (rc) 684 677 goto out; 685 678 679 + req_ctx->async_op = OP_FINUP; 680 + 686 681 /* Try synchronous operations if no active engine usage */ 687 682 if (!atomic_read(&tfm_ctx->via_engine_ctr)) { 688 683 rc = phmac_kmac_update(req, false); 689 684 if (rc == 0) 690 - req->nbytes = 0; 685 + req_ctx->async_op = OP_FINAL; 691 686 } 692 - if (!rc && !req->nbytes && !atomic_read(&tfm_ctx->via_engine_ctr)) { 687 + if (!rc && req_ctx->async_op == OP_FINAL && 688 + !atomic_read(&tfm_ctx->via_engine_ctr)) { 693 689 rc = phmac_kmac_final(req, false); 694 690 if (rc == 0) 695 691 goto out; ··· 704 694 * using engine to serialize requests. 705 695 */ 706 696 if (rc == 0 || rc == -EKEYEXPIRED) { 707 - req_ctx->final = true; 697 + /* req->async_op has been set to either OP_FINUP or OP_FINAL */ 708 698 atomic_inc(&tfm_ctx->via_engine_ctr); 709 699 rc = crypto_transfer_hash_request_to_engine(phmac_crypto_engine, req); 710 700 if (rc != -EINPROGRESS) ··· 865 855 866 856 /* 867 857 * Three kinds of requests come in here: 868 - * update when req->nbytes > 0 and req_ctx->final is false 869 - * final when req->nbytes = 0 and req_ctx->final is true 870 - * finup when req->nbytes > 0 and req_ctx->final is true 871 - * For update and finup the hwh walk needs to be prepared and 872 - * up to date but the actual nr of bytes in req->nbytes may be 873 - * any non zero number. For final there is no hwh walk needed. 858 + * 1. req->async_op == OP_UPDATE with req->nbytes > 0 859 + * 2. req->async_op == OP_FINUP with req->nbytes > 0 860 + * 3. req->async_op == OP_FINAL 861 + * For update and finup the hwh walk has already been prepared 862 + * by the caller. For final there is no hwh walk needed. 874 863 */ 875 864 876 - if (req->nbytes) { 865 + switch (req_ctx->async_op) { 866 + case OP_UPDATE: 867 + case OP_FINUP: 877 868 rc = phmac_kmac_update(req, true); 878 869 if (rc == -EKEYEXPIRED) { 879 870 /* ··· 891 880 hwh_advance(hwh, rc); 892 881 goto out; 893 882 } 894 - req->nbytes = 0; 895 - } 896 - 897 - if (req_ctx->final) { 883 + if (req_ctx->async_op == OP_UPDATE) 884 + break; 885 + req_ctx->async_op = OP_FINAL; 886 + fallthrough; 887 + case OP_FINAL: 898 888 rc = phmac_kmac_final(req, true); 899 889 if (rc == -EKEYEXPIRED) { 900 890 /* ··· 909 897 cond_resched(); 910 898 return -ENOSPC; 911 899 } 900 + break; 901 + default: 902 + /* unknown/unsupported/unimplemented asynch op */ 903 + return -EOPNOTSUPP; 912 904 } 913 905 914 906 out: 915 - if (rc || req_ctx->final) 907 + if (rc || req_ctx->async_op == OP_FINAL) 916 908 memzero_explicit(kmac_ctx, sizeof(*kmac_ctx)); 917 909 pr_debug("request complete with rc=%d\n", rc); 918 910 local_bh_disable();