crypto: krb5enc - fix async decrypt skipping hash verification
PATCH 1/1 crypto: krb5enc - fix async decrypt skipping hash verification
krb5enc_dispatch_decrypt() sets req->base.complete as the skcipher callback, which is the caller's own completion handler. When the skcipher completes asynchronously, this signals "done" to the caller without executing krb5enc_dispatch_decrypt_hash(), completely bypassing the integrity verification (hash check).
Compare with the encrypt path which correctly uses krb5enc_encrypt_done as an intermediate callback to chain into the hash computation on async completion.
Fix by adding krb5enc_decrypt_done as an intermediate callback that chains into krb5enc_dispatch_decrypt_hash() upon async skcipher completion, matching the encrypt path's callback pattern. Handle both -EINPROGRESS and -EBUSY notifications from backlogged requests, consistent with authenc's authenc_request_complete(). Also fix krb5enc_request_complete() to filter -EBUSY in addition to -EINPROGRESS, matching the authenc reference implementation.
--- crypto/krb5enc.c | 22 ++++++++++++++++++++-- 1 file changed, 20 insertions(+), 2 deletions(-)
crypto/krb5enc.c +20 -2
@@ -41,7 +41,7 @@ struct krb5enc_request_ctx {static void krb5enc_request_complete (struct aead_request *req,int err) { -if (err != -EINPROGRESS ) +if (err != -EINPROGRESS && err != -EBUSY )aead_request_complete (req, err); }
@@ -300,6 +300,24 @@ static int krb5enc_dispatch_decrypt_hash(struct aead_request *req)return krb5enc_verify_hash (req); } +static void krb5enc_decrypt_done (void *data,int err) +{ +struct aead_request *req = data; + +if (err == -EINPROGRESS || err == -EBUSY ) +return krb5enc_request_complete (req, err); + +if (err) + goto out; + + err =krb5enc_dispatch_decrypt_hash (req); +if (err == -EINPROGRESS || err == -EBUSY ) +return ; + +out: +aead_request_complete (req, err); +} +/* * Dispatch the decryption of the ciphertext. */
@@ -323,7 +341,7 @@ static int krb5enc_dispatch_decrypt(struct aead_request *req)skcipher_request_set_tfm (skreq, ctx->enc);skcipher_request_set_callback (skreq,aead_request_flags (req), - req->base.complete, req->base.data); + krb5enc_decrypt_done, req);skcipher_request_set_crypt (skreq, src, dst, req->cryptlen - authsize, req->iv);
Signature · 1 line
2.39.3 (Apple Git-145)
Herbert Xu
maintainercrypto/krb5enc.c struct krb5enc_request_ctx { · line 44
Quoted 11 lines · Dudu Lu
crypto/krb5enc.c +1
-1@@ -41,7 +41,7 @@ struct krb5enc_request_ctx {static void krb5enc_request_complete (struct aead_request *req,int err) { -if (err != -EINPROGRESS ) +if (err != -EINPROGRESS && err != -EBUSY )
This shouldn't filter anything out. The filtering needs to occur further up the call stack. In fact just get rid of it and use aead_request_complete directly.
The encrypt path is just as broken as the decrypt path and needs to be fixed accordingly to filter out EBUSY/EINPROGRESS. In particular, this should be done in krb5enc_encrypt_ahash_done. Currently it's only filtering out EINPROGRESS.
crypto/krb5enc.c static int krb5enc_dispatch_decrypt_hash(struct aead_request *req) · line 308
Quoted 6 lines
crypto/krb5enc.c +6
-0+static void krb5enc_decrypt_done (void *data,int err) +{ +struct aead_request *req = data; + +if (err == -EINPROGRESS || err == -EBUSY ) +return krb5enc_request_complete (req, err);
EINPROGRESS should always get passed up here because it means that we originally returned an EBUSY and the caller is potentially blocking on this notification.
EBUSY cannot occur in the context of the callback so there is no need to check for it.
So this should simply become
if (err) goto out;
crypto/krb5enc.c static int krb5enc_dispatch_decrypt_hash(struct aead_request *req) · line 315
Quoted 3 lines
crypto/krb5enc.c +3
-0+ err =krb5enc_dispatch_decrypt_hash (req); +if (err == -EINPROGRESS || err == -EBUSY ) +return ;
This is the only place where EBUSY needs to be checked.
Thanks,
Signature · 3 lines
Email: Herbert Xu <[email protected]> Home Page: http://gondor.apana.org.au/~herbert/ PGP Key: http://gondor.apana.org.au/~herbert/pubkey.txt