Linux cryptographic layer development
 help / color / mirror / Atom feed
* [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