[PATCH 10/18] SUNRPC: Switch MIC token verification to crypto/krb5
From: Chuck Lever
Date: Mon Apr 27 2026 - 09:56:01 EST
From: Chuck Lever <chuck.lever@xxxxxxxxxx>
gss_krb5_verify_mic_v2() currently recomputes a checksum using
gss_krb5_checksum() and then compares it against the received
checksum with memcmp(). Replace this with a call to
crypto_krb5_verify_mic(), which performs the hash, comparison,
and offset/length adjustment in a single operation through the
crypto/krb5 library.
The scatterlist layout required by RFC 4121 Section 4.2.4 is
constructed via gss_krb5_mic_build_sg(), the shared helper
introduced in the preceding commit. The received checksum
occupies the first scatterlist entry, pointing directly into
the token buffer.
The errno result from crypto_krb5_verify_mic() is mapped to a
GSS major status code via gss_krb5_errno_to_status(), which
returns GSS_S_BAD_SIG for -EBADMSG (checksum mismatch).
Signed-off-by: Chuck Lever <chuck.lever@xxxxxxxxxx>
---
net/sunrpc/auth_gss/gss_krb5_unseal.c | 36 ++++++++++++++++++++++-------------
1 file changed, 23 insertions(+), 13 deletions(-)
diff --git a/net/sunrpc/auth_gss/gss_krb5_unseal.c b/net/sunrpc/auth_gss/gss_krb5_unseal.c
index ef0e6af9fc95..b5fb70419faa 100644
--- a/net/sunrpc/auth_gss/gss_krb5_unseal.c
+++ b/net/sunrpc/auth_gss/gss_krb5_unseal.c
@@ -60,6 +60,8 @@
#include <linux/types.h>
#include <linux/jiffies.h>
#include <linux/sunrpc/gss_krb5.h>
+#include <linux/scatterlist.h>
+#include <linux/slab.h>
#include "gss_krb5_internal.h"
@@ -71,18 +73,19 @@ u32
gss_krb5_verify_mic_v2(struct krb5_ctx *ctx, struct xdr_buf *message_buffer,
struct xdr_netobj *read_token)
{
- struct crypto_ahash *tfm = ctx->initiate ?
- ctx->acceptor_sign : ctx->initiator_sign;
- char cksumdata[GSS_KRB5_MAX_CKSUM_LEN];
- struct xdr_netobj cksumobj = {
- .len = ctx->gk5e->cksumlength,
- .data = cksumdata,
- };
+ const struct krb5_enctype *krb5 = ctx->krb5e;
+ struct crypto_shash *shash = ctx->initiate ?
+ ctx->acceptor_sign_shash : ctx->initiator_sign_shash;
+ unsigned int cksum_len = krb5->cksum_len;
+ struct scatterlist sg_head[XDR_BUF_TO_SG_NENTS];
+ struct scatterlist *sg_overflow;
+ size_t mic_offset, mic_len;
u8 *ptr = read_token->data;
__be16 be16_ptr;
time64_t now;
u8 flags;
- int i;
+ int nsg, i;
+ int ret;
dprintk("RPC: %s\n", __func__);
@@ -104,13 +107,20 @@ gss_krb5_verify_mic_v2(struct krb5_ctx *ctx, struct xdr_buf *message_buffer,
if (ptr[i] != 0xff)
return GSS_S_DEFECTIVE_TOKEN;
- if (gss_krb5_checksum(tfm, ptr, GSS_KRB5_TOK_HDR_LEN,
- message_buffer, 0, &cksumobj))
+ nsg = gss_krb5_mic_build_sg(message_buffer,
+ ptr + GSS_KRB5_TOK_HDR_LEN,
+ cksum_len, ptr,
+ sg_head, &sg_overflow);
+ if (nsg < 0)
return GSS_S_FAILURE;
- if (memcmp(cksumobj.data, ptr + GSS_KRB5_TOK_HDR_LEN,
- ctx->gk5e->cksumlength))
- return GSS_S_BAD_SIG;
+ mic_offset = 0;
+ mic_len = cksum_len + message_buffer->len + GSS_KRB5_TOK_HDR_LEN;
+ ret = crypto_krb5_verify_mic(krb5, shash, NULL, sg_head, nsg,
+ &mic_offset, &mic_len);
+ kfree(sg_overflow);
+ if (ret)
+ return gss_krb5_errno_to_status(ret);
/* it got through unscathed. Make sure the context is unexpired */
now = ktime_get_real_seconds();
--
2.53.0