* [PATCH net v2 2/4] crypto/krb5, rxrpc: Fix lack of pre-decrypt/pre-verify length checks [not found] <20260513131941.1439155-1-dhowells@redhat.com> @ 2026-05-13 13:19 ` David Howells 2026-05-13 14:33 ` Jeffrey E Altman 2026-05-13 20:16 ` David Howells 0 siblings, 2 replies; 3+ messages in thread From: David Howells @ 2026-05-13 13:19 UTC (permalink / raw) To: netdev Cc: David Howells, Hyunwoo Kim, Marc Dionne, Jakub Kicinski, David S. Miller, Eric Dumazet, Paolo Abeni, Simon Horman, linux-afs, linux-kernel, Jeffrey Altman, Herbert Xu, Chuck Lever, linux-nfs, linux-crypto, stable Change the krb5 crypto library to provide facilities to precheck the length of the message about to be decrypted or verified. Fix AF_RXRPC to make use of this to validate DATA packets secured with RxGK. Fixes: 9d1d2b59341f ("rxrpc: rxgk: Implement the yfs-rxgk security class (GSSAPI)") Closes: https://sashiko.dev/#/patchset/20260511160753.607296-1-dhowells%40redhat.com Signed-off-by: David Howells <dhowells@redhat.com> cc: Marc Dionne <marc.dionne@auristor.com> cc: Jeffrey Altman <jaltman@auristor.com> cc: Herbert Xu <herbert@gondor.apana.org.au> cc: "David S. Miller" <davem@davemloft.net> cc: Eric Dumazet <edumazet@google.com> cc: Jakub Kicinski <kuba@kernel.org> cc: Paolo Abeni <pabeni@redhat.com> cc: Simon Horman <horms@kernel.org> cc: Chuck Lever <chuck.lever@oracle.com> cc: netdev@vger.kernel.org cc: linux-afs@lists.infradead.org cc: linux-nfs@vger.kernel.org cc: linux-crypto@vger.kernel.org cc: stable@vger.kernel.org --- Documentation/crypto/krb5.rst | 17 ++++++++--- crypto/krb5/krb5_api.c | 54 +++++++++++++++++++++++++++++++---- include/crypto/krb5.h | 9 ++++-- include/trace/events/rxrpc.h | 1 + net/rxrpc/rxgk.c | 11 +++++-- 5 files changed, 77 insertions(+), 15 deletions(-) diff --git a/Documentation/crypto/krb5.rst b/Documentation/crypto/krb5.rst index beffa0133446..f62e07ac6811 100644 --- a/Documentation/crypto/krb5.rst +++ b/Documentation/crypto/krb5.rst @@ -158,13 +158,22 @@ returned. When a message has been received, the location and size of the data with the message can be determined by calling:: - void crypto_krb5_where_is_the_data(const struct krb5_enctype *krb5, - enum krb5_crypto_mode mode, - size_t *_offset, size_t *_len); + int crypto_krb5_where_is_the_data(const struct krb5_enctype *krb5, + enum krb5_crypto_mode mode, + size_t *_offset, size_t *_len); The caller provides the offset and length of the message to the function, which then alters those values to indicate the region containing the data (plus any -padding). It is up to the caller to determine how much padding there is. +padding). It is up to the caller to determine how much padding there is. The +function returns an error if the length is too small or if the mode is +unsupported. An additional function:: + + int crypto_krb5_check_data_len(const struct krb5_enctype *krb5, + enum krb5_crypto_mode mode, + size_t len, size_t min_content); + +is provided to just do a basic check that the decrypted/verified message would +have a sufficient minimum payload. Preparation Functions --------------------- diff --git a/crypto/krb5/krb5_api.c b/crypto/krb5/krb5_api.c index 23026d4206c8..c7ea40f900a7 100644 --- a/crypto/krb5/krb5_api.c +++ b/crypto/krb5/krb5_api.c @@ -134,27 +134,69 @@ EXPORT_SYMBOL(crypto_krb5_how_much_data); * Find the offset and size of the data in a secure message so that this * information can be used in the metadata buffer which will get added to the * digest by crypto_krb5_verify_mic(). + * + * Return: 0 if successful, -EBADMSG if the message is too short or -EINVAL if + * the mode is unsupported. */ -void crypto_krb5_where_is_the_data(const struct krb5_enctype *krb5, - enum krb5_crypto_mode mode, - size_t *_offset, size_t *_len) +int crypto_krb5_where_is_the_data(const struct krb5_enctype *krb5, + enum krb5_crypto_mode mode, + size_t *_offset, size_t *_len) { switch (mode) { case KRB5_CHECKSUM_MODE: + if (*_len < krb5->cksum_len) + return -EBADMSG; *_offset += krb5->cksum_len; *_len -= krb5->cksum_len; - return; + return 0; case KRB5_ENCRYPT_MODE: + if (*_len < krb5->conf_len + krb5->cksum_len) + return -EBADMSG; *_offset += krb5->conf_len; *_len -= krb5->conf_len + krb5->cksum_len; - return; + return 0; default: WARN_ON_ONCE(1); - return; + return -EINVAL; } } EXPORT_SYMBOL(crypto_krb5_where_is_the_data); +/** + * crypto_krb5_check_data_len - Check a message is big enough + * @krb5: The encoding to use. + * @mode: Mode of operation. + * @len: The length of the secure blob. + * @min_content: Minimum length of the content inside the blob. + * + * Check that a message is large enough to hold whatever bits the encryption + * type wants to glue on (nonce, checksum) plus a minimum amount of content. + * + * Return: 0 if successful, -EBADMSG if the message is too short or -EINVAL if + * the mode is unsupported. + */ +int crypto_krb5_check_data_len(const struct krb5_enctype *krb5, + enum krb5_crypto_mode mode, + size_t len, size_t min_content) +{ + switch (mode) { + case KRB5_CHECKSUM_MODE: + if (len < krb5->cksum_len || + len - krb5->cksum_len < min_content) + return -EBADMSG; + return 0; + case KRB5_ENCRYPT_MODE: + if (len < krb5->conf_len + krb5->cksum_len || + len - (krb5->conf_len + krb5->cksum_len) < min_content) + return -EBADMSG; + return 0; + default: + WARN_ON_ONCE(1); + return -EINVAL; + } +} +EXPORT_SYMBOL(crypto_krb5_check_data_len); + /* * Prepare the encryption with derived key data. */ diff --git a/include/crypto/krb5.h b/include/crypto/krb5.h index 71dd38f59be1..aac3ecf88467 100644 --- a/include/crypto/krb5.h +++ b/include/crypto/krb5.h @@ -121,9 +121,12 @@ size_t crypto_krb5_how_much_buffer(const struct krb5_enctype *krb5, size_t crypto_krb5_how_much_data(const struct krb5_enctype *krb5, enum krb5_crypto_mode mode, size_t *_buffer_size, size_t *_offset); -void crypto_krb5_where_is_the_data(const struct krb5_enctype *krb5, - enum krb5_crypto_mode mode, - size_t *_offset, size_t *_len); +int crypto_krb5_where_is_the_data(const struct krb5_enctype *krb5, + enum krb5_crypto_mode mode, + size_t *_offset, size_t *_len); +int crypto_krb5_check_data_len(const struct krb5_enctype *krb5, + enum krb5_crypto_mode mode, + size_t len, size_t min_content); struct crypto_aead *crypto_krb5_prepare_encryption(const struct krb5_enctype *krb5, const struct krb5_buffer *TK, u32 usage, gfp_t gfp); diff --git a/include/trace/events/rxrpc.h b/include/trace/events/rxrpc.h index 573f2df3a2c9..704a10de6670 100644 --- a/include/trace/events/rxrpc.h +++ b/include/trace/events/rxrpc.h @@ -71,6 +71,7 @@ EM(rxkad_abort_resp_unknown_tkt, "rxkad-resp-unknown-tkt") \ EM(rxkad_abort_resp_version, "rxkad-resp-version") \ /* RxGK security errors */ \ + EM(rxgk_abort_1_short_header, "rxgk1-short-hdr") \ EM(rxgk_abort_1_verify_mic_eproto, "rxgk1-vfy-mic-eproto") \ EM(rxgk_abort_2_decrypt_eproto, "rxgk2-dec-eproto") \ EM(rxgk_abort_2_short_data, "rxgk2-short-data") \ diff --git a/net/rxrpc/rxgk.c b/net/rxrpc/rxgk.c index 0d5e654da918..41180263e527 100644 --- a/net/rxrpc/rxgk.c +++ b/net/rxrpc/rxgk.c @@ -480,8 +480,10 @@ static int rxgk_verify_packet_integrity(struct rxrpc_call *call, _enter(""); - crypto_krb5_where_is_the_data(gk->krb5, KRB5_CHECKSUM_MODE, - &data_offset, &data_len); + if (crypto_krb5_where_is_the_data(gk->krb5, KRB5_CHECKSUM_MODE, + &data_offset, &data_len) < 0) + return rxrpc_abort_eproto(call, skb, RXKADSEALEDINCON, + rxgk_abort_1_short_header); hdr = kzalloc_obj(*hdr, GFP_NOFS); if (!hdr) @@ -529,6 +531,11 @@ static int rxgk_verify_packet_encrypted(struct rxrpc_call *call, _enter(""); + if (crypto_krb5_check_data_len(gk->krb5, KRB5_ENCRYPT_MODE, + len, sizeof(*hdr)) < 0) + return rxrpc_abort_eproto(call, skb, RXKADSEALEDINCON, + rxgk_abort_2_short_header); + ret = rxgk_decrypt_skb(gk->krb5, gk->rx_enc, skb, &offset, &len, &ac); if (ret < 0) { if (ret != -ENOMEM) ^ permalink raw reply related [flat|nested] 3+ messages in thread
* Re: [PATCH net v2 2/4] crypto/krb5, rxrpc: Fix lack of pre-decrypt/pre-verify length checks 2026-05-13 13:19 ` [PATCH net v2 2/4] crypto/krb5, rxrpc: Fix lack of pre-decrypt/pre-verify length checks David Howells @ 2026-05-13 14:33 ` Jeffrey E Altman 2026-05-13 20:16 ` David Howells 1 sibling, 0 replies; 3+ messages in thread From: Jeffrey E Altman @ 2026-05-13 14:33 UTC (permalink / raw) To: David Howells, netdev Cc: Hyunwoo Kim, Marc Dionne, Jakub Kicinski, David S. Miller, Eric Dumazet, Paolo Abeni, Simon Horman, linux-afs, linux-kernel, Herbert Xu, Chuck Lever, linux-nfs, linux-crypto, stable [-- Attachment #1: Type: text/plain, Size: 8427 bytes --] On 5/13/2026 9:19 AM, David Howells wrote: > Change the krb5 crypto library to provide facilities to precheck the length > of the message about to be decrypted or verified. > > Fix AF_RXRPC to make use of this to validate DATA packets secured with > RxGK. > > Fixes: 9d1d2b59341f ("rxrpc: rxgk: Implement the yfs-rxgk security class (GSSAPI)") > Closes: https://sashiko.dev/#/patchset/20260511160753.607296-1-dhowells%40redhat.com > Signed-off-by: David Howells <dhowells@redhat.com> > cc: Marc Dionne <marc.dionne@auristor.com> > cc: Jeffrey Altman <jaltman@auristor.com> > cc: Herbert Xu <herbert@gondor.apana.org.au> > cc: "David S. Miller" <davem@davemloft.net> > cc: Eric Dumazet <edumazet@google.com> > cc: Jakub Kicinski <kuba@kernel.org> > cc: Paolo Abeni <pabeni@redhat.com> > cc: Simon Horman <horms@kernel.org> > cc: Chuck Lever <chuck.lever@oracle.com> > cc: netdev@vger.kernel.org > cc: linux-afs@lists.infradead.org > cc: linux-nfs@vger.kernel.org > cc: linux-crypto@vger.kernel.org > cc: stable@vger.kernel.org > --- > Documentation/crypto/krb5.rst | 17 ++++++++--- > crypto/krb5/krb5_api.c | 54 +++++++++++++++++++++++++++++++---- > include/crypto/krb5.h | 9 ++++-- > include/trace/events/rxrpc.h | 1 + > net/rxrpc/rxgk.c | 11 +++++-- > 5 files changed, 77 insertions(+), 15 deletions(-) > > diff --git a/Documentation/crypto/krb5.rst b/Documentation/crypto/krb5.rst > index beffa0133446..f62e07ac6811 100644 > --- a/Documentation/crypto/krb5.rst > +++ b/Documentation/crypto/krb5.rst > @@ -158,13 +158,22 @@ returned. > When a message has been received, the location and size of the data with the > message can be determined by calling:: > > - void crypto_krb5_where_is_the_data(const struct krb5_enctype *krb5, > - enum krb5_crypto_mode mode, > - size_t *_offset, size_t *_len); > + int crypto_krb5_where_is_the_data(const struct krb5_enctype *krb5, > + enum krb5_crypto_mode mode, > + size_t *_offset, size_t *_len); > > The caller provides the offset and length of the message to the function, which > then alters those values to indicate the region containing the data (plus any > -padding). It is up to the caller to determine how much padding there is. > +padding). It is up to the caller to determine how much padding there is. The > +function returns an error if the length is too small or if the mode is > +unsupported. An additional function:: > + > + int crypto_krb5_check_data_len(const struct krb5_enctype *krb5, > + enum krb5_crypto_mode mode, > + size_t len, size_t min_content); > + > +is provided to just do a basic check that the decrypted/verified message would > +have a sufficient minimum payload. > > Preparation Functions > --------------------- > diff --git a/crypto/krb5/krb5_api.c b/crypto/krb5/krb5_api.c > index 23026d4206c8..c7ea40f900a7 100644 > --- a/crypto/krb5/krb5_api.c > +++ b/crypto/krb5/krb5_api.c > @@ -134,27 +134,69 @@ EXPORT_SYMBOL(crypto_krb5_how_much_data); > * Find the offset and size of the data in a secure message so that this > * information can be used in the metadata buffer which will get added to the > * digest by crypto_krb5_verify_mic(). > + * > + * Return: 0 if successful, -EBADMSG if the message is too short or -EINVAL if > + * the mode is unsupported. > */ > -void crypto_krb5_where_is_the_data(const struct krb5_enctype *krb5, > - enum krb5_crypto_mode mode, > - size_t *_offset, size_t *_len) > +int crypto_krb5_where_is_the_data(const struct krb5_enctype *krb5, > + enum krb5_crypto_mode mode, > + size_t *_offset, size_t *_len) > { > switch (mode) { > case KRB5_CHECKSUM_MODE: > + if (*_len < krb5->cksum_len) > + return -EBADMSG; > *_offset += krb5->cksum_len; > *_len -= krb5->cksum_len; > - return; > + return 0; > case KRB5_ENCRYPT_MODE: > + if (*_len < krb5->conf_len + krb5->cksum_len) > + return -EBADMSG; > *_offset += krb5->conf_len; > *_len -= krb5->conf_len + krb5->cksum_len; > - return; > + return 0; > default: > WARN_ON_ONCE(1); > - return; > + return -EINVAL; > } > } > EXPORT_SYMBOL(crypto_krb5_where_is_the_data); > > +/** > + * crypto_krb5_check_data_len - Check a message is big enough > + * @krb5: The encoding to use. > + * @mode: Mode of operation. > + * @len: The length of the secure blob. > + * @min_content: Minimum length of the content inside the blob. > + * > + * Check that a message is large enough to hold whatever bits the encryption > + * type wants to glue on (nonce, checksum) plus a minimum amount of content. > + * > + * Return: 0 if successful, -EBADMSG if the message is too short or -EINVAL if > + * the mode is unsupported. > + */ > +int crypto_krb5_check_data_len(const struct krb5_enctype *krb5, > + enum krb5_crypto_mode mode, > + size_t len, size_t min_content) > +{ > + switch (mode) { > + case KRB5_CHECKSUM_MODE: > + if (len < krb5->cksum_len || > + len - krb5->cksum_len < min_content) > + return -EBADMSG; > + return 0; > + case KRB5_ENCRYPT_MODE: > + if (len < krb5->conf_len + krb5->cksum_len || > + len - (krb5->conf_len + krb5->cksum_len) < min_content) > + return -EBADMSG; > + return 0; > + default: > + WARN_ON_ONCE(1); > + return -EINVAL; > + } > +} > +EXPORT_SYMBOL(crypto_krb5_check_data_len); > + > /* > * Prepare the encryption with derived key data. > */ > diff --git a/include/crypto/krb5.h b/include/crypto/krb5.h > index 71dd38f59be1..aac3ecf88467 100644 > --- a/include/crypto/krb5.h > +++ b/include/crypto/krb5.h > @@ -121,9 +121,12 @@ size_t crypto_krb5_how_much_buffer(const struct krb5_enctype *krb5, > size_t crypto_krb5_how_much_data(const struct krb5_enctype *krb5, > enum krb5_crypto_mode mode, > size_t *_buffer_size, size_t *_offset); > -void crypto_krb5_where_is_the_data(const struct krb5_enctype *krb5, > - enum krb5_crypto_mode mode, > - size_t *_offset, size_t *_len); > +int crypto_krb5_where_is_the_data(const struct krb5_enctype *krb5, > + enum krb5_crypto_mode mode, > + size_t *_offset, size_t *_len); > +int crypto_krb5_check_data_len(const struct krb5_enctype *krb5, > + enum krb5_crypto_mode mode, > + size_t len, size_t min_content); > struct crypto_aead *crypto_krb5_prepare_encryption(const struct krb5_enctype *krb5, > const struct krb5_buffer *TK, > u32 usage, gfp_t gfp); > diff --git a/include/trace/events/rxrpc.h b/include/trace/events/rxrpc.h > index 573f2df3a2c9..704a10de6670 100644 > --- a/include/trace/events/rxrpc.h > +++ b/include/trace/events/rxrpc.h > @@ -71,6 +71,7 @@ > EM(rxkad_abort_resp_unknown_tkt, "rxkad-resp-unknown-tkt") \ > EM(rxkad_abort_resp_version, "rxkad-resp-version") \ > /* RxGK security errors */ \ > + EM(rxgk_abort_1_short_header, "rxgk1-short-hdr") \ > EM(rxgk_abort_1_verify_mic_eproto, "rxgk1-vfy-mic-eproto") \ > EM(rxgk_abort_2_decrypt_eproto, "rxgk2-dec-eproto") \ > EM(rxgk_abort_2_short_data, "rxgk2-short-data") \ > diff --git a/net/rxrpc/rxgk.c b/net/rxrpc/rxgk.c > index 0d5e654da918..41180263e527 100644 > --- a/net/rxrpc/rxgk.c > +++ b/net/rxrpc/rxgk.c > @@ -480,8 +480,10 @@ static int rxgk_verify_packet_integrity(struct rxrpc_call *call, > > _enter(""); > > - crypto_krb5_where_is_the_data(gk->krb5, KRB5_CHECKSUM_MODE, > - &data_offset, &data_len); > + if (crypto_krb5_where_is_the_data(gk->krb5, KRB5_CHECKSUM_MODE, > + &data_offset, &data_len) < 0) > + return rxrpc_abort_eproto(call, skb, RXKADSEALEDINCON, > + rxgk_abort_1_short_header); > > hdr = kzalloc_obj(*hdr, GFP_NOFS); > if (!hdr) > @@ -529,6 +531,11 @@ static int rxgk_verify_packet_encrypted(struct rxrpc_call *call, > > _enter(""); > > + if (crypto_krb5_check_data_len(gk->krb5, KRB5_ENCRYPT_MODE, > + len, sizeof(*hdr)) < 0) > + return rxrpc_abort_eproto(call, skb, RXKADSEALEDINCON, > + rxgk_abort_2_short_header); > + > ret = rxgk_decrypt_skb(gk->krb5, gk->rx_enc, skb, &offset, &len, &ac); > if (ret < 0) { > if (ret != -ENOMEM) Reviewed-by: Jeffrey Altman <jaltman@auristor.com> [-- Attachment #2: S/MIME Cryptographic Signature --] [-- Type: application/pkcs7-signature, Size: 4467 bytes --] ^ permalink raw reply [flat|nested] 3+ messages in thread
* Re: [PATCH net v2 2/4] crypto/krb5, rxrpc: Fix lack of pre-decrypt/pre-verify length checks 2026-05-13 13:19 ` [PATCH net v2 2/4] crypto/krb5, rxrpc: Fix lack of pre-decrypt/pre-verify length checks David Howells 2026-05-13 14:33 ` Jeffrey E Altman @ 2026-05-13 20:16 ` David Howells 1 sibling, 0 replies; 3+ messages in thread From: David Howells @ 2026-05-13 20:16 UTC (permalink / raw) Cc: dhowells, netdev, Hyunwoo Kim, Marc Dionne, Jakub Kicinski, David S. Miller, Eric Dumazet, Paolo Abeni, Simon Horman, linux-afs, linux-kernel, Jeffrey Altman, Herbert Xu, Chuck Lever, linux-nfs, linux-crypto, stable David Howells <dhowells@redhat.com> wrote: > + if (crypto_krb5_check_data_len(gk->krb5, KRB5_ENCRYPT_MODE, > + len, sizeof(*hdr)) < 0) This should be sizeof(hdr) here in patch 2 and sizeof(*hdr) in patch 3. David ^ permalink raw reply [flat|nested] 3+ messages in thread
end of thread, other threads:[~2026-05-13 20:16 UTC | newest]
Thread overview: 3+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
[not found] <20260513131941.1439155-1-dhowells@redhat.com>
2026-05-13 13:19 ` [PATCH net v2 2/4] crypto/krb5, rxrpc: Fix lack of pre-decrypt/pre-verify length checks David Howells
2026-05-13 14:33 ` Jeffrey E Altman
2026-05-13 20:16 ` David Howells
This is a public inbox, see mirroring instructions for how to clone and mirror all data and code used for this inbox