]> git.ipfire.org Git - thirdparty/kernel/stable.git/commitdiff
SUNRPC: Switch MIC token verification to crypto/krb5
authorChuck Lever <chuck.lever@oracle.com>
Mon, 27 Apr 2026 13:50:54 +0000 (09:50 -0400)
committerChuck Lever <cel@kernel.org>
Tue, 9 Jun 2026 20:32:59 +0000 (16:32 -0400)
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).

Assisted-by: Claude:claude-opus-4-6
Reviewed-by: Jeff Layton <jlayton@kernel.org>
Acked-by: Anna Schumaker <anna.schumaker@hammerspace.com>
Signed-off-by: Chuck Lever <chuck.lever@oracle.com>
net/sunrpc/auth_gss/gss_krb5_unseal.c

index ef0e6af9fc959c217867f469100d035339ca7342..b5fb70419faaa395377f7bee99153af2d37b1d90 100644 (file)
@@ -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();