public inbox for netdev@vger.kernel.org
 help / color / mirror / Atom feed
* [PATCH 00/18] Migrate rpcsec_gss_krb5 to the crypto/krb5 library
@ 2026-04-27 13:50 Chuck Lever
  2026-04-27 13:50 ` [PATCH 01/18] SUNRPC: Add Kconfig dependency on CRYPTO_KRB5 Chuck Lever
                   ` (18 more replies)
  0 siblings, 19 replies; 21+ messages in thread
From: Chuck Lever @ 2026-04-27 13:50 UTC (permalink / raw)
  To: Trond Myklebust, Anna Schumaker, Chuck Lever, Jeff Layton,
	NeilBrown, Olga Kornievskaia, Dai Ngo, Tom Talpey,
	David S. Miller, Eric Dumazet, Jakub Kicinski, Paolo Abeni,
	Simon Horman
  Cc: linux-nfs, netdev, linux-kernel, Herbert Xu, David Howells,
	Simo Sorce

The rpcsec_gss_krb5 module carries its own Kerberos 5 crypto imple-
mentation: key derivation, CBC-CTS encryption, HMAC checksumming,
and the encrypt-then-MAC construction from RFC 8009. Keeping
cryptographic code inside an RPC module means it receives review
only from the SUNRPC maintainers, who lack deep crypto expertise.
Vulnerabilities and algorithmic errors can persist unnoticed.

Replacing the private SunRPC Kerberos implementation eliminates
this duplicated audit surface. A single implementation of Kerberos
5 key derivation and authenticated encryption is easier to verify
than two independent copies. New encryption types and hardware
offload added to crypto/krb5 will automatically become available
to SunRPC Kerberos consumers.

The crypto/krb5 library handles enctype differences internally, so
a single encrypt function and a single decrypt function serve all
enctypes, eliminating the per-enctype dispatch table that previously
existed in struct gss_krb5_enctype.

RFC 4121 Section 4.2.4 requires MIC checksums to cover the message
body followed by the GSS token header. The crypto/krb5 get_mic/
verify_mic API hashes optional metadata before the scatterlist
data, which is the wrong order for the GSS header. The header is
therefore placed at the end of the scatterlist rather than passed
as the metadata parameter, and a dedicated gss_krb5_mic_build_sg()
helper constructs this three-section layout (checksum area, message
body, token header) with proper sg_mark_end() termination.

This implementation was available during the Spring 2026 NFS bake-
a-thon, and received testing there.

---
Chuck Lever (18):
      SUNRPC: Add Kconfig dependency on CRYPTO_KRB5
      SUNRPC: Add crypto/krb5 enctype lookup to krb5_ctx
      SUNRPC: Add helpers to convert xdr_buf byte ranges to scatterlists
      SUNRPC: Add errno-to-GSS status conversion helper
      SUNRPC: Prepare crypto/krb5 encryption and checksum handles
      SUNRPC: Switch wrap token encryption to crypto/krb5
      SUNRPC: Switch wrap token decryption to crypto/krb5
      SUNRPC: Switch Camellia decrypt to crypto/krb5
      SUNRPC: Switch MIC token generation to crypto/krb5
      SUNRPC: Switch MIC token verification to crypto/krb5
      SUNRPC: Remove get_mic/verify_mic function pointers from enctype table
      SUNRPC: Remove wrap/unwrap function pointers from enctype table
      SUNRPC: Remove encrypt/decrypt function pointers from enctype table
      SUNRPC: Remove legacy skcipher/ahash handles from krb5_ctx
      SUNRPC: Remove dead code from rpcsec_gss_krb5
      SUNRPC: Remove per-enctype Kconfig options
      SUNRPC: Remove redundant crypto Kconfig dependencies
      SUNRPC: Remove dead rpcsec_gss_krb5 definitions

 include/linux/sunrpc/gss_krb5.h         |  105 --
 include/linux/sunrpc/xdr.h              |   16 +-
 net/sunrpc/.kunitconfig                 |   29 -
 net/sunrpc/Kconfig                      |   56 +-
 net/sunrpc/auth_gss/Makefile            |    4 +-
 net/sunrpc/auth_gss/gss_krb5_crypto.c   | 1014 ++++-------------
 net/sunrpc/auth_gss/gss_krb5_internal.h |  155 +--
 net/sunrpc/auth_gss/gss_krb5_keys.c     |  546 ---------
 net/sunrpc/auth_gss/gss_krb5_mech.c     |  441 ++------
 net/sunrpc/auth_gss/gss_krb5_seal.c     |   47 +-
 net/sunrpc/auth_gss/gss_krb5_test.c     | 1868 -------------------------------
 net/sunrpc/auth_gss/gss_krb5_unseal.c   |   36 +-
 net/sunrpc/auth_gss/gss_krb5_wrap.c     |   13 +-
 net/sunrpc/xdr.c                        |  266 +++--
 14 files changed, 573 insertions(+), 4023 deletions(-)
---
base-commit: f3a96328282e8d41ba9f478d24ac122e4cbd2989
change-id: 20260316-crypto-krb5-api-b9ee22636698

Best regards,
--  
Chuck Lever


^ permalink raw reply	[flat|nested] 21+ messages in thread

* [PATCH 01/18] SUNRPC: Add Kconfig dependency on CRYPTO_KRB5
  2026-04-27 13:50 [PATCH 00/18] Migrate rpcsec_gss_krb5 to the crypto/krb5 library Chuck Lever
@ 2026-04-27 13:50 ` Chuck Lever
  2026-04-27 13:50 ` [PATCH 02/18] SUNRPC: Add crypto/krb5 enctype lookup to krb5_ctx Chuck Lever
                   ` (17 subsequent siblings)
  18 siblings, 0 replies; 21+ messages in thread
From: Chuck Lever @ 2026-04-27 13:50 UTC (permalink / raw)
  To: Trond Myklebust, Anna Schumaker, Chuck Lever, Jeff Layton,
	NeilBrown, Olga Kornievskaia, Dai Ngo, Tom Talpey,
	David S. Miller, Eric Dumazet, Jakub Kicinski, Paolo Abeni,
	Simon Horman
  Cc: linux-nfs, netdev, linux-kernel, Herbert Xu, David Howells,
	Simo Sorce

From: Chuck Lever <chuck.lever@oracle.com>

The rpcsec_gss_krb5 module currently contains its own Kerberos 5
crypto implementation (key derivation, encryption, checksumming)
that duplicates functionality available in the common crypto/krb5
library. As a first step toward migrating to that library, add a
Kconfig select so that building rpcsec_gss_krb5 pulls in the
common Kerberos 5 crypto support.

The per-enctype Kconfig options (AES_SHA1, CAMELLIA, AES_SHA2)
remain: they continue to gate which encryption types are offered
by the GSS mechanism. The individual crypto algorithm selects
they carry become redundant once the migration is complete, since
CRYPTO_KRB5 already selects all needed ciphers and hashes.

Signed-off-by: Chuck Lever <chuck.lever@oracle.com>
---
 net/sunrpc/Kconfig | 1 +
 1 file changed, 1 insertion(+)

diff --git a/net/sunrpc/Kconfig b/net/sunrpc/Kconfig
index a570e7adf270..381e76975ea9 100644
--- a/net/sunrpc/Kconfig
+++ b/net/sunrpc/Kconfig
@@ -21,6 +21,7 @@ config RPCSEC_GSS_KRB5
 	depends on SUNRPC && CRYPTO
 	default y
 	select SUNRPC_GSS
+	select CRYPTO_KRB5
 	select CRYPTO_SKCIPHER
 	select CRYPTO_HASH
 	help

-- 
2.53.0


^ permalink raw reply related	[flat|nested] 21+ messages in thread

* [PATCH 02/18] SUNRPC: Add crypto/krb5 enctype lookup to krb5_ctx
  2026-04-27 13:50 [PATCH 00/18] Migrate rpcsec_gss_krb5 to the crypto/krb5 library Chuck Lever
  2026-04-27 13:50 ` [PATCH 01/18] SUNRPC: Add Kconfig dependency on CRYPTO_KRB5 Chuck Lever
@ 2026-04-27 13:50 ` Chuck Lever
  2026-04-27 13:50 ` [PATCH 03/18] SUNRPC: Add helpers to convert xdr_buf byte ranges to scatterlists Chuck Lever
                   ` (16 subsequent siblings)
  18 siblings, 0 replies; 21+ messages in thread
From: Chuck Lever @ 2026-04-27 13:50 UTC (permalink / raw)
  To: Trond Myklebust, Anna Schumaker, Chuck Lever, Jeff Layton,
	NeilBrown, Olga Kornievskaia, Dai Ngo, Tom Talpey,
	David S. Miller, Eric Dumazet, Jakub Kicinski, Paolo Abeni,
	Simon Horman
  Cc: linux-nfs, netdev, linux-kernel, Herbert Xu, David Howells,
	Simo Sorce

From: Chuck Lever <chuck.lever@oracle.com>

Each krb5_ctx currently points to a gss_krb5_enctype, the
rpcsec_gss_krb5 module's own enctype descriptor. To begin
using the common crypto/krb5 library, store a pointer to the
corresponding struct krb5_enctype (from <crypto/krb5.h>) as
well.

The lookup is performed in gss_import_v2_context() immediately
after the existing gss_krb5_lookup_enctype() call. If
crypto_krb5_find_enctype() cannot find a matching enctype the
context import fails, ensuring the module never operates with
a partially-initialized krb5_ctx.

Signed-off-by: Chuck Lever <chuck.lever@oracle.com>
---
 net/sunrpc/auth_gss/gss_krb5_internal.h | 3 +++
 net/sunrpc/auth_gss/gss_krb5_mech.c     | 7 +++++++
 2 files changed, 10 insertions(+)

diff --git a/net/sunrpc/auth_gss/gss_krb5_internal.h b/net/sunrpc/auth_gss/gss_krb5_internal.h
index 8769e9e705bf..11402c3b4972 100644
--- a/net/sunrpc/auth_gss/gss_krb5_internal.h
+++ b/net/sunrpc/auth_gss/gss_krb5_internal.h
@@ -8,6 +8,8 @@
 #ifndef _NET_SUNRPC_AUTH_GSS_KRB5_INTERNAL_H
 #define _NET_SUNRPC_AUTH_GSS_KRB5_INTERNAL_H
 
+#include <crypto/krb5.h>
+
 /*
  * The RFCs often specify payload lengths in bits. This helper
  * converts a specified bit-length to the number of octets/bytes.
@@ -62,6 +64,7 @@ struct krb5_ctx {
 	u32			enctype;
 	u32			flags;
 	const struct gss_krb5_enctype *gk5e; /* enctype-specific info */
+	const struct krb5_enctype *krb5e; /* crypto/krb5 enctype */
 	struct crypto_sync_skcipher *enc;
 	struct crypto_sync_skcipher *seq;
 	struct crypto_sync_skcipher *acceptor_enc;
diff --git a/net/sunrpc/auth_gss/gss_krb5_mech.c b/net/sunrpc/auth_gss/gss_krb5_mech.c
index 6db64a9111a9..060d8fc4358e 100644
--- a/net/sunrpc/auth_gss/gss_krb5_mech.c
+++ b/net/sunrpc/auth_gss/gss_krb5_mech.c
@@ -432,6 +432,13 @@ gss_import_v2_context(const void *p, const void *end, struct krb5_ctx *ctx,
 		p = ERR_PTR(-EINVAL);
 		goto out_err;
 	}
+	ctx->krb5e = crypto_krb5_find_enctype(ctx->enctype);
+	if (!ctx->krb5e) {
+		dprintk("gss_kerberos_mech: crypto/krb5 missing enctype %u\n",
+			ctx->enctype);
+		p = ERR_PTR(-EINVAL);
+		goto out_err;
+	}
 	keylen = ctx->gk5e->keylength;
 
 	p = simple_get_bytes(p, end, ctx->Ksess, keylen);

-- 
2.53.0


^ permalink raw reply related	[flat|nested] 21+ messages in thread

* [PATCH 03/18] SUNRPC: Add helpers to convert xdr_buf byte ranges to scatterlists
  2026-04-27 13:50 [PATCH 00/18] Migrate rpcsec_gss_krb5 to the crypto/krb5 library Chuck Lever
  2026-04-27 13:50 ` [PATCH 01/18] SUNRPC: Add Kconfig dependency on CRYPTO_KRB5 Chuck Lever
  2026-04-27 13:50 ` [PATCH 02/18] SUNRPC: Add crypto/krb5 enctype lookup to krb5_ctx Chuck Lever
@ 2026-04-27 13:50 ` Chuck Lever
  2026-04-27 13:50 ` [PATCH 04/18] SUNRPC: Add errno-to-GSS status conversion helper Chuck Lever
                   ` (15 subsequent siblings)
  18 siblings, 0 replies; 21+ messages in thread
From: Chuck Lever @ 2026-04-27 13:50 UTC (permalink / raw)
  To: Trond Myklebust, Anna Schumaker, Chuck Lever, Jeff Layton,
	NeilBrown, Olga Kornievskaia, Dai Ngo, Tom Talpey,
	David S. Miller, Eric Dumazet, Jakub Kicinski, Paolo Abeni,
	Simon Horman
  Cc: linux-nfs, netdev, linux-kernel, Herbert Xu, David Howells,
	Simo Sorce

From: Chuck Lever <chuck.lever@oracle.com>

The crypto/krb5 library accepts data in scatterlist form, but
the GSS-API layer presents RPC payloads as struct xdr_buf.
Bridge that gap with a pair of helper functions:

  xdr_buf_to_sg()        - populate a caller-supplied scatterlist
                           array from a byte range
  xdr_buf_to_sg_alloc()  - populate a caller-supplied inline
                           scatterlist, chaining to a heap-
                           allocated overflow for large payloads

The inline array (typically stack-allocated at eight entries)
covers the common case of small RPCs with no heap allocation
on the encrypt/decrypt path. Only buffers spanning many pages
incur a kmalloc for the chained extension.

The segment-walking logic follows the same head, page array,
tail traversal as xdr_process_buf(), but populates a
scatterlist directly rather than invoking a per-segment
callback. sg_next() traversal makes the walker safe for
chained scatterlists. Once subsequent patches reroute all
per-message crypto operations through crypto/krb5,
xdr_process_buf() loses its last callers and is removed.

Signed-off-by: Chuck Lever <chuck.lever@oracle.com>
---
 include/linux/sunrpc/xdr.h |  15 ++++
 net/sunrpc/xdr.c           | 199 +++++++++++++++++++++++++++++++++++++++++++++
 2 files changed, 214 insertions(+)

diff --git a/include/linux/sunrpc/xdr.h b/include/linux/sunrpc/xdr.h
index b639a6fafcbc..f82446993fde 100644
--- a/include/linux/sunrpc/xdr.h
+++ b/include/linux/sunrpc/xdr.h
@@ -140,6 +140,21 @@ int	xdr_alloc_bvec(struct xdr_buf *buf, gfp_t gfp);
 void	xdr_free_bvec(struct xdr_buf *buf);
 unsigned int xdr_buf_to_bvec(struct bio_vec *bvec, unsigned int bvec_size,
 			     const struct xdr_buf *xdr);
+int xdr_buf_to_sg(const struct xdr_buf *buf, unsigned int offset,
+		  unsigned int len, struct scatterlist *sg, unsigned int nsg);
+int xdr_buf_to_sg_alloc(const struct xdr_buf *buf, unsigned int offset,
+			unsigned int len, struct scatterlist *sg_head,
+			unsigned int sg_head_nents,
+			struct scatterlist **sg_overflow, gfp_t gfp);
+
+/*
+ * Inline scatterlist entries for xdr_buf_to_sg_alloc().  Sized to cover the
+ * head kvec, tail kvec, and a few page fragments without any heap allocation.
+ */
+enum {
+	XDR_BUF_TO_SG_NENTS	= 8,
+};
+
 
 static inline __be32 *xdr_encode_array(__be32 *p, const void *s, unsigned int len)
 {
diff --git a/net/sunrpc/xdr.c b/net/sunrpc/xdr.c
index e83d5d0be78b..516833b4c114 100644
--- a/net/sunrpc/xdr.c
+++ b/net/sunrpc/xdr.c
@@ -187,6 +187,205 @@ unsigned int xdr_buf_to_bvec(struct bio_vec *bvec, unsigned int bvec_size,
 }
 EXPORT_SYMBOL_GPL(xdr_buf_to_bvec);
 
+/**
+ * xdr_buf_to_sg - Populate a scatterlist from an xdr_buf range
+ * @buf: xdr_buf to map
+ * @offset: starting byte offset within @buf
+ * @len: number of bytes to cover
+ * @sg: scatterlist array initialized with sg_init_table()
+ * @nsg: number of entries available in @sg
+ *
+ * @sg is traversed with sg_next(), so callers may pass a list
+ * assembled with sg_chain().
+ *
+ * Return: on success, the number of scatterlist entries used; the
+ * last used entry is marked with sg_mark_end().  On failure, a
+ * negative errno.
+ */
+int xdr_buf_to_sg(const struct xdr_buf *buf, unsigned int offset,
+		  unsigned int len, struct scatterlist *sg, unsigned int nsg)
+{
+	unsigned int page_len, thislen, page_offset;
+	struct scatterlist *cur = sg, *prev = NULL;
+	int nents = 0;
+	int i;
+
+	if (len == 0)
+		return 0;
+
+	if (offset >= buf->head[0].iov_len) {
+		offset -= buf->head[0].iov_len;
+	} else {
+		thislen = min_t(unsigned int,
+				buf->head[0].iov_len - offset, len);
+		if (nents >= nsg)
+			return -ENOSPC;
+		sg_set_buf(cur, buf->head[0].iov_base + offset,
+			   thislen);
+		prev = cur;
+		cur = sg_next(cur);
+		nents++;
+		len -= thislen;
+		offset = 0;
+	}
+	if (len == 0)
+		goto done;
+
+	if (offset >= buf->page_len) {
+		offset -= buf->page_len;
+	} else {
+		page_len = min(buf->page_len - offset, len);
+		len -= page_len;
+		page_offset = (offset + buf->page_base) & (PAGE_SIZE - 1);
+		i = (offset + buf->page_base) >> PAGE_SHIFT;
+		thislen = PAGE_SIZE - page_offset;
+		do {
+			if (thislen > page_len)
+				thislen = page_len;
+			if (nents >= nsg)
+				return -ENOSPC;
+			sg_set_page(cur, buf->pages[i],
+				    thislen, page_offset);
+			prev = cur;
+			cur = sg_next(cur);
+			nents++;
+			page_len -= thislen;
+			i++;
+			page_offset = 0;
+			thislen = PAGE_SIZE;
+		} while (page_len != 0);
+		offset = 0;
+	}
+	if (len == 0)
+		goto done;
+
+	if (offset < buf->tail[0].iov_len) {
+		thislen = min_t(unsigned int,
+				buf->tail[0].iov_len - offset, len);
+		if (nents >= nsg)
+			return -ENOSPC;
+		sg_set_buf(cur, buf->tail[0].iov_base + offset,
+			   thislen);
+		prev = cur;
+		nents++;
+		len -= thislen;
+	}
+	if (len != 0)
+		return -EINVAL;
+
+done:
+	if (prev)
+		sg_mark_end(prev);
+	return nents;
+}
+EXPORT_SYMBOL_GPL(xdr_buf_to_sg);
+
+/*
+ * Count the scatterlist entries needed to cover [offset, offset + len)
+ * within @buf.  Mirrors the walk in xdr_buf_to_sg() so the caller can
+ * size an allocation that matches the requested sub-range rather than
+ * the full xdr_buf.
+ */
+static unsigned int xdr_buf_sg_nents(const struct xdr_buf *buf,
+				     unsigned int offset, unsigned int len)
+{
+	unsigned int nsg = 0, thislen, page_offset;
+
+	if (len == 0)
+		return 0;
+
+	if (offset < buf->head[0].iov_len) {
+		thislen = min_t(unsigned int,
+				buf->head[0].iov_len - offset, len);
+		nsg++;
+		len -= thislen;
+		offset = 0;
+	} else {
+		offset -= buf->head[0].iov_len;
+	}
+	if (len == 0)
+		return nsg;
+
+	if (offset < buf->page_len) {
+		thislen = min(buf->page_len - offset, len);
+		page_offset = (offset + buf->page_base) & (PAGE_SIZE - 1);
+		nsg += DIV_ROUND_UP(page_offset + thislen, PAGE_SIZE);
+		len -= thislen;
+		offset = 0;
+	} else {
+		offset -= buf->page_len;
+	}
+	if (len == 0)
+		return nsg;
+
+	if (offset < buf->tail[0].iov_len)
+		nsg++;
+	return nsg;
+}
+
+/**
+ * xdr_buf_to_sg_alloc - Populate a scatterlist for an xdr_buf range
+ * @buf: xdr_buf to map
+ * @offset: starting byte offset within @buf
+ * @len: number of bytes to cover
+ * @sg_head: caller-provided scatterlist array (typically stack-allocated)
+ * @sg_head_nents: number of entries in @sg_head
+ * @sg_overflow: OUT: chained extension, or NULL when @sg_head sufficed
+ * @gfp: memory allocation flags for overflow
+ *
+ * Populates @sg_head directly when the xdr_buf fits.  When more
+ * entries are needed, an overflow scatterlist is allocated and
+ * chained from @sg_head so that the result is traversable with
+ * sg_next().
+ *
+ * Return: on success, the number of populated scatterlist entries
+ * (counting only data entries, not chain entries).  @sg_head is
+ * the head of the resulting list.  Caller must kfree @sg_overflow
+ * when done.  On failure, a negative errno.
+ */
+int xdr_buf_to_sg_alloc(const struct xdr_buf *buf, unsigned int offset,
+			unsigned int len, struct scatterlist *sg_head,
+			unsigned int sg_head_nents,
+			struct scatterlist **sg_overflow, gfp_t gfp)
+{
+	unsigned int nsg;
+	int ret;
+
+	*sg_overflow = NULL;
+	if (len == 0)
+		return 0;
+
+	nsg = xdr_buf_sg_nents(buf, offset, len);
+	if (nsg == 0)
+		return -EINVAL;
+
+	if (nsg <= sg_head_nents) {
+		sg_init_table(sg_head, nsg);
+	} else {
+		/* +1 replaces the slot sg_chain() consumes as the link. */
+		unsigned int overflow_nents = nsg - sg_head_nents + 1;
+		struct scatterlist *overflow;
+
+		overflow = kmalloc_array(overflow_nents, sizeof(*overflow),
+					 gfp);
+		if (!overflow)
+			return -ENOMEM;
+
+		sg_init_table(sg_head, sg_head_nents);
+		sg_init_table(overflow, overflow_nents);
+		sg_chain(sg_head, sg_head_nents, overflow);
+		*sg_overflow = overflow;
+	}
+
+	ret = xdr_buf_to_sg(buf, offset, len, sg_head, nsg);
+	if (ret < 0) {
+		kfree(*sg_overflow);
+		*sg_overflow = NULL;
+	}
+	return ret;
+}
+EXPORT_SYMBOL_GPL(xdr_buf_to_sg_alloc);
+
 /**
  * xdr_inline_pages - Prepare receive buffer for a large reply
  * @xdr: xdr_buf into which reply will be placed

-- 
2.53.0


^ permalink raw reply related	[flat|nested] 21+ messages in thread

* [PATCH 04/18] SUNRPC: Add errno-to-GSS status conversion helper
  2026-04-27 13:50 [PATCH 00/18] Migrate rpcsec_gss_krb5 to the crypto/krb5 library Chuck Lever
                   ` (2 preceding siblings ...)
  2026-04-27 13:50 ` [PATCH 03/18] SUNRPC: Add helpers to convert xdr_buf byte ranges to scatterlists Chuck Lever
@ 2026-04-27 13:50 ` Chuck Lever
  2026-04-27 13:50 ` [PATCH 05/18] SUNRPC: Prepare crypto/krb5 encryption and checksum handles Chuck Lever
                   ` (14 subsequent siblings)
  18 siblings, 0 replies; 21+ messages in thread
From: Chuck Lever @ 2026-04-27 13:50 UTC (permalink / raw)
  To: Trond Myklebust, Anna Schumaker, Chuck Lever, Jeff Layton,
	NeilBrown, Olga Kornievskaia, Dai Ngo, Tom Talpey,
	David S. Miller, Eric Dumazet, Jakub Kicinski, Paolo Abeni,
	Simon Horman
  Cc: linux-nfs, netdev, linux-kernel, Herbert Xu, David Howells,
	Simo Sorce

From: Chuck Lever <chuck.lever@oracle.com>

The crypto/krb5 library returns standard negative errno values,
but the GSS mechanism layer reports results as GSS_S_* major
status codes. A translation is needed at each call site that
will be switched to the new library.

Rather than open-coding the mapping in every wrapper, provide a
single helper function.

Signed-off-by: Chuck Lever <chuck.lever@oracle.com>
---
 net/sunrpc/auth_gss/gss_krb5_internal.h |  2 ++
 net/sunrpc/auth_gss/gss_krb5_mech.c     | 24 ++++++++++++++++++++++++
 2 files changed, 26 insertions(+)

diff --git a/net/sunrpc/auth_gss/gss_krb5_internal.h b/net/sunrpc/auth_gss/gss_krb5_internal.h
index 11402c3b4972..a3fe4be3b9ae 100644
--- a/net/sunrpc/auth_gss/gss_krb5_internal.h
+++ b/net/sunrpc/auth_gss/gss_krb5_internal.h
@@ -180,6 +180,8 @@ u32 krb5_etm_encrypt(struct krb5_ctx *kctx, u32 offset, struct xdr_buf *buf,
 u32 krb5_etm_decrypt(struct krb5_ctx *kctx, u32 offset, u32 len,
 		     struct xdr_buf *buf, u32 *headskip, u32 *tailskip);
 
+u32 gss_krb5_errno_to_status(int err);
+
 #if IS_ENABLED(CONFIG_KUNIT)
 void krb5_nfold(u32 inbits, const u8 *in, u32 outbits, u8 *out);
 const struct gss_krb5_enctype *gss_krb5_lookup_enctype(u32 etype);
diff --git a/net/sunrpc/auth_gss/gss_krb5_mech.c b/net/sunrpc/auth_gss/gss_krb5_mech.c
index 060d8fc4358e..7606bbd7b8c4 100644
--- a/net/sunrpc/auth_gss/gss_krb5_mech.c
+++ b/net/sunrpc/auth_gss/gss_krb5_mech.c
@@ -516,6 +516,30 @@ gss_krb5_delete_sec_context(void *internal_ctx)
 	kfree(kctx);
 }
 
+/**
+ * gss_krb5_errno_to_status - Map a negative errno to a GSS major status
+ * @err: negative errno value, or zero
+ *
+ * Returns:
+ *   %GSS_S_COMPLETE if @err is zero
+ *   %GSS_S_BAD_SIG if @err is -EBADMSG (integrity check failure)
+ *   %GSS_S_DEFECTIVE_TOKEN if @err is -EPROTO (malformed token)
+ *   %GSS_S_FAILURE for all other negative values
+ */
+u32 gss_krb5_errno_to_status(int err)
+{
+	switch (err) {
+	case 0:
+		return GSS_S_COMPLETE;
+	case -EBADMSG:
+		return GSS_S_BAD_SIG;
+	case -EPROTO:
+		return GSS_S_DEFECTIVE_TOKEN;
+	default:
+		return GSS_S_FAILURE;
+	}
+}
+
 /**
  * gss_krb5_get_mic - get_mic for the Kerberos GSS mechanism
  * @gctx: GSS context

-- 
2.53.0


^ permalink raw reply related	[flat|nested] 21+ messages in thread

* [PATCH 05/18] SUNRPC: Prepare crypto/krb5 encryption and checksum handles
  2026-04-27 13:50 [PATCH 00/18] Migrate rpcsec_gss_krb5 to the crypto/krb5 library Chuck Lever
                   ` (3 preceding siblings ...)
  2026-04-27 13:50 ` [PATCH 04/18] SUNRPC: Add errno-to-GSS status conversion helper Chuck Lever
@ 2026-04-27 13:50 ` Chuck Lever
  2026-04-27 13:50 ` [PATCH 06/18] SUNRPC: Switch wrap token encryption to crypto/krb5 Chuck Lever
                   ` (13 subsequent siblings)
  18 siblings, 0 replies; 21+ messages in thread
From: Chuck Lever @ 2026-04-27 13:50 UTC (permalink / raw)
  To: Trond Myklebust, Anna Schumaker, Chuck Lever, Jeff Layton,
	NeilBrown, Olga Kornievskaia, Dai Ngo, Tom Talpey,
	David S. Miller, Eric Dumazet, Jakub Kicinski, Paolo Abeni,
	Simon Horman
  Cc: linux-nfs, netdev, linux-kernel, Herbert Xu, David Howells,
	Simo Sorce

From: Chuck Lever <chuck.lever@oracle.com>

Allocate crypto_aead handles for encryption (one per direction)
and crypto_shash handles for checksumming (one per direction)
using the crypto/krb5 library's key preparation functions.

These four handles derive their subkeys from the session key
and the RFC 4121 usage numbers and are ready for use in
encrypt, decrypt, get_mic, and verify_mic operations.

The existing crypto_sync_skcipher and crypto_ahash handles
remain in place for now; subsequent patches switch the
per-message operations to the new handles and then remove
the old ones.

Signed-off-by: Chuck Lever <chuck.lever@oracle.com>
---
 net/sunrpc/auth_gss/gss_krb5_internal.h |  4 +++
 net/sunrpc/auth_gss/gss_krb5_mech.c     | 45 +++++++++++++++++++++++++++++++++
 2 files changed, 49 insertions(+)

diff --git a/net/sunrpc/auth_gss/gss_krb5_internal.h b/net/sunrpc/auth_gss/gss_krb5_internal.h
index a3fe4be3b9ae..33d41d972bd1 100644
--- a/net/sunrpc/auth_gss/gss_krb5_internal.h
+++ b/net/sunrpc/auth_gss/gss_krb5_internal.h
@@ -65,6 +65,10 @@ struct krb5_ctx {
 	u32			flags;
 	const struct gss_krb5_enctype *gk5e; /* enctype-specific info */
 	const struct krb5_enctype *krb5e; /* crypto/krb5 enctype */
+	struct crypto_aead	*initiator_enc_aead;
+	struct crypto_aead	*acceptor_enc_aead;
+	struct crypto_shash	*initiator_sign_shash;
+	struct crypto_shash	*acceptor_sign_shash;
 	struct crypto_sync_skcipher *enc;
 	struct crypto_sync_skcipher *seq;
 	struct crypto_sync_skcipher *acceptor_enc;
diff --git a/net/sunrpc/auth_gss/gss_krb5_mech.c b/net/sunrpc/auth_gss/gss_krb5_mech.c
index 7606bbd7b8c4..35189c57fd0c 100644
--- a/net/sunrpc/auth_gss/gss_krb5_mech.c
+++ b/net/sunrpc/auth_gss/gss_krb5_mech.c
@@ -300,6 +300,10 @@ gss_krb5_import_ctx_v2(struct krb5_ctx *ctx, gfp_t gfp_mask)
 		.len	= ctx->gk5e->keylength,
 		.data	= ctx->Ksess,
 	};
+	struct krb5_buffer TK = {
+		.len	= ctx->gk5e->keylength,
+		.data	= ctx->Ksess,
+	};
 	struct xdr_netobj keyout;
 	int ret = -EINVAL;
 
@@ -374,12 +378,49 @@ gss_krb5_import_ctx_v2(struct krb5_ctx *ctx, gfp_t gfp_mask)
 	if (ctx->acceptor_integ == NULL)
 		goto out_free;
 
+	ctx->initiator_enc_aead =
+		crypto_krb5_prepare_encryption(ctx->krb5e, &TK,
+					       KG_USAGE_INITIATOR_SEAL,
+					       gfp_mask);
+	if (IS_ERR(ctx->initiator_enc_aead)) {
+		ret = PTR_ERR(ctx->initiator_enc_aead);
+		goto out_free;
+	}
+	ctx->acceptor_enc_aead =
+		crypto_krb5_prepare_encryption(ctx->krb5e, &TK,
+					       KG_USAGE_ACCEPTOR_SEAL,
+					       gfp_mask);
+	if (IS_ERR(ctx->acceptor_enc_aead)) {
+		ret = PTR_ERR(ctx->acceptor_enc_aead);
+		goto out_free;
+	}
+	ctx->initiator_sign_shash =
+		crypto_krb5_prepare_checksum(ctx->krb5e, &TK,
+					     KG_USAGE_INITIATOR_SIGN,
+					     gfp_mask);
+	if (IS_ERR(ctx->initiator_sign_shash)) {
+		ret = PTR_ERR(ctx->initiator_sign_shash);
+		goto out_free;
+	}
+	ctx->acceptor_sign_shash =
+		crypto_krb5_prepare_checksum(ctx->krb5e, &TK,
+					     KG_USAGE_ACCEPTOR_SIGN,
+					     gfp_mask);
+	if (IS_ERR(ctx->acceptor_sign_shash)) {
+		ret = PTR_ERR(ctx->acceptor_sign_shash);
+		goto out_free;
+	}
+
 	ret = 0;
 out:
 	kfree_sensitive(keyout.data);
 	return ret;
 
 out_free:
+	crypto_free_shash(ctx->acceptor_sign_shash);
+	crypto_free_shash(ctx->initiator_sign_shash);
+	crypto_free_aead(ctx->acceptor_enc_aead);
+	crypto_free_aead(ctx->initiator_enc_aead);
 	crypto_free_ahash(ctx->acceptor_integ);
 	crypto_free_ahash(ctx->initiator_integ);
 	crypto_free_ahash(ctx->acceptor_sign);
@@ -502,6 +543,10 @@ gss_krb5_delete_sec_context(void *internal_ctx)
 {
 	struct krb5_ctx *kctx = internal_ctx;
 
+	crypto_free_shash(kctx->acceptor_sign_shash);
+	crypto_free_shash(kctx->initiator_sign_shash);
+	crypto_free_aead(kctx->acceptor_enc_aead);
+	crypto_free_aead(kctx->initiator_enc_aead);
 	crypto_free_sync_skcipher(kctx->seq);
 	crypto_free_sync_skcipher(kctx->enc);
 	crypto_free_sync_skcipher(kctx->acceptor_enc);

-- 
2.53.0


^ permalink raw reply related	[flat|nested] 21+ messages in thread

* [PATCH 06/18] SUNRPC: Switch wrap token encryption to crypto/krb5
  2026-04-27 13:50 [PATCH 00/18] Migrate rpcsec_gss_krb5 to the crypto/krb5 library Chuck Lever
                   ` (4 preceding siblings ...)
  2026-04-27 13:50 ` [PATCH 05/18] SUNRPC: Prepare crypto/krb5 encryption and checksum handles Chuck Lever
@ 2026-04-27 13:50 ` Chuck Lever
  2026-04-27 13:50 ` [PATCH 07/18] SUNRPC: Switch wrap token decryption " Chuck Lever
                   ` (12 subsequent siblings)
  18 siblings, 0 replies; 21+ messages in thread
From: Chuck Lever @ 2026-04-27 13:50 UTC (permalink / raw)
  To: Trond Myklebust, Anna Schumaker, Chuck Lever, Jeff Layton,
	NeilBrown, Olga Kornievskaia, Dai Ngo, Tom Talpey,
	David S. Miller, Eric Dumazet, Jakub Kicinski, Paolo Abeni,
	Simon Horman
  Cc: linux-nfs, netdev, linux-kernel, Herbert Xu, David Howells,
	Simo Sorce

From: Chuck Lever <chuck.lever@oracle.com>

Replace the per-enctype .encrypt callbacks (gss_krb5_aes_encrypt and
krb5_etm_encrypt) with a single gss_krb5_aead_encrypt() wrapper that
delegates to crypto_krb5_encrypt().

The xdr_buf setup -- GSS header insertion, confounder space
allocation, and token header copy -- remains unchanged. The
difference is that the CBC-CTS encryption and HMAC computation are
now a single AEAD operation through the crypto/krb5 library. Both
the MtE construction (RFC 3962) and the EtM construction (RFC 8009)
are handled transparently by the AEAD transform.

The plaintext page data must be copied from the page cache pages to
the scratch output pages before building the scatterlist, since the
AEAD operates in-place rather than using separate input and output
scatterlists.

Signed-off-by: Chuck Lever <chuck.lever@oracle.com>
---
 net/sunrpc/auth_gss/gss_krb5_crypto.c   | 97 +++++++++++++++++++++++++++++++++
 net/sunrpc/auth_gss/gss_krb5_internal.h |  5 ++
 net/sunrpc/auth_gss/gss_krb5_mech.c     | 12 ++--
 3 files changed, 108 insertions(+), 6 deletions(-)

diff --git a/net/sunrpc/auth_gss/gss_krb5_crypto.c b/net/sunrpc/auth_gss/gss_krb5_crypto.c
index 16dcf115de1e..85425d4a28c2 100644
--- a/net/sunrpc/auth_gss/gss_krb5_crypto.c
+++ b/net/sunrpc/auth_gss/gss_krb5_crypto.c
@@ -953,3 +953,100 @@ krb5_etm_decrypt(struct krb5_ctx *kctx, u32 offset, u32 len,
 		ret = GSS_S_FAILURE;
 	return ret;
 }
+
+/**
+ * gss_krb5_aead_encrypt - Encrypt a wrap token using crypto/krb5
+ * @kctx: Kerberos context
+ * @offset: byte offset of the GSS token header in @buf
+ * @buf: OUT: send buffer
+ * @pages: plaintext payload pages (page cache data)
+ *
+ * The xdr_buf setup mirrors the original per-enctype encrypt
+ * functions, but the CBC-CTS encryption and HMAC are replaced
+ * by a single AEAD operation through the crypto/krb5 library.
+ *
+ * Return values:
+ *   %GSS_S_COMPLETE: Encryption successful
+ *   %GSS_S_FAILURE: Encryption failed
+ */
+u32
+gss_krb5_aead_encrypt(struct krb5_ctx *kctx, u32 offset,
+		      struct xdr_buf *buf, struct page **pages)
+{
+	const struct krb5_enctype *krb5 = kctx->krb5e;
+	struct crypto_aead *aead = kctx->initiate ?
+		kctx->initiator_enc_aead : kctx->acceptor_enc_aead;
+	unsigned int conflen = krb5->conf_len;
+	unsigned int cksum_len = krb5->cksum_len;
+	unsigned int sec_offset, sec_len, data_len;
+	struct scatterlist sg[XDR_BUF_TO_SG_NENTS];
+	struct scatterlist *sg_overflow = NULL;
+	ssize_t ret;
+	int nsg;
+
+	/* Insert space for the confounder */
+	if (xdr_extend_head(buf, offset + GSS_KRB5_TOK_HDR_LEN, conflen))
+		return GSS_S_FAILURE;
+
+	/* Ensure a tail segment exists */
+	if (buf->tail[0].iov_base == NULL) {
+		buf->tail[0].iov_base = buf->head[0].iov_base
+						+ buf->head[0].iov_len;
+		buf->tail[0].iov_len = 0;
+	}
+
+	/* Append a copy of the plaintext GSS token header (RFC 4121 Sec 4.2.4) */
+	memcpy(buf->tail[0].iov_base + buf->tail[0].iov_len,
+	       buf->head[0].iov_base + offset, GSS_KRB5_TOK_HDR_LEN);
+	buf->tail[0].iov_len += GSS_KRB5_TOK_HDR_LEN;
+	buf->len += GSS_KRB5_TOK_HDR_LEN;
+
+	/* Reserve space for the integrity checksum */
+	buf->tail[0].iov_len += cksum_len;
+	buf->len += cksum_len;
+
+	/*
+	 * The AEAD operates in-place, but on the client send path the
+	 * plaintext payload lives in page cache pages that must not be
+	 * modified.  Copy the payload into the scratch output pages
+	 * first.  On the server send path @pages and buf->pages are
+	 * the same array, and no copy is needed.
+	 *
+	 * Both arrays share buf->page_base, so the same index and
+	 * intra-page offset address corresponding data in each.
+	 */
+	if (pages != buf->pages) {
+		unsigned int poff = buf->page_base;
+		unsigned int plen = buf->page_len;
+		unsigned int i = poff >> PAGE_SHIFT;
+		unsigned int off = offset_in_page(poff);
+
+		while (plen) {
+			unsigned int n = min_t(unsigned int, plen,
+					       PAGE_SIZE - off);
+			memcpy_page(buf->pages[i], off, pages[i], off, n);
+			plen -= n;
+			i++;
+			off = 0;
+		}
+	}
+
+	/* Build scatterlist covering the secured region */
+	sec_offset = offset + GSS_KRB5_TOK_HDR_LEN;
+	sec_len = buf->len - sec_offset;
+	data_len = sec_len - conflen - cksum_len;
+
+	nsg = xdr_buf_to_sg_alloc(buf, sec_offset, sec_len,
+				  sg, ARRAY_SIZE(sg),
+				  &sg_overflow, GFP_NOFS);
+	if (nsg < 0)
+		return GSS_S_FAILURE;
+
+	ret = crypto_krb5_encrypt(krb5, aead, sg, nsg, sec_len,
+				  conflen, data_len, false);
+	kfree(sg_overflow);
+	if (ret < 0)
+		return GSS_S_FAILURE;
+
+	return GSS_S_COMPLETE;
+}
diff --git a/net/sunrpc/auth_gss/gss_krb5_internal.h b/net/sunrpc/auth_gss/gss_krb5_internal.h
index 33d41d972bd1..ce43e1be7577 100644
--- a/net/sunrpc/auth_gss/gss_krb5_internal.h
+++ b/net/sunrpc/auth_gss/gss_krb5_internal.h
@@ -186,6 +186,11 @@ u32 krb5_etm_decrypt(struct krb5_ctx *kctx, u32 offset, u32 len,
 
 u32 gss_krb5_errno_to_status(int err);
 
+u32 gss_krb5_aead_encrypt(struct krb5_ctx *kctx, u32 offset,
+			  struct xdr_buf *buf, struct page **pages);
+u32 gss_krb5_aead_decrypt(struct krb5_ctx *kctx, u32 offset, u32 len,
+			  struct xdr_buf *buf, u32 *headskip, u32 *tailskip);
+
 #if IS_ENABLED(CONFIG_KUNIT)
 void krb5_nfold(u32 inbits, const u8 *in, u32 outbits, u8 *out);
 const struct gss_krb5_enctype *gss_krb5_lookup_enctype(u32 etype);
diff --git a/net/sunrpc/auth_gss/gss_krb5_mech.c b/net/sunrpc/auth_gss/gss_krb5_mech.c
index 35189c57fd0c..6cd7eb203350 100644
--- a/net/sunrpc/auth_gss/gss_krb5_mech.c
+++ b/net/sunrpc/auth_gss/gss_krb5_mech.c
@@ -43,7 +43,7 @@ static const struct gss_krb5_enctype supported_gss_krb5_enctypes[] = {
 	  .aux_cipher = "cbc(aes)",
 	  .cksum_name = "hmac(sha1)",
 	  .derive_key = krb5_derive_key_v2,
-	  .encrypt = gss_krb5_aes_encrypt,
+	  .encrypt = gss_krb5_aead_encrypt,
 	  .decrypt = gss_krb5_aes_decrypt,
 
 	  .get_mic = gss_krb5_get_mic_v2,
@@ -72,7 +72,7 @@ static const struct gss_krb5_enctype supported_gss_krb5_enctypes[] = {
 	  .aux_cipher = "cbc(aes)",
 	  .cksum_name = "hmac(sha1)",
 	  .derive_key = krb5_derive_key_v2,
-	  .encrypt = gss_krb5_aes_encrypt,
+	  .encrypt = gss_krb5_aead_encrypt,
 	  .decrypt = gss_krb5_aes_decrypt,
 
 	  .get_mic = gss_krb5_get_mic_v2,
@@ -111,7 +111,7 @@ static const struct gss_krb5_enctype supported_gss_krb5_enctypes[] = {
 		.Ki_length	= BITS2OCTETS(128),
 
 		.derive_key	= krb5_kdf_feedback_cmac,
-		.encrypt	= gss_krb5_aes_encrypt,
+		.encrypt	= gss_krb5_aead_encrypt,
 		.decrypt	= gss_krb5_aes_decrypt,
 
 		.get_mic	= gss_krb5_get_mic_v2,
@@ -137,7 +137,7 @@ static const struct gss_krb5_enctype supported_gss_krb5_enctypes[] = {
 		.Ki_length	= BITS2OCTETS(256),
 
 		.derive_key	= krb5_kdf_feedback_cmac,
-		.encrypt	= gss_krb5_aes_encrypt,
+		.encrypt	= gss_krb5_aead_encrypt,
 		.decrypt	= gss_krb5_aes_decrypt,
 
 		.get_mic	= gss_krb5_get_mic_v2,
@@ -166,7 +166,7 @@ static const struct gss_krb5_enctype supported_gss_krb5_enctypes[] = {
 		.Ki_length	= BITS2OCTETS(128),
 
 		.derive_key	= krb5_kdf_hmac_sha2,
-		.encrypt	= krb5_etm_encrypt,
+		.encrypt	= gss_krb5_aead_encrypt,
 		.decrypt	= krb5_etm_decrypt,
 
 		.get_mic	= gss_krb5_get_mic_v2,
@@ -192,7 +192,7 @@ static const struct gss_krb5_enctype supported_gss_krb5_enctypes[] = {
 		.Ki_length	= BITS2OCTETS(192),
 
 		.derive_key	= krb5_kdf_hmac_sha2,
-		.encrypt	= krb5_etm_encrypt,
+		.encrypt	= gss_krb5_aead_encrypt,
 		.decrypt	= krb5_etm_decrypt,
 
 		.get_mic	= gss_krb5_get_mic_v2,

-- 
2.53.0


^ permalink raw reply related	[flat|nested] 21+ messages in thread

* [PATCH 07/18] SUNRPC: Switch wrap token decryption to crypto/krb5
  2026-04-27 13:50 [PATCH 00/18] Migrate rpcsec_gss_krb5 to the crypto/krb5 library Chuck Lever
                   ` (5 preceding siblings ...)
  2026-04-27 13:50 ` [PATCH 06/18] SUNRPC: Switch wrap token encryption to crypto/krb5 Chuck Lever
@ 2026-04-27 13:50 ` Chuck Lever
  2026-04-27 13:50 ` [PATCH 08/18] SUNRPC: Switch Camellia decrypt " Chuck Lever
                   ` (11 subsequent siblings)
  18 siblings, 0 replies; 21+ messages in thread
From: Chuck Lever @ 2026-04-27 13:50 UTC (permalink / raw)
  To: Trond Myklebust, Anna Schumaker, Chuck Lever, Jeff Layton,
	NeilBrown, Olga Kornievskaia, Dai Ngo, Tom Talpey,
	David S. Miller, Eric Dumazet, Jakub Kicinski, Paolo Abeni,
	Simon Horman
  Cc: linux-nfs, netdev, linux-kernel, Herbert Xu, David Howells,
	Simo Sorce

From: Chuck Lever <chuck.lever@oracle.com>

Replace the per-enctype .decrypt callbacks (gss_krb5_aes_decrypt
and krb5_etm_decrypt) with a single gss_krb5_aead_decrypt()
wrapper that delegates to crypto_krb5_decrypt().

The new wrapper builds a scatterlist covering the secured
region (confounder through checksum), passes it to the AEAD
decrypt operation, and derives the confounder and checksum
lengths from the data offset and length that
crypto_krb5_decrypt() reports. The caller's token header
verification and buffer adjustment logic is unchanged.

Signed-off-by: Chuck Lever <chuck.lever@oracle.com>
---
 net/sunrpc/auth_gss/gss_krb5_crypto.c | 53 +++++++++++++++++++++++++++++++++++
 net/sunrpc/auth_gss/gss_krb5_mech.c   |  8 +++---
 2 files changed, 57 insertions(+), 4 deletions(-)

diff --git a/net/sunrpc/auth_gss/gss_krb5_crypto.c b/net/sunrpc/auth_gss/gss_krb5_crypto.c
index 85425d4a28c2..31c2c86b873f 100644
--- a/net/sunrpc/auth_gss/gss_krb5_crypto.c
+++ b/net/sunrpc/auth_gss/gss_krb5_crypto.c
@@ -1050,3 +1050,56 @@ gss_krb5_aead_encrypt(struct krb5_ctx *kctx, u32 offset,
 
 	return GSS_S_COMPLETE;
 }
+
+/**
+ * gss_krb5_aead_decrypt - Decrypt a wrap token using crypto/krb5
+ * @kctx: Kerberos context
+ * @offset: byte offset of the GSS token header in @buf
+ * @len: total length of the GSS token
+ * @buf: ciphertext buffer, decrypted in-place
+ * @headskip: OUT: confounder length, in octets
+ * @tailskip: OUT: checksum length, in octets
+ *
+ * Return values:
+ *   %GSS_S_COMPLETE: Decryption and integrity verification succeeded
+ *   %GSS_S_BAD_SIG: Integrity checksum did not match
+ *   %GSS_S_DEFECTIVE_TOKEN: Token is malformed or truncated
+ *   %GSS_S_FAILURE: Decryption failed
+ */
+u32
+gss_krb5_aead_decrypt(struct krb5_ctx *kctx, u32 offset, u32 len,
+		      struct xdr_buf *buf, u32 *headskip, u32 *tailskip)
+{
+	const struct krb5_enctype *krb5 = kctx->krb5e;
+	struct crypto_aead *aead = kctx->initiate ?
+		kctx->acceptor_enc_aead : kctx->initiator_enc_aead;
+	unsigned int sec_offset, sec_len;
+	size_t data_offset, data_len;
+	struct scatterlist sg[XDR_BUF_TO_SG_NENTS];
+	struct scatterlist *sg_overflow = NULL;
+	int nsg, ret;
+
+	/* Secured region starts after the GSS token header */
+	sec_offset = offset + GSS_KRB5_TOK_HDR_LEN;
+	if (len < sec_offset)
+		return GSS_S_DEFECTIVE_TOKEN;
+	sec_len = len - sec_offset;
+
+	nsg = xdr_buf_to_sg_alloc(buf, sec_offset, sec_len,
+				  sg, ARRAY_SIZE(sg),
+				  &sg_overflow, GFP_NOFS);
+	if (nsg < 0)
+		return GSS_S_FAILURE;
+
+	data_offset = 0;
+	data_len = sec_len;
+	ret = crypto_krb5_decrypt(krb5, aead, sg, nsg,
+				  &data_offset, &data_len);
+	kfree(sg_overflow);
+	if (ret < 0)
+		return gss_krb5_errno_to_status(ret);
+
+	*headskip = data_offset;
+	*tailskip = sec_len - data_offset - data_len;
+	return GSS_S_COMPLETE;
+}
diff --git a/net/sunrpc/auth_gss/gss_krb5_mech.c b/net/sunrpc/auth_gss/gss_krb5_mech.c
index 6cd7eb203350..66372e152c3b 100644
--- a/net/sunrpc/auth_gss/gss_krb5_mech.c
+++ b/net/sunrpc/auth_gss/gss_krb5_mech.c
@@ -44,7 +44,7 @@ static const struct gss_krb5_enctype supported_gss_krb5_enctypes[] = {
 	  .cksum_name = "hmac(sha1)",
 	  .derive_key = krb5_derive_key_v2,
 	  .encrypt = gss_krb5_aead_encrypt,
-	  .decrypt = gss_krb5_aes_decrypt,
+	  .decrypt = gss_krb5_aead_decrypt,
 
 	  .get_mic = gss_krb5_get_mic_v2,
 	  .verify_mic = gss_krb5_verify_mic_v2,
@@ -73,7 +73,7 @@ static const struct gss_krb5_enctype supported_gss_krb5_enctypes[] = {
 	  .cksum_name = "hmac(sha1)",
 	  .derive_key = krb5_derive_key_v2,
 	  .encrypt = gss_krb5_aead_encrypt,
-	  .decrypt = gss_krb5_aes_decrypt,
+	  .decrypt = gss_krb5_aead_decrypt,
 
 	  .get_mic = gss_krb5_get_mic_v2,
 	  .verify_mic = gss_krb5_verify_mic_v2,
@@ -167,7 +167,7 @@ static const struct gss_krb5_enctype supported_gss_krb5_enctypes[] = {
 
 		.derive_key	= krb5_kdf_hmac_sha2,
 		.encrypt	= gss_krb5_aead_encrypt,
-		.decrypt	= krb5_etm_decrypt,
+		.decrypt	= gss_krb5_aead_decrypt,
 
 		.get_mic	= gss_krb5_get_mic_v2,
 		.verify_mic	= gss_krb5_verify_mic_v2,
@@ -193,7 +193,7 @@ static const struct gss_krb5_enctype supported_gss_krb5_enctypes[] = {
 
 		.derive_key	= krb5_kdf_hmac_sha2,
 		.encrypt	= gss_krb5_aead_encrypt,
-		.decrypt	= krb5_etm_decrypt,
+		.decrypt	= gss_krb5_aead_decrypt,
 
 		.get_mic	= gss_krb5_get_mic_v2,
 		.verify_mic	= gss_krb5_verify_mic_v2,

-- 
2.53.0


^ permalink raw reply related	[flat|nested] 21+ messages in thread

* [PATCH 08/18] SUNRPC: Switch Camellia decrypt to crypto/krb5
  2026-04-27 13:50 [PATCH 00/18] Migrate rpcsec_gss_krb5 to the crypto/krb5 library Chuck Lever
                   ` (6 preceding siblings ...)
  2026-04-27 13:50 ` [PATCH 07/18] SUNRPC: Switch wrap token decryption " Chuck Lever
@ 2026-04-27 13:50 ` Chuck Lever
  2026-04-27 13:50 ` [PATCH 09/18] SUNRPC: Switch MIC token generation " Chuck Lever
                   ` (10 subsequent siblings)
  18 siblings, 0 replies; 21+ messages in thread
From: Chuck Lever @ 2026-04-27 13:50 UTC (permalink / raw)
  To: Trond Myklebust, Anna Schumaker, Chuck Lever, Jeff Layton,
	NeilBrown, Olga Kornievskaia, Dai Ngo, Tom Talpey,
	David S. Miller, Eric Dumazet, Jakub Kicinski, Paolo Abeni,
	Simon Horman
  Cc: linux-nfs, netdev, linux-kernel, Herbert Xu, David Howells,
	Simo Sorce

From: Chuck Lever <chuck.lever@oracle.com>

The Camellia enctypes (RFC 6803) use the same MtE authenticated
encryption construction as AES-SHA1 (RFC 3962), implemented in
crypto/krb5 by the rfc3961_simplified profile. The encrypt path
already uses gss_krb5_aead_encrypt() for Camellia, but the decrypt
path was left on the old gss_krb5_aes_decrypt() code when the AES
enctypes were migrated.

Switch the Camellia .decrypt callback to gss_krb5_aead_decrypt() to
complete the AEAD migration for all enctypes. The conf_len and
cksum_len values in crypto/krb5's Camellia enctype descriptors match
the block size and checksum length that gss_krb5_aes_decrypt() was
using, so the headskip and tailskip returned to the unwrap layer are
unchanged.

Signed-off-by: Chuck Lever <chuck.lever@oracle.com>
---
 net/sunrpc/auth_gss/gss_krb5_mech.c | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/net/sunrpc/auth_gss/gss_krb5_mech.c b/net/sunrpc/auth_gss/gss_krb5_mech.c
index 66372e152c3b..9a5e367fef5b 100644
--- a/net/sunrpc/auth_gss/gss_krb5_mech.c
+++ b/net/sunrpc/auth_gss/gss_krb5_mech.c
@@ -112,7 +112,7 @@ static const struct gss_krb5_enctype supported_gss_krb5_enctypes[] = {
 
 		.derive_key	= krb5_kdf_feedback_cmac,
 		.encrypt	= gss_krb5_aead_encrypt,
-		.decrypt	= gss_krb5_aes_decrypt,
+		.decrypt	= gss_krb5_aead_decrypt,
 
 		.get_mic	= gss_krb5_get_mic_v2,
 		.verify_mic	= gss_krb5_verify_mic_v2,
@@ -138,7 +138,7 @@ static const struct gss_krb5_enctype supported_gss_krb5_enctypes[] = {
 
 		.derive_key	= krb5_kdf_feedback_cmac,
 		.encrypt	= gss_krb5_aead_encrypt,
-		.decrypt	= gss_krb5_aes_decrypt,
+		.decrypt	= gss_krb5_aead_decrypt,
 
 		.get_mic	= gss_krb5_get_mic_v2,
 		.verify_mic	= gss_krb5_verify_mic_v2,

-- 
2.53.0


^ permalink raw reply related	[flat|nested] 21+ messages in thread

* [PATCH 09/18] SUNRPC: Switch MIC token generation to crypto/krb5
  2026-04-27 13:50 [PATCH 00/18] Migrate rpcsec_gss_krb5 to the crypto/krb5 library Chuck Lever
                   ` (7 preceding siblings ...)
  2026-04-27 13:50 ` [PATCH 08/18] SUNRPC: Switch Camellia decrypt " Chuck Lever
@ 2026-04-27 13:50 ` Chuck Lever
  2026-04-27 13:50 ` [PATCH 10/18] SUNRPC: Switch MIC token verification " Chuck Lever
                   ` (9 subsequent siblings)
  18 siblings, 0 replies; 21+ messages in thread
From: Chuck Lever @ 2026-04-27 13:50 UTC (permalink / raw)
  To: Trond Myklebust, Anna Schumaker, Chuck Lever, Jeff Layton,
	NeilBrown, Olga Kornievskaia, Dai Ngo, Tom Talpey,
	David S. Miller, Eric Dumazet, Jakub Kicinski, Paolo Abeni,
	Simon Horman
  Cc: linux-nfs, netdev, linux-kernel, Herbert Xu, David Howells,
	Simo Sorce

From: Chuck Lever <chuck.lever@oracle.com>

gss_krb5_get_mic_v2() currently computes the MIC checksum by
driving a crypto_ahash directly, calling gss_krb5_checksum()
with the message body and GSS token header. Replace this with
a call to crypto_krb5_get_mic(), which performs the same keyed
hash operation through the crypto/krb5 library.

RFC 4121 Section 4.2.4 specifies that the checksum covers the
message body followed by the token header. Because the
crypto/krb5 metadata parameter is hashed before the data, the
GSS header cannot be passed as metadata. Instead, the header
is appended to the scatterlist after the body data, producing
the correct hash input ordering without using the metadata
parameter.

The scatterlist layout is:
  [checksum_output | message_body | gss_header]

The first scatterlist entry points directly into the
token buffer, so the checksum is written in place.

A shared helper, gss_krb5_mic_build_sg(), is introduced in
gss_krb5_crypto.c to construct this scatterlist layout. The
helper handles overflow allocation and scatterlist chaining
for large xdr_buf page arrays. It is reused by the verify_mic
counterpart in the following commit.

Signed-off-by: Chuck Lever <chuck.lever@oracle.com>
---
 net/sunrpc/auth_gss/gss_krb5_crypto.c   | 82 +++++++++++++++++++++++++++++++++
 net/sunrpc/auth_gss/gss_krb5_internal.h |  6 +++
 net/sunrpc/auth_gss/gss_krb5_seal.c     | 45 +++++++++++++-----
 3 files changed, 121 insertions(+), 12 deletions(-)

diff --git a/net/sunrpc/auth_gss/gss_krb5_crypto.c b/net/sunrpc/auth_gss/gss_krb5_crypto.c
index 31c2c86b873f..3a8e6710a51b 100644
--- a/net/sunrpc/auth_gss/gss_krb5_crypto.c
+++ b/net/sunrpc/auth_gss/gss_krb5_crypto.c
@@ -1103,3 +1103,85 @@ gss_krb5_aead_decrypt(struct krb5_ctx *kctx, u32 offset, u32 len,
 	*tailskip = sec_len - data_offset - data_len;
 	return GSS_S_COMPLETE;
 }
+
+/**
+ * gss_krb5_mic_build_sg - Build scatterlist for MIC token operations
+ * @body: xdr_buf containing the message body
+ * @cksum: pointer to checksum area in the token buffer
+ * @cksum_len: length of checksum area
+ * @hdr: pointer to GSS token header
+ * @sg_head: caller-provided scatterlist array; if more than
+ *	XDR_BUF_TO_SG_NENTS entries are needed, an overflow
+ *	scatterlist is allocated and chained automatically
+ * @sg_overflow: OUT: overflow scatterlist, caller must kfree
+ *
+ * Per RFC 4121 Section 4.2.4, MIC token checksums cover the
+ * message body followed by the token header. The checksum
+ * output or received checksum occupies the first scatterlist
+ * entry.  This layout cannot be constructed by
+ * xdr_buf_to_sg_alloc() because the checksum area and the GSS
+ * header lie outside the xdr_buf.
+ *
+ * Returns the number of scatterlist entries on success, or a
+ * negative errno on failure.
+ */
+int gss_krb5_mic_build_sg(const struct xdr_buf *body,
+			  void *cksum, unsigned int cksum_len,
+			  void *hdr,
+			  struct scatterlist *sg_head,
+			  struct scatterlist **sg_overflow)
+{
+	struct scatterlist *entry;
+	int body_max, body_nsg, nsg;
+
+	*sg_overflow = NULL;
+
+	body_max = 2;
+	if (body->page_len)
+		body_max += DIV_ROUND_UP(body->page_len +
+					 offset_in_page(body->page_base),
+					 PAGE_SIZE);
+	nsg = 1 + body_max + 1;
+	if (nsg <= XDR_BUF_TO_SG_NENTS) {
+		sg_init_table(sg_head, nsg);
+	} else {
+		unsigned int overflow_nents =
+			nsg - XDR_BUF_TO_SG_NENTS + 1;
+
+		*sg_overflow = kmalloc_array(overflow_nents,
+					     sizeof(**sg_overflow),
+					     GFP_NOFS);
+		if (!*sg_overflow)
+			return -ENOMEM;
+
+		sg_init_table(sg_head, XDR_BUF_TO_SG_NENTS);
+		sg_init_table(*sg_overflow, overflow_nents);
+		sg_chain(sg_head, XDR_BUF_TO_SG_NENTS, *sg_overflow);
+	}
+
+	sg_set_buf(&sg_head[0], cksum, cksum_len);
+	body_nsg = xdr_buf_to_sg(body, 0, body->len,
+				 sg_next(&sg_head[0]), body_max);
+	if (body_nsg < 0)
+		goto out_err;
+
+	/*
+	 * xdr_buf_to_sg marks the last body entry as end-of-list;
+	 * clear it so the trailing header entry is reachable.
+	 */
+	if (body_nsg > 0) {
+		entry = sg_last(sg_next(&sg_head[0]), body_nsg);
+		sg_unmark_end(entry);
+		entry = sg_next(entry);
+	} else {
+		entry = sg_next(&sg_head[0]);
+	}
+	sg_set_buf(entry, hdr, GSS_KRB5_TOK_HDR_LEN);
+	sg_mark_end(entry);
+	return 1 + body_nsg + 1;
+
+out_err:
+	kfree(*sg_overflow);
+	*sg_overflow = NULL;
+	return body_nsg;
+}
diff --git a/net/sunrpc/auth_gss/gss_krb5_internal.h b/net/sunrpc/auth_gss/gss_krb5_internal.h
index ce43e1be7577..83e969494b54 100644
--- a/net/sunrpc/auth_gss/gss_krb5_internal.h
+++ b/net/sunrpc/auth_gss/gss_krb5_internal.h
@@ -186,6 +186,12 @@ u32 krb5_etm_decrypt(struct krb5_ctx *kctx, u32 offset, u32 len,
 
 u32 gss_krb5_errno_to_status(int err);
 
+int gss_krb5_mic_build_sg(const struct xdr_buf *body,
+			  void *cksum, unsigned int cksum_len,
+			  void *hdr,
+			  struct scatterlist *sg_head,
+			  struct scatterlist **sg_overflow);
+
 u32 gss_krb5_aead_encrypt(struct krb5_ctx *kctx, u32 offset,
 			  struct xdr_buf *buf, struct page **pages);
 u32 gss_krb5_aead_decrypt(struct krb5_ctx *kctx, u32 offset, u32 len,
diff --git a/net/sunrpc/auth_gss/gss_krb5_seal.c b/net/sunrpc/auth_gss/gss_krb5_seal.c
index ce540df9bce4..66c179337029 100644
--- a/net/sunrpc/auth_gss/gss_krb5_seal.c
+++ b/net/sunrpc/auth_gss/gss_krb5_seal.c
@@ -64,6 +64,8 @@
 #include <linux/random.h>
 #include <linux/crypto.h>
 #include <linux/atomic.h>
+#include <linux/scatterlist.h>
+#include <linux/slab.h>
 
 #include "gss_krb5_internal.h"
 
@@ -78,10 +80,10 @@ setup_token_v2(struct krb5_ctx *ctx, struct xdr_netobj *token)
 	void *krb5_hdr;
 	u8 *p, flags = 0x00;
 
-	if ((ctx->flags & KRB5_CTX_FLAG_INITIATOR) == 0)
-		flags |= 0x01;
+	if (!ctx->initiate)
+		flags |= KG2_TOKEN_FLAG_SENTBYACCEPTOR;
 	if (ctx->flags & KRB5_CTX_FLAG_ACCEPTOR_SUBKEY)
-		flags |= 0x04;
+		flags |= KG2_TOKEN_FLAG_ACCEPTORSUBKEY;
 
 	/* Per rfc 4121, sec 4.2.6.1, there is no header,
 	 * just start the token.
@@ -97,7 +99,7 @@ setup_token_v2(struct krb5_ctx *ctx, struct xdr_netobj *token)
 	*ptr++ = 0xffff;
 	*ptr = 0xffff;
 
-	token->len = GSS_KRB5_TOK_HDR_LEN + ctx->gk5e->cksumlength;
+	token->len = GSS_KRB5_TOK_HDR_LEN + ctx->krb5e->cksum_len;
 	return krb5_hdr;
 }
 
@@ -105,14 +107,17 @@ u32
 gss_krb5_get_mic_v2(struct krb5_ctx *ctx, struct xdr_buf *text,
 		    struct xdr_netobj *token)
 {
-	struct crypto_ahash *tfm = ctx->initiate ?
-				   ctx->initiator_sign : ctx->acceptor_sign;
-	struct xdr_netobj cksumobj = {
-		.len =	ctx->gk5e->cksumlength,
-	};
+	const struct krb5_enctype *krb5 = ctx->krb5e;
+	struct crypto_shash *shash = ctx->initiate ?
+		ctx->initiator_sign_shash : ctx->acceptor_sign_shash;
+	unsigned int cksum_len = krb5->cksum_len;
+	struct scatterlist sg_head[XDR_BUF_TO_SG_NENTS];
+	struct scatterlist *sg_overflow;
 	__be64 seq_send_be64;
 	void *krb5_hdr;
 	time64_t now;
+	ssize_t ret;
+	int nsg;
 
 	dprintk("RPC:       %s\n", __func__);
 
@@ -123,9 +128,25 @@ gss_krb5_get_mic_v2(struct krb5_ctx *ctx, struct xdr_buf *text,
 	seq_send_be64 = cpu_to_be64(atomic64_fetch_inc(&ctx->seq_send64));
 	memcpy(krb5_hdr + 8, (char *) &seq_send_be64, 8);
 
-	cksumobj.data = krb5_hdr + GSS_KRB5_TOK_HDR_LEN;
-	if (gss_krb5_checksum(tfm, krb5_hdr, GSS_KRB5_TOK_HDR_LEN,
-			      text, 0, &cksumobj))
+	/*
+	 * The checksum is written directly into the token buffer.
+	 * This is safe: crypto_krb5_get_mic uses shash (software
+	 * hash), so the scatterlist is never DMA-mapped.
+	 */
+	nsg = gss_krb5_mic_build_sg(text,
+				    krb5_hdr + GSS_KRB5_TOK_HDR_LEN,
+				    cksum_len, krb5_hdr,
+				    sg_head, &sg_overflow);
+	if (nsg < 0)
+		return GSS_S_FAILURE;
+
+	ret = crypto_krb5_get_mic(krb5, shash, NULL, sg_head, nsg,
+				  cksum_len + text->len +
+					GSS_KRB5_TOK_HDR_LEN,
+				  cksum_len,
+				  text->len + GSS_KRB5_TOK_HDR_LEN);
+	kfree(sg_overflow);
+	if (ret < 0)
 		return GSS_S_FAILURE;
 
 	now = ktime_get_real_seconds();

-- 
2.53.0


^ permalink raw reply related	[flat|nested] 21+ messages in thread

* [PATCH 10/18] SUNRPC: Switch MIC token verification to crypto/krb5
  2026-04-27 13:50 [PATCH 00/18] Migrate rpcsec_gss_krb5 to the crypto/krb5 library Chuck Lever
                   ` (8 preceding siblings ...)
  2026-04-27 13:50 ` [PATCH 09/18] SUNRPC: Switch MIC token generation " Chuck Lever
@ 2026-04-27 13:50 ` Chuck Lever
  2026-04-27 13:50 ` [PATCH 11/18] SUNRPC: Remove get_mic/verify_mic function pointers from enctype table Chuck Lever
                   ` (8 subsequent siblings)
  18 siblings, 0 replies; 21+ messages in thread
From: Chuck Lever @ 2026-04-27 13:50 UTC (permalink / raw)
  To: Trond Myklebust, Anna Schumaker, Chuck Lever, Jeff Layton,
	NeilBrown, Olga Kornievskaia, Dai Ngo, Tom Talpey,
	David S. Miller, Eric Dumazet, Jakub Kicinski, Paolo Abeni,
	Simon Horman
  Cc: linux-nfs, netdev, linux-kernel, Herbert Xu, David Howells,
	Simo Sorce

From: Chuck Lever <chuck.lever@oracle.com>

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@oracle.com>
---
 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


^ permalink raw reply related	[flat|nested] 21+ messages in thread

* [PATCH 11/18] SUNRPC: Remove get_mic/verify_mic function pointers from enctype table
  2026-04-27 13:50 [PATCH 00/18] Migrate rpcsec_gss_krb5 to the crypto/krb5 library Chuck Lever
                   ` (9 preceding siblings ...)
  2026-04-27 13:50 ` [PATCH 10/18] SUNRPC: Switch MIC token verification " Chuck Lever
@ 2026-04-27 13:50 ` Chuck Lever
  2026-04-27 13:50 ` [PATCH 12/18] SUNRPC: Remove wrap/unwrap " Chuck Lever
                   ` (7 subsequent siblings)
  18 siblings, 0 replies; 21+ messages in thread
From: Chuck Lever @ 2026-04-27 13:50 UTC (permalink / raw)
  To: Trond Myklebust, Anna Schumaker, Chuck Lever, Jeff Layton,
	NeilBrown, Olga Kornievskaia, Dai Ngo, Tom Talpey,
	David S. Miller, Eric Dumazet, Jakub Kicinski, Paolo Abeni,
	Simon Horman
  Cc: linux-nfs, netdev, linux-kernel, Herbert Xu, David Howells,
	Simo Sorce

From: Chuck Lever <chuck.lever@oracle.com>

Every enctype in the table points .get_mic and .verify_mic at
the same pair of functions. The indirection served no purpose
after the v1 enctype support was removed. Call
gss_krb5_get_mic_v2() and gss_krb5_verify_mic_v2() directly
from the GSS mechanism dispatch and drop the function pointers
from struct gss_krb5_enctype.

Signed-off-by: Chuck Lever <chuck.lever@oracle.com>
---
 net/sunrpc/auth_gss/gss_krb5_internal.h |  4 ----
 net/sunrpc/auth_gss/gss_krb5_mech.c     | 16 ++--------------
 2 files changed, 2 insertions(+), 18 deletions(-)

diff --git a/net/sunrpc/auth_gss/gss_krb5_internal.h b/net/sunrpc/auth_gss/gss_krb5_internal.h
index 83e969494b54..a63f8d465b63 100644
--- a/net/sunrpc/auth_gss/gss_krb5_internal.h
+++ b/net/sunrpc/auth_gss/gss_krb5_internal.h
@@ -44,10 +44,6 @@ struct gss_krb5_enctype {
 		       struct xdr_buf *buf, struct page **pages);
 	u32 (*decrypt)(struct krb5_ctx *kctx, u32 offset, u32 len,
 		       struct xdr_buf *buf, u32 *headskip, u32 *tailskip);
-	u32 (*get_mic)(struct krb5_ctx *kctx, struct xdr_buf *text,
-		       struct xdr_netobj *token);
-	u32 (*verify_mic)(struct krb5_ctx *kctx, struct xdr_buf *message_buffer,
-			  struct xdr_netobj *read_token);
 	u32 (*wrap)(struct krb5_ctx *kctx, int offset,
 		    struct xdr_buf *buf, struct page **pages);
 	u32 (*unwrap)(struct krb5_ctx *kctx, int offset, int len,
diff --git a/net/sunrpc/auth_gss/gss_krb5_mech.c b/net/sunrpc/auth_gss/gss_krb5_mech.c
index 9a5e367fef5b..511e19e0e786 100644
--- a/net/sunrpc/auth_gss/gss_krb5_mech.c
+++ b/net/sunrpc/auth_gss/gss_krb5_mech.c
@@ -46,8 +46,6 @@ static const struct gss_krb5_enctype supported_gss_krb5_enctypes[] = {
 	  .encrypt = gss_krb5_aead_encrypt,
 	  .decrypt = gss_krb5_aead_decrypt,
 
-	  .get_mic = gss_krb5_get_mic_v2,
-	  .verify_mic = gss_krb5_verify_mic_v2,
 	  .wrap = gss_krb5_wrap_v2,
 	  .unwrap = gss_krb5_unwrap_v2,
 
@@ -75,8 +73,6 @@ static const struct gss_krb5_enctype supported_gss_krb5_enctypes[] = {
 	  .encrypt = gss_krb5_aead_encrypt,
 	  .decrypt = gss_krb5_aead_decrypt,
 
-	  .get_mic = gss_krb5_get_mic_v2,
-	  .verify_mic = gss_krb5_verify_mic_v2,
 	  .wrap = gss_krb5_wrap_v2,
 	  .unwrap = gss_krb5_unwrap_v2,
 
@@ -114,8 +110,6 @@ static const struct gss_krb5_enctype supported_gss_krb5_enctypes[] = {
 		.encrypt	= gss_krb5_aead_encrypt,
 		.decrypt	= gss_krb5_aead_decrypt,
 
-		.get_mic	= gss_krb5_get_mic_v2,
-		.verify_mic	= gss_krb5_verify_mic_v2,
 		.wrap		= gss_krb5_wrap_v2,
 		.unwrap		= gss_krb5_unwrap_v2,
 	},
@@ -140,8 +134,6 @@ static const struct gss_krb5_enctype supported_gss_krb5_enctypes[] = {
 		.encrypt	= gss_krb5_aead_encrypt,
 		.decrypt	= gss_krb5_aead_decrypt,
 
-		.get_mic	= gss_krb5_get_mic_v2,
-		.verify_mic	= gss_krb5_verify_mic_v2,
 		.wrap		= gss_krb5_wrap_v2,
 		.unwrap		= gss_krb5_unwrap_v2,
 	},
@@ -169,8 +161,6 @@ static const struct gss_krb5_enctype supported_gss_krb5_enctypes[] = {
 		.encrypt	= gss_krb5_aead_encrypt,
 		.decrypt	= gss_krb5_aead_decrypt,
 
-		.get_mic	= gss_krb5_get_mic_v2,
-		.verify_mic	= gss_krb5_verify_mic_v2,
 		.wrap		= gss_krb5_wrap_v2,
 		.unwrap		= gss_krb5_unwrap_v2,
 	},
@@ -195,8 +185,6 @@ static const struct gss_krb5_enctype supported_gss_krb5_enctypes[] = {
 		.encrypt	= gss_krb5_aead_encrypt,
 		.decrypt	= gss_krb5_aead_decrypt,
 
-		.get_mic	= gss_krb5_get_mic_v2,
-		.verify_mic	= gss_krb5_verify_mic_v2,
 		.wrap		= gss_krb5_wrap_v2,
 		.unwrap		= gss_krb5_unwrap_v2,
 	},
@@ -601,7 +589,7 @@ static u32 gss_krb5_get_mic(struct gss_ctx *gctx, struct xdr_buf *text,
 {
 	struct krb5_ctx *kctx = gctx->internal_ctx_id;
 
-	return kctx->gk5e->get_mic(kctx, text, token);
+	return gss_krb5_get_mic_v2(kctx, text, token);
 }
 
 /**
@@ -623,7 +611,7 @@ static u32 gss_krb5_verify_mic(struct gss_ctx *gctx,
 {
 	struct krb5_ctx *kctx = gctx->internal_ctx_id;
 
-	return kctx->gk5e->verify_mic(kctx, message_buffer, read_token);
+	return gss_krb5_verify_mic_v2(kctx, message_buffer, read_token);
 }
 
 /**

-- 
2.53.0


^ permalink raw reply related	[flat|nested] 21+ messages in thread

* [PATCH 12/18] SUNRPC: Remove wrap/unwrap function pointers from enctype table
  2026-04-27 13:50 [PATCH 00/18] Migrate rpcsec_gss_krb5 to the crypto/krb5 library Chuck Lever
                   ` (10 preceding siblings ...)
  2026-04-27 13:50 ` [PATCH 11/18] SUNRPC: Remove get_mic/verify_mic function pointers from enctype table Chuck Lever
@ 2026-04-27 13:50 ` Chuck Lever
  2026-04-27 13:50 ` [PATCH 13/18] SUNRPC: Remove encrypt/decrypt " Chuck Lever
                   ` (6 subsequent siblings)
  18 siblings, 0 replies; 21+ messages in thread
From: Chuck Lever @ 2026-04-27 13:50 UTC (permalink / raw)
  To: Trond Myklebust, Anna Schumaker, Chuck Lever, Jeff Layton,
	NeilBrown, Olga Kornievskaia, Dai Ngo, Tom Talpey,
	David S. Miller, Eric Dumazet, Jakub Kicinski, Paolo Abeni,
	Simon Horman
  Cc: linux-nfs, netdev, linux-kernel, Herbert Xu, David Howells,
	Simo Sorce

From: Chuck Lever <chuck.lever@oracle.com>

Every enctype points .wrap and .unwrap at gss_krb5_wrap_v2()
and gss_krb5_unwrap_v2(). As with get_mic/verify_mic, the
indirection dates from when v1 enctypes had different wrap
implementations. Call the functions directly and remove the
pointers from struct gss_krb5_enctype.

Signed-off-by: Chuck Lever <chuck.lever@oracle.com>
---
 net/sunrpc/auth_gss/gss_krb5_internal.h |  5 -----
 net/sunrpc/auth_gss/gss_krb5_mech.c     | 18 ++----------------
 2 files changed, 2 insertions(+), 21 deletions(-)

diff --git a/net/sunrpc/auth_gss/gss_krb5_internal.h b/net/sunrpc/auth_gss/gss_krb5_internal.h
index a63f8d465b63..92b0baed920c 100644
--- a/net/sunrpc/auth_gss/gss_krb5_internal.h
+++ b/net/sunrpc/auth_gss/gss_krb5_internal.h
@@ -44,11 +44,6 @@ struct gss_krb5_enctype {
 		       struct xdr_buf *buf, struct page **pages);
 	u32 (*decrypt)(struct krb5_ctx *kctx, u32 offset, u32 len,
 		       struct xdr_buf *buf, u32 *headskip, u32 *tailskip);
-	u32 (*wrap)(struct krb5_ctx *kctx, int offset,
-		    struct xdr_buf *buf, struct page **pages);
-	u32 (*unwrap)(struct krb5_ctx *kctx, int offset, int len,
-		      struct xdr_buf *buf, unsigned int *slack,
-		      unsigned int *align);
 };
 
 /* krb5_ctx flags definitions */
diff --git a/net/sunrpc/auth_gss/gss_krb5_mech.c b/net/sunrpc/auth_gss/gss_krb5_mech.c
index 511e19e0e786..d027ddab132f 100644
--- a/net/sunrpc/auth_gss/gss_krb5_mech.c
+++ b/net/sunrpc/auth_gss/gss_krb5_mech.c
@@ -46,9 +46,6 @@ static const struct gss_krb5_enctype supported_gss_krb5_enctypes[] = {
 	  .encrypt = gss_krb5_aead_encrypt,
 	  .decrypt = gss_krb5_aead_decrypt,
 
-	  .wrap = gss_krb5_wrap_v2,
-	  .unwrap = gss_krb5_unwrap_v2,
-
 	  .signalg = -1,
 	  .sealalg = -1,
 	  .keybytes = 16,
@@ -73,9 +70,6 @@ static const struct gss_krb5_enctype supported_gss_krb5_enctypes[] = {
 	  .encrypt = gss_krb5_aead_encrypt,
 	  .decrypt = gss_krb5_aead_decrypt,
 
-	  .wrap = gss_krb5_wrap_v2,
-	  .unwrap = gss_krb5_unwrap_v2,
-
 	  .signalg = -1,
 	  .sealalg = -1,
 	  .keybytes = 32,
@@ -110,8 +104,6 @@ static const struct gss_krb5_enctype supported_gss_krb5_enctypes[] = {
 		.encrypt	= gss_krb5_aead_encrypt,
 		.decrypt	= gss_krb5_aead_decrypt,
 
-		.wrap		= gss_krb5_wrap_v2,
-		.unwrap		= gss_krb5_unwrap_v2,
 	},
 	/*
 	 * Camellia-256 with CMAC (RFC 6803)
@@ -134,8 +126,6 @@ static const struct gss_krb5_enctype supported_gss_krb5_enctypes[] = {
 		.encrypt	= gss_krb5_aead_encrypt,
 		.decrypt	= gss_krb5_aead_decrypt,
 
-		.wrap		= gss_krb5_wrap_v2,
-		.unwrap		= gss_krb5_unwrap_v2,
 	},
 #endif
 
@@ -161,8 +151,6 @@ static const struct gss_krb5_enctype supported_gss_krb5_enctypes[] = {
 		.encrypt	= gss_krb5_aead_encrypt,
 		.decrypt	= gss_krb5_aead_decrypt,
 
-		.wrap		= gss_krb5_wrap_v2,
-		.unwrap		= gss_krb5_unwrap_v2,
 	},
 	/*
 	 * AES-256 with SHA-384 (RFC 8009)
@@ -185,8 +173,6 @@ static const struct gss_krb5_enctype supported_gss_krb5_enctypes[] = {
 		.encrypt	= gss_krb5_aead_encrypt,
 		.decrypt	= gss_krb5_aead_decrypt,
 
-		.wrap		= gss_krb5_wrap_v2,
-		.unwrap		= gss_krb5_unwrap_v2,
 	},
 #endif
 };
@@ -631,7 +617,7 @@ static u32 gss_krb5_wrap(struct gss_ctx *gctx, int offset,
 {
 	struct krb5_ctx	*kctx = gctx->internal_ctx_id;
 
-	return kctx->gk5e->wrap(kctx, offset, buf, pages);
+	return gss_krb5_wrap_v2(kctx, offset, buf, pages);
 }
 
 /**
@@ -653,7 +639,7 @@ static u32 gss_krb5_unwrap(struct gss_ctx *gctx, int offset,
 {
 	struct krb5_ctx	*kctx = gctx->internal_ctx_id;
 
-	return kctx->gk5e->unwrap(kctx, offset, len, buf,
+	return gss_krb5_unwrap_v2(kctx, offset, len, buf,
 				  &gctx->slack, &gctx->align);
 }
 

-- 
2.53.0


^ permalink raw reply related	[flat|nested] 21+ messages in thread

* [PATCH 13/18] SUNRPC: Remove encrypt/decrypt function pointers from enctype table
  2026-04-27 13:50 [PATCH 00/18] Migrate rpcsec_gss_krb5 to the crypto/krb5 library Chuck Lever
                   ` (11 preceding siblings ...)
  2026-04-27 13:50 ` [PATCH 12/18] SUNRPC: Remove wrap/unwrap " Chuck Lever
@ 2026-04-27 13:50 ` Chuck Lever
  2026-04-27 13:50 ` [PATCH 14/18] SUNRPC: Remove legacy skcipher/ahash handles from krb5_ctx Chuck Lever
                   ` (5 subsequent siblings)
  18 siblings, 0 replies; 21+ messages in thread
From: Chuck Lever @ 2026-04-27 13:50 UTC (permalink / raw)
  To: Trond Myklebust, Anna Schumaker, Chuck Lever, Jeff Layton,
	NeilBrown, Olga Kornievskaia, Dai Ngo, Tom Talpey,
	David S. Miller, Eric Dumazet, Jakub Kicinski, Paolo Abeni,
	Simon Horman
  Cc: linux-nfs, netdev, linux-kernel, Herbert Xu, David Howells,
	Simo Sorce

From: Chuck Lever <chuck.lever@oracle.com>

All enctypes now route through gss_krb5_aead_encrypt() and
gss_krb5_aead_decrypt(). The per-enctype .encrypt and .decrypt
function pointers served the same purpose as .get_mic and
.wrap before them: dispatching v1 versus v2 implementations.
With v1 support long removed and the Camellia decrypt path
migrated in a preceding patch, every table entry points to
the same pair of functions.

Call gss_krb5_aead_encrypt() and gss_krb5_aead_decrypt()
directly from gss_krb5_wrap_v2() and gss_krb5_unwrap_v2(),
and drop the function pointers from struct gss_krb5_enctype.

While here, propagate the GSS status code returned by
gss_krb5_aead_decrypt() instead of discarding it.
The old indirect call sites returned GSS_S_FAILURE
unconditionally, losing the distinction between an
integrity failure (GSS_S_BAD_SIG) and a structural
error (GSS_S_DEFECTIVE_TOKEN).

Signed-off-by: Chuck Lever <chuck.lever@oracle.com>
---
 net/sunrpc/auth_gss/gss_krb5_internal.h |  4 ----
 net/sunrpc/auth_gss/gss_krb5_mech.c     | 12 ------------
 net/sunrpc/auth_gss/gss_krb5_wrap.c     | 12 ++++++------
 3 files changed, 6 insertions(+), 22 deletions(-)

diff --git a/net/sunrpc/auth_gss/gss_krb5_internal.h b/net/sunrpc/auth_gss/gss_krb5_internal.h
index 92b0baed920c..8258e6862aa2 100644
--- a/net/sunrpc/auth_gss/gss_krb5_internal.h
+++ b/net/sunrpc/auth_gss/gss_krb5_internal.h
@@ -40,10 +40,6 @@ struct gss_krb5_enctype {
 			  struct xdr_netobj *out,
 			  const struct xdr_netobj *label,
 			  gfp_t gfp_mask);
-	u32 (*encrypt)(struct krb5_ctx *kctx, u32 offset,
-		       struct xdr_buf *buf, struct page **pages);
-	u32 (*decrypt)(struct krb5_ctx *kctx, u32 offset, u32 len,
-		       struct xdr_buf *buf, u32 *headskip, u32 *tailskip);
 };
 
 /* krb5_ctx flags definitions */
diff --git a/net/sunrpc/auth_gss/gss_krb5_mech.c b/net/sunrpc/auth_gss/gss_krb5_mech.c
index d027ddab132f..912821efc937 100644
--- a/net/sunrpc/auth_gss/gss_krb5_mech.c
+++ b/net/sunrpc/auth_gss/gss_krb5_mech.c
@@ -43,8 +43,6 @@ static const struct gss_krb5_enctype supported_gss_krb5_enctypes[] = {
 	  .aux_cipher = "cbc(aes)",
 	  .cksum_name = "hmac(sha1)",
 	  .derive_key = krb5_derive_key_v2,
-	  .encrypt = gss_krb5_aead_encrypt,
-	  .decrypt = gss_krb5_aead_decrypt,
 
 	  .signalg = -1,
 	  .sealalg = -1,
@@ -67,8 +65,6 @@ static const struct gss_krb5_enctype supported_gss_krb5_enctypes[] = {
 	  .aux_cipher = "cbc(aes)",
 	  .cksum_name = "hmac(sha1)",
 	  .derive_key = krb5_derive_key_v2,
-	  .encrypt = gss_krb5_aead_encrypt,
-	  .decrypt = gss_krb5_aead_decrypt,
 
 	  .signalg = -1,
 	  .sealalg = -1,
@@ -101,8 +97,6 @@ static const struct gss_krb5_enctype supported_gss_krb5_enctypes[] = {
 		.Ki_length	= BITS2OCTETS(128),
 
 		.derive_key	= krb5_kdf_feedback_cmac,
-		.encrypt	= gss_krb5_aead_encrypt,
-		.decrypt	= gss_krb5_aead_decrypt,
 
 	},
 	/*
@@ -123,8 +117,6 @@ static const struct gss_krb5_enctype supported_gss_krb5_enctypes[] = {
 		.Ki_length	= BITS2OCTETS(256),
 
 		.derive_key	= krb5_kdf_feedback_cmac,
-		.encrypt	= gss_krb5_aead_encrypt,
-		.decrypt	= gss_krb5_aead_decrypt,
 
 	},
 #endif
@@ -148,8 +140,6 @@ static const struct gss_krb5_enctype supported_gss_krb5_enctypes[] = {
 		.Ki_length	= BITS2OCTETS(128),
 
 		.derive_key	= krb5_kdf_hmac_sha2,
-		.encrypt	= gss_krb5_aead_encrypt,
-		.decrypt	= gss_krb5_aead_decrypt,
 
 	},
 	/*
@@ -170,8 +160,6 @@ static const struct gss_krb5_enctype supported_gss_krb5_enctypes[] = {
 		.Ki_length	= BITS2OCTETS(192),
 
 		.derive_key	= krb5_kdf_hmac_sha2,
-		.encrypt	= gss_krb5_aead_encrypt,
-		.decrypt	= gss_krb5_aead_decrypt,
 
 	},
 #endif
diff --git a/net/sunrpc/auth_gss/gss_krb5_wrap.c b/net/sunrpc/auth_gss/gss_krb5_wrap.c
index b3e1738ff6bf..93aa7500d032 100644
--- a/net/sunrpc/auth_gss/gss_krb5_wrap.c
+++ b/net/sunrpc/auth_gss/gss_krb5_wrap.c
@@ -112,9 +112,9 @@ gss_krb5_wrap_v2(struct krb5_ctx *kctx, int offset,
 	*ptr++ = (unsigned char) ((KG2_TOK_WRAP>>8) & 0xff);
 	*ptr++ = (unsigned char) (KG2_TOK_WRAP & 0xff);
 
-	if ((kctx->flags & KRB5_CTX_FLAG_INITIATOR) == 0)
+	if (!kctx->initiate)
 		flags |= KG2_TOKEN_FLAG_SENTBYACCEPTOR;
-	if ((kctx->flags & KRB5_CTX_FLAG_ACCEPTOR_SUBKEY) != 0)
+	if (kctx->flags & KRB5_CTX_FLAG_ACCEPTOR_SUBKEY)
 		flags |= KG2_TOKEN_FLAG_ACCEPTORSUBKEY;
 	/* We always do confidentiality in wrap tokens */
 	flags |= KG2_TOKEN_FLAG_SEALED;
@@ -130,7 +130,7 @@ gss_krb5_wrap_v2(struct krb5_ctx *kctx, int offset,
 	be64ptr = (__be64 *)be16ptr;
 	*be64ptr = cpu_to_be64(atomic64_fetch_inc(&kctx->seq_send64));
 
-	err = (*kctx->gk5e->encrypt)(kctx, offset, buf, pages);
+	err = gss_krb5_aead_encrypt(kctx, offset, buf, pages);
 	if (err)
 		return err;
 
@@ -184,10 +184,10 @@ gss_krb5_unwrap_v2(struct krb5_ctx *kctx, int offset, int len,
 	if (rrc != 0)
 		rotate_left(offset + 16, buf, rrc);
 
-	err = (*kctx->gk5e->decrypt)(kctx, offset, len, buf,
-				     &headskip, &tailskip);
+	err = gss_krb5_aead_decrypt(kctx, offset, len, buf,
+				    &headskip, &tailskip);
 	if (err)
-		return GSS_S_FAILURE;
+		return err;
 
 	/*
 	 * Retrieve the decrypted gss token header and verify

-- 
2.53.0


^ permalink raw reply related	[flat|nested] 21+ messages in thread

* [PATCH 14/18] SUNRPC: Remove legacy skcipher/ahash handles from krb5_ctx
  2026-04-27 13:50 [PATCH 00/18] Migrate rpcsec_gss_krb5 to the crypto/krb5 library Chuck Lever
                   ` (12 preceding siblings ...)
  2026-04-27 13:50 ` [PATCH 13/18] SUNRPC: Remove encrypt/decrypt " Chuck Lever
@ 2026-04-27 13:50 ` Chuck Lever
  2026-04-27 13:50 ` [PATCH 15/18] SUNRPC: Remove dead code from rpcsec_gss_krb5 Chuck Lever
                   ` (4 subsequent siblings)
  18 siblings, 0 replies; 21+ messages in thread
From: Chuck Lever @ 2026-04-27 13:50 UTC (permalink / raw)
  To: Trond Myklebust, Anna Schumaker, Chuck Lever, Jeff Layton,
	NeilBrown, Olga Kornievskaia, Dai Ngo, Tom Talpey,
	David S. Miller, Eric Dumazet, Jakub Kicinski, Paolo Abeni,
	Simon Horman
  Cc: linux-nfs, netdev, linux-kernel, Herbert Xu, David Howells,
	Simo Sorce

From: Chuck Lever <chuck.lever@oracle.com>

Previous patches switched all per-message crypto operations
(encrypt, decrypt, get_mic, verify_mic) from the internal
skcipher/ahash primitives to crypto/krb5 AEAD and shash
handles. The old crypto_sync_skcipher and crypto_ahash fields in
struct krb5_ctx are no longer referenced at runtime.

Remove the ten legacy handle fields from struct krb5_ctx
along with the key derivation and handle allocation code in
gss_krb5_import_ctx_v2() that populated them. Context import
now prepares only the four crypto/krb5 handles (two AEAD for
encryption, two shash for checksums). The corresponding cleanup
in gss_krb5_delete_sec_context() and the error path is likewise
reduced.

The krb5_derive_key() inline wrapper, gss_krb5_alloc_cipher_v2(),
and gss_krb5_alloc_hash_v2() become unused and are removed.
The per-enctype encrypt/decrypt functions (gss_krb5_aes_encrypt,
gss_krb5_aes_decrypt, krb5_etm_encrypt, krb5_etm_decrypt) that
were the sole remaining consumers of these fields are also removed;
their function-pointer call sites were already deleted in earlier
patches.

Signed-off-by: Chuck Lever <chuck.lever@oracle.com>
---
 net/sunrpc/auth_gss/gss_krb5_crypto.c   | 307 --------------------------------
 net/sunrpc/auth_gss/gss_krb5_internal.h |  54 ------
 net/sunrpc/auth_gss/gss_krb5_mech.c     | 135 +-------------
 3 files changed, 3 insertions(+), 493 deletions(-)

diff --git a/net/sunrpc/auth_gss/gss_krb5_crypto.c b/net/sunrpc/auth_gss/gss_krb5_crypto.c
index 3a8e6710a51b..cfd5b56d1b52 100644
--- a/net/sunrpc/auth_gss/gss_krb5_crypto.c
+++ b/net/sunrpc/auth_gss/gss_krb5_crypto.c
@@ -578,137 +578,6 @@ int krb5_cbc_cts_decrypt(struct crypto_sync_skcipher *cts_tfm,
 }
 EXPORT_SYMBOL_IF_KUNIT(krb5_cbc_cts_decrypt);
 
-u32
-gss_krb5_aes_encrypt(struct krb5_ctx *kctx, u32 offset,
-		     struct xdr_buf *buf, struct page **pages)
-{
-	u32 err;
-	struct xdr_netobj hmac;
-	u8 *ecptr;
-	struct crypto_sync_skcipher *cipher, *aux_cipher;
-	struct crypto_ahash *ahash;
-	struct page **save_pages;
-	unsigned int conflen;
-
-	if (kctx->initiate) {
-		cipher = kctx->initiator_enc;
-		aux_cipher = kctx->initiator_enc_aux;
-		ahash = kctx->initiator_integ;
-	} else {
-		cipher = kctx->acceptor_enc;
-		aux_cipher = kctx->acceptor_enc_aux;
-		ahash = kctx->acceptor_integ;
-	}
-	conflen = crypto_sync_skcipher_blocksize(cipher);
-
-	/* hide the gss token header and insert the confounder */
-	offset += GSS_KRB5_TOK_HDR_LEN;
-	if (xdr_extend_head(buf, offset, conflen))
-		return GSS_S_FAILURE;
-	krb5_make_confounder(buf->head[0].iov_base + offset, conflen);
-	offset -= GSS_KRB5_TOK_HDR_LEN;
-
-	if (buf->tail[0].iov_base != NULL) {
-		ecptr = buf->tail[0].iov_base + buf->tail[0].iov_len;
-	} else {
-		buf->tail[0].iov_base = buf->head[0].iov_base
-							+ buf->head[0].iov_len;
-		buf->tail[0].iov_len = 0;
-		ecptr = buf->tail[0].iov_base;
-	}
-
-	/* copy plaintext gss token header after filler (if any) */
-	memcpy(ecptr, buf->head[0].iov_base + offset, GSS_KRB5_TOK_HDR_LEN);
-	buf->tail[0].iov_len += GSS_KRB5_TOK_HDR_LEN;
-	buf->len += GSS_KRB5_TOK_HDR_LEN;
-
-	hmac.len = kctx->gk5e->cksumlength;
-	hmac.data = buf->tail[0].iov_base + buf->tail[0].iov_len;
-
-	/*
-	 * When we are called, pages points to the real page cache
-	 * data -- which we can't go and encrypt!  buf->pages points
-	 * to scratch pages which we are going to send off to the
-	 * client/server.  Swap in the plaintext pages to calculate
-	 * the hmac.
-	 */
-	save_pages = buf->pages;
-	buf->pages = pages;
-
-	err = gss_krb5_checksum(ahash, NULL, 0, buf,
-				offset + GSS_KRB5_TOK_HDR_LEN, &hmac);
-	buf->pages = save_pages;
-	if (err)
-		return GSS_S_FAILURE;
-
-	err = krb5_cbc_cts_encrypt(cipher, aux_cipher,
-				   offset + GSS_KRB5_TOK_HDR_LEN,
-				   buf, pages, NULL, 0);
-	if (err)
-		return GSS_S_FAILURE;
-
-	/* Now update buf to account for HMAC */
-	buf->tail[0].iov_len += kctx->gk5e->cksumlength;
-	buf->len += kctx->gk5e->cksumlength;
-
-	return GSS_S_COMPLETE;
-}
-
-u32
-gss_krb5_aes_decrypt(struct krb5_ctx *kctx, u32 offset, u32 len,
-		     struct xdr_buf *buf, u32 *headskip, u32 *tailskip)
-{
-	struct crypto_sync_skcipher *cipher, *aux_cipher;
-	struct crypto_ahash *ahash;
-	struct xdr_netobj our_hmac_obj;
-	u8 our_hmac[GSS_KRB5_MAX_CKSUM_LEN];
-	u8 pkt_hmac[GSS_KRB5_MAX_CKSUM_LEN];
-	struct xdr_buf subbuf;
-	u32 ret = 0;
-
-	if (kctx->initiate) {
-		cipher = kctx->acceptor_enc;
-		aux_cipher = kctx->acceptor_enc_aux;
-		ahash = kctx->acceptor_integ;
-	} else {
-		cipher = kctx->initiator_enc;
-		aux_cipher = kctx->initiator_enc_aux;
-		ahash = kctx->initiator_integ;
-	}
-
-	/* create a segment skipping the header and leaving out the checksum */
-	xdr_buf_subsegment(buf, &subbuf, offset + GSS_KRB5_TOK_HDR_LEN,
-				    (len - offset - GSS_KRB5_TOK_HDR_LEN -
-				     kctx->gk5e->cksumlength));
-
-	ret = krb5_cbc_cts_decrypt(cipher, aux_cipher, 0, &subbuf);
-	if (ret)
-		goto out_err;
-
-	our_hmac_obj.len = kctx->gk5e->cksumlength;
-	our_hmac_obj.data = our_hmac;
-	ret = gss_krb5_checksum(ahash, NULL, 0, &subbuf, 0, &our_hmac_obj);
-	if (ret)
-		goto out_err;
-
-	/* Get the packet's hmac value */
-	ret = read_bytes_from_xdr_buf(buf, len - kctx->gk5e->cksumlength,
-				      pkt_hmac, kctx->gk5e->cksumlength);
-	if (ret)
-		goto out_err;
-
-	if (crypto_memneq(pkt_hmac, our_hmac, kctx->gk5e->cksumlength) != 0) {
-		ret = GSS_S_BAD_SIG;
-		goto out_err;
-	}
-	*headskip = crypto_sync_skcipher_blocksize(cipher);
-	*tailskip = kctx->gk5e->cksumlength;
-out_err:
-	if (ret && ret != GSS_S_BAD_SIG)
-		ret = GSS_S_FAILURE;
-	return ret;
-}
-
 /**
  * krb5_etm_checksum - Compute a MAC for a GSS Wrap token
  * @cipher: an initialized cipher transform
@@ -778,182 +647,6 @@ u32 krb5_etm_checksum(struct crypto_sync_skcipher *cipher,
 }
 EXPORT_SYMBOL_IF_KUNIT(krb5_etm_checksum);
 
-/**
- * krb5_etm_encrypt - Encrypt using the RFC 8009 rules
- * @kctx: Kerberos context
- * @offset: starting offset of the payload, in bytes
- * @buf: OUT: send buffer to contain the encrypted payload
- * @pages: plaintext payload
- *
- * The main difference with aes_encrypt is that "The HMAC is
- * calculated over the cipher state concatenated with the AES
- * output, instead of being calculated over the confounder and
- * plaintext.  This allows the message receiver to verify the
- * integrity of the message before decrypting the message."
- *
- * RFC 8009 Section 5:
- *
- * encryption function: as follows, where E() is AES encryption in
- * CBC-CS3 mode, and h is the size of truncated HMAC (128 bits or
- * 192 bits as described above).
- *
- *    N = random value of length 128 bits (the AES block size)
- *    IV = cipher state
- *    C = E(Ke, N | plaintext, IV)
- *    H = HMAC(Ki, IV | C)
- *    ciphertext = C | H[1..h]
- *
- * This encryption formula provides AEAD EtM with key separation.
- *
- * Return values:
- *   %GSS_S_COMPLETE: Encryption successful
- *   %GSS_S_FAILURE: Encryption failed
- */
-u32
-krb5_etm_encrypt(struct krb5_ctx *kctx, u32 offset,
-		 struct xdr_buf *buf, struct page **pages)
-{
-	struct crypto_sync_skcipher *cipher, *aux_cipher;
-	struct crypto_ahash *ahash;
-	struct xdr_netobj hmac;
-	unsigned int conflen;
-	u8 *ecptr;
-	u32 err;
-
-	if (kctx->initiate) {
-		cipher = kctx->initiator_enc;
-		aux_cipher = kctx->initiator_enc_aux;
-		ahash = kctx->initiator_integ;
-	} else {
-		cipher = kctx->acceptor_enc;
-		aux_cipher = kctx->acceptor_enc_aux;
-		ahash = kctx->acceptor_integ;
-	}
-	conflen = crypto_sync_skcipher_blocksize(cipher);
-
-	offset += GSS_KRB5_TOK_HDR_LEN;
-	if (xdr_extend_head(buf, offset, conflen))
-		return GSS_S_FAILURE;
-	krb5_make_confounder(buf->head[0].iov_base + offset, conflen);
-	offset -= GSS_KRB5_TOK_HDR_LEN;
-
-	if (buf->tail[0].iov_base) {
-		ecptr = buf->tail[0].iov_base + buf->tail[0].iov_len;
-	} else {
-		buf->tail[0].iov_base = buf->head[0].iov_base
-							+ buf->head[0].iov_len;
-		buf->tail[0].iov_len = 0;
-		ecptr = buf->tail[0].iov_base;
-	}
-
-	memcpy(ecptr, buf->head[0].iov_base + offset, GSS_KRB5_TOK_HDR_LEN);
-	buf->tail[0].iov_len += GSS_KRB5_TOK_HDR_LEN;
-	buf->len += GSS_KRB5_TOK_HDR_LEN;
-
-	err = krb5_cbc_cts_encrypt(cipher, aux_cipher,
-				   offset + GSS_KRB5_TOK_HDR_LEN,
-				   buf, pages, NULL, 0);
-	if (err)
-		return GSS_S_FAILURE;
-
-	hmac.data = buf->tail[0].iov_base + buf->tail[0].iov_len;
-	hmac.len = kctx->gk5e->cksumlength;
-	err = krb5_etm_checksum(cipher, ahash,
-				buf, offset + GSS_KRB5_TOK_HDR_LEN, &hmac);
-	if (err)
-		goto out_err;
-	buf->tail[0].iov_len += kctx->gk5e->cksumlength;
-	buf->len += kctx->gk5e->cksumlength;
-
-	return GSS_S_COMPLETE;
-
-out_err:
-	return GSS_S_FAILURE;
-}
-
-/**
- * krb5_etm_decrypt - Decrypt using the RFC 8009 rules
- * @kctx: Kerberos context
- * @offset: starting offset of the ciphertext, in bytes
- * @len: size of ciphertext to unwrap
- * @buf: ciphertext to unwrap
- * @headskip: OUT: the enctype's confounder length, in octets
- * @tailskip: OUT: the enctype's HMAC length, in octets
- *
- * RFC 8009 Section 5:
- *
- * decryption function: as follows, where D() is AES decryption in
- * CBC-CS3 mode, and h is the size of truncated HMAC.
- *
- *    (C, H) = ciphertext
- *        (Note: H is the last h bits of the ciphertext.)
- *    IV = cipher state
- *    if H != HMAC(Ki, IV | C)[1..h]
- *        stop, report error
- *    (N, P) = D(Ke, C, IV)
- *
- * Return values:
- *   %GSS_S_COMPLETE: Decryption successful
- *   %GSS_S_BAD_SIG: computed HMAC != received HMAC
- *   %GSS_S_FAILURE: Decryption failed
- */
-u32
-krb5_etm_decrypt(struct krb5_ctx *kctx, u32 offset, u32 len,
-		 struct xdr_buf *buf, u32 *headskip, u32 *tailskip)
-{
-	struct crypto_sync_skcipher *cipher, *aux_cipher;
-	u8 our_hmac[GSS_KRB5_MAX_CKSUM_LEN];
-	u8 pkt_hmac[GSS_KRB5_MAX_CKSUM_LEN];
-	struct xdr_netobj our_hmac_obj;
-	struct crypto_ahash *ahash;
-	struct xdr_buf subbuf;
-	u32 ret = 0;
-
-	if (kctx->initiate) {
-		cipher = kctx->acceptor_enc;
-		aux_cipher = kctx->acceptor_enc_aux;
-		ahash = kctx->acceptor_integ;
-	} else {
-		cipher = kctx->initiator_enc;
-		aux_cipher = kctx->initiator_enc_aux;
-		ahash = kctx->initiator_integ;
-	}
-
-	/* Extract the ciphertext into @subbuf. */
-	xdr_buf_subsegment(buf, &subbuf, offset + GSS_KRB5_TOK_HDR_LEN,
-			   (len - offset - GSS_KRB5_TOK_HDR_LEN -
-			    kctx->gk5e->cksumlength));
-
-	our_hmac_obj.data = our_hmac;
-	our_hmac_obj.len = kctx->gk5e->cksumlength;
-	ret = krb5_etm_checksum(cipher, ahash, &subbuf, 0, &our_hmac_obj);
-	if (ret)
-		goto out_err;
-	ret = read_bytes_from_xdr_buf(buf, len - kctx->gk5e->cksumlength,
-				      pkt_hmac, kctx->gk5e->cksumlength);
-	if (ret)
-		goto out_err;
-	if (crypto_memneq(pkt_hmac, our_hmac, kctx->gk5e->cksumlength) != 0) {
-		ret = GSS_S_BAD_SIG;
-		goto out_err;
-	}
-
-	ret = krb5_cbc_cts_decrypt(cipher, aux_cipher, 0, &subbuf);
-	if (ret) {
-		ret = GSS_S_FAILURE;
-		goto out_err;
-	}
-
-	*headskip = crypto_sync_skcipher_blocksize(cipher);
-	*tailskip = kctx->gk5e->cksumlength;
-	return GSS_S_COMPLETE;
-
-out_err:
-	if (ret != GSS_S_BAD_SIG)
-		ret = GSS_S_FAILURE;
-	return ret;
-}
-
 /**
  * gss_krb5_aead_encrypt - Encrypt a wrap token using crypto/krb5
  * @kctx: Kerberos context
diff --git a/net/sunrpc/auth_gss/gss_krb5_internal.h b/net/sunrpc/auth_gss/gss_krb5_internal.h
index 8258e6862aa2..6b08a7486e0b 100644
--- a/net/sunrpc/auth_gss/gss_krb5_internal.h
+++ b/net/sunrpc/auth_gss/gss_krb5_internal.h
@@ -56,16 +56,6 @@ struct krb5_ctx {
 	struct crypto_aead	*acceptor_enc_aead;
 	struct crypto_shash	*initiator_sign_shash;
 	struct crypto_shash	*acceptor_sign_shash;
-	struct crypto_sync_skcipher *enc;
-	struct crypto_sync_skcipher *seq;
-	struct crypto_sync_skcipher *acceptor_enc;
-	struct crypto_sync_skcipher *initiator_enc;
-	struct crypto_sync_skcipher *acceptor_enc_aux;
-	struct crypto_sync_skcipher *initiator_enc_aux;
-	struct crypto_ahash	*acceptor_sign;
-	struct crypto_ahash	*initiator_sign;
-	struct crypto_ahash	*initiator_integ;
-	struct crypto_ahash	*acceptor_integ;
 	u8			Ksess[GSS_KRB5_MAX_KEYLEN]; /* session key */
 	u8			cksum[GSS_KRB5_MAX_KEYLEN];
 	atomic_t		seq_send;
@@ -115,38 +105,6 @@ int krb5_kdf_feedback_cmac(const struct gss_krb5_enctype *gk5e,
 			   const struct xdr_netobj *in_constant,
 			   gfp_t gfp_mask);
 
-/**
- * krb5_derive_key - Derive a subkey from a protocol key
- * @kctx: Kerberos 5 context
- * @inkey: base protocol key
- * @outkey: OUT: derived key
- * @usage: key usage value
- * @seed: key usage seed (one octet)
- * @gfp_mask: memory allocation control flags
- *
- * Caller sets @outkey->len to the desired length of the derived key.
- *
- * On success, returns 0 and fills in @outkey. A negative errno value
- * is returned on failure.
- */
-static inline int krb5_derive_key(struct krb5_ctx *kctx,
-				  const struct xdr_netobj *inkey,
-				  struct xdr_netobj *outkey,
-				  u32 usage, u8 seed, gfp_t gfp_mask)
-{
-	const struct gss_krb5_enctype *gk5e = kctx->gk5e;
-	u8 label_data[GSS_KRB5_K5CLENGTH];
-	struct xdr_netobj label = {
-		.len	= sizeof(label_data),
-		.data	= label_data,
-	};
-	__be32 *p = (__be32 *)label_data;
-
-	*p = cpu_to_be32(usage);
-	label_data[4] = seed;
-	return gk5e->derive_key(gk5e, inkey, outkey, &label, gfp_mask);
-}
-
 void krb5_make_confounder(u8 *p, int conflen);
 
 u32 gss_krb5_checksum(struct crypto_ahash *tfm, char *header, int hdrlen,
@@ -159,18 +117,6 @@ u32 krb5_encrypt(struct crypto_sync_skcipher *key, void *iv, void *in,
 int xdr_extend_head(struct xdr_buf *buf, unsigned int base,
 		    unsigned int shiftlen);
 
-u32 gss_krb5_aes_encrypt(struct krb5_ctx *kctx, u32 offset,
-			 struct xdr_buf *buf, struct page **pages);
-
-u32 gss_krb5_aes_decrypt(struct krb5_ctx *kctx, u32 offset, u32 len,
-			 struct xdr_buf *buf, u32 *plainoffset, u32 *plainlen);
-
-u32 krb5_etm_encrypt(struct krb5_ctx *kctx, u32 offset, struct xdr_buf *buf,
-		     struct page **pages);
-
-u32 krb5_etm_decrypt(struct krb5_ctx *kctx, u32 offset, u32 len,
-		     struct xdr_buf *buf, u32 *headskip, u32 *tailskip);
-
 u32 gss_krb5_errno_to_status(int err);
 
 int gss_krb5_mic_build_sg(const struct xdr_buf *body,
diff --git a/net/sunrpc/auth_gss/gss_krb5_mech.c b/net/sunrpc/auth_gss/gss_krb5_mech.c
index 912821efc937..d8cb79fd2463 100644
--- a/net/sunrpc/auth_gss/gss_krb5_mech.c
+++ b/net/sunrpc/auth_gss/gss_krb5_mech.c
@@ -9,8 +9,6 @@
  *  J. Bruce Fields <bfields@umich.edu>
  */
 
-#include <crypto/hash.h>
-#include <crypto/skcipher.h>
 #include <linux/err.h>
 #include <linux/module.h>
 #include <linux/init.h>
@@ -225,120 +223,14 @@ const struct gss_krb5_enctype *gss_krb5_lookup_enctype(u32 etype)
 }
 EXPORT_SYMBOL_IF_KUNIT(gss_krb5_lookup_enctype);
 
-static struct crypto_sync_skcipher *
-gss_krb5_alloc_cipher_v2(const char *cname, const struct xdr_netobj *key)
-{
-	struct crypto_sync_skcipher *tfm;
-
-	tfm = crypto_alloc_sync_skcipher(cname, 0, 0);
-	if (IS_ERR(tfm))
-		return NULL;
-	if (crypto_sync_skcipher_setkey(tfm, key->data, key->len)) {
-		crypto_free_sync_skcipher(tfm);
-		return NULL;
-	}
-	return tfm;
-}
-
-static struct crypto_ahash *
-gss_krb5_alloc_hash_v2(struct krb5_ctx *kctx, const struct xdr_netobj *key)
-{
-	struct crypto_ahash *tfm;
-
-	tfm = crypto_alloc_ahash(kctx->gk5e->cksum_name, 0, CRYPTO_ALG_ASYNC);
-	if (IS_ERR(tfm))
-		return NULL;
-	if (crypto_ahash_setkey(tfm, key->data, key->len)) {
-		crypto_free_ahash(tfm);
-		return NULL;
-	}
-	return tfm;
-}
-
 static int
 gss_krb5_import_ctx_v2(struct krb5_ctx *ctx, gfp_t gfp_mask)
 {
-	struct xdr_netobj keyin = {
-		.len	= ctx->gk5e->keylength,
-		.data	= ctx->Ksess,
-	};
 	struct krb5_buffer TK = {
 		.len	= ctx->gk5e->keylength,
 		.data	= ctx->Ksess,
 	};
-	struct xdr_netobj keyout;
-	int ret = -EINVAL;
-
-	keyout.data = kmalloc(GSS_KRB5_MAX_KEYLEN, gfp_mask);
-	if (!keyout.data)
-		return -ENOMEM;
-
-	/* initiator seal encryption */
-	keyout.len = ctx->gk5e->Ke_length;
-	if (krb5_derive_key(ctx, &keyin, &keyout, KG_USAGE_INITIATOR_SEAL,
-			    KEY_USAGE_SEED_ENCRYPTION, gfp_mask))
-		goto out;
-	ctx->initiator_enc = gss_krb5_alloc_cipher_v2(ctx->gk5e->encrypt_name,
-						      &keyout);
-	if (ctx->initiator_enc == NULL)
-		goto out;
-	if (ctx->gk5e->aux_cipher) {
-		ctx->initiator_enc_aux =
-			gss_krb5_alloc_cipher_v2(ctx->gk5e->aux_cipher,
-						 &keyout);
-		if (ctx->initiator_enc_aux == NULL)
-			goto out_free;
-	}
-
-	/* acceptor seal encryption */
-	if (krb5_derive_key(ctx, &keyin, &keyout, KG_USAGE_ACCEPTOR_SEAL,
-			    KEY_USAGE_SEED_ENCRYPTION, gfp_mask))
-		goto out_free;
-	ctx->acceptor_enc = gss_krb5_alloc_cipher_v2(ctx->gk5e->encrypt_name,
-						     &keyout);
-	if (ctx->acceptor_enc == NULL)
-		goto out_free;
-	if (ctx->gk5e->aux_cipher) {
-		ctx->acceptor_enc_aux =
-			gss_krb5_alloc_cipher_v2(ctx->gk5e->aux_cipher,
-						 &keyout);
-		if (ctx->acceptor_enc_aux == NULL)
-			goto out_free;
-	}
-
-	/* initiator sign checksum */
-	keyout.len = ctx->gk5e->Kc_length;
-	if (krb5_derive_key(ctx, &keyin, &keyout, KG_USAGE_INITIATOR_SIGN,
-			    KEY_USAGE_SEED_CHECKSUM, gfp_mask))
-		goto out_free;
-	ctx->initiator_sign = gss_krb5_alloc_hash_v2(ctx, &keyout);
-	if (ctx->initiator_sign == NULL)
-		goto out_free;
-
-	/* acceptor sign checksum */
-	if (krb5_derive_key(ctx, &keyin, &keyout, KG_USAGE_ACCEPTOR_SIGN,
-			    KEY_USAGE_SEED_CHECKSUM, gfp_mask))
-		goto out_free;
-	ctx->acceptor_sign = gss_krb5_alloc_hash_v2(ctx, &keyout);
-	if (ctx->acceptor_sign == NULL)
-		goto out_free;
-
-	/* initiator seal integrity */
-	keyout.len = ctx->gk5e->Ki_length;
-	if (krb5_derive_key(ctx, &keyin, &keyout, KG_USAGE_INITIATOR_SEAL,
-			    KEY_USAGE_SEED_INTEGRITY, gfp_mask))
-		goto out_free;
-	ctx->initiator_integ = gss_krb5_alloc_hash_v2(ctx, &keyout);
-	if (ctx->initiator_integ == NULL)
-		goto out_free;
-
-	/* acceptor seal integrity */
-	if (krb5_derive_key(ctx, &keyin, &keyout, KG_USAGE_ACCEPTOR_SEAL,
-			    KEY_USAGE_SEED_INTEGRITY, gfp_mask))
-		goto out_free;
-	ctx->acceptor_integ = gss_krb5_alloc_hash_v2(ctx, &keyout);
-	if (ctx->acceptor_integ == NULL)
-		goto out_free;
+	int ret;
 
 	ctx->initiator_enc_aead =
 		crypto_krb5_prepare_encryption(ctx->krb5e, &TK,
@@ -373,25 +265,14 @@ gss_krb5_import_ctx_v2(struct krb5_ctx *ctx, gfp_t gfp_mask)
 		goto out_free;
 	}
 
-	ret = 0;
-out:
-	kfree_sensitive(keyout.data);
-	return ret;
+	return 0;
 
 out_free:
 	crypto_free_shash(ctx->acceptor_sign_shash);
 	crypto_free_shash(ctx->initiator_sign_shash);
 	crypto_free_aead(ctx->acceptor_enc_aead);
 	crypto_free_aead(ctx->initiator_enc_aead);
-	crypto_free_ahash(ctx->acceptor_integ);
-	crypto_free_ahash(ctx->initiator_integ);
-	crypto_free_ahash(ctx->acceptor_sign);
-	crypto_free_ahash(ctx->initiator_sign);
-	crypto_free_sync_skcipher(ctx->acceptor_enc_aux);
-	crypto_free_sync_skcipher(ctx->acceptor_enc);
-	crypto_free_sync_skcipher(ctx->initiator_enc_aux);
-	crypto_free_sync_skcipher(ctx->initiator_enc);
-	goto out;
+	return ret;
 }
 
 static int
@@ -509,16 +390,6 @@ gss_krb5_delete_sec_context(void *internal_ctx)
 	crypto_free_shash(kctx->initiator_sign_shash);
 	crypto_free_aead(kctx->acceptor_enc_aead);
 	crypto_free_aead(kctx->initiator_enc_aead);
-	crypto_free_sync_skcipher(kctx->seq);
-	crypto_free_sync_skcipher(kctx->enc);
-	crypto_free_sync_skcipher(kctx->acceptor_enc);
-	crypto_free_sync_skcipher(kctx->initiator_enc);
-	crypto_free_sync_skcipher(kctx->acceptor_enc_aux);
-	crypto_free_sync_skcipher(kctx->initiator_enc_aux);
-	crypto_free_ahash(kctx->acceptor_sign);
-	crypto_free_ahash(kctx->initiator_sign);
-	crypto_free_ahash(kctx->acceptor_integ);
-	crypto_free_ahash(kctx->initiator_integ);
 	kfree(kctx->mech_used.data);
 	kfree(kctx);
 }

-- 
2.53.0


^ permalink raw reply related	[flat|nested] 21+ messages in thread

* [PATCH 15/18] SUNRPC: Remove dead code from rpcsec_gss_krb5
  2026-04-27 13:50 [PATCH 00/18] Migrate rpcsec_gss_krb5 to the crypto/krb5 library Chuck Lever
                   ` (13 preceding siblings ...)
  2026-04-27 13:50 ` [PATCH 14/18] SUNRPC: Remove legacy skcipher/ahash handles from krb5_ctx Chuck Lever
@ 2026-04-27 13:50 ` Chuck Lever
  2026-04-27 13:51 ` [PATCH 16/18] SUNRPC: Remove per-enctype Kconfig options Chuck Lever
                   ` (3 subsequent siblings)
  18 siblings, 0 replies; 21+ messages in thread
From: Chuck Lever @ 2026-04-27 13:50 UTC (permalink / raw)
  To: Trond Myklebust, Anna Schumaker, Chuck Lever, Jeff Layton,
	NeilBrown, Olga Kornievskaia, Dai Ngo, Tom Talpey,
	David S. Miller, Eric Dumazet, Jakub Kicinski, Paolo Abeni,
	Simon Horman
  Cc: linux-nfs, netdev, linux-kernel, Herbert Xu, David Howells,
	Simo Sorce

From: Chuck Lever <chuck.lever@oracle.com>

With all per-message crypto operations routed through crypto/krb5,
a substantial body of code in rpcsec_gss_krb5 has no remaining
callers. The internal key derivation functions (krb5_derive_key_v2,
krb5_kdf_hmac_sha2, krb5_kdf_feedback_cmac) and the low-level
crypto primitives (krb5_encrypt, gss_krb5_checksum, krb5_cbc_cts_
encrypt/decrypt, krb5_etm_checksum) are unreachable because their
only call sites were the per-enctype function pointers removed in
previous patches. Delete gss_krb5_keys.c entirely and strip the
dead functions from gss_krb5_crypto.c.

The KUnit test suite in gss_krb5_test.c exercised exactly these
internal functions: RFC 3961 n-fold, RFC 3962 key derivation,
RFC 6803 Camellia key derivation, and RFC 8009 AES-SHA2 key
derivation, plus encryption self-tests that drove the now-removed
encrypt routines. The corresponding test coverage is provided by
the crypto/krb5 selftests in crypto/krb5/selftest.c. Remove the
test file, the RPCSEC_GSS_KRB5_KUNIT_TEST Kconfig symbol, the
.kunitconfig, and all VISIBLE_IF_KUNIT / EXPORT_SYMBOL_IF_KUNIT
annotations.

xdr_process_buf() walked xdr_buf segments through a per-segment
callback and existed solely for the crypto routines in
gss_krb5_crypto.c. With that file removed, xdr_process_buf()
has no remaining callers. Its successor, xdr_buf_to_sg(),
populates a scatterlist directly from an xdr_buf byte range
and was introduced earlier in this series.

With every consumer of struct gss_krb5_enctype removed, replace
its remaining uses with the equivalent fields from struct
krb5_enctype (key_len). Remove struct gss_krb5_enctype, the
supported_gss_krb5_enctypes[] table, gss_krb5_lookup_enctype(),
and the gk5e pointer from krb5_ctx.

Signed-off-by: Chuck Lever <chuck.lever@oracle.com>
---
 include/linux/sunrpc/xdr.h              |    1 -
 net/sunrpc/.kunitconfig                 |   29 -
 net/sunrpc/Kconfig                      |   15 -
 net/sunrpc/auth_gss/Makefile            |    4 +-
 net/sunrpc/auth_gss/gss_krb5_crypto.c   |  561 +---------
 net/sunrpc/auth_gss/gss_krb5_internal.h |   75 --
 net/sunrpc/auth_gss/gss_krb5_keys.c     |  546 ---------
 net/sunrpc/auth_gss/gss_krb5_mech.c     |  178 +--
 net/sunrpc/auth_gss/gss_krb5_test.c     | 1868 -------------------------------
 net/sunrpc/xdr.c                        |   67 --
 10 files changed, 6 insertions(+), 3338 deletions(-)

diff --git a/include/linux/sunrpc/xdr.h b/include/linux/sunrpc/xdr.h
index f82446993fde..31971b01d962 100644
--- a/include/linux/sunrpc/xdr.h
+++ b/include/linux/sunrpc/xdr.h
@@ -275,7 +275,6 @@ extern void xdr_finish_decode(struct xdr_stream *xdr);
 extern __be32 *xdr_inline_decode(struct xdr_stream *xdr, size_t nbytes);
 extern unsigned int xdr_read_pages(struct xdr_stream *xdr, unsigned int len);
 extern void xdr_enter_page(struct xdr_stream *xdr, unsigned int len);
-extern int xdr_process_buf(const struct xdr_buf *buf, unsigned int offset, unsigned int len, int (*actor)(struct scatterlist *, void *), void *data);
 extern void xdr_set_pagelen(struct xdr_stream *, unsigned int len);
 extern bool xdr_stream_subsegment(struct xdr_stream *xdr, struct xdr_buf *subbuf,
 				  unsigned int len);
diff --git a/net/sunrpc/.kunitconfig b/net/sunrpc/.kunitconfig
deleted file mode 100644
index eb02b906c295..000000000000
--- a/net/sunrpc/.kunitconfig
+++ /dev/null
@@ -1,29 +0,0 @@
-CONFIG_KUNIT=y
-CONFIG_UBSAN=y
-CONFIG_STACKTRACE=y
-CONFIG_NET=y
-CONFIG_NETWORK_FILESYSTEMS=y
-CONFIG_INET=y
-CONFIG_FILE_LOCKING=y
-CONFIG_MULTIUSER=y
-CONFIG_CRYPTO=y
-CONFIG_CRYPTO_CBC=y
-CONFIG_CRYPTO_CTS=y
-CONFIG_CRYPTO_ECB=y
-CONFIG_CRYPTO_HMAC=y
-CONFIG_CRYPTO_CMAC=y
-CONFIG_CRYPTO_MD5=y
-CONFIG_CRYPTO_SHA1=y
-CONFIG_CRYPTO_SHA256=y
-CONFIG_CRYPTO_SHA512=y
-CONFIG_CRYPTO_DES=y
-CONFIG_CRYPTO_AES=y
-CONFIG_CRYPTO_CAMELLIA=y
-CONFIG_NFS_FS=y
-CONFIG_SUNRPC=y
-CONFIG_SUNRPC_GSS=y
-CONFIG_RPCSEC_GSS_KRB5=y
-CONFIG_RPCSEC_GSS_KRB5_ENCTYPES_AES_SHA1=y
-CONFIG_RPCSEC_GSS_KRB5_ENCTYPES_CAMELLIA=y
-CONFIG_RPCSEC_GSS_KRB5_ENCTYPES_AES_SHA2=y
-CONFIG_RPCSEC_GSS_KRB5_KUNIT_TEST=y
diff --git a/net/sunrpc/Kconfig b/net/sunrpc/Kconfig
index 381e76975ea9..1c2e1fe9d365 100644
--- a/net/sunrpc/Kconfig
+++ b/net/sunrpc/Kconfig
@@ -73,21 +73,6 @@ config RPCSEC_GSS_KRB5_ENCTYPES_AES_SHA2
 	  SHA-2 digests. These include aes128-cts-hmac-sha256-128 and
 	  aes256-cts-hmac-sha384-192.
 
-config RPCSEC_GSS_KRB5_KUNIT_TEST
-	tristate "KUnit tests for RPCSEC GSS Kerberos" if !KUNIT_ALL_TESTS
-	depends on RPCSEC_GSS_KRB5 && KUNIT
-	default KUNIT_ALL_TESTS
-	help
-	  This builds the KUnit tests for RPCSEC GSS Kerberos 5.
-
-	  KUnit tests run during boot and output the results to the debug
-	  log in TAP format (https://testanything.org/). Only useful for
-	  kernel devs running KUnit test harness and are not for inclusion
-	  into a production build.
-
-	  For more information on KUnit and unit tests in general, refer
-	  to the KUnit documentation in Documentation/dev-tools/kunit/.
-
 config SUNRPC_DEBUG
 	bool "RPC: Enable dprintk debugging"
 	depends on SUNRPC && SYSCTL
diff --git a/net/sunrpc/auth_gss/Makefile b/net/sunrpc/auth_gss/Makefile
index 452f67deebc6..68676389d65f 100644
--- a/net/sunrpc/auth_gss/Makefile
+++ b/net/sunrpc/auth_gss/Makefile
@@ -12,6 +12,4 @@ auth_rpcgss-y := auth_gss.o \
 obj-$(CONFIG_RPCSEC_GSS_KRB5) += rpcsec_gss_krb5.o
 
 rpcsec_gss_krb5-y := gss_krb5_mech.o gss_krb5_seal.o gss_krb5_unseal.o \
-	gss_krb5_wrap.o gss_krb5_crypto.o gss_krb5_keys.o
-
-obj-$(CONFIG_RPCSEC_GSS_KRB5_KUNIT_TEST) += gss_krb5_test.o
+	gss_krb5_wrap.o gss_krb5_crypto.o
diff --git a/net/sunrpc/auth_gss/gss_krb5_crypto.c b/net/sunrpc/auth_gss/gss_krb5_crypto.c
index cfd5b56d1b52..cf461ebcdde5 100644
--- a/net/sunrpc/auth_gss/gss_krb5_crypto.c
+++ b/net/sunrpc/auth_gss/gss_krb5_crypto.c
@@ -34,19 +34,14 @@
  * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
  */
 
-#include <crypto/hash.h>
-#include <crypto/skcipher.h>
-#include <crypto/utils.h>
 #include <linux/err.h>
 #include <linux/types.h>
 #include <linux/mm.h>
 #include <linux/scatterlist.h>
 #include <linux/highmem.h>
 #include <linux/pagemap.h>
-#include <linux/random.h>
 #include <linux/sunrpc/gss_krb5.h>
 #include <linux/sunrpc/xdr.h>
-#include <kunit/visibility.h>
 
 #include "gss_krb5_internal.h"
 
@@ -54,303 +49,6 @@
 # define RPCDBG_FACILITY        RPCDBG_AUTH
 #endif
 
-/**
- * krb5_make_confounder - Generate a confounder string
- * @p: memory location into which to write the string
- * @conflen: string length to write, in octets
- *
- * RFCs 1964 and 3961 mention only "a random confounder" without going
- * into detail about its function or cryptographic requirements. The
- * assumed purpose is to prevent repeated encryption of a plaintext with
- * the same key from generating the same ciphertext. It is also used to
- * pad minimum plaintext length to at least a single cipher block.
- *
- * However, in situations like the GSS Kerberos 5 mechanism, where the
- * encryption IV is always all zeroes, the confounder also effectively
- * functions like an IV. Thus, not only must it be unique from message
- * to message, but it must also be difficult to predict. Otherwise an
- * attacker can correlate the confounder to previous or future values,
- * making the encryption easier to break.
- *
- * Given that the primary consumer of this encryption mechanism is a
- * network storage protocol, a type of traffic that often carries
- * predictable payloads (eg, all zeroes when reading unallocated blocks
- * from a file), our confounder generation has to be cryptographically
- * strong.
- */
-void krb5_make_confounder(u8 *p, int conflen)
-{
-	get_random_bytes(p, conflen);
-}
-
-/**
- * krb5_encrypt - simple encryption of an RPCSEC GSS payload
- * @tfm: initialized cipher transform
- * @iv: pointer to an IV
- * @in: plaintext to encrypt
- * @out: OUT: ciphertext
- * @length: length of input and output buffers, in bytes
- *
- * @iv may be NULL to force the use of an all-zero IV.
- * The buffer containing the IV must be as large as the
- * cipher's ivsize.
- *
- * Return values:
- *   %0: @in successfully encrypted into @out
- *   negative errno: @in not encrypted
- */
-u32
-krb5_encrypt(
-	struct crypto_sync_skcipher *tfm,
-	void * iv,
-	void * in,
-	void * out,
-	int length)
-{
-	u32 ret = -EINVAL;
-	struct scatterlist sg[1];
-	u8 local_iv[GSS_KRB5_MAX_BLOCKSIZE] = {0};
-	SYNC_SKCIPHER_REQUEST_ON_STACK(req, tfm);
-
-	if (length % crypto_sync_skcipher_blocksize(tfm) != 0)
-		goto out;
-
-	if (crypto_sync_skcipher_ivsize(tfm) > GSS_KRB5_MAX_BLOCKSIZE) {
-		dprintk("RPC:       gss_k5encrypt: tfm iv size too large %d\n",
-			crypto_sync_skcipher_ivsize(tfm));
-		goto out;
-	}
-
-	if (iv)
-		memcpy(local_iv, iv, crypto_sync_skcipher_ivsize(tfm));
-
-	memcpy(out, in, length);
-	sg_init_one(sg, out, length);
-
-	skcipher_request_set_sync_tfm(req, tfm);
-	skcipher_request_set_callback(req, 0, NULL, NULL);
-	skcipher_request_set_crypt(req, sg, sg, length, local_iv);
-
-	ret = crypto_skcipher_encrypt(req);
-	skcipher_request_zero(req);
-out:
-	dprintk("RPC:       krb5_encrypt returns %d\n", ret);
-	return ret;
-}
-
-static int
-checksummer(struct scatterlist *sg, void *data)
-{
-	struct ahash_request *req = data;
-
-	ahash_request_set_crypt(req, sg, NULL, sg->length);
-
-	return crypto_ahash_update(req);
-}
-
-/**
- * gss_krb5_checksum - Compute the MAC for a GSS Wrap or MIC token
- * @tfm: an initialized hash transform
- * @header: pointer to a buffer containing the token header, or NULL
- * @hdrlen: number of octets in @header
- * @body: xdr_buf containing an RPC message (body.len is the message length)
- * @body_offset: byte offset into @body to start checksumming
- * @cksumout: OUT: a buffer to be filled in with the computed HMAC
- *
- * Usually expressed as H = HMAC(K, message)[1..h] .
- *
- * Caller provides the truncation length of the output token (h) in
- * cksumout.len.
- *
- * Return values:
- *   %GSS_S_COMPLETE: Digest computed, @cksumout filled in
- *   %GSS_S_FAILURE: Call failed
- */
-u32
-gss_krb5_checksum(struct crypto_ahash *tfm, char *header, int hdrlen,
-		  const struct xdr_buf *body, int body_offset,
-		  struct xdr_netobj *cksumout)
-{
-	struct ahash_request *req;
-	int err = -ENOMEM;
-	u8 *checksumdata;
-
-	checksumdata = kmalloc(crypto_ahash_digestsize(tfm), GFP_KERNEL);
-	if (!checksumdata)
-		return GSS_S_FAILURE;
-
-	req = ahash_request_alloc(tfm, GFP_KERNEL);
-	if (!req)
-		goto out_free_cksum;
-	ahash_request_set_callback(req, CRYPTO_TFM_REQ_MAY_SLEEP, NULL, NULL);
-	err = crypto_ahash_init(req);
-	if (err)
-		goto out_free_ahash;
-
-	/*
-	 * Per RFC 4121 Section 4.2.4, the checksum is performed over the
-	 * data body first, then over the octets in "header".
-	 */
-	err = xdr_process_buf(body, body_offset, body->len - body_offset,
-			      checksummer, req);
-	if (err)
-		goto out_free_ahash;
-	if (header) {
-		struct scatterlist sg[1];
-
-		sg_init_one(sg, header, hdrlen);
-		ahash_request_set_crypt(req, sg, NULL, hdrlen);
-		err = crypto_ahash_update(req);
-		if (err)
-			goto out_free_ahash;
-	}
-
-	ahash_request_set_crypt(req, NULL, checksumdata, 0);
-	err = crypto_ahash_final(req);
-	if (err)
-		goto out_free_ahash;
-
-	memcpy(cksumout->data, checksumdata,
-	       min_t(int, cksumout->len, crypto_ahash_digestsize(tfm)));
-
-out_free_ahash:
-	ahash_request_free(req);
-out_free_cksum:
-	kfree_sensitive(checksumdata);
-	return err ? GSS_S_FAILURE : GSS_S_COMPLETE;
-}
-EXPORT_SYMBOL_IF_KUNIT(gss_krb5_checksum);
-
-struct encryptor_desc {
-	u8 iv[GSS_KRB5_MAX_BLOCKSIZE];
-	struct skcipher_request *req;
-	int pos;
-	struct xdr_buf *outbuf;
-	struct page **pages;
-	struct scatterlist infrags[4];
-	struct scatterlist outfrags[4];
-	int fragno;
-	int fraglen;
-};
-
-static int
-encryptor(struct scatterlist *sg, void *data)
-{
-	struct encryptor_desc *desc = data;
-	struct xdr_buf *outbuf = desc->outbuf;
-	struct crypto_sync_skcipher *tfm =
-		crypto_sync_skcipher_reqtfm(desc->req);
-	struct page *in_page;
-	int thislen = desc->fraglen + sg->length;
-	int fraglen, ret;
-	int page_pos;
-
-	/* Worst case is 4 fragments: head, end of page 1, start
-	 * of page 2, tail.  Anything more is a bug. */
-	BUG_ON(desc->fragno > 3);
-
-	page_pos = desc->pos - outbuf->head[0].iov_len;
-	if (page_pos >= 0 && page_pos < outbuf->page_len) {
-		/* pages are not in place: */
-		int i = (page_pos + outbuf->page_base) >> PAGE_SHIFT;
-		in_page = desc->pages[i];
-	} else {
-		in_page = sg_page(sg);
-	}
-	sg_set_page(&desc->infrags[desc->fragno], in_page, sg->length,
-		    sg->offset);
-	sg_set_page(&desc->outfrags[desc->fragno], sg_page(sg), sg->length,
-		    sg->offset);
-	desc->fragno++;
-	desc->fraglen += sg->length;
-	desc->pos += sg->length;
-
-	fraglen = thislen & (crypto_sync_skcipher_blocksize(tfm) - 1);
-	thislen -= fraglen;
-
-	if (thislen == 0)
-		return 0;
-
-	sg_mark_end(&desc->infrags[desc->fragno - 1]);
-	sg_mark_end(&desc->outfrags[desc->fragno - 1]);
-
-	skcipher_request_set_crypt(desc->req, desc->infrags, desc->outfrags,
-				   thislen, desc->iv);
-
-	ret = crypto_skcipher_encrypt(desc->req);
-	if (ret)
-		return ret;
-
-	sg_init_table(desc->infrags, 4);
-	sg_init_table(desc->outfrags, 4);
-
-	if (fraglen) {
-		sg_set_page(&desc->outfrags[0], sg_page(sg), fraglen,
-				sg->offset + sg->length - fraglen);
-		desc->infrags[0] = desc->outfrags[0];
-		sg_assign_page(&desc->infrags[0], in_page);
-		desc->fragno = 1;
-		desc->fraglen = fraglen;
-	} else {
-		desc->fragno = 0;
-		desc->fraglen = 0;
-	}
-	return 0;
-}
-
-struct decryptor_desc {
-	u8 iv[GSS_KRB5_MAX_BLOCKSIZE];
-	struct skcipher_request *req;
-	struct scatterlist frags[4];
-	int fragno;
-	int fraglen;
-};
-
-static int
-decryptor(struct scatterlist *sg, void *data)
-{
-	struct decryptor_desc *desc = data;
-	int thislen = desc->fraglen + sg->length;
-	struct crypto_sync_skcipher *tfm =
-		crypto_sync_skcipher_reqtfm(desc->req);
-	int fraglen, ret;
-
-	/* Worst case is 4 fragments: head, end of page 1, start
-	 * of page 2, tail.  Anything more is a bug. */
-	BUG_ON(desc->fragno > 3);
-	sg_set_page(&desc->frags[desc->fragno], sg_page(sg), sg->length,
-		    sg->offset);
-	desc->fragno++;
-	desc->fraglen += sg->length;
-
-	fraglen = thislen & (crypto_sync_skcipher_blocksize(tfm) - 1);
-	thislen -= fraglen;
-
-	if (thislen == 0)
-		return 0;
-
-	sg_mark_end(&desc->frags[desc->fragno - 1]);
-
-	skcipher_request_set_crypt(desc->req, desc->frags, desc->frags,
-				   thislen, desc->iv);
-
-	ret = crypto_skcipher_decrypt(desc->req);
-	if (ret)
-		return ret;
-
-	sg_init_table(desc->frags, 4);
-
-	if (fraglen) {
-		sg_set_page(&desc->frags[0], sg_page(sg), fraglen,
-				sg->offset + sg->length - fraglen);
-		desc->fragno = 1;
-		desc->fraglen = fraglen;
-	} else {
-		desc->fragno = 0;
-		desc->fraglen = 0;
-	}
-	return 0;
-}
 
 /*
  * This function makes the assumption that it was ultimately called
@@ -363,7 +61,7 @@ decryptor(struct scatterlist *sg, void *data)
  *
  * Even with that guarantee, this function may be called more than
  * once in the processing of gss_wrap().  The best we can do is
- * verify at compile-time (see GSS_KRB5_SLACK_CHECK) that the
+ * verify at compile-time (see GSS_KRB5_MAX_SLACK_NEEDED) that the
  * largest expected shift will fit within RPC_MAX_AUTH_SIZE.
  * At run-time we can verify that a single invocation of this
  * function doesn't attempt to use more the RPC_MAX_AUTH_SIZE.
@@ -389,263 +87,6 @@ xdr_extend_head(struct xdr_buf *buf, unsigned int base, unsigned int shiftlen)
 	return 0;
 }
 
-static u32
-gss_krb5_cts_crypt(struct crypto_sync_skcipher *cipher, struct xdr_buf *buf,
-		   u32 offset, u8 *iv, struct page **pages, int encrypt)
-{
-	u32 ret;
-	struct scatterlist sg[1];
-	SYNC_SKCIPHER_REQUEST_ON_STACK(req, cipher);
-	u8 *data;
-	struct page **save_pages;
-	u32 len = buf->len - offset;
-
-	if (len > GSS_KRB5_MAX_BLOCKSIZE * 2) {
-		WARN_ON(0);
-		return -ENOMEM;
-	}
-	data = kmalloc(GSS_KRB5_MAX_BLOCKSIZE * 2, GFP_KERNEL);
-	if (!data)
-		return -ENOMEM;
-
-	/*
-	 * For encryption, we want to read from the cleartext
-	 * page cache pages, and write the encrypted data to
-	 * the supplied xdr_buf pages.
-	 */
-	save_pages = buf->pages;
-	if (encrypt)
-		buf->pages = pages;
-
-	ret = read_bytes_from_xdr_buf(buf, offset, data, len);
-	buf->pages = save_pages;
-	if (ret)
-		goto out;
-
-	sg_init_one(sg, data, len);
-
-	skcipher_request_set_sync_tfm(req, cipher);
-	skcipher_request_set_callback(req, 0, NULL, NULL);
-	skcipher_request_set_crypt(req, sg, sg, len, iv);
-
-	if (encrypt)
-		ret = crypto_skcipher_encrypt(req);
-	else
-		ret = crypto_skcipher_decrypt(req);
-
-	skcipher_request_zero(req);
-
-	if (ret)
-		goto out;
-
-	ret = write_bytes_to_xdr_buf(buf, offset, data, len);
-
-#if IS_ENABLED(CONFIG_KUNIT)
-	/*
-	 * CBC-CTS does not define an output IV but RFC 3962 defines it as the
-	 * penultimate block of ciphertext, so copy that into the IV buffer
-	 * before returning.
-	 */
-	if (encrypt)
-		memcpy(iv, data, crypto_sync_skcipher_ivsize(cipher));
-#endif
-
-out:
-	kfree(data);
-	return ret;
-}
-
-/**
- * krb5_cbc_cts_encrypt - encrypt in CBC mode with CTS
- * @cts_tfm: CBC cipher with CTS
- * @cbc_tfm: base CBC cipher
- * @offset: starting byte offset for plaintext
- * @buf: OUT: output buffer
- * @pages: plaintext
- * @iv: output CBC initialization vector, or NULL
- * @ivsize: size of @iv, in octets
- *
- * To provide confidentiality, encrypt using cipher block chaining
- * with ciphertext stealing. Message integrity is handled separately.
- *
- * Return values:
- *   %0: encryption successful
- *   negative errno: encryption could not be completed
- */
-VISIBLE_IF_KUNIT
-int krb5_cbc_cts_encrypt(struct crypto_sync_skcipher *cts_tfm,
-			 struct crypto_sync_skcipher *cbc_tfm,
-			 u32 offset, struct xdr_buf *buf, struct page **pages,
-			 u8 *iv, unsigned int ivsize)
-{
-	u32 blocksize, nbytes, nblocks, cbcbytes;
-	struct encryptor_desc desc;
-	int err;
-
-	blocksize = crypto_sync_skcipher_blocksize(cts_tfm);
-	nbytes = buf->len - offset;
-	nblocks = (nbytes + blocksize - 1) / blocksize;
-	cbcbytes = 0;
-	if (nblocks > 2)
-		cbcbytes = (nblocks - 2) * blocksize;
-
-	memset(desc.iv, 0, sizeof(desc.iv));
-
-	/* Handle block-sized chunks of plaintext with CBC. */
-	if (cbcbytes) {
-		SYNC_SKCIPHER_REQUEST_ON_STACK(req, cbc_tfm);
-
-		desc.pos = offset;
-		desc.fragno = 0;
-		desc.fraglen = 0;
-		desc.pages = pages;
-		desc.outbuf = buf;
-		desc.req = req;
-
-		skcipher_request_set_sync_tfm(req, cbc_tfm);
-		skcipher_request_set_callback(req, 0, NULL, NULL);
-
-		sg_init_table(desc.infrags, 4);
-		sg_init_table(desc.outfrags, 4);
-
-		err = xdr_process_buf(buf, offset, cbcbytes, encryptor, &desc);
-		skcipher_request_zero(req);
-		if (err)
-			return err;
-	}
-
-	/* Remaining plaintext is handled with CBC-CTS. */
-	err = gss_krb5_cts_crypt(cts_tfm, buf, offset + cbcbytes,
-				 desc.iv, pages, 1);
-	if (err)
-		return err;
-
-	if (unlikely(iv))
-		memcpy(iv, desc.iv, ivsize);
-	return 0;
-}
-EXPORT_SYMBOL_IF_KUNIT(krb5_cbc_cts_encrypt);
-
-/**
- * krb5_cbc_cts_decrypt - decrypt in CBC mode with CTS
- * @cts_tfm: CBC cipher with CTS
- * @cbc_tfm: base CBC cipher
- * @offset: starting byte offset for plaintext
- * @buf: OUT: output buffer
- *
- * Return values:
- *   %0: decryption successful
- *   negative errno: decryption could not be completed
- */
-VISIBLE_IF_KUNIT
-int krb5_cbc_cts_decrypt(struct crypto_sync_skcipher *cts_tfm,
-			 struct crypto_sync_skcipher *cbc_tfm,
-			 u32 offset, struct xdr_buf *buf)
-{
-	u32 blocksize, nblocks, cbcbytes;
-	struct decryptor_desc desc;
-	int err;
-
-	blocksize = crypto_sync_skcipher_blocksize(cts_tfm);
-	nblocks = (buf->len + blocksize - 1) / blocksize;
-	cbcbytes = 0;
-	if (nblocks > 2)
-		cbcbytes = (nblocks - 2) * blocksize;
-
-	memset(desc.iv, 0, sizeof(desc.iv));
-
-	/* Handle block-sized chunks of plaintext with CBC. */
-	if (cbcbytes) {
-		SYNC_SKCIPHER_REQUEST_ON_STACK(req, cbc_tfm);
-
-		desc.fragno = 0;
-		desc.fraglen = 0;
-		desc.req = req;
-
-		skcipher_request_set_sync_tfm(req, cbc_tfm);
-		skcipher_request_set_callback(req, 0, NULL, NULL);
-
-		sg_init_table(desc.frags, 4);
-
-		err = xdr_process_buf(buf, 0, cbcbytes, decryptor, &desc);
-		skcipher_request_zero(req);
-		if (err)
-			return err;
-	}
-
-	/* Remaining plaintext is handled with CBC-CTS. */
-	return gss_krb5_cts_crypt(cts_tfm, buf, cbcbytes, desc.iv, NULL, 0);
-}
-EXPORT_SYMBOL_IF_KUNIT(krb5_cbc_cts_decrypt);
-
-/**
- * krb5_etm_checksum - Compute a MAC for a GSS Wrap token
- * @cipher: an initialized cipher transform
- * @tfm: an initialized hash transform
- * @body: xdr_buf containing an RPC message (body.len is the message length)
- * @body_offset: byte offset into @body to start checksumming
- * @cksumout: OUT: a buffer to be filled in with the computed HMAC
- *
- * Usually expressed as H = HMAC(K, IV | ciphertext)[1..h] .
- *
- * Caller provides the truncation length of the output token (h) in
- * cksumout.len.
- *
- * Return values:
- *   %GSS_S_COMPLETE: Digest computed, @cksumout filled in
- *   %GSS_S_FAILURE: Call failed
- */
-VISIBLE_IF_KUNIT
-u32 krb5_etm_checksum(struct crypto_sync_skcipher *cipher,
-		      struct crypto_ahash *tfm, const struct xdr_buf *body,
-		      int body_offset, struct xdr_netobj *cksumout)
-{
-	unsigned int ivsize = crypto_sync_skcipher_ivsize(cipher);
-	struct ahash_request *req;
-	struct scatterlist sg[1];
-	u8 *iv, *checksumdata;
-	int err = -ENOMEM;
-
-	checksumdata = kmalloc(crypto_ahash_digestsize(tfm), GFP_KERNEL);
-	if (!checksumdata)
-		return GSS_S_FAILURE;
-	/* For RPCSEC, the "initial cipher state" is always all zeroes. */
-	iv = kzalloc(ivsize, GFP_KERNEL);
-	if (!iv)
-		goto out_free_mem;
-
-	req = ahash_request_alloc(tfm, GFP_KERNEL);
-	if (!req)
-		goto out_free_mem;
-	ahash_request_set_callback(req, CRYPTO_TFM_REQ_MAY_SLEEP, NULL, NULL);
-	err = crypto_ahash_init(req);
-	if (err)
-		goto out_free_ahash;
-
-	sg_init_one(sg, iv, ivsize);
-	ahash_request_set_crypt(req, sg, NULL, ivsize);
-	err = crypto_ahash_update(req);
-	if (err)
-		goto out_free_ahash;
-	err = xdr_process_buf(body, body_offset, body->len - body_offset,
-			      checksummer, req);
-	if (err)
-		goto out_free_ahash;
-
-	ahash_request_set_crypt(req, NULL, checksumdata, 0);
-	err = crypto_ahash_final(req);
-	if (err)
-		goto out_free_ahash;
-	memcpy(cksumout->data, checksumdata, cksumout->len);
-
-out_free_ahash:
-	ahash_request_free(req);
-out_free_mem:
-	kfree(iv);
-	kfree_sensitive(checksumdata);
-	return err ? GSS_S_FAILURE : GSS_S_COMPLETE;
-}
-EXPORT_SYMBOL_IF_KUNIT(krb5_etm_checksum);
 
 /**
  * gss_krb5_aead_encrypt - Encrypt a wrap token using crypto/krb5
diff --git a/net/sunrpc/auth_gss/gss_krb5_internal.h b/net/sunrpc/auth_gss/gss_krb5_internal.h
index 6b08a7486e0b..208f9df9ea96 100644
--- a/net/sunrpc/auth_gss/gss_krb5_internal.h
+++ b/net/sunrpc/auth_gss/gss_krb5_internal.h
@@ -10,38 +10,8 @@
 
 #include <crypto/krb5.h>
 
-/*
- * The RFCs often specify payload lengths in bits. This helper
- * converts a specified bit-length to the number of octets/bytes.
- */
-#define BITS2OCTETS(x)	((x) / 8)
-
 struct krb5_ctx;
 
-struct gss_krb5_enctype {
-	const u32		etype;		/* encryption (key) type */
-	const u32		ctype;		/* checksum type */
-	const char		*name;		/* "friendly" name */
-	const char		*encrypt_name;	/* crypto encrypt name */
-	const char		*aux_cipher;	/* aux encrypt cipher name */
-	const char		*cksum_name;	/* crypto checksum name */
-	const u16		signalg;	/* signing algorithm */
-	const u16		sealalg;	/* sealing algorithm */
-	const u32		cksumlength;	/* checksum length */
-	const u32		keyed_cksum;	/* is it a keyed cksum? */
-	const u32		keybytes;	/* raw key len, in bytes */
-	const u32		keylength;	/* protocol key length, in octets */
-	const u32		Kc_length;	/* checksum subkey length, in octets */
-	const u32		Ke_length;	/* encryption subkey length, in octets */
-	const u32		Ki_length;	/* integrity subkey length, in octets */
-
-	int (*derive_key)(const struct gss_krb5_enctype *gk5e,
-			  const struct xdr_netobj *in,
-			  struct xdr_netobj *out,
-			  const struct xdr_netobj *label,
-			  gfp_t gfp_mask);
-};
-
 /* krb5_ctx flags definitions */
 #define KRB5_CTX_FLAG_INITIATOR         0x00000001
 #define KRB5_CTX_FLAG_ACCEPTOR_SUBKEY   0x00000004
@@ -50,7 +20,6 @@ struct krb5_ctx {
 	int			initiate; /* 1 = initiating, 0 = accepting */
 	u32			enctype;
 	u32			flags;
-	const struct gss_krb5_enctype *gk5e; /* enctype-specific info */
 	const struct krb5_enctype *krb5e; /* crypto/krb5 enctype */
 	struct crypto_aead	*initiator_enc_aead;
 	struct crypto_aead	*acceptor_enc_aead;
@@ -58,7 +27,6 @@ struct krb5_ctx {
 	struct crypto_shash	*acceptor_sign_shash;
 	u8			Ksess[GSS_KRB5_MAX_KEYLEN]; /* session key */
 	u8			cksum[GSS_KRB5_MAX_KEYLEN];
-	atomic_t		seq_send;
 	atomic64_t		seq_send64;
 	time64_t		endtime;
 	struct xdr_netobj	mech_used;
@@ -85,35 +53,6 @@ u32 gss_krb5_unwrap_v2(struct krb5_ctx *kctx, int offset, int len,
  * Implementation internal functions
  */
 
-/* Key Derivation Functions */
-
-int krb5_derive_key_v2(const struct gss_krb5_enctype *gk5e,
-		       const struct xdr_netobj *inkey,
-		       struct xdr_netobj *outkey,
-		       const struct xdr_netobj *label,
-		       gfp_t gfp_mask);
-
-int krb5_kdf_hmac_sha2(const struct gss_krb5_enctype *gk5e,
-		       const struct xdr_netobj *inkey,
-		       struct xdr_netobj *outkey,
-		       const struct xdr_netobj *in_constant,
-		       gfp_t gfp_mask);
-
-int krb5_kdf_feedback_cmac(const struct gss_krb5_enctype *gk5e,
-			   const struct xdr_netobj *inkey,
-			   struct xdr_netobj *outkey,
-			   const struct xdr_netobj *in_constant,
-			   gfp_t gfp_mask);
-
-void krb5_make_confounder(u8 *p, int conflen);
-
-u32 gss_krb5_checksum(struct crypto_ahash *tfm, char *header, int hdrlen,
-		      const struct xdr_buf *body, int body_offset,
-		      struct xdr_netobj *cksumout);
-
-u32 krb5_encrypt(struct crypto_sync_skcipher *key, void *iv, void *in,
-		 void *out, int length);
-
 int xdr_extend_head(struct xdr_buf *buf, unsigned int base,
 		    unsigned int shiftlen);
 
@@ -130,19 +69,5 @@ u32 gss_krb5_aead_encrypt(struct krb5_ctx *kctx, u32 offset,
 u32 gss_krb5_aead_decrypt(struct krb5_ctx *kctx, u32 offset, u32 len,
 			  struct xdr_buf *buf, u32 *headskip, u32 *tailskip);
 
-#if IS_ENABLED(CONFIG_KUNIT)
-void krb5_nfold(u32 inbits, const u8 *in, u32 outbits, u8 *out);
-const struct gss_krb5_enctype *gss_krb5_lookup_enctype(u32 etype);
-int krb5_cbc_cts_encrypt(struct crypto_sync_skcipher *cts_tfm,
-			 struct crypto_sync_skcipher *cbc_tfm, u32 offset,
-			 struct xdr_buf *buf, struct page **pages,
-			 u8 *iv, unsigned int ivsize);
-int krb5_cbc_cts_decrypt(struct crypto_sync_skcipher *cts_tfm,
-			 struct crypto_sync_skcipher *cbc_tfm,
-			 u32 offset, struct xdr_buf *buf);
-u32 krb5_etm_checksum(struct crypto_sync_skcipher *cipher,
-		      struct crypto_ahash *tfm, const struct xdr_buf *body,
-		      int body_offset, struct xdr_netobj *cksumout);
-#endif
 
 #endif /* _NET_SUNRPC_AUTH_GSS_KRB5_INTERNAL_H */
diff --git a/net/sunrpc/auth_gss/gss_krb5_keys.c b/net/sunrpc/auth_gss/gss_krb5_keys.c
deleted file mode 100644
index 4eb19c3a54c7..000000000000
--- a/net/sunrpc/auth_gss/gss_krb5_keys.c
+++ /dev/null
@@ -1,546 +0,0 @@
-/*
- * COPYRIGHT (c) 2008
- * The Regents of the University of Michigan
- * ALL RIGHTS RESERVED
- *
- * Permission is granted to use, copy, create derivative works
- * and redistribute this software and such derivative works
- * for any purpose, so long as the name of The University of
- * Michigan is not used in any advertising or publicity
- * pertaining to the use of distribution of this software
- * without specific, written prior authorization.  If the
- * above copyright notice or any other identification of the
- * University of Michigan is included in any copy of any
- * portion of this software, then the disclaimer below must
- * also be included.
- *
- * THIS SOFTWARE IS PROVIDED AS IS, WITHOUT REPRESENTATION
- * FROM THE UNIVERSITY OF MICHIGAN AS TO ITS FITNESS FOR ANY
- * PURPOSE, AND WITHOUT WARRANTY BY THE UNIVERSITY OF
- * MICHIGAN OF ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING
- * WITHOUT LIMITATION THE IMPLIED WARRANTIES OF
- * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE
- * REGENTS OF THE UNIVERSITY OF MICHIGAN SHALL NOT BE LIABLE
- * FOR ANY DAMAGES, INCLUDING SPECIAL, INDIRECT, INCIDENTAL, OR
- * CONSEQUENTIAL DAMAGES, WITH RESPECT TO ANY CLAIM ARISING
- * OUT OF OR IN CONNECTION WITH THE USE OF THE SOFTWARE, EVEN
- * IF IT HAS BEEN OR IS HEREAFTER ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGES.
- */
-
-/*
- * Copyright (C) 1998 by the FundsXpress, INC.
- *
- * All rights reserved.
- *
- * Export of this software from the United States of America may require
- * a specific license from the United States Government.  It is the
- * responsibility of any person or organization contemplating export to
- * obtain such a license before exporting.
- *
- * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and
- * distribute this software and its documentation for any purpose and
- * without fee is hereby granted, provided that the above copyright
- * notice appear in all copies and that both that copyright notice and
- * this permission notice appear in supporting documentation, and that
- * the name of FundsXpress. not be used in advertising or publicity pertaining
- * to distribution of the software without specific, written prior
- * permission.  FundsXpress makes no representations about the suitability of
- * this software for any purpose.  It is provided "as is" without express
- * or implied warranty.
- *
- * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
- * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
- * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
- */
-
-#include <crypto/skcipher.h>
-#include <linux/err.h>
-#include <linux/types.h>
-#include <linux/sunrpc/gss_krb5.h>
-#include <linux/sunrpc/xdr.h>
-#include <linux/lcm.h>
-#include <crypto/hash.h>
-#include <kunit/visibility.h>
-
-#include "gss_krb5_internal.h"
-
-#if IS_ENABLED(CONFIG_SUNRPC_DEBUG)
-# define RPCDBG_FACILITY        RPCDBG_AUTH
-#endif
-
-/**
- * krb5_nfold - n-fold function
- * @inbits: number of bits in @in
- * @in: buffer containing input to fold
- * @outbits: number of bits in the output buffer
- * @out: buffer to hold the result
- *
- * This is the n-fold function as described in rfc3961, sec 5.1
- * Taken from MIT Kerberos and modified.
- */
-VISIBLE_IF_KUNIT
-void krb5_nfold(u32 inbits, const u8 *in, u32 outbits, u8 *out)
-{
-	unsigned long ulcm;
-	int byte, i, msbit;
-
-	/* the code below is more readable if I make these bytes
-	   instead of bits */
-
-	inbits >>= 3;
-	outbits >>= 3;
-
-	/* first compute lcm(n,k) */
-	ulcm = lcm(inbits, outbits);
-
-	/* now do the real work */
-
-	memset(out, 0, outbits);
-	byte = 0;
-
-	/* this will end up cycling through k lcm(k,n)/k times, which
-	   is correct */
-	for (i = ulcm-1; i >= 0; i--) {
-		/* compute the msbit in k which gets added into this byte */
-		msbit = (
-			/* first, start with the msbit in the first,
-			 * unrotated byte */
-			 ((inbits << 3) - 1)
-			 /* then, for each byte, shift to the right
-			  * for each repetition */
-			 + (((inbits << 3) + 13) * (i/inbits))
-			 /* last, pick out the correct byte within
-			  * that shifted repetition */
-			 + ((inbits - (i % inbits)) << 3)
-			 ) % (inbits << 3);
-
-		/* pull out the byte value itself */
-		byte += (((in[((inbits - 1) - (msbit >> 3)) % inbits] << 8)|
-				  (in[((inbits) - (msbit >> 3)) % inbits]))
-				 >> ((msbit & 7) + 1)) & 0xff;
-
-		/* do the addition */
-		byte += out[i % outbits];
-		out[i % outbits] = byte & 0xff;
-
-		/* keep around the carry bit, if any */
-		byte >>= 8;
-
-	}
-
-	/* if there's a carry bit left over, add it back in */
-	if (byte) {
-		for (i = outbits - 1; i >= 0; i--) {
-			/* do the addition */
-			byte += out[i];
-			out[i] = byte & 0xff;
-
-			/* keep around the carry bit, if any */
-			byte >>= 8;
-		}
-	}
-}
-EXPORT_SYMBOL_IF_KUNIT(krb5_nfold);
-
-/*
- * This is the DK (derive_key) function as described in rfc3961, sec 5.1
- * Taken from MIT Kerberos and modified.
- */
-static int krb5_DK(const struct gss_krb5_enctype *gk5e,
-		   const struct xdr_netobj *inkey, u8 *rawkey,
-		   const struct xdr_netobj *in_constant, gfp_t gfp_mask)
-{
-	size_t blocksize, keybytes, keylength, n;
-	unsigned char *inblockdata, *outblockdata;
-	struct xdr_netobj inblock, outblock;
-	struct crypto_sync_skcipher *cipher;
-	int ret = -EINVAL;
-
-	keybytes = gk5e->keybytes;
-	keylength = gk5e->keylength;
-
-	if (inkey->len != keylength)
-		goto err_return;
-
-	cipher = crypto_alloc_sync_skcipher(gk5e->encrypt_name, 0, 0);
-	if (IS_ERR(cipher))
-		goto err_return;
-	blocksize = crypto_sync_skcipher_blocksize(cipher);
-	if (crypto_sync_skcipher_setkey(cipher, inkey->data, inkey->len))
-		goto err_free_cipher;
-
-	ret = -ENOMEM;
-	inblockdata = kmalloc(blocksize, gfp_mask);
-	if (inblockdata == NULL)
-		goto err_free_cipher;
-
-	outblockdata = kmalloc(blocksize, gfp_mask);
-	if (outblockdata == NULL)
-		goto err_free_in;
-
-	inblock.data = (char *) inblockdata;
-	inblock.len = blocksize;
-
-	outblock.data = (char *) outblockdata;
-	outblock.len = blocksize;
-
-	/* initialize the input block */
-
-	if (in_constant->len == inblock.len) {
-		memcpy(inblock.data, in_constant->data, inblock.len);
-	} else {
-		krb5_nfold(in_constant->len * 8, in_constant->data,
-			   inblock.len * 8, inblock.data);
-	}
-
-	/* loop encrypting the blocks until enough key bytes are generated */
-
-	n = 0;
-	while (n < keybytes) {
-		krb5_encrypt(cipher, NULL, inblock.data, outblock.data,
-			     inblock.len);
-
-		if ((keybytes - n) <= outblock.len) {
-			memcpy(rawkey + n, outblock.data, (keybytes - n));
-			break;
-		}
-
-		memcpy(rawkey + n, outblock.data, outblock.len);
-		memcpy(inblock.data, outblock.data, outblock.len);
-		n += outblock.len;
-	}
-
-	ret = 0;
-
-	kfree_sensitive(outblockdata);
-err_free_in:
-	kfree_sensitive(inblockdata);
-err_free_cipher:
-	crypto_free_sync_skcipher(cipher);
-err_return:
-	return ret;
-}
-
-/*
- * This is the identity function, with some sanity checking.
- */
-static int krb5_random_to_key_v2(const struct gss_krb5_enctype *gk5e,
-				 struct xdr_netobj *randombits,
-				 struct xdr_netobj *key)
-{
-	int ret = -EINVAL;
-
-	if (key->len != 16 && key->len != 32) {
-		dprintk("%s: key->len is %d\n", __func__, key->len);
-		goto err_out;
-	}
-	if (randombits->len != 16 && randombits->len != 32) {
-		dprintk("%s: randombits->len is %d\n",
-			__func__, randombits->len);
-		goto err_out;
-	}
-	if (randombits->len != key->len) {
-		dprintk("%s: randombits->len is %d, key->len is %d\n",
-			__func__, randombits->len, key->len);
-		goto err_out;
-	}
-	memcpy(key->data, randombits->data, key->len);
-	ret = 0;
-err_out:
-	return ret;
-}
-
-/**
- * krb5_derive_key_v2 - Derive a subkey for an RFC 3962 enctype
- * @gk5e: Kerberos 5 enctype profile
- * @inkey: base protocol key
- * @outkey: OUT: derived key
- * @label: subkey usage label
- * @gfp_mask: memory allocation control flags
- *
- * Caller sets @outkey->len to the desired length of the derived key.
- *
- * On success, returns 0 and fills in @outkey. A negative errno value
- * is returned on failure.
- */
-int krb5_derive_key_v2(const struct gss_krb5_enctype *gk5e,
-		       const struct xdr_netobj *inkey,
-		       struct xdr_netobj *outkey,
-		       const struct xdr_netobj *label,
-		       gfp_t gfp_mask)
-{
-	struct xdr_netobj inblock;
-	int ret;
-
-	inblock.len = gk5e->keybytes;
-	inblock.data = kmalloc(inblock.len, gfp_mask);
-	if (!inblock.data)
-		return -ENOMEM;
-
-	ret = krb5_DK(gk5e, inkey, inblock.data, label, gfp_mask);
-	if (!ret)
-		ret = krb5_random_to_key_v2(gk5e, &inblock, outkey);
-
-	kfree_sensitive(inblock.data);
-	return ret;
-}
-
-/*
- * K(i) = CMAC(key, K(i-1) | i | constant | 0x00 | k)
- *
- *    i: A block counter is used with a length of 4 bytes, represented
- *       in big-endian order.
- *
- *    constant: The label input to the KDF is the usage constant supplied
- *              to the key derivation function
- *
- *    k: The length of the output key in bits, represented as a 4-byte
- *       string in big-endian order.
- *
- * Caller fills in K(i-1) in @step, and receives the result K(i)
- * in the same buffer.
- */
-static int
-krb5_cmac_Ki(struct crypto_shash *tfm, const struct xdr_netobj *constant,
-	     u32 outlen, u32 count, struct xdr_netobj *step)
-{
-	__be32 k = cpu_to_be32(outlen * 8);
-	SHASH_DESC_ON_STACK(desc, tfm);
-	__be32 i = cpu_to_be32(count);
-	u8 zero = 0;
-	int ret;
-
-	desc->tfm = tfm;
-	ret = crypto_shash_init(desc);
-	if (ret)
-		goto out_err;
-
-	ret = crypto_shash_update(desc, step->data, step->len);
-	if (ret)
-		goto out_err;
-	ret = crypto_shash_update(desc, (u8 *)&i, sizeof(i));
-	if (ret)
-		goto out_err;
-	ret = crypto_shash_update(desc, constant->data, constant->len);
-	if (ret)
-		goto out_err;
-	ret = crypto_shash_update(desc, &zero, sizeof(zero));
-	if (ret)
-		goto out_err;
-	ret = crypto_shash_update(desc, (u8 *)&k, sizeof(k));
-	if (ret)
-		goto out_err;
-	ret = crypto_shash_final(desc, step->data);
-	if (ret)
-		goto out_err;
-
-out_err:
-	shash_desc_zero(desc);
-	return ret;
-}
-
-/**
- * krb5_kdf_feedback_cmac - Derive a subkey for a Camellia/CMAC-based enctype
- * @gk5e: Kerberos 5 enctype parameters
- * @inkey: base protocol key
- * @outkey: OUT: derived key
- * @constant: subkey usage label
- * @gfp_mask: memory allocation control flags
- *
- * RFC 6803 Section 3:
- *
- * "We use a key derivation function from the family specified in
- *  [SP800-108], Section 5.2, 'KDF in Feedback Mode'."
- *
- *	n = ceiling(k / 128)
- *	K(0) = zeros
- *	K(i) = CMAC(key, K(i-1) | i | constant | 0x00 | k)
- *	DR(key, constant) = k-truncate(K(1) | K(2) | ... | K(n))
- *	KDF-FEEDBACK-CMAC(key, constant) = random-to-key(DR(key, constant))
- *
- * Caller sets @outkey->len to the desired length of the derived key (k).
- *
- * On success, returns 0 and fills in @outkey. A negative errno value
- * is returned on failure.
- */
-int
-krb5_kdf_feedback_cmac(const struct gss_krb5_enctype *gk5e,
-		       const struct xdr_netobj *inkey,
-		       struct xdr_netobj *outkey,
-		       const struct xdr_netobj *constant,
-		       gfp_t gfp_mask)
-{
-	struct xdr_netobj step = { .data = NULL };
-	struct xdr_netobj DR = { .data = NULL };
-	unsigned int blocksize, offset;
-	struct crypto_shash *tfm;
-	int n, count, ret;
-
-	/*
-	 * This implementation assumes the CMAC used for an enctype's
-	 * key derivation is the same as the CMAC used for its
-	 * checksumming. This happens to be true for enctypes that
-	 * are currently supported by this implementation.
-	 */
-	tfm = crypto_alloc_shash(gk5e->cksum_name, 0, 0);
-	if (IS_ERR(tfm)) {
-		ret = PTR_ERR(tfm);
-		goto out;
-	}
-	ret = crypto_shash_setkey(tfm, inkey->data, inkey->len);
-	if (ret)
-		goto out_free_tfm;
-
-	blocksize = crypto_shash_digestsize(tfm);
-	n = (outkey->len + blocksize - 1) / blocksize;
-
-	/* K(0) is all zeroes */
-	ret = -ENOMEM;
-	step.len = blocksize;
-	step.data = kzalloc(step.len, gfp_mask);
-	if (!step.data)
-		goto out_free_tfm;
-
-	DR.len = blocksize * n;
-	DR.data = kmalloc(DR.len, gfp_mask);
-	if (!DR.data)
-		goto out_free_tfm;
-
-	/* XXX: Does not handle partial-block key sizes */
-	for (offset = 0, count = 1; count <= n; count++) {
-		ret = krb5_cmac_Ki(tfm, constant, outkey->len, count, &step);
-		if (ret)
-			goto out_free_tfm;
-
-		memcpy(DR.data + offset, step.data, blocksize);
-		offset += blocksize;
-	}
-
-	/* k-truncate and random-to-key */
-	memcpy(outkey->data, DR.data, outkey->len);
-	ret = 0;
-
-out_free_tfm:
-	crypto_free_shash(tfm);
-out:
-	kfree_sensitive(step.data);
-	kfree_sensitive(DR.data);
-	return ret;
-}
-
-/*
- * K1 = HMAC-SHA(key, 0x00000001 | label | 0x00 | k)
- *
- *    key: The source of entropy from which subsequent keys are derived.
- *
- *    label: An octet string describing the intended usage of the
- *    derived key.
- *
- *    k: Length in bits of the key to be outputted, expressed in
- *    big-endian binary representation in 4 bytes.
- */
-static int
-krb5_hmac_K1(struct crypto_shash *tfm, const struct xdr_netobj *label,
-	     u32 outlen, struct xdr_netobj *K1)
-{
-	__be32 k = cpu_to_be32(outlen * 8);
-	SHASH_DESC_ON_STACK(desc, tfm);
-	__be32 one = cpu_to_be32(1);
-	u8 zero = 0;
-	int ret;
-
-	desc->tfm = tfm;
-	ret = crypto_shash_init(desc);
-	if (ret)
-		goto out_err;
-	ret = crypto_shash_update(desc, (u8 *)&one, sizeof(one));
-	if (ret)
-		goto out_err;
-	ret = crypto_shash_update(desc, label->data, label->len);
-	if (ret)
-		goto out_err;
-	ret = crypto_shash_update(desc, &zero, sizeof(zero));
-	if (ret)
-		goto out_err;
-	ret = crypto_shash_update(desc, (u8 *)&k, sizeof(k));
-	if (ret)
-		goto out_err;
-	ret = crypto_shash_final(desc, K1->data);
-	if (ret)
-		goto out_err;
-
-out_err:
-	shash_desc_zero(desc);
-	return ret;
-}
-
-/**
- * krb5_kdf_hmac_sha2 - Derive a subkey for an AES/SHA2-based enctype
- * @gk5e: Kerberos 5 enctype policy parameters
- * @inkey: base protocol key
- * @outkey: OUT: derived key
- * @label: subkey usage label
- * @gfp_mask: memory allocation control flags
- *
- * RFC 8009 Section 3:
- *
- *  "We use a key derivation function from Section 5.1 of [SP800-108],
- *   which uses the HMAC algorithm as the PRF."
- *
- *	function KDF-HMAC-SHA2(key, label, [context,] k):
- *		k-truncate(K1)
- *
- * Caller sets @outkey->len to the desired length of the derived key.
- *
- * On success, returns 0 and fills in @outkey. A negative errno value
- * is returned on failure.
- */
-int
-krb5_kdf_hmac_sha2(const struct gss_krb5_enctype *gk5e,
-		   const struct xdr_netobj *inkey,
-		   struct xdr_netobj *outkey,
-		   const struct xdr_netobj *label,
-		   gfp_t gfp_mask)
-{
-	struct crypto_shash *tfm;
-	struct xdr_netobj K1 = {
-		.data = NULL,
-	};
-	int ret;
-
-	/*
-	 * This implementation assumes the HMAC used for an enctype's
-	 * key derivation is the same as the HMAC used for its
-	 * checksumming. This happens to be true for enctypes that
-	 * are currently supported by this implementation.
-	 */
-	tfm = crypto_alloc_shash(gk5e->cksum_name, 0, 0);
-	if (IS_ERR(tfm)) {
-		ret = PTR_ERR(tfm);
-		goto out;
-	}
-	ret = crypto_shash_setkey(tfm, inkey->data, inkey->len);
-	if (ret)
-		goto out_free_tfm;
-
-	K1.len = crypto_shash_digestsize(tfm);
-	K1.data = kmalloc(K1.len, gfp_mask);
-	if (!K1.data) {
-		ret = -ENOMEM;
-		goto out_free_tfm;
-	}
-
-	ret = krb5_hmac_K1(tfm, label, outkey->len, &K1);
-	if (ret)
-		goto out_free_tfm;
-
-	/* k-truncate and random-to-key */
-	memcpy(outkey->data, K1.data, outkey->len);
-
-out_free_tfm:
-	kfree_sensitive(K1.data);
-	crypto_free_shash(tfm);
-out:
-	return ret;
-}
diff --git a/net/sunrpc/auth_gss/gss_krb5_mech.c b/net/sunrpc/auth_gss/gss_krb5_mech.c
index d8cb79fd2463..5a52fd84f946 100644
--- a/net/sunrpc/auth_gss/gss_krb5_mech.c
+++ b/net/sunrpc/auth_gss/gss_krb5_mech.c
@@ -17,7 +17,6 @@
 #include <linux/sunrpc/auth.h>
 #include <linux/sunrpc/gss_krb5.h>
 #include <linux/sunrpc/xdr.h>
-#include <kunit/visibility.h>
 
 #include "auth_gss_internal.h"
 #include "gss_krb5_internal.h"
@@ -28,141 +27,6 @@
 
 static struct gss_api_mech gss_kerberos_mech;
 
-static const struct gss_krb5_enctype supported_gss_krb5_enctypes[] = {
-#if defined(CONFIG_RPCSEC_GSS_KRB5_ENCTYPES_AES_SHA1)
-	/*
-	 * AES-128 with SHA-1 (RFC 3962)
-	 */
-	{
-	  .etype = ENCTYPE_AES128_CTS_HMAC_SHA1_96,
-	  .ctype = CKSUMTYPE_HMAC_SHA1_96_AES128,
-	  .name = "aes128-cts",
-	  .encrypt_name = "cts(cbc(aes))",
-	  .aux_cipher = "cbc(aes)",
-	  .cksum_name = "hmac(sha1)",
-	  .derive_key = krb5_derive_key_v2,
-
-	  .signalg = -1,
-	  .sealalg = -1,
-	  .keybytes = 16,
-	  .keylength = BITS2OCTETS(128),
-	  .Kc_length = BITS2OCTETS(128),
-	  .Ke_length = BITS2OCTETS(128),
-	  .Ki_length = BITS2OCTETS(128),
-	  .cksumlength = BITS2OCTETS(96),
-	  .keyed_cksum = 1,
-	},
-	/*
-	 * AES-256 with SHA-1 (RFC 3962)
-	 */
-	{
-	  .etype = ENCTYPE_AES256_CTS_HMAC_SHA1_96,
-	  .ctype = CKSUMTYPE_HMAC_SHA1_96_AES256,
-	  .name = "aes256-cts",
-	  .encrypt_name = "cts(cbc(aes))",
-	  .aux_cipher = "cbc(aes)",
-	  .cksum_name = "hmac(sha1)",
-	  .derive_key = krb5_derive_key_v2,
-
-	  .signalg = -1,
-	  .sealalg = -1,
-	  .keybytes = 32,
-	  .keylength = BITS2OCTETS(256),
-	  .Kc_length = BITS2OCTETS(256),
-	  .Ke_length = BITS2OCTETS(256),
-	  .Ki_length = BITS2OCTETS(256),
-	  .cksumlength = BITS2OCTETS(96),
-	  .keyed_cksum = 1,
-	},
-#endif
-
-#if defined(CONFIG_RPCSEC_GSS_KRB5_ENCTYPES_CAMELLIA)
-	/*
-	 * Camellia-128 with CMAC (RFC 6803)
-	 */
-	{
-		.etype		= ENCTYPE_CAMELLIA128_CTS_CMAC,
-		.ctype		= CKSUMTYPE_CMAC_CAMELLIA128,
-		.name		= "camellia128-cts-cmac",
-		.encrypt_name	= "cts(cbc(camellia))",
-		.aux_cipher	= "cbc(camellia)",
-		.cksum_name	= "cmac(camellia)",
-		.cksumlength	= BITS2OCTETS(128),
-		.keyed_cksum	= 1,
-		.keylength	= BITS2OCTETS(128),
-		.Kc_length	= BITS2OCTETS(128),
-		.Ke_length	= BITS2OCTETS(128),
-		.Ki_length	= BITS2OCTETS(128),
-
-		.derive_key	= krb5_kdf_feedback_cmac,
-
-	},
-	/*
-	 * Camellia-256 with CMAC (RFC 6803)
-	 */
-	{
-		.etype		= ENCTYPE_CAMELLIA256_CTS_CMAC,
-		.ctype		= CKSUMTYPE_CMAC_CAMELLIA256,
-		.name		= "camellia256-cts-cmac",
-		.encrypt_name	= "cts(cbc(camellia))",
-		.aux_cipher	= "cbc(camellia)",
-		.cksum_name	= "cmac(camellia)",
-		.cksumlength	= BITS2OCTETS(128),
-		.keyed_cksum	= 1,
-		.keylength	= BITS2OCTETS(256),
-		.Kc_length	= BITS2OCTETS(256),
-		.Ke_length	= BITS2OCTETS(256),
-		.Ki_length	= BITS2OCTETS(256),
-
-		.derive_key	= krb5_kdf_feedback_cmac,
-
-	},
-#endif
-
-#if defined(CONFIG_RPCSEC_GSS_KRB5_ENCTYPES_AES_SHA2)
-	/*
-	 * AES-128 with SHA-256 (RFC 8009)
-	 */
-	{
-		.etype		= ENCTYPE_AES128_CTS_HMAC_SHA256_128,
-		.ctype		= CKSUMTYPE_HMAC_SHA256_128_AES128,
-		.name		= "aes128-cts-hmac-sha256-128",
-		.encrypt_name	= "cts(cbc(aes))",
-		.aux_cipher	= "cbc(aes)",
-		.cksum_name	= "hmac(sha256)",
-		.cksumlength	= BITS2OCTETS(128),
-		.keyed_cksum	= 1,
-		.keylength	= BITS2OCTETS(128),
-		.Kc_length	= BITS2OCTETS(128),
-		.Ke_length	= BITS2OCTETS(128),
-		.Ki_length	= BITS2OCTETS(128),
-
-		.derive_key	= krb5_kdf_hmac_sha2,
-
-	},
-	/*
-	 * AES-256 with SHA-384 (RFC 8009)
-	 */
-	{
-		.etype		= ENCTYPE_AES256_CTS_HMAC_SHA384_192,
-		.ctype		= CKSUMTYPE_HMAC_SHA384_192_AES256,
-		.name		= "aes256-cts-hmac-sha384-192",
-		.encrypt_name	= "cts(cbc(aes))",
-		.aux_cipher	= "cbc(aes)",
-		.cksum_name	= "hmac(sha384)",
-		.cksumlength	= BITS2OCTETS(192),
-		.keyed_cksum	= 1,
-		.keylength	= BITS2OCTETS(256),
-		.Kc_length	= BITS2OCTETS(192),
-		.Ke_length	= BITS2OCTETS(256),
-		.Ki_length	= BITS2OCTETS(192),
-
-		.derive_key	= krb5_kdf_hmac_sha2,
-
-	},
-#endif
-};
-
 /*
  * The list of advertised enctypes is specified in order of most
  * preferred to least.
@@ -204,30 +68,11 @@ static void gss_krb5_prepare_enctype_priority_list(void)
 	}
 }
 
-/**
- * gss_krb5_lookup_enctype - Retrieve profile information for a given enctype
- * @etype: ENCTYPE value
- *
- * Returns a pointer to a gss_krb5_enctype structure, or NULL if no
- * matching etype is found.
- */
-VISIBLE_IF_KUNIT
-const struct gss_krb5_enctype *gss_krb5_lookup_enctype(u32 etype)
-{
-	size_t i;
-
-	for (i = 0; i < ARRAY_SIZE(supported_gss_krb5_enctypes); i++)
-		if (supported_gss_krb5_enctypes[i].etype == etype)
-			return &supported_gss_krb5_enctypes[i];
-	return NULL;
-}
-EXPORT_SYMBOL_IF_KUNIT(gss_krb5_lookup_enctype);
-
 static int
 gss_krb5_import_ctx_v2(struct krb5_ctx *ctx, gfp_t gfp_mask)
 {
 	struct krb5_buffer TK = {
-		.len	= ctx->gk5e->keylength,
+		.len	= ctx->krb5e->key_len,
 		.data	= ctx->Ksess,
 	};
 	int ret;
@@ -298,32 +143,17 @@ gss_import_v2_context(const void *p, const void *end, struct krb5_ctx *ctx,
 	if (IS_ERR(p))
 		goto out_err;
 	atomic64_set(&ctx->seq_send64, seq_send64);
-	/* set seq_send for use by "older" enctypes */
-	atomic_set(&ctx->seq_send, seq_send64);
-	if (seq_send64 != atomic_read(&ctx->seq_send)) {
-		dprintk("%s: seq_send64 %llx, seq_send %x overflow?\n", __func__,
-			seq_send64, atomic_read(&ctx->seq_send));
-		p = ERR_PTR(-EINVAL);
-		goto out_err;
-	}
 	p = simple_get_bytes(p, end, &ctx->enctype, sizeof(ctx->enctype));
 	if (IS_ERR(p))
 		goto out_err;
-	ctx->gk5e = gss_krb5_lookup_enctype(ctx->enctype);
-	if (ctx->gk5e == NULL) {
+	ctx->krb5e = crypto_krb5_find_enctype(ctx->enctype);
+	if (!ctx->krb5e) {
 		dprintk("gss_kerberos_mech: unsupported krb5 enctype %u\n",
 			ctx->enctype);
 		p = ERR_PTR(-EINVAL);
 		goto out_err;
 	}
-	ctx->krb5e = crypto_krb5_find_enctype(ctx->enctype);
-	if (!ctx->krb5e) {
-		dprintk("gss_kerberos_mech: crypto/krb5 missing enctype %u\n",
-			ctx->enctype);
-		p = ERR_PTR(-EINVAL);
-		goto out_err;
-	}
-	keylen = ctx->gk5e->keylength;
+	keylen = ctx->krb5e->key_len;
 
 	p = simple_get_bytes(p, end, ctx->Ksess, keylen);
 	if (IS_ERR(p))
diff --git a/net/sunrpc/auth_gss/gss_krb5_test.c b/net/sunrpc/auth_gss/gss_krb5_test.c
deleted file mode 100644
index dde1ee934d0d..000000000000
--- a/net/sunrpc/auth_gss/gss_krb5_test.c
+++ /dev/null
@@ -1,1868 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0
-/*
- * Copyright (c) 2022 Oracle and/or its affiliates.
- *
- * KUnit test of SunRPC's GSS Kerberos mechanism. Subsystem
- * name is "rpcsec_gss_krb5".
- */
-
-#include <kunit/test.h>
-#include <kunit/visibility.h>
-
-#include <linux/kernel.h>
-#include <crypto/hash.h>
-
-#include <linux/sunrpc/xdr.h>
-#include <linux/sunrpc/gss_krb5.h>
-
-#include "gss_krb5_internal.h"
-
-MODULE_IMPORT_NS("EXPORTED_FOR_KUNIT_TESTING");
-
-struct gss_krb5_test_param {
-	const char			*desc;
-	u32				enctype;
-	u32				nfold;
-	u32				constant;
-	const struct xdr_netobj		*base_key;
-	const struct xdr_netobj		*Ke;
-	const struct xdr_netobj		*usage;
-	const struct xdr_netobj		*plaintext;
-	const struct xdr_netobj		*confounder;
-	const struct xdr_netobj		*expected_result;
-	const struct xdr_netobj		*expected_hmac;
-	const struct xdr_netobj		*next_iv;
-};
-
-static inline void gss_krb5_get_desc(const struct gss_krb5_test_param *param,
-				     char *desc)
-{
-	strscpy(desc, param->desc, KUNIT_PARAM_DESC_SIZE);
-}
-
-static void kdf_case(struct kunit *test)
-{
-	const struct gss_krb5_test_param *param = test->param_value;
-	const struct gss_krb5_enctype *gk5e;
-	struct xdr_netobj derivedkey;
-	int err;
-
-	/* Arrange */
-	gk5e = gss_krb5_lookup_enctype(param->enctype);
-	if (!gk5e)
-		kunit_skip(test, "Encryption type is not available");
-
-	derivedkey.data = kunit_kzalloc(test, param->expected_result->len,
-					GFP_KERNEL);
-	KUNIT_ASSERT_NOT_ERR_OR_NULL(test, derivedkey.data);
-	derivedkey.len = param->expected_result->len;
-
-	/* Act */
-	err = gk5e->derive_key(gk5e, param->base_key, &derivedkey,
-			       param->usage, GFP_KERNEL);
-	KUNIT_ASSERT_EQ(test, err, 0);
-
-	/* Assert */
-	KUNIT_EXPECT_MEMEQ_MSG(test,
-			       param->expected_result->data,
-			       derivedkey.data,
-			       derivedkey.len,
-			       "key mismatch");
-}
-
-static void checksum_case(struct kunit *test)
-{
-	const struct gss_krb5_test_param *param = test->param_value;
-	struct xdr_buf buf = {
-		.head[0].iov_len	= param->plaintext->len,
-		.len			= param->plaintext->len,
-	};
-	const struct gss_krb5_enctype *gk5e;
-	struct xdr_netobj Kc, checksum;
-	struct crypto_ahash *tfm;
-	int err;
-
-	/* Arrange */
-	gk5e = gss_krb5_lookup_enctype(param->enctype);
-	if (!gk5e)
-		kunit_skip(test, "Encryption type is not available");
-
-	Kc.len = gk5e->Kc_length;
-	Kc.data = kunit_kzalloc(test, Kc.len, GFP_KERNEL);
-	KUNIT_ASSERT_NOT_ERR_OR_NULL(test, Kc.data);
-	err = gk5e->derive_key(gk5e, param->base_key, &Kc,
-			       param->usage, GFP_KERNEL);
-	KUNIT_ASSERT_EQ(test, err, 0);
-
-	tfm = crypto_alloc_ahash(gk5e->cksum_name, 0, CRYPTO_ALG_ASYNC);
-	KUNIT_ASSERT_NOT_ERR_OR_NULL(test, tfm);
-	err = crypto_ahash_setkey(tfm, Kc.data, Kc.len);
-	KUNIT_ASSERT_EQ(test, err, 0);
-
-	buf.head[0].iov_base = kunit_kzalloc(test, buf.head[0].iov_len, GFP_KERNEL);
-	KUNIT_ASSERT_NOT_ERR_OR_NULL(test, buf.head[0].iov_base);
-	memcpy(buf.head[0].iov_base, param->plaintext->data, buf.head[0].iov_len);
-
-	checksum.len = gk5e->cksumlength;
-	checksum.data = kunit_kzalloc(test, checksum.len, GFP_KERNEL);
-	KUNIT_ASSERT_NOT_ERR_OR_NULL(test, checksum.data);
-
-	/* Act */
-	err = gss_krb5_checksum(tfm, NULL, 0, &buf, 0, &checksum);
-	KUNIT_ASSERT_EQ(test, err, 0);
-
-	/* Assert */
-	KUNIT_EXPECT_MEMEQ_MSG(test,
-			       param->expected_result->data,
-			       checksum.data,
-			       checksum.len,
-			       "checksum mismatch");
-
-	crypto_free_ahash(tfm);
-}
-
-#define DEFINE_HEX_XDR_NETOBJ(name, hex_array...)		\
-	static const u8 name ## _data[] = { hex_array };	\
-	static const struct xdr_netobj name = {			\
-		.data	= (u8 *)name##_data,			\
-		.len	= sizeof(name##_data),			\
-	}
-
-#define DEFINE_STR_XDR_NETOBJ(name, string)			\
-	static const u8 name ## _str[] = string;		\
-	static const struct xdr_netobj name = {			\
-		.data	= (u8 *)name##_str,			\
-		.len	= sizeof(name##_str) - 1,		\
-	}
-
-/*
- * RFC 3961 Appendix A.1.  n-fold
- *
- * The n-fold function is defined in section 5.1 of RFC 3961.
- *
- * This test material is copyright (C) The Internet Society (2005).
- */
-
-DEFINE_HEX_XDR_NETOBJ(nfold_test1_plaintext,
-		      0x30, 0x31, 0x32, 0x33, 0x34, 0x35
-);
-DEFINE_HEX_XDR_NETOBJ(nfold_test1_expected_result,
-		      0xbe, 0x07, 0x26, 0x31, 0x27, 0x6b, 0x19, 0x55
-);
-
-DEFINE_HEX_XDR_NETOBJ(nfold_test2_plaintext,
-		      0x70, 0x61, 0x73, 0x73, 0x77, 0x6f, 0x72, 0x64
-);
-DEFINE_HEX_XDR_NETOBJ(nfold_test2_expected_result,
-		      0x78, 0xa0, 0x7b, 0x6c, 0xaf, 0x85, 0xfa
-);
-
-DEFINE_HEX_XDR_NETOBJ(nfold_test3_plaintext,
-		      0x52, 0x6f, 0x75, 0x67, 0x68, 0x20, 0x43, 0x6f,
-		      0x6e, 0x73, 0x65, 0x6e, 0x73, 0x75, 0x73, 0x2c,
-		      0x20, 0x61, 0x6e, 0x64, 0x20, 0x52, 0x75, 0x6e,
-		      0x6e, 0x69, 0x6e, 0x67, 0x20, 0x43, 0x6f, 0x64,
-		      0x65
-);
-DEFINE_HEX_XDR_NETOBJ(nfold_test3_expected_result,
-		      0xbb, 0x6e, 0xd3, 0x08, 0x70, 0xb7, 0xf0, 0xe0
-);
-
-DEFINE_HEX_XDR_NETOBJ(nfold_test4_plaintext,
-		      0x70, 0x61, 0x73, 0x73, 0x77, 0x6f, 0x72, 0x64
-);
-DEFINE_HEX_XDR_NETOBJ(nfold_test4_expected_result,
-		      0x59, 0xe4, 0xa8, 0xca, 0x7c, 0x03, 0x85, 0xc3,
-		      0xc3, 0x7b, 0x3f, 0x6d, 0x20, 0x00, 0x24, 0x7c,
-		      0xb6, 0xe6, 0xbd, 0x5b, 0x3e
-);
-
-DEFINE_HEX_XDR_NETOBJ(nfold_test5_plaintext,
-		      0x4d, 0x41, 0x53, 0x53, 0x41, 0x43, 0x48, 0x56,
-		      0x53, 0x45, 0x54, 0x54, 0x53, 0x20, 0x49, 0x4e,
-		      0x53, 0x54, 0x49, 0x54, 0x56, 0x54, 0x45, 0x20,
-		      0x4f, 0x46, 0x20, 0x54, 0x45, 0x43, 0x48, 0x4e,
-		      0x4f, 0x4c, 0x4f, 0x47, 0x59
-);
-DEFINE_HEX_XDR_NETOBJ(nfold_test5_expected_result,
-		      0xdb, 0x3b, 0x0d, 0x8f, 0x0b, 0x06, 0x1e, 0x60,
-		      0x32, 0x82, 0xb3, 0x08, 0xa5, 0x08, 0x41, 0x22,
-		      0x9a, 0xd7, 0x98, 0xfa, 0xb9, 0x54, 0x0c, 0x1b
-);
-
-DEFINE_HEX_XDR_NETOBJ(nfold_test6_plaintext,
-		      0x51
-);
-DEFINE_HEX_XDR_NETOBJ(nfold_test6_expected_result,
-		      0x51, 0x8a, 0x54, 0xa2, 0x15, 0xa8, 0x45, 0x2a,
-		      0x51, 0x8a, 0x54, 0xa2, 0x15, 0xa8, 0x45, 0x2a,
-		      0x51, 0x8a, 0x54, 0xa2, 0x15
-);
-
-DEFINE_HEX_XDR_NETOBJ(nfold_test7_plaintext,
-		      0x62, 0x61
-);
-DEFINE_HEX_XDR_NETOBJ(nfold_test7_expected_result,
-		      0xfb, 0x25, 0xd5, 0x31, 0xae, 0x89, 0x74, 0x49,
-		      0x9f, 0x52, 0xfd, 0x92, 0xea, 0x98, 0x57, 0xc4,
-		      0xba, 0x24, 0xcf, 0x29, 0x7e
-);
-
-DEFINE_HEX_XDR_NETOBJ(nfold_test_kerberos,
-		      0x6b, 0x65, 0x72, 0x62, 0x65, 0x72, 0x6f, 0x73
-);
-DEFINE_HEX_XDR_NETOBJ(nfold_test8_expected_result,
-		      0x6b, 0x65, 0x72, 0x62, 0x65, 0x72, 0x6f, 0x73
-);
-DEFINE_HEX_XDR_NETOBJ(nfold_test9_expected_result,
-		      0x6b, 0x65, 0x72, 0x62, 0x65, 0x72, 0x6f, 0x73,
-		      0x7b, 0x9b, 0x5b, 0x2b, 0x93, 0x13, 0x2b, 0x93
-);
-DEFINE_HEX_XDR_NETOBJ(nfold_test10_expected_result,
-		      0x83, 0x72, 0xc2, 0x36, 0x34, 0x4e, 0x5f, 0x15,
-		      0x50, 0xcd, 0x07, 0x47, 0xe1, 0x5d, 0x62, 0xca,
-		      0x7a, 0x5a, 0x3b, 0xce, 0xa4
-);
-DEFINE_HEX_XDR_NETOBJ(nfold_test11_expected_result,
-		      0x6b, 0x65, 0x72, 0x62, 0x65, 0x72, 0x6f, 0x73,
-		      0x7b, 0x9b, 0x5b, 0x2b, 0x93, 0x13, 0x2b, 0x93,
-		      0x5c, 0x9b, 0xdc, 0xda, 0xd9, 0x5c, 0x98, 0x99,
-		      0xc4, 0xca, 0xe4, 0xde, 0xe6, 0xd6, 0xca, 0xe4
-);
-
-static const struct gss_krb5_test_param rfc3961_nfold_test_params[] = {
-	{
-		.desc			= "64-fold(\"012345\")",
-		.nfold			= 64,
-		.plaintext		= &nfold_test1_plaintext,
-		.expected_result	= &nfold_test1_expected_result,
-	},
-	{
-		.desc			= "56-fold(\"password\")",
-		.nfold			= 56,
-		.plaintext		= &nfold_test2_plaintext,
-		.expected_result	= &nfold_test2_expected_result,
-	},
-	{
-		.desc			= "64-fold(\"Rough Consensus, and Running Code\")",
-		.nfold			= 64,
-		.plaintext		= &nfold_test3_plaintext,
-		.expected_result	= &nfold_test3_expected_result,
-	},
-	{
-		.desc			= "168-fold(\"password\")",
-		.nfold			= 168,
-		.plaintext		= &nfold_test4_plaintext,
-		.expected_result	= &nfold_test4_expected_result,
-	},
-	{
-		.desc			= "192-fold(\"MASSACHVSETTS INSTITVTE OF TECHNOLOGY\")",
-		.nfold			= 192,
-		.plaintext		= &nfold_test5_plaintext,
-		.expected_result	= &nfold_test5_expected_result,
-	},
-	{
-		.desc			= "168-fold(\"Q\")",
-		.nfold			= 168,
-		.plaintext		= &nfold_test6_plaintext,
-		.expected_result	= &nfold_test6_expected_result,
-	},
-	{
-		.desc			= "168-fold(\"ba\")",
-		.nfold			= 168,
-		.plaintext		= &nfold_test7_plaintext,
-		.expected_result	= &nfold_test7_expected_result,
-	},
-	{
-		.desc			= "64-fold(\"kerberos\")",
-		.nfold			= 64,
-		.plaintext		= &nfold_test_kerberos,
-		.expected_result	= &nfold_test8_expected_result,
-	},
-	{
-		.desc			= "128-fold(\"kerberos\")",
-		.nfold			= 128,
-		.plaintext		= &nfold_test_kerberos,
-		.expected_result	= &nfold_test9_expected_result,
-	},
-	{
-		.desc			= "168-fold(\"kerberos\")",
-		.nfold			= 168,
-		.plaintext		= &nfold_test_kerberos,
-		.expected_result	= &nfold_test10_expected_result,
-	},
-	{
-		.desc			= "256-fold(\"kerberos\")",
-		.nfold			= 256,
-		.plaintext		= &nfold_test_kerberos,
-		.expected_result	= &nfold_test11_expected_result,
-	},
-};
-
-/* Creates the function rfc3961_nfold_gen_params */
-KUNIT_ARRAY_PARAM(rfc3961_nfold, rfc3961_nfold_test_params, gss_krb5_get_desc);
-
-static void rfc3961_nfold_case(struct kunit *test)
-{
-	const struct gss_krb5_test_param *param = test->param_value;
-	u8 *result;
-
-	/* Arrange */
-	result = kunit_kzalloc(test, 4096, GFP_KERNEL);
-	KUNIT_ASSERT_NOT_ERR_OR_NULL(test, result);
-
-	/* Act */
-	krb5_nfold(param->plaintext->len * 8, param->plaintext->data,
-		   param->expected_result->len * 8, result);
-
-	/* Assert */
-	KUNIT_EXPECT_MEMEQ_MSG(test,
-			       param->expected_result->data,
-			       result,
-			       param->expected_result->len,
-			       "result mismatch");
-}
-
-static struct kunit_case rfc3961_test_cases[] = {
-	{
-		.name			= "RFC 3961 n-fold",
-		.run_case		= rfc3961_nfold_case,
-		.generate_params	= rfc3961_nfold_gen_params,
-	},
-	{}
-};
-
-static struct kunit_suite rfc3961_suite = {
-	.name			= "RFC 3961 tests",
-	.test_cases		= rfc3961_test_cases,
-};
-
-/*
- * From RFC 3962 Appendix B:   Sample Test Vectors
- *
- * Some test vectors for CBC with ciphertext stealing, using an
- * initial vector of all-zero.
- *
- * This test material is copyright (C) The Internet Society (2005).
- */
-
-DEFINE_HEX_XDR_NETOBJ(rfc3962_encryption_key,
-		      0x63, 0x68, 0x69, 0x63, 0x6b, 0x65, 0x6e, 0x20,
-		      0x74, 0x65, 0x72, 0x69, 0x79, 0x61, 0x6b, 0x69
-);
-
-DEFINE_HEX_XDR_NETOBJ(rfc3962_enc_test1_plaintext,
-		      0x49, 0x20, 0x77, 0x6f, 0x75, 0x6c, 0x64, 0x20,
-		      0x6c, 0x69, 0x6b, 0x65, 0x20, 0x74, 0x68, 0x65,
-		      0x20
-);
-DEFINE_HEX_XDR_NETOBJ(rfc3962_enc_test1_expected_result,
-		      0xc6, 0x35, 0x35, 0x68, 0xf2, 0xbf, 0x8c, 0xb4,
-		      0xd8, 0xa5, 0x80, 0x36, 0x2d, 0xa7, 0xff, 0x7f,
-		      0x97
-);
-DEFINE_HEX_XDR_NETOBJ(rfc3962_enc_test1_next_iv,
-		      0xc6, 0x35, 0x35, 0x68, 0xf2, 0xbf, 0x8c, 0xb4,
-		      0xd8, 0xa5, 0x80, 0x36, 0x2d, 0xa7, 0xff, 0x7f
-);
-
-DEFINE_HEX_XDR_NETOBJ(rfc3962_enc_test2_plaintext,
-		      0x49, 0x20, 0x77, 0x6f, 0x75, 0x6c, 0x64, 0x20,
-		      0x6c, 0x69, 0x6b, 0x65, 0x20, 0x74, 0x68, 0x65,
-		      0x20, 0x47, 0x65, 0x6e, 0x65, 0x72, 0x61, 0x6c,
-		      0x20, 0x47, 0x61, 0x75, 0x27, 0x73, 0x20
-);
-DEFINE_HEX_XDR_NETOBJ(rfc3962_enc_test2_expected_result,
-		      0xfc, 0x00, 0x78, 0x3e, 0x0e, 0xfd, 0xb2, 0xc1,
-		      0xd4, 0x45, 0xd4, 0xc8, 0xef, 0xf7, 0xed, 0x22,
-		      0x97, 0x68, 0x72, 0x68, 0xd6, 0xec, 0xcc, 0xc0,
-		      0xc0, 0x7b, 0x25, 0xe2, 0x5e, 0xcf, 0xe5
-);
-DEFINE_HEX_XDR_NETOBJ(rfc3962_enc_test2_next_iv,
-		      0xfc, 0x00, 0x78, 0x3e, 0x0e, 0xfd, 0xb2, 0xc1,
-		      0xd4, 0x45, 0xd4, 0xc8, 0xef, 0xf7, 0xed, 0x22
-);
-
-DEFINE_HEX_XDR_NETOBJ(rfc3962_enc_test3_plaintext,
-		      0x49, 0x20, 0x77, 0x6f, 0x75, 0x6c, 0x64, 0x20,
-		      0x6c, 0x69, 0x6b, 0x65, 0x20, 0x74, 0x68, 0x65,
-		      0x20, 0x47, 0x65, 0x6e, 0x65, 0x72, 0x61, 0x6c,
-		      0x20, 0x47, 0x61, 0x75, 0x27, 0x73, 0x20, 0x43
-);
-DEFINE_HEX_XDR_NETOBJ(rfc3962_enc_test3_expected_result,
-		      0x39, 0x31, 0x25, 0x23, 0xa7, 0x86, 0x62, 0xd5,
-		      0xbe, 0x7f, 0xcb, 0xcc, 0x98, 0xeb, 0xf5, 0xa8,
-		      0x97, 0x68, 0x72, 0x68, 0xd6, 0xec, 0xcc, 0xc0,
-		      0xc0, 0x7b, 0x25, 0xe2, 0x5e, 0xcf, 0xe5, 0x84
-);
-DEFINE_HEX_XDR_NETOBJ(rfc3962_enc_test3_next_iv,
-		      0x39, 0x31, 0x25, 0x23, 0xa7, 0x86, 0x62, 0xd5,
-		      0xbe, 0x7f, 0xcb, 0xcc, 0x98, 0xeb, 0xf5, 0xa8
-);
-
-DEFINE_HEX_XDR_NETOBJ(rfc3962_enc_test4_plaintext,
-		      0x49, 0x20, 0x77, 0x6f, 0x75, 0x6c, 0x64, 0x20,
-		      0x6c, 0x69, 0x6b, 0x65, 0x20, 0x74, 0x68, 0x65,
-		      0x20, 0x47, 0x65, 0x6e, 0x65, 0x72, 0x61, 0x6c,
-		      0x20, 0x47, 0x61, 0x75, 0x27, 0x73, 0x20, 0x43,
-		      0x68, 0x69, 0x63, 0x6b, 0x65, 0x6e, 0x2c, 0x20,
-		      0x70, 0x6c, 0x65, 0x61, 0x73, 0x65, 0x2c
-);
-DEFINE_HEX_XDR_NETOBJ(rfc3962_enc_test4_expected_result,
-		      0x97, 0x68, 0x72, 0x68, 0xd6, 0xec, 0xcc, 0xc0,
-		      0xc0, 0x7b, 0x25, 0xe2, 0x5e, 0xcf, 0xe5, 0x84,
-		      0xb3, 0xff, 0xfd, 0x94, 0x0c, 0x16, 0xa1, 0x8c,
-		      0x1b, 0x55, 0x49, 0xd2, 0xf8, 0x38, 0x02, 0x9e,
-		      0x39, 0x31, 0x25, 0x23, 0xa7, 0x86, 0x62, 0xd5,
-		      0xbe, 0x7f, 0xcb, 0xcc, 0x98, 0xeb, 0xf5
-);
-DEFINE_HEX_XDR_NETOBJ(rfc3962_enc_test4_next_iv,
-		      0xb3, 0xff, 0xfd, 0x94, 0x0c, 0x16, 0xa1, 0x8c,
-		      0x1b, 0x55, 0x49, 0xd2, 0xf8, 0x38, 0x02, 0x9e
-);
-
-DEFINE_HEX_XDR_NETOBJ(rfc3962_enc_test5_plaintext,
-		      0x49, 0x20, 0x77, 0x6f, 0x75, 0x6c, 0x64, 0x20,
-		      0x6c, 0x69, 0x6b, 0x65, 0x20, 0x74, 0x68, 0x65,
-		      0x20, 0x47, 0x65, 0x6e, 0x65, 0x72, 0x61, 0x6c,
-		      0x20, 0x47, 0x61, 0x75, 0x27, 0x73, 0x20, 0x43,
-		      0x68, 0x69, 0x63, 0x6b, 0x65, 0x6e, 0x2c, 0x20,
-		      0x70, 0x6c, 0x65, 0x61, 0x73, 0x65, 0x2c, 0x20
-);
-DEFINE_HEX_XDR_NETOBJ(rfc3962_enc_test5_expected_result,
-		      0x97, 0x68, 0x72, 0x68, 0xd6, 0xec, 0xcc, 0xc0,
-		      0xc0, 0x7b, 0x25, 0xe2, 0x5e, 0xcf, 0xe5, 0x84,
-		      0x9d, 0xad, 0x8b, 0xbb, 0x96, 0xc4, 0xcd, 0xc0,
-		      0x3b, 0xc1, 0x03, 0xe1, 0xa1, 0x94, 0xbb, 0xd8,
-		      0x39, 0x31, 0x25, 0x23, 0xa7, 0x86, 0x62, 0xd5,
-		      0xbe, 0x7f, 0xcb, 0xcc, 0x98, 0xeb, 0xf5, 0xa8
-);
-DEFINE_HEX_XDR_NETOBJ(rfc3962_enc_test5_next_iv,
-		      0x9d, 0xad, 0x8b, 0xbb, 0x96, 0xc4, 0xcd, 0xc0,
-		      0x3b, 0xc1, 0x03, 0xe1, 0xa1, 0x94, 0xbb, 0xd8
-);
-
-DEFINE_HEX_XDR_NETOBJ(rfc3962_enc_test6_plaintext,
-		      0x49, 0x20, 0x77, 0x6f, 0x75, 0x6c, 0x64, 0x20,
-		      0x6c, 0x69, 0x6b, 0x65, 0x20, 0x74, 0x68, 0x65,
-		      0x20, 0x47, 0x65, 0x6e, 0x65, 0x72, 0x61, 0x6c,
-		      0x20, 0x47, 0x61, 0x75, 0x27, 0x73, 0x20, 0x43,
-		      0x68, 0x69, 0x63, 0x6b, 0x65, 0x6e, 0x2c, 0x20,
-		      0x70, 0x6c, 0x65, 0x61, 0x73, 0x65, 0x2c, 0x20,
-		      0x61, 0x6e, 0x64, 0x20, 0x77, 0x6f, 0x6e, 0x74,
-		      0x6f, 0x6e, 0x20, 0x73, 0x6f, 0x75, 0x70, 0x2e
-);
-DEFINE_HEX_XDR_NETOBJ(rfc3962_enc_test6_expected_result,
-		      0x97, 0x68, 0x72, 0x68, 0xd6, 0xec, 0xcc, 0xc0,
-		      0xc0, 0x7b, 0x25, 0xe2, 0x5e, 0xcf, 0xe5, 0x84,
-		      0x39, 0x31, 0x25, 0x23, 0xa7, 0x86, 0x62, 0xd5,
-		      0xbe, 0x7f, 0xcb, 0xcc, 0x98, 0xeb, 0xf5, 0xa8,
-		      0x48, 0x07, 0xef, 0xe8, 0x36, 0xee, 0x89, 0xa5,
-		      0x26, 0x73, 0x0d, 0xbc, 0x2f, 0x7b, 0xc8, 0x40,
-		      0x9d, 0xad, 0x8b, 0xbb, 0x96, 0xc4, 0xcd, 0xc0,
-		      0x3b, 0xc1, 0x03, 0xe1, 0xa1, 0x94, 0xbb, 0xd8
-);
-DEFINE_HEX_XDR_NETOBJ(rfc3962_enc_test6_next_iv,
-		      0x48, 0x07, 0xef, 0xe8, 0x36, 0xee, 0x89, 0xa5,
-		      0x26, 0x73, 0x0d, 0xbc, 0x2f, 0x7b, 0xc8, 0x40
-);
-
-static const struct gss_krb5_test_param rfc3962_encrypt_test_params[] = {
-	{
-		.desc			= "Encrypt with aes128-cts-hmac-sha1-96 case 1",
-		.enctype		= ENCTYPE_AES128_CTS_HMAC_SHA1_96,
-		.Ke			= &rfc3962_encryption_key,
-		.plaintext		= &rfc3962_enc_test1_plaintext,
-		.expected_result	= &rfc3962_enc_test1_expected_result,
-		.next_iv		= &rfc3962_enc_test1_next_iv,
-	},
-	{
-		.desc			= "Encrypt with aes128-cts-hmac-sha1-96 case 2",
-		.enctype		= ENCTYPE_AES128_CTS_HMAC_SHA1_96,
-		.Ke			= &rfc3962_encryption_key,
-		.plaintext		= &rfc3962_enc_test2_plaintext,
-		.expected_result	= &rfc3962_enc_test2_expected_result,
-		.next_iv		= &rfc3962_enc_test2_next_iv,
-	},
-	{
-		.desc			= "Encrypt with aes128-cts-hmac-sha1-96 case 3",
-		.enctype		= ENCTYPE_AES128_CTS_HMAC_SHA1_96,
-		.Ke			= &rfc3962_encryption_key,
-		.plaintext		= &rfc3962_enc_test3_plaintext,
-		.expected_result	= &rfc3962_enc_test3_expected_result,
-		.next_iv		= &rfc3962_enc_test3_next_iv,
-	},
-	{
-		.desc			= "Encrypt with aes128-cts-hmac-sha1-96 case 4",
-		.enctype		= ENCTYPE_AES128_CTS_HMAC_SHA1_96,
-		.Ke			= &rfc3962_encryption_key,
-		.plaintext		= &rfc3962_enc_test4_plaintext,
-		.expected_result	= &rfc3962_enc_test4_expected_result,
-		.next_iv		= &rfc3962_enc_test4_next_iv,
-	},
-	{
-		.desc			= "Encrypt with aes128-cts-hmac-sha1-96 case 5",
-		.enctype		= ENCTYPE_AES128_CTS_HMAC_SHA1_96,
-		.Ke			= &rfc3962_encryption_key,
-		.plaintext		= &rfc3962_enc_test5_plaintext,
-		.expected_result	= &rfc3962_enc_test5_expected_result,
-		.next_iv		= &rfc3962_enc_test5_next_iv,
-	},
-	{
-		.desc			= "Encrypt with aes128-cts-hmac-sha1-96 case 6",
-		.enctype		= ENCTYPE_AES128_CTS_HMAC_SHA1_96,
-		.Ke			= &rfc3962_encryption_key,
-		.plaintext		= &rfc3962_enc_test6_plaintext,
-		.expected_result	= &rfc3962_enc_test6_expected_result,
-		.next_iv		= &rfc3962_enc_test6_next_iv,
-	},
-};
-
-/* Creates the function rfc3962_encrypt_gen_params */
-KUNIT_ARRAY_PARAM(rfc3962_encrypt, rfc3962_encrypt_test_params,
-		  gss_krb5_get_desc);
-
-/*
- * This tests the implementation of the encryption part of the mechanism.
- * It does not apply a confounder or test the result of HMAC over the
- * plaintext.
- */
-static void rfc3962_encrypt_case(struct kunit *test)
-{
-	const struct gss_krb5_test_param *param = test->param_value;
-	struct crypto_sync_skcipher *cts_tfm, *cbc_tfm;
-	const struct gss_krb5_enctype *gk5e;
-	struct xdr_buf buf;
-	void *iv, *text;
-	u32 err;
-
-	/* Arrange */
-	gk5e = gss_krb5_lookup_enctype(param->enctype);
-	if (!gk5e)
-		kunit_skip(test, "Encryption type is not available");
-
-	cbc_tfm = crypto_alloc_sync_skcipher(gk5e->aux_cipher, 0, 0);
-	KUNIT_ASSERT_NOT_ERR_OR_NULL(test, cbc_tfm);
-	err = crypto_sync_skcipher_setkey(cbc_tfm, param->Ke->data, param->Ke->len);
-	KUNIT_ASSERT_EQ(test, err, 0);
-
-	cts_tfm = crypto_alloc_sync_skcipher(gk5e->encrypt_name, 0, 0);
-	KUNIT_ASSERT_NOT_ERR_OR_NULL(test, cts_tfm);
-	err = crypto_sync_skcipher_setkey(cts_tfm, param->Ke->data, param->Ke->len);
-	KUNIT_ASSERT_EQ(test, err, 0);
-
-	iv = kunit_kzalloc(test, crypto_sync_skcipher_ivsize(cts_tfm), GFP_KERNEL);
-	KUNIT_ASSERT_NOT_ERR_OR_NULL(test, iv);
-
-	text = kunit_kzalloc(test, param->plaintext->len, GFP_KERNEL);
-	KUNIT_ASSERT_NOT_ERR_OR_NULL(test, text);
-
-	memcpy(text, param->plaintext->data, param->plaintext->len);
-	memset(&buf, 0, sizeof(buf));
-	buf.head[0].iov_base = text;
-	buf.head[0].iov_len = param->plaintext->len;
-	buf.len = buf.head[0].iov_len;
-
-	/* Act */
-	err = krb5_cbc_cts_encrypt(cts_tfm, cbc_tfm, 0, &buf, NULL,
-				   iv, crypto_sync_skcipher_ivsize(cts_tfm));
-	KUNIT_ASSERT_EQ(test, err, 0);
-
-	/* Assert */
-	KUNIT_EXPECT_EQ_MSG(test,
-			    param->expected_result->len, buf.len,
-			    "ciphertext length mismatch");
-	KUNIT_EXPECT_MEMEQ_MSG(test,
-			       param->expected_result->data,
-			       text,
-			       param->expected_result->len,
-			       "ciphertext mismatch");
-	KUNIT_EXPECT_MEMEQ_MSG(test,
-			       param->next_iv->data,
-			       iv,
-			       param->next_iv->len,
-			       "IV mismatch");
-
-	crypto_free_sync_skcipher(cts_tfm);
-	crypto_free_sync_skcipher(cbc_tfm);
-}
-
-static struct kunit_case rfc3962_test_cases[] = {
-	{
-		.name			= "RFC 3962 encryption",
-		.run_case		= rfc3962_encrypt_case,
-		.generate_params	= rfc3962_encrypt_gen_params,
-	},
-	{}
-};
-
-static struct kunit_suite rfc3962_suite = {
-	.name			= "RFC 3962 suite",
-	.test_cases		= rfc3962_test_cases,
-};
-
-/*
- * From RFC 6803 Section 10.  Test vectors
- *
- * Sample results for key derivation
- *
- * Copyright (c) 2012 IETF Trust and the persons identified as the
- * document authors.  All rights reserved.
- */
-
-DEFINE_HEX_XDR_NETOBJ(camellia128_cts_cmac_basekey,
-		      0x57, 0xd0, 0x29, 0x72, 0x98, 0xff, 0xd9, 0xd3,
-		      0x5d, 0xe5, 0xa4, 0x7f, 0xb4, 0xbd, 0xe2, 0x4b
-);
-DEFINE_HEX_XDR_NETOBJ(camellia128_cts_cmac_Kc,
-		      0xd1, 0x55, 0x77, 0x5a, 0x20, 0x9d, 0x05, 0xf0,
-		      0x2b, 0x38, 0xd4, 0x2a, 0x38, 0x9e, 0x5a, 0x56
-);
-DEFINE_HEX_XDR_NETOBJ(camellia128_cts_cmac_Ke,
-		      0x64, 0xdf, 0x83, 0xf8, 0x5a, 0x53, 0x2f, 0x17,
-		      0x57, 0x7d, 0x8c, 0x37, 0x03, 0x57, 0x96, 0xab
-);
-DEFINE_HEX_XDR_NETOBJ(camellia128_cts_cmac_Ki,
-		      0x3e, 0x4f, 0xbd, 0xf3, 0x0f, 0xb8, 0x25, 0x9c,
-		      0x42, 0x5c, 0xb6, 0xc9, 0x6f, 0x1f, 0x46, 0x35
-);
-
-DEFINE_HEX_XDR_NETOBJ(camellia256_cts_cmac_basekey,
-		      0xb9, 0xd6, 0x82, 0x8b, 0x20, 0x56, 0xb7, 0xbe,
-		      0x65, 0x6d, 0x88, 0xa1, 0x23, 0xb1, 0xfa, 0xc6,
-		      0x82, 0x14, 0xac, 0x2b, 0x72, 0x7e, 0xcf, 0x5f,
-		      0x69, 0xaf, 0xe0, 0xc4, 0xdf, 0x2a, 0x6d, 0x2c
-);
-DEFINE_HEX_XDR_NETOBJ(camellia256_cts_cmac_Kc,
-		      0xe4, 0x67, 0xf9, 0xa9, 0x55, 0x2b, 0xc7, 0xd3,
-		      0x15, 0x5a, 0x62, 0x20, 0xaf, 0x9c, 0x19, 0x22,
-		      0x0e, 0xee, 0xd4, 0xff, 0x78, 0xb0, 0xd1, 0xe6,
-		      0xa1, 0x54, 0x49, 0x91, 0x46, 0x1a, 0x9e, 0x50
-);
-DEFINE_HEX_XDR_NETOBJ(camellia256_cts_cmac_Ke,
-		      0x41, 0x2a, 0xef, 0xc3, 0x62, 0xa7, 0x28, 0x5f,
-		      0xc3, 0x96, 0x6c, 0x6a, 0x51, 0x81, 0xe7, 0x60,
-		      0x5a, 0xe6, 0x75, 0x23, 0x5b, 0x6d, 0x54, 0x9f,
-		      0xbf, 0xc9, 0xab, 0x66, 0x30, 0xa4, 0xc6, 0x04
-);
-DEFINE_HEX_XDR_NETOBJ(camellia256_cts_cmac_Ki,
-		      0xfa, 0x62, 0x4f, 0xa0, 0xe5, 0x23, 0x99, 0x3f,
-		      0xa3, 0x88, 0xae, 0xfd, 0xc6, 0x7e, 0x67, 0xeb,
-		      0xcd, 0x8c, 0x08, 0xe8, 0xa0, 0x24, 0x6b, 0x1d,
-		      0x73, 0xb0, 0xd1, 0xdd, 0x9f, 0xc5, 0x82, 0xb0
-);
-
-DEFINE_HEX_XDR_NETOBJ(usage_checksum,
-		      0x00, 0x00, 0x00, 0x02, KEY_USAGE_SEED_CHECKSUM
-);
-DEFINE_HEX_XDR_NETOBJ(usage_encryption,
-		      0x00, 0x00, 0x00, 0x02, KEY_USAGE_SEED_ENCRYPTION
-);
-DEFINE_HEX_XDR_NETOBJ(usage_integrity,
-		      0x00, 0x00, 0x00, 0x02, KEY_USAGE_SEED_INTEGRITY
-);
-
-static const struct gss_krb5_test_param rfc6803_kdf_test_params[] = {
-	{
-		.desc			= "Derive Kc subkey for camellia128-cts-cmac",
-		.enctype		= ENCTYPE_CAMELLIA128_CTS_CMAC,
-		.base_key		= &camellia128_cts_cmac_basekey,
-		.usage			= &usage_checksum,
-		.expected_result	= &camellia128_cts_cmac_Kc,
-	},
-	{
-		.desc			= "Derive Ke subkey for camellia128-cts-cmac",
-		.enctype		= ENCTYPE_CAMELLIA128_CTS_CMAC,
-		.base_key		= &camellia128_cts_cmac_basekey,
-		.usage			= &usage_encryption,
-		.expected_result	= &camellia128_cts_cmac_Ke,
-	},
-	{
-		.desc			= "Derive Ki subkey for camellia128-cts-cmac",
-		.enctype		= ENCTYPE_CAMELLIA128_CTS_CMAC,
-		.base_key		= &camellia128_cts_cmac_basekey,
-		.usage			= &usage_integrity,
-		.expected_result	= &camellia128_cts_cmac_Ki,
-	},
-	{
-		.desc			= "Derive Kc subkey for camellia256-cts-cmac",
-		.enctype		= ENCTYPE_CAMELLIA256_CTS_CMAC,
-		.base_key		= &camellia256_cts_cmac_basekey,
-		.usage			= &usage_checksum,
-		.expected_result	= &camellia256_cts_cmac_Kc,
-	},
-	{
-		.desc			= "Derive Ke subkey for camellia256-cts-cmac",
-		.enctype		= ENCTYPE_CAMELLIA256_CTS_CMAC,
-		.base_key		= &camellia256_cts_cmac_basekey,
-		.usage			= &usage_encryption,
-		.expected_result	= &camellia256_cts_cmac_Ke,
-	},
-	{
-		.desc			= "Derive Ki subkey for camellia256-cts-cmac",
-		.enctype		= ENCTYPE_CAMELLIA256_CTS_CMAC,
-		.base_key		= &camellia256_cts_cmac_basekey,
-		.usage			= &usage_integrity,
-		.expected_result	= &camellia256_cts_cmac_Ki,
-	},
-};
-
-/* Creates the function rfc6803_kdf_gen_params */
-KUNIT_ARRAY_PARAM(rfc6803_kdf, rfc6803_kdf_test_params, gss_krb5_get_desc);
-
-/*
- * From RFC 6803 Section 10.  Test vectors
- *
- * Sample checksums.
- *
- * Copyright (c) 2012 IETF Trust and the persons identified as the
- * document authors.  All rights reserved.
- *
- * XXX: These tests are likely to fail on EBCDIC or Unicode platforms.
- */
-DEFINE_STR_XDR_NETOBJ(rfc6803_checksum_test1_plaintext,
-		      "abcdefghijk");
-DEFINE_HEX_XDR_NETOBJ(rfc6803_checksum_test1_basekey,
-		      0x1d, 0xc4, 0x6a, 0x8d, 0x76, 0x3f, 0x4f, 0x93,
-		      0x74, 0x2b, 0xcb, 0xa3, 0x38, 0x75, 0x76, 0xc3
-);
-DEFINE_HEX_XDR_NETOBJ(rfc6803_checksum_test1_usage,
-		      0x00, 0x00, 0x00, 0x07, KEY_USAGE_SEED_CHECKSUM
-);
-DEFINE_HEX_XDR_NETOBJ(rfc6803_checksum_test1_expected_result,
-		      0x11, 0x78, 0xe6, 0xc5, 0xc4, 0x7a, 0x8c, 0x1a,
-		      0xe0, 0xc4, 0xb9, 0xc7, 0xd4, 0xeb, 0x7b, 0x6b
-);
-
-DEFINE_STR_XDR_NETOBJ(rfc6803_checksum_test2_plaintext,
-		      "ABCDEFGHIJKLMNOPQRSTUVWXYZ");
-DEFINE_HEX_XDR_NETOBJ(rfc6803_checksum_test2_basekey,
-		      0x50, 0x27, 0xbc, 0x23, 0x1d, 0x0f, 0x3a, 0x9d,
-		      0x23, 0x33, 0x3f, 0x1c, 0xa6, 0xfd, 0xbe, 0x7c
-);
-DEFINE_HEX_XDR_NETOBJ(rfc6803_checksum_test2_usage,
-		      0x00, 0x00, 0x00, 0x08, KEY_USAGE_SEED_CHECKSUM
-);
-DEFINE_HEX_XDR_NETOBJ(rfc6803_checksum_test2_expected_result,
-		      0xd1, 0xb3, 0x4f, 0x70, 0x04, 0xa7, 0x31, 0xf2,
-		      0x3a, 0x0c, 0x00, 0xbf, 0x6c, 0x3f, 0x75, 0x3a
-);
-
-DEFINE_STR_XDR_NETOBJ(rfc6803_checksum_test3_plaintext,
-		      "123456789");
-DEFINE_HEX_XDR_NETOBJ(rfc6803_checksum_test3_basekey,
-		      0xb6, 0x1c, 0x86, 0xcc, 0x4e, 0x5d, 0x27, 0x57,
-		      0x54, 0x5a, 0xd4, 0x23, 0x39, 0x9f, 0xb7, 0x03,
-		      0x1e, 0xca, 0xb9, 0x13, 0xcb, 0xb9, 0x00, 0xbd,
-		      0x7a, 0x3c, 0x6d, 0xd8, 0xbf, 0x92, 0x01, 0x5b
-);
-DEFINE_HEX_XDR_NETOBJ(rfc6803_checksum_test3_usage,
-		      0x00, 0x00, 0x00, 0x09, KEY_USAGE_SEED_CHECKSUM
-);
-DEFINE_HEX_XDR_NETOBJ(rfc6803_checksum_test3_expected_result,
-		      0x87, 0xa1, 0x2c, 0xfd, 0x2b, 0x96, 0x21, 0x48,
-		      0x10, 0xf0, 0x1c, 0x82, 0x6e, 0x77, 0x44, 0xb1
-);
-
-DEFINE_STR_XDR_NETOBJ(rfc6803_checksum_test4_plaintext,
-		      "!@#$%^&*()!@#$%^&*()!@#$%^&*()");
-DEFINE_HEX_XDR_NETOBJ(rfc6803_checksum_test4_basekey,
-		      0x32, 0x16, 0x4c, 0x5b, 0x43, 0x4d, 0x1d, 0x15,
-		      0x38, 0xe4, 0xcf, 0xd9, 0xbe, 0x80, 0x40, 0xfe,
-		      0x8c, 0x4a, 0xc7, 0xac, 0xc4, 0xb9, 0x3d, 0x33,
-		      0x14, 0xd2, 0x13, 0x36, 0x68, 0x14, 0x7a, 0x05
-);
-DEFINE_HEX_XDR_NETOBJ(rfc6803_checksum_test4_usage,
-		      0x00, 0x00, 0x00, 0x0a, KEY_USAGE_SEED_CHECKSUM
-);
-DEFINE_HEX_XDR_NETOBJ(rfc6803_checksum_test4_expected_result,
-		      0x3f, 0xa0, 0xb4, 0x23, 0x55, 0xe5, 0x2b, 0x18,
-		      0x91, 0x87, 0x29, 0x4a, 0xa2, 0x52, 0xab, 0x64
-);
-
-static const struct gss_krb5_test_param rfc6803_checksum_test_params[] = {
-	{
-		.desc			= "camellia128-cts-cmac checksum test 1",
-		.enctype		= ENCTYPE_CAMELLIA128_CTS_CMAC,
-		.base_key		= &rfc6803_checksum_test1_basekey,
-		.usage			= &rfc6803_checksum_test1_usage,
-		.plaintext		= &rfc6803_checksum_test1_plaintext,
-		.expected_result	= &rfc6803_checksum_test1_expected_result,
-	},
-	{
-		.desc			= "camellia128-cts-cmac checksum test 2",
-		.enctype		= ENCTYPE_CAMELLIA128_CTS_CMAC,
-		.base_key		= &rfc6803_checksum_test2_basekey,
-		.usage			= &rfc6803_checksum_test2_usage,
-		.plaintext		= &rfc6803_checksum_test2_plaintext,
-		.expected_result	= &rfc6803_checksum_test2_expected_result,
-	},
-	{
-		.desc			= "camellia256-cts-cmac checksum test 3",
-		.enctype		= ENCTYPE_CAMELLIA256_CTS_CMAC,
-		.base_key		= &rfc6803_checksum_test3_basekey,
-		.usage			= &rfc6803_checksum_test3_usage,
-		.plaintext		= &rfc6803_checksum_test3_plaintext,
-		.expected_result	= &rfc6803_checksum_test3_expected_result,
-	},
-	{
-		.desc			= "camellia256-cts-cmac checksum test 4",
-		.enctype		= ENCTYPE_CAMELLIA256_CTS_CMAC,
-		.base_key		= &rfc6803_checksum_test4_basekey,
-		.usage			= &rfc6803_checksum_test4_usage,
-		.plaintext		= &rfc6803_checksum_test4_plaintext,
-		.expected_result	= &rfc6803_checksum_test4_expected_result,
-	},
-};
-
-/* Creates the function rfc6803_checksum_gen_params */
-KUNIT_ARRAY_PARAM(rfc6803_checksum, rfc6803_checksum_test_params,
-		  gss_krb5_get_desc);
-
-/*
- * From RFC 6803 Section 10.  Test vectors
- *
- * Sample encryptions (all using the default cipher state)
- *
- * Copyright (c) 2012 IETF Trust and the persons identified as the
- * document authors.  All rights reserved.
- *
- * Key usage values are from errata 4326 against RFC 6803.
- */
-
-static const struct xdr_netobj rfc6803_enc_empty_plaintext = {
-	.len	= 0,
-};
-
-DEFINE_STR_XDR_NETOBJ(rfc6803_enc_1byte_plaintext, "1");
-DEFINE_STR_XDR_NETOBJ(rfc6803_enc_9byte_plaintext, "9 bytesss");
-DEFINE_STR_XDR_NETOBJ(rfc6803_enc_13byte_plaintext, "13 bytes byte");
-DEFINE_STR_XDR_NETOBJ(rfc6803_enc_30byte_plaintext,
-		      "30 bytes bytes bytes bytes byt"
-);
-
-DEFINE_HEX_XDR_NETOBJ(rfc6803_enc_test1_confounder,
-		      0xb6, 0x98, 0x22, 0xa1, 0x9a, 0x6b, 0x09, 0xc0,
-		      0xeb, 0xc8, 0x55, 0x7d, 0x1f, 0x1b, 0x6c, 0x0a
-);
-DEFINE_HEX_XDR_NETOBJ(rfc6803_enc_test1_basekey,
-		      0x1d, 0xc4, 0x6a, 0x8d, 0x76, 0x3f, 0x4f, 0x93,
-		      0x74, 0x2b, 0xcb, 0xa3, 0x38, 0x75, 0x76, 0xc3
-);
-DEFINE_HEX_XDR_NETOBJ(rfc6803_enc_test1_expected_result,
-		      0xc4, 0x66, 0xf1, 0x87, 0x10, 0x69, 0x92, 0x1e,
-		      0xdb, 0x7c, 0x6f, 0xde, 0x24, 0x4a, 0x52, 0xdb,
-		      0x0b, 0xa1, 0x0e, 0xdc, 0x19, 0x7b, 0xdb, 0x80,
-		      0x06, 0x65, 0x8c, 0xa3, 0xcc, 0xce, 0x6e, 0xb8
-);
-
-DEFINE_HEX_XDR_NETOBJ(rfc6803_enc_test2_confounder,
-		      0x6f, 0x2f, 0xc3, 0xc2, 0xa1, 0x66, 0xfd, 0x88,
-		      0x98, 0x96, 0x7a, 0x83, 0xde, 0x95, 0x96, 0xd9
-);
-DEFINE_HEX_XDR_NETOBJ(rfc6803_enc_test2_basekey,
-		      0x50, 0x27, 0xbc, 0x23, 0x1d, 0x0f, 0x3a, 0x9d,
-		      0x23, 0x33, 0x3f, 0x1c, 0xa6, 0xfd, 0xbe, 0x7c
-);
-DEFINE_HEX_XDR_NETOBJ(rfc6803_enc_test2_expected_result,
-		      0x84, 0x2d, 0x21, 0xfd, 0x95, 0x03, 0x11, 0xc0,
-		      0xdd, 0x46, 0x4a, 0x3f, 0x4b, 0xe8, 0xd6, 0xda,
-		      0x88, 0xa5, 0x6d, 0x55, 0x9c, 0x9b, 0x47, 0xd3,
-		      0xf9, 0xa8, 0x50, 0x67, 0xaf, 0x66, 0x15, 0x59,
-		      0xb8
-);
-
-DEFINE_HEX_XDR_NETOBJ(rfc6803_enc_test3_confounder,
-		      0xa5, 0xb4, 0xa7, 0x1e, 0x07, 0x7a, 0xee, 0xf9,
-		      0x3c, 0x87, 0x63, 0xc1, 0x8f, 0xdb, 0x1f, 0x10
-);
-DEFINE_HEX_XDR_NETOBJ(rfc6803_enc_test3_basekey,
-		      0xa1, 0xbb, 0x61, 0xe8, 0x05, 0xf9, 0xba, 0x6d,
-		      0xde, 0x8f, 0xdb, 0xdd, 0xc0, 0x5c, 0xde, 0xa0
-);
-DEFINE_HEX_XDR_NETOBJ(rfc6803_enc_test3_expected_result,
-		      0x61, 0x9f, 0xf0, 0x72, 0xe3, 0x62, 0x86, 0xff,
-		      0x0a, 0x28, 0xde, 0xb3, 0xa3, 0x52, 0xec, 0x0d,
-		      0x0e, 0xdf, 0x5c, 0x51, 0x60, 0xd6, 0x63, 0xc9,
-		      0x01, 0x75, 0x8c, 0xcf, 0x9d, 0x1e, 0xd3, 0x3d,
-		      0x71, 0xdb, 0x8f, 0x23, 0xaa, 0xbf, 0x83, 0x48,
-		      0xa0
-);
-
-DEFINE_HEX_XDR_NETOBJ(rfc6803_enc_test4_confounder,
-		      0x19, 0xfe, 0xe4, 0x0d, 0x81, 0x0c, 0x52, 0x4b,
-		      0x5b, 0x22, 0xf0, 0x18, 0x74, 0xc6, 0x93, 0xda
-);
-DEFINE_HEX_XDR_NETOBJ(rfc6803_enc_test4_basekey,
-		      0x2c, 0xa2, 0x7a, 0x5f, 0xaf, 0x55, 0x32, 0x24,
-		      0x45, 0x06, 0x43, 0x4e, 0x1c, 0xef, 0x66, 0x76
-);
-DEFINE_HEX_XDR_NETOBJ(rfc6803_enc_test4_expected_result,
-		      0xb8, 0xec, 0xa3, 0x16, 0x7a, 0xe6, 0x31, 0x55,
-		      0x12, 0xe5, 0x9f, 0x98, 0xa7, 0xc5, 0x00, 0x20,
-		      0x5e, 0x5f, 0x63, 0xff, 0x3b, 0xb3, 0x89, 0xaf,
-		      0x1c, 0x41, 0xa2, 0x1d, 0x64, 0x0d, 0x86, 0x15,
-		      0xc9, 0xed, 0x3f, 0xbe, 0xb0, 0x5a, 0xb6, 0xac,
-		      0xb6, 0x76, 0x89, 0xb5, 0xea
-);
-
-DEFINE_HEX_XDR_NETOBJ(rfc6803_enc_test5_confounder,
-		      0xca, 0x7a, 0x7a, 0xb4, 0xbe, 0x19, 0x2d, 0xab,
-		      0xd6, 0x03, 0x50, 0x6d, 0xb1, 0x9c, 0x39, 0xe2
-);
-DEFINE_HEX_XDR_NETOBJ(rfc6803_enc_test5_basekey,
-		      0x78, 0x24, 0xf8, 0xc1, 0x6f, 0x83, 0xff, 0x35,
-		      0x4c, 0x6b, 0xf7, 0x51, 0x5b, 0x97, 0x3f, 0x43
-);
-DEFINE_HEX_XDR_NETOBJ(rfc6803_enc_test5_expected_result,
-		      0xa2, 0x6a, 0x39, 0x05, 0xa4, 0xff, 0xd5, 0x81,
-		      0x6b, 0x7b, 0x1e, 0x27, 0x38, 0x0d, 0x08, 0x09,
-		      0x0c, 0x8e, 0xc1, 0xf3, 0x04, 0x49, 0x6e, 0x1a,
-		      0xbd, 0xcd, 0x2b, 0xdc, 0xd1, 0xdf, 0xfc, 0x66,
-		      0x09, 0x89, 0xe1, 0x17, 0xa7, 0x13, 0xdd, 0xbb,
-		      0x57, 0xa4, 0x14, 0x6c, 0x15, 0x87, 0xcb, 0xa4,
-		      0x35, 0x66, 0x65, 0x59, 0x1d, 0x22, 0x40, 0x28,
-		      0x2f, 0x58, 0x42, 0xb1, 0x05, 0xa5
-);
-
-DEFINE_HEX_XDR_NETOBJ(rfc6803_enc_test6_confounder,
-		      0x3c, 0xbb, 0xd2, 0xb4, 0x59, 0x17, 0x94, 0x10,
-		      0x67, 0xf9, 0x65, 0x99, 0xbb, 0x98, 0x92, 0x6c
-);
-DEFINE_HEX_XDR_NETOBJ(rfc6803_enc_test6_basekey,
-		      0xb6, 0x1c, 0x86, 0xcc, 0x4e, 0x5d, 0x27, 0x57,
-		      0x54, 0x5a, 0xd4, 0x23, 0x39, 0x9f, 0xb7, 0x03,
-		      0x1e, 0xca, 0xb9, 0x13, 0xcb, 0xb9, 0x00, 0xbd,
-		      0x7a, 0x3c, 0x6d, 0xd8, 0xbf, 0x92, 0x01, 0x5b
-);
-DEFINE_HEX_XDR_NETOBJ(rfc6803_enc_test6_expected_result,
-		      0x03, 0x88, 0x6d, 0x03, 0x31, 0x0b, 0x47, 0xa6,
-		      0xd8, 0xf0, 0x6d, 0x7b, 0x94, 0xd1, 0xdd, 0x83,
-		      0x7e, 0xcc, 0xe3, 0x15, 0xef, 0x65, 0x2a, 0xff,
-		      0x62, 0x08, 0x59, 0xd9, 0x4a, 0x25, 0x92, 0x66
-);
-
-DEFINE_HEX_XDR_NETOBJ(rfc6803_enc_test7_confounder,
-		      0xde, 0xf4, 0x87, 0xfc, 0xeb, 0xe6, 0xde, 0x63,
-		      0x46, 0xd4, 0xda, 0x45, 0x21, 0xbb, 0xa2, 0xd2
-);
-DEFINE_HEX_XDR_NETOBJ(rfc6803_enc_test7_basekey,
-		      0x1b, 0x97, 0xfe, 0x0a, 0x19, 0x0e, 0x20, 0x21,
-		      0xeb, 0x30, 0x75, 0x3e, 0x1b, 0x6e, 0x1e, 0x77,
-		      0xb0, 0x75, 0x4b, 0x1d, 0x68, 0x46, 0x10, 0x35,
-		      0x58, 0x64, 0x10, 0x49, 0x63, 0x46, 0x38, 0x33
-);
-DEFINE_HEX_XDR_NETOBJ(rfc6803_enc_test7_expected_result,
-		      0x2c, 0x9c, 0x15, 0x70, 0x13, 0x3c, 0x99, 0xbf,
-		      0x6a, 0x34, 0xbc, 0x1b, 0x02, 0x12, 0x00, 0x2f,
-		      0xd1, 0x94, 0x33, 0x87, 0x49, 0xdb, 0x41, 0x35,
-		      0x49, 0x7a, 0x34, 0x7c, 0xfc, 0xd9, 0xd1, 0x8a,
-		      0x12
-);
-
-DEFINE_HEX_XDR_NETOBJ(rfc6803_enc_test8_confounder,
-		      0xad, 0x4f, 0xf9, 0x04, 0xd3, 0x4e, 0x55, 0x53,
-		      0x84, 0xb1, 0x41, 0x00, 0xfc, 0x46, 0x5f, 0x88
-);
-DEFINE_HEX_XDR_NETOBJ(rfc6803_enc_test8_basekey,
-		      0x32, 0x16, 0x4c, 0x5b, 0x43, 0x4d, 0x1d, 0x15,
-		      0x38, 0xe4, 0xcf, 0xd9, 0xbe, 0x80, 0x40, 0xfe,
-		      0x8c, 0x4a, 0xc7, 0xac, 0xc4, 0xb9, 0x3d, 0x33,
-		      0x14, 0xd2, 0x13, 0x36, 0x68, 0x14, 0x7a, 0x05
-);
-DEFINE_HEX_XDR_NETOBJ(rfc6803_enc_test8_expected_result,
-		      0x9c, 0x6d, 0xe7, 0x5f, 0x81, 0x2d, 0xe7, 0xed,
-		      0x0d, 0x28, 0xb2, 0x96, 0x35, 0x57, 0xa1, 0x15,
-		      0x64, 0x09, 0x98, 0x27, 0x5b, 0x0a, 0xf5, 0x15,
-		      0x27, 0x09, 0x91, 0x3f, 0xf5, 0x2a, 0x2a, 0x9c,
-		      0x8e, 0x63, 0xb8, 0x72, 0xf9, 0x2e, 0x64, 0xc8,
-		      0x39
-);
-
-DEFINE_HEX_XDR_NETOBJ(rfc6803_enc_test9_confounder,
-		      0xcf, 0x9b, 0xca, 0x6d, 0xf1, 0x14, 0x4e, 0x0c,
-		      0x0a, 0xf9, 0xb8, 0xf3, 0x4c, 0x90, 0xd5, 0x14
-);
-DEFINE_HEX_XDR_NETOBJ(rfc6803_enc_test9_basekey,
-		      0xb0, 0x38, 0xb1, 0x32, 0xcd, 0x8e, 0x06, 0x61,
-		      0x22, 0x67, 0xfa, 0xb7, 0x17, 0x00, 0x66, 0xd8,
-		      0x8a, 0xec, 0xcb, 0xa0, 0xb7, 0x44, 0xbf, 0xc6,
-		      0x0d, 0xc8, 0x9b, 0xca, 0x18, 0x2d, 0x07, 0x15
-);
-DEFINE_HEX_XDR_NETOBJ(rfc6803_enc_test9_expected_result,
-		      0xee, 0xec, 0x85, 0xa9, 0x81, 0x3c, 0xdc, 0x53,
-		      0x67, 0x72, 0xab, 0x9b, 0x42, 0xde, 0xfc, 0x57,
-		      0x06, 0xf7, 0x26, 0xe9, 0x75, 0xdd, 0xe0, 0x5a,
-		      0x87, 0xeb, 0x54, 0x06, 0xea, 0x32, 0x4c, 0xa1,
-		      0x85, 0xc9, 0x98, 0x6b, 0x42, 0xaa, 0xbe, 0x79,
-		      0x4b, 0x84, 0x82, 0x1b, 0xee
-);
-
-DEFINE_HEX_XDR_NETOBJ(rfc6803_enc_test10_confounder,
-		      0x64, 0x4d, 0xef, 0x38, 0xda, 0x35, 0x00, 0x72,
-		      0x75, 0x87, 0x8d, 0x21, 0x68, 0x55, 0xe2, 0x28
-);
-DEFINE_HEX_XDR_NETOBJ(rfc6803_enc_test10_basekey,
-		      0xcc, 0xfc, 0xd3, 0x49, 0xbf, 0x4c, 0x66, 0x77,
-		      0xe8, 0x6e, 0x4b, 0x02, 0xb8, 0xea, 0xb9, 0x24,
-		      0xa5, 0x46, 0xac, 0x73, 0x1c, 0xf9, 0xbf, 0x69,
-		      0x89, 0xb9, 0x96, 0xe7, 0xd6, 0xbf, 0xbb, 0xa7
-);
-DEFINE_HEX_XDR_NETOBJ(rfc6803_enc_test10_expected_result,
-		      0x0e, 0x44, 0x68, 0x09, 0x85, 0x85, 0x5f, 0x2d,
-		      0x1f, 0x18, 0x12, 0x52, 0x9c, 0xa8, 0x3b, 0xfd,
-		      0x8e, 0x34, 0x9d, 0xe6, 0xfd, 0x9a, 0xda, 0x0b,
-		      0xaa, 0xa0, 0x48, 0xd6, 0x8e, 0x26, 0x5f, 0xeb,
-		      0xf3, 0x4a, 0xd1, 0x25, 0x5a, 0x34, 0x49, 0x99,
-		      0xad, 0x37, 0x14, 0x68, 0x87, 0xa6, 0xc6, 0x84,
-		      0x57, 0x31, 0xac, 0x7f, 0x46, 0x37, 0x6a, 0x05,
-		      0x04, 0xcd, 0x06, 0x57, 0x14, 0x74
-);
-
-static const struct gss_krb5_test_param rfc6803_encrypt_test_params[] = {
-	{
-		.desc			= "Encrypt empty plaintext with camellia128-cts-cmac",
-		.enctype		= ENCTYPE_CAMELLIA128_CTS_CMAC,
-		.constant		= 0,
-		.base_key		= &rfc6803_enc_test1_basekey,
-		.plaintext		= &rfc6803_enc_empty_plaintext,
-		.confounder		= &rfc6803_enc_test1_confounder,
-		.expected_result	= &rfc6803_enc_test1_expected_result,
-	},
-	{
-		.desc			= "Encrypt 1 byte with camellia128-cts-cmac",
-		.enctype		= ENCTYPE_CAMELLIA128_CTS_CMAC,
-		.constant		= 1,
-		.base_key		= &rfc6803_enc_test2_basekey,
-		.plaintext		= &rfc6803_enc_1byte_plaintext,
-		.confounder		= &rfc6803_enc_test2_confounder,
-		.expected_result	= &rfc6803_enc_test2_expected_result,
-	},
-	{
-		.desc			= "Encrypt 9 bytes with camellia128-cts-cmac",
-		.enctype		= ENCTYPE_CAMELLIA128_CTS_CMAC,
-		.constant		= 2,
-		.base_key		= &rfc6803_enc_test3_basekey,
-		.plaintext		= &rfc6803_enc_9byte_plaintext,
-		.confounder		= &rfc6803_enc_test3_confounder,
-		.expected_result	= &rfc6803_enc_test3_expected_result,
-	},
-	{
-		.desc			= "Encrypt 13 bytes with camellia128-cts-cmac",
-		.enctype		= ENCTYPE_CAMELLIA128_CTS_CMAC,
-		.constant		= 3,
-		.base_key		= &rfc6803_enc_test4_basekey,
-		.plaintext		= &rfc6803_enc_13byte_plaintext,
-		.confounder		= &rfc6803_enc_test4_confounder,
-		.expected_result	= &rfc6803_enc_test4_expected_result,
-	},
-	{
-		.desc			= "Encrypt 30 bytes with camellia128-cts-cmac",
-		.enctype		= ENCTYPE_CAMELLIA128_CTS_CMAC,
-		.constant		= 4,
-		.base_key		= &rfc6803_enc_test5_basekey,
-		.plaintext		= &rfc6803_enc_30byte_plaintext,
-		.confounder		= &rfc6803_enc_test5_confounder,
-		.expected_result	= &rfc6803_enc_test5_expected_result,
-	},
-	{
-		.desc			= "Encrypt empty plaintext with camellia256-cts-cmac",
-		.enctype		= ENCTYPE_CAMELLIA256_CTS_CMAC,
-		.constant		= 0,
-		.base_key		= &rfc6803_enc_test6_basekey,
-		.plaintext		= &rfc6803_enc_empty_plaintext,
-		.confounder		= &rfc6803_enc_test6_confounder,
-		.expected_result	= &rfc6803_enc_test6_expected_result,
-	},
-	{
-		.desc			= "Encrypt 1 byte with camellia256-cts-cmac",
-		.enctype		= ENCTYPE_CAMELLIA256_CTS_CMAC,
-		.constant		= 1,
-		.base_key		= &rfc6803_enc_test7_basekey,
-		.plaintext		= &rfc6803_enc_1byte_plaintext,
-		.confounder		= &rfc6803_enc_test7_confounder,
-		.expected_result	= &rfc6803_enc_test7_expected_result,
-	},
-	{
-		.desc			= "Encrypt 9 bytes with camellia256-cts-cmac",
-		.enctype		= ENCTYPE_CAMELLIA256_CTS_CMAC,
-		.constant		= 2,
-		.base_key		= &rfc6803_enc_test8_basekey,
-		.plaintext		= &rfc6803_enc_9byte_plaintext,
-		.confounder		= &rfc6803_enc_test8_confounder,
-		.expected_result	= &rfc6803_enc_test8_expected_result,
-	},
-	{
-		.desc			= "Encrypt 13 bytes with camellia256-cts-cmac",
-		.enctype		= ENCTYPE_CAMELLIA256_CTS_CMAC,
-		.constant		= 3,
-		.base_key		= &rfc6803_enc_test9_basekey,
-		.plaintext		= &rfc6803_enc_13byte_plaintext,
-		.confounder		= &rfc6803_enc_test9_confounder,
-		.expected_result	= &rfc6803_enc_test9_expected_result,
-	},
-	{
-		.desc			= "Encrypt 30 bytes with camellia256-cts-cmac",
-		.enctype		= ENCTYPE_CAMELLIA256_CTS_CMAC,
-		.constant		= 4,
-		.base_key		= &rfc6803_enc_test10_basekey,
-		.plaintext		= &rfc6803_enc_30byte_plaintext,
-		.confounder		= &rfc6803_enc_test10_confounder,
-		.expected_result	= &rfc6803_enc_test10_expected_result,
-	},
-};
-
-/* Creates the function rfc6803_encrypt_gen_params */
-KUNIT_ARRAY_PARAM(rfc6803_encrypt, rfc6803_encrypt_test_params,
-		  gss_krb5_get_desc);
-
-static void rfc6803_encrypt_case(struct kunit *test)
-{
-	const struct gss_krb5_test_param *param = test->param_value;
-	struct crypto_sync_skcipher *cts_tfm, *cbc_tfm;
-	const struct gss_krb5_enctype *gk5e;
-	struct xdr_netobj Ke, Ki, checksum;
-	u8 usage_data[GSS_KRB5_K5CLENGTH];
-	struct xdr_netobj usage = {
-		.data = usage_data,
-		.len = sizeof(usage_data),
-	};
-	struct crypto_ahash *ahash_tfm;
-	unsigned int blocksize;
-	struct xdr_buf buf;
-	void *text;
-	size_t len;
-	u32 err;
-
-	/* Arrange */
-	gk5e = gss_krb5_lookup_enctype(param->enctype);
-	if (!gk5e)
-		kunit_skip(test, "Encryption type is not available");
-
-	memset(usage_data, 0, sizeof(usage_data));
-	usage.data[3] = param->constant;
-
-	Ke.len = gk5e->Ke_length;
-	Ke.data = kunit_kzalloc(test, Ke.len, GFP_KERNEL);
-	KUNIT_ASSERT_NOT_ERR_OR_NULL(test, Ke.data);
-	usage.data[4] = KEY_USAGE_SEED_ENCRYPTION;
-	err = gk5e->derive_key(gk5e, param->base_key, &Ke, &usage, GFP_KERNEL);
-	KUNIT_ASSERT_EQ(test, err, 0);
-
-	cbc_tfm = crypto_alloc_sync_skcipher(gk5e->aux_cipher, 0, 0);
-	KUNIT_ASSERT_NOT_ERR_OR_NULL(test, cbc_tfm);
-	err = crypto_sync_skcipher_setkey(cbc_tfm, Ke.data, Ke.len);
-	KUNIT_ASSERT_EQ(test, err, 0);
-
-	cts_tfm = crypto_alloc_sync_skcipher(gk5e->encrypt_name, 0, 0);
-	KUNIT_ASSERT_NOT_ERR_OR_NULL(test, cts_tfm);
-	err = crypto_sync_skcipher_setkey(cts_tfm, Ke.data, Ke.len);
-	KUNIT_ASSERT_EQ(test, err, 0);
-	blocksize = crypto_sync_skcipher_blocksize(cts_tfm);
-
-	len = param->confounder->len + param->plaintext->len + blocksize;
-	text = kunit_kzalloc(test, len, GFP_KERNEL);
-	KUNIT_ASSERT_NOT_ERR_OR_NULL(test, text);
-	memcpy(text, param->confounder->data, param->confounder->len);
-	memcpy(text + param->confounder->len, param->plaintext->data,
-	       param->plaintext->len);
-
-	memset(&buf, 0, sizeof(buf));
-	buf.head[0].iov_base = text;
-	buf.head[0].iov_len = param->confounder->len + param->plaintext->len;
-	buf.len = buf.head[0].iov_len;
-
-	checksum.len = gk5e->cksumlength;
-	checksum.data = kunit_kzalloc(test, checksum.len, GFP_KERNEL);
-	KUNIT_ASSERT_NOT_ERR_OR_NULL(test, checksum.data);
-
-	Ki.len = gk5e->Ki_length;
-	Ki.data = kunit_kzalloc(test, Ki.len, GFP_KERNEL);
-	KUNIT_ASSERT_NOT_ERR_OR_NULL(test, Ki.data);
-	usage.data[4] = KEY_USAGE_SEED_INTEGRITY;
-	err = gk5e->derive_key(gk5e, param->base_key, &Ki,
-			       &usage, GFP_KERNEL);
-	KUNIT_ASSERT_EQ(test, err, 0);
-	ahash_tfm = crypto_alloc_ahash(gk5e->cksum_name, 0, CRYPTO_ALG_ASYNC);
-	KUNIT_ASSERT_NOT_ERR_OR_NULL(test, ahash_tfm);
-	err = crypto_ahash_setkey(ahash_tfm, Ki.data, Ki.len);
-	KUNIT_ASSERT_EQ(test, err, 0);
-
-	/* Act */
-	err = gss_krb5_checksum(ahash_tfm, NULL, 0, &buf, 0, &checksum);
-	KUNIT_ASSERT_EQ(test, err, 0);
-
-	err = krb5_cbc_cts_encrypt(cts_tfm, cbc_tfm, 0, &buf, NULL, NULL, 0);
-	KUNIT_ASSERT_EQ(test, err, 0);
-
-	/* Assert */
-	KUNIT_EXPECT_EQ_MSG(test, param->expected_result->len,
-			    buf.len + checksum.len,
-			    "ciphertext length mismatch");
-	KUNIT_EXPECT_MEMEQ_MSG(test,
-			       param->expected_result->data,
-			       buf.head[0].iov_base,
-			       buf.len,
-			       "encrypted result mismatch");
-	KUNIT_EXPECT_MEMEQ_MSG(test,
-			       param->expected_result->data +
-					(param->expected_result->len - checksum.len),
-			       checksum.data,
-			       checksum.len,
-			       "HMAC mismatch");
-
-	crypto_free_ahash(ahash_tfm);
-	crypto_free_sync_skcipher(cts_tfm);
-	crypto_free_sync_skcipher(cbc_tfm);
-}
-
-static struct kunit_case rfc6803_test_cases[] = {
-	{
-		.name			= "RFC 6803 key derivation",
-		.run_case		= kdf_case,
-		.generate_params	= rfc6803_kdf_gen_params,
-	},
-	{
-		.name			= "RFC 6803 checksum",
-		.run_case		= checksum_case,
-		.generate_params	= rfc6803_checksum_gen_params,
-	},
-	{
-		.name			= "RFC 6803 encryption",
-		.run_case		= rfc6803_encrypt_case,
-		.generate_params	= rfc6803_encrypt_gen_params,
-	},
-	{}
-};
-
-static struct kunit_suite rfc6803_suite = {
-	.name			= "RFC 6803 suite",
-	.test_cases		= rfc6803_test_cases,
-};
-
-/*
- * From RFC 8009 Appendix A.  Test Vectors
- *
- * Sample results for SHA-2 enctype key derivation
- *
- * This test material is copyright (c) 2016 IETF Trust and the
- * persons identified as the document authors.  All rights reserved.
- */
-
-DEFINE_HEX_XDR_NETOBJ(aes128_cts_hmac_sha256_128_basekey,
-		      0x37, 0x05, 0xd9, 0x60, 0x80, 0xc1, 0x77, 0x28,
-		      0xa0, 0xe8, 0x00, 0xea, 0xb6, 0xe0, 0xd2, 0x3c
-);
-DEFINE_HEX_XDR_NETOBJ(aes128_cts_hmac_sha256_128_Kc,
-		      0xb3, 0x1a, 0x01, 0x8a, 0x48, 0xf5, 0x47, 0x76,
-		      0xf4, 0x03, 0xe9, 0xa3, 0x96, 0x32, 0x5d, 0xc3
-);
-DEFINE_HEX_XDR_NETOBJ(aes128_cts_hmac_sha256_128_Ke,
-		      0x9b, 0x19, 0x7d, 0xd1, 0xe8, 0xc5, 0x60, 0x9d,
-		      0x6e, 0x67, 0xc3, 0xe3, 0x7c, 0x62, 0xc7, 0x2e
-);
-DEFINE_HEX_XDR_NETOBJ(aes128_cts_hmac_sha256_128_Ki,
-		      0x9f, 0xda, 0x0e, 0x56, 0xab, 0x2d, 0x85, 0xe1,
-		      0x56, 0x9a, 0x68, 0x86, 0x96, 0xc2, 0x6a, 0x6c
-);
-
-DEFINE_HEX_XDR_NETOBJ(aes256_cts_hmac_sha384_192_basekey,
-		      0x6d, 0x40, 0x4d, 0x37, 0xfa, 0xf7, 0x9f, 0x9d,
-		      0xf0, 0xd3, 0x35, 0x68, 0xd3, 0x20, 0x66, 0x98,
-		      0x00, 0xeb, 0x48, 0x36, 0x47, 0x2e, 0xa8, 0xa0,
-		      0x26, 0xd1, 0x6b, 0x71, 0x82, 0x46, 0x0c, 0x52
-);
-DEFINE_HEX_XDR_NETOBJ(aes256_cts_hmac_sha384_192_Kc,
-		      0xef, 0x57, 0x18, 0xbe, 0x86, 0xcc, 0x84, 0x96,
-		      0x3d, 0x8b, 0xbb, 0x50, 0x31, 0xe9, 0xf5, 0xc4,
-		      0xba, 0x41, 0xf2, 0x8f, 0xaf, 0x69, 0xe7, 0x3d
-);
-DEFINE_HEX_XDR_NETOBJ(aes256_cts_hmac_sha384_192_Ke,
-		      0x56, 0xab, 0x22, 0xbe, 0xe6, 0x3d, 0x82, 0xd7,
-		      0xbc, 0x52, 0x27, 0xf6, 0x77, 0x3f, 0x8e, 0xa7,
-		      0xa5, 0xeb, 0x1c, 0x82, 0x51, 0x60, 0xc3, 0x83,
-		      0x12, 0x98, 0x0c, 0x44, 0x2e, 0x5c, 0x7e, 0x49
-);
-DEFINE_HEX_XDR_NETOBJ(aes256_cts_hmac_sha384_192_Ki,
-		      0x69, 0xb1, 0x65, 0x14, 0xe3, 0xcd, 0x8e, 0x56,
-		      0xb8, 0x20, 0x10, 0xd5, 0xc7, 0x30, 0x12, 0xb6,
-		      0x22, 0xc4, 0xd0, 0x0f, 0xfc, 0x23, 0xed, 0x1f
-);
-
-static const struct gss_krb5_test_param rfc8009_kdf_test_params[] = {
-	{
-		.desc			= "Derive Kc subkey for aes128-cts-hmac-sha256-128",
-		.enctype		= ENCTYPE_AES128_CTS_HMAC_SHA256_128,
-		.base_key		= &aes128_cts_hmac_sha256_128_basekey,
-		.usage			= &usage_checksum,
-		.expected_result	= &aes128_cts_hmac_sha256_128_Kc,
-	},
-	{
-		.desc			= "Derive Ke subkey for aes128-cts-hmac-sha256-128",
-		.enctype		= ENCTYPE_AES128_CTS_HMAC_SHA256_128,
-		.base_key		= &aes128_cts_hmac_sha256_128_basekey,
-		.usage			= &usage_encryption,
-		.expected_result	= &aes128_cts_hmac_sha256_128_Ke,
-	},
-	{
-		.desc			= "Derive Ki subkey for aes128-cts-hmac-sha256-128",
-		.enctype		= ENCTYPE_AES128_CTS_HMAC_SHA256_128,
-		.base_key		= &aes128_cts_hmac_sha256_128_basekey,
-		.usage			= &usage_integrity,
-		.expected_result	= &aes128_cts_hmac_sha256_128_Ki,
-	},
-	{
-		.desc			= "Derive Kc subkey for aes256-cts-hmac-sha384-192",
-		.enctype		= ENCTYPE_AES256_CTS_HMAC_SHA384_192,
-		.base_key		= &aes256_cts_hmac_sha384_192_basekey,
-		.usage			= &usage_checksum,
-		.expected_result	= &aes256_cts_hmac_sha384_192_Kc,
-	},
-	{
-		.desc			= "Derive Ke subkey for aes256-cts-hmac-sha384-192",
-		.enctype		= ENCTYPE_AES256_CTS_HMAC_SHA384_192,
-		.base_key		= &aes256_cts_hmac_sha384_192_basekey,
-		.usage			= &usage_encryption,
-		.expected_result	= &aes256_cts_hmac_sha384_192_Ke,
-	},
-	{
-		.desc			= "Derive Ki subkey for aes256-cts-hmac-sha384-192",
-		.enctype		= ENCTYPE_AES256_CTS_HMAC_SHA384_192,
-		.base_key		= &aes256_cts_hmac_sha384_192_basekey,
-		.usage			= &usage_integrity,
-		.expected_result	= &aes256_cts_hmac_sha384_192_Ki,
-	},
-};
-
-/* Creates the function rfc8009_kdf_gen_params */
-KUNIT_ARRAY_PARAM(rfc8009_kdf, rfc8009_kdf_test_params, gss_krb5_get_desc);
-
-/*
- * From RFC 8009 Appendix A.  Test Vectors
- *
- * These sample checksums use the above sample key derivation results,
- * including use of the same base-key and key usage values.
- *
- * This test material is copyright (c) 2016 IETF Trust and the
- * persons identified as the document authors.  All rights reserved.
- */
-
-DEFINE_HEX_XDR_NETOBJ(rfc8009_checksum_plaintext,
-		      0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
-		      0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
-		      0x10, 0x11, 0x12, 0x13, 0x14
-);
-DEFINE_HEX_XDR_NETOBJ(rfc8009_checksum_test1_expected_result,
-		      0xd7, 0x83, 0x67, 0x18, 0x66, 0x43, 0xd6, 0x7b,
-		      0x41, 0x1c, 0xba, 0x91, 0x39, 0xfc, 0x1d, 0xee
-);
-DEFINE_HEX_XDR_NETOBJ(rfc8009_checksum_test2_expected_result,
-		      0x45, 0xee, 0x79, 0x15, 0x67, 0xee, 0xfc, 0xa3,
-		      0x7f, 0x4a, 0xc1, 0xe0, 0x22, 0x2d, 0xe8, 0x0d,
-		      0x43, 0xc3, 0xbf, 0xa0, 0x66, 0x99, 0x67, 0x2a
-);
-
-static const struct gss_krb5_test_param rfc8009_checksum_test_params[] = {
-	{
-		.desc			= "Checksum with aes128-cts-hmac-sha256-128",
-		.enctype		= ENCTYPE_AES128_CTS_HMAC_SHA256_128,
-		.base_key		= &aes128_cts_hmac_sha256_128_basekey,
-		.usage			= &usage_checksum,
-		.plaintext		= &rfc8009_checksum_plaintext,
-		.expected_result	= &rfc8009_checksum_test1_expected_result,
-	},
-	{
-		.desc			= "Checksum with aes256-cts-hmac-sha384-192",
-		.enctype		= ENCTYPE_AES256_CTS_HMAC_SHA384_192,
-		.base_key		= &aes256_cts_hmac_sha384_192_basekey,
-		.usage			= &usage_checksum,
-		.plaintext		= &rfc8009_checksum_plaintext,
-		.expected_result	= &rfc8009_checksum_test2_expected_result,
-	},
-};
-
-/* Creates the function rfc8009_checksum_gen_params */
-KUNIT_ARRAY_PARAM(rfc8009_checksum, rfc8009_checksum_test_params,
-		  gss_krb5_get_desc);
-
-/*
- * From RFC 8009 Appendix A.  Test Vectors
- *
- * Sample encryptions (all using the default cipher state):
- * --------------------------------------------------------
- *
- * These sample encryptions use the above sample key derivation results,
- * including use of the same base-key and key usage values.
- *
- * This test material is copyright (c) 2016 IETF Trust and the
- * persons identified as the document authors.  All rights reserved.
- */
-
-static const struct xdr_netobj rfc8009_enc_empty_plaintext = {
-	.len	= 0,
-};
-DEFINE_HEX_XDR_NETOBJ(rfc8009_enc_short_plaintext,
-		      0x00, 0x01, 0x02, 0x03, 0x04, 0x05
-);
-DEFINE_HEX_XDR_NETOBJ(rfc8009_enc_block_plaintext,
-		      0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
-		      0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f
-);
-DEFINE_HEX_XDR_NETOBJ(rfc8009_enc_long_plaintext,
-		      0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
-		      0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
-		      0x10, 0x11, 0x12, 0x13, 0x14
-);
-
-DEFINE_HEX_XDR_NETOBJ(rfc8009_enc_test1_confounder,
-		      0x7e, 0x58, 0x95, 0xea, 0xf2, 0x67, 0x24, 0x35,
-		      0xba, 0xd8, 0x17, 0xf5, 0x45, 0xa3, 0x71, 0x48
-);
-DEFINE_HEX_XDR_NETOBJ(rfc8009_enc_test1_expected_result,
-		      0xef, 0x85, 0xfb, 0x89, 0x0b, 0xb8, 0x47, 0x2f,
-		      0x4d, 0xab, 0x20, 0x39, 0x4d, 0xca, 0x78, 0x1d
-);
-DEFINE_HEX_XDR_NETOBJ(rfc8009_enc_test1_expected_hmac,
-		      0xad, 0x87, 0x7e, 0xda, 0x39, 0xd5, 0x0c, 0x87,
-		      0x0c, 0x0d, 0x5a, 0x0a, 0x8e, 0x48, 0xc7, 0x18
-);
-
-DEFINE_HEX_XDR_NETOBJ(rfc8009_enc_test2_confounder,
-		      0x7b, 0xca, 0x28, 0x5e, 0x2f, 0xd4, 0x13, 0x0f,
-		      0xb5, 0x5b, 0x1a, 0x5c, 0x83, 0xbc, 0x5b, 0x24
-);
-DEFINE_HEX_XDR_NETOBJ(rfc8009_enc_test2_expected_result,
-		      0x84, 0xd7, 0xf3, 0x07, 0x54, 0xed, 0x98, 0x7b,
-		      0xab, 0x0b, 0xf3, 0x50, 0x6b, 0xeb, 0x09, 0xcf,
-		      0xb5, 0x54, 0x02, 0xce, 0xf7, 0xe6
-);
-DEFINE_HEX_XDR_NETOBJ(rfc8009_enc_test2_expected_hmac,
-		      0x87, 0x7c, 0xe9, 0x9e, 0x24, 0x7e, 0x52, 0xd1,
-		      0x6e, 0xd4, 0x42, 0x1d, 0xfd, 0xf8, 0x97, 0x6c
-);
-
-DEFINE_HEX_XDR_NETOBJ(rfc8009_enc_test3_confounder,
-		      0x56, 0xab, 0x21, 0x71, 0x3f, 0xf6, 0x2c, 0x0a,
-		      0x14, 0x57, 0x20, 0x0f, 0x6f, 0xa9, 0x94, 0x8f
-);
-DEFINE_HEX_XDR_NETOBJ(rfc8009_enc_test3_expected_result,
-		      0x35, 0x17, 0xd6, 0x40, 0xf5, 0x0d, 0xdc, 0x8a,
-		      0xd3, 0x62, 0x87, 0x22, 0xb3, 0x56, 0x9d, 0x2a,
-		      0xe0, 0x74, 0x93, 0xfa, 0x82, 0x63, 0x25, 0x40,
-		      0x80, 0xea, 0x65, 0xc1, 0x00, 0x8e, 0x8f, 0xc2
-);
-DEFINE_HEX_XDR_NETOBJ(rfc8009_enc_test3_expected_hmac,
-		      0x95, 0xfb, 0x48, 0x52, 0xe7, 0xd8, 0x3e, 0x1e,
-		      0x7c, 0x48, 0xc3, 0x7e, 0xeb, 0xe6, 0xb0, 0xd3
-);
-
-DEFINE_HEX_XDR_NETOBJ(rfc8009_enc_test4_confounder,
-		      0xa7, 0xa4, 0xe2, 0x9a, 0x47, 0x28, 0xce, 0x10,
-		      0x66, 0x4f, 0xb6, 0x4e, 0x49, 0xad, 0x3f, 0xac
-);
-DEFINE_HEX_XDR_NETOBJ(rfc8009_enc_test4_expected_result,
-		      0x72, 0x0f, 0x73, 0xb1, 0x8d, 0x98, 0x59, 0xcd,
-		      0x6c, 0xcb, 0x43, 0x46, 0x11, 0x5c, 0xd3, 0x36,
-		      0xc7, 0x0f, 0x58, 0xed, 0xc0, 0xc4, 0x43, 0x7c,
-		      0x55, 0x73, 0x54, 0x4c, 0x31, 0xc8, 0x13, 0xbc,
-		      0xe1, 0xe6, 0xd0, 0x72, 0xc1
-);
-DEFINE_HEX_XDR_NETOBJ(rfc8009_enc_test4_expected_hmac,
-		      0x86, 0xb3, 0x9a, 0x41, 0x3c, 0x2f, 0x92, 0xca,
-		      0x9b, 0x83, 0x34, 0xa2, 0x87, 0xff, 0xcb, 0xfc
-);
-
-DEFINE_HEX_XDR_NETOBJ(rfc8009_enc_test5_confounder,
-		      0xf7, 0x64, 0xe9, 0xfa, 0x15, 0xc2, 0x76, 0x47,
-		      0x8b, 0x2c, 0x7d, 0x0c, 0x4e, 0x5f, 0x58, 0xe4
-);
-DEFINE_HEX_XDR_NETOBJ(rfc8009_enc_test5_expected_result,
-		      0x41, 0xf5, 0x3f, 0xa5, 0xbf, 0xe7, 0x02, 0x6d,
-		      0x91, 0xfa, 0xf9, 0xbe, 0x95, 0x91, 0x95, 0xa0
-);
-DEFINE_HEX_XDR_NETOBJ(rfc8009_enc_test5_expected_hmac,
-		      0x58, 0x70, 0x72, 0x73, 0xa9, 0x6a, 0x40, 0xf0,
-		      0xa0, 0x19, 0x60, 0x62, 0x1a, 0xc6, 0x12, 0x74,
-		      0x8b, 0x9b, 0xbf, 0xbe, 0x7e, 0xb4, 0xce, 0x3c
-);
-
-DEFINE_HEX_XDR_NETOBJ(rfc8009_enc_test6_confounder,
-		      0xb8, 0x0d, 0x32, 0x51, 0xc1, 0xf6, 0x47, 0x14,
-		      0x94, 0x25, 0x6f, 0xfe, 0x71, 0x2d, 0x0b, 0x9a
-);
-DEFINE_HEX_XDR_NETOBJ(rfc8009_enc_test6_expected_result,
-		      0x4e, 0xd7, 0xb3, 0x7c, 0x2b, 0xca, 0xc8, 0xf7,
-		      0x4f, 0x23, 0xc1, 0xcf, 0x07, 0xe6, 0x2b, 0xc7,
-		      0xb7, 0x5f, 0xb3, 0xf6, 0x37, 0xb9
-);
-DEFINE_HEX_XDR_NETOBJ(rfc8009_enc_test6_expected_hmac,
-		      0xf5, 0x59, 0xc7, 0xf6, 0x64, 0xf6, 0x9e, 0xab,
-		      0x7b, 0x60, 0x92, 0x23, 0x75, 0x26, 0xea, 0x0d,
-		      0x1f, 0x61, 0xcb, 0x20, 0xd6, 0x9d, 0x10, 0xf2
-);
-
-DEFINE_HEX_XDR_NETOBJ(rfc8009_enc_test7_confounder,
-		      0x53, 0xbf, 0x8a, 0x0d, 0x10, 0x52, 0x65, 0xd4,
-		      0xe2, 0x76, 0x42, 0x86, 0x24, 0xce, 0x5e, 0x63
-);
-DEFINE_HEX_XDR_NETOBJ(rfc8009_enc_test7_expected_result,
-		      0xbc, 0x47, 0xff, 0xec, 0x79, 0x98, 0xeb, 0x91,
-		      0xe8, 0x11, 0x5c, 0xf8, 0xd1, 0x9d, 0xac, 0x4b,
-		      0xbb, 0xe2, 0xe1, 0x63, 0xe8, 0x7d, 0xd3, 0x7f,
-		      0x49, 0xbe, 0xca, 0x92, 0x02, 0x77, 0x64, 0xf6
-);
-DEFINE_HEX_XDR_NETOBJ(rfc8009_enc_test7_expected_hmac,
-		      0x8c, 0xf5, 0x1f, 0x14, 0xd7, 0x98, 0xc2, 0x27,
-		      0x3f, 0x35, 0xdf, 0x57, 0x4d, 0x1f, 0x93, 0x2e,
-		      0x40, 0xc4, 0xff, 0x25, 0x5b, 0x36, 0xa2, 0x66
-);
-
-DEFINE_HEX_XDR_NETOBJ(rfc8009_enc_test8_confounder,
-		      0x76, 0x3e, 0x65, 0x36, 0x7e, 0x86, 0x4f, 0x02,
-		      0xf5, 0x51, 0x53, 0xc7, 0xe3, 0xb5, 0x8a, 0xf1
-);
-DEFINE_HEX_XDR_NETOBJ(rfc8009_enc_test8_expected_result,
-		      0x40, 0x01, 0x3e, 0x2d, 0xf5, 0x8e, 0x87, 0x51,
-		      0x95, 0x7d, 0x28, 0x78, 0xbc, 0xd2, 0xd6, 0xfe,
-		      0x10, 0x1c, 0xcf, 0xd5, 0x56, 0xcb, 0x1e, 0xae,
-		      0x79, 0xdb, 0x3c, 0x3e, 0xe8, 0x64, 0x29, 0xf2,
-		      0xb2, 0xa6, 0x02, 0xac, 0x86
-);
-DEFINE_HEX_XDR_NETOBJ(rfc8009_enc_test8_expected_hmac,
-		      0xfe, 0xf6, 0xec, 0xb6, 0x47, 0xd6, 0x29, 0x5f,
-		      0xae, 0x07, 0x7a, 0x1f, 0xeb, 0x51, 0x75, 0x08,
-		      0xd2, 0xc1, 0x6b, 0x41, 0x92, 0xe0, 0x1f, 0x62
-);
-
-static const struct gss_krb5_test_param rfc8009_encrypt_test_params[] = {
-	{
-		.desc			= "Encrypt empty plaintext with aes128-cts-hmac-sha256-128",
-		.enctype		= ENCTYPE_AES128_CTS_HMAC_SHA256_128,
-		.plaintext		= &rfc8009_enc_empty_plaintext,
-		.confounder		= &rfc8009_enc_test1_confounder,
-		.base_key		= &aes128_cts_hmac_sha256_128_basekey,
-		.expected_result	= &rfc8009_enc_test1_expected_result,
-		.expected_hmac		= &rfc8009_enc_test1_expected_hmac,
-	},
-	{
-		.desc			= "Encrypt short plaintext with aes128-cts-hmac-sha256-128",
-		.enctype		= ENCTYPE_AES128_CTS_HMAC_SHA256_128,
-		.plaintext		= &rfc8009_enc_short_plaintext,
-		.confounder		= &rfc8009_enc_test2_confounder,
-		.base_key		= &aes128_cts_hmac_sha256_128_basekey,
-		.expected_result	= &rfc8009_enc_test2_expected_result,
-		.expected_hmac		= &rfc8009_enc_test2_expected_hmac,
-	},
-	{
-		.desc			= "Encrypt block plaintext with aes128-cts-hmac-sha256-128",
-		.enctype		= ENCTYPE_AES128_CTS_HMAC_SHA256_128,
-		.plaintext		= &rfc8009_enc_block_plaintext,
-		.confounder		= &rfc8009_enc_test3_confounder,
-		.base_key		= &aes128_cts_hmac_sha256_128_basekey,
-		.expected_result	= &rfc8009_enc_test3_expected_result,
-		.expected_hmac		= &rfc8009_enc_test3_expected_hmac,
-	},
-	{
-		.desc			= "Encrypt long plaintext with aes128-cts-hmac-sha256-128",
-		.enctype		= ENCTYPE_AES128_CTS_HMAC_SHA256_128,
-		.plaintext		= &rfc8009_enc_long_plaintext,
-		.confounder		= &rfc8009_enc_test4_confounder,
-		.base_key		= &aes128_cts_hmac_sha256_128_basekey,
-		.expected_result	= &rfc8009_enc_test4_expected_result,
-		.expected_hmac		= &rfc8009_enc_test4_expected_hmac,
-	},
-	{
-		.desc			= "Encrypt empty plaintext with aes256-cts-hmac-sha384-192",
-		.enctype		= ENCTYPE_AES256_CTS_HMAC_SHA384_192,
-		.plaintext		= &rfc8009_enc_empty_plaintext,
-		.confounder		= &rfc8009_enc_test5_confounder,
-		.base_key		= &aes256_cts_hmac_sha384_192_basekey,
-		.expected_result	= &rfc8009_enc_test5_expected_result,
-		.expected_hmac		= &rfc8009_enc_test5_expected_hmac,
-	},
-	{
-		.desc			= "Encrypt short plaintext with aes256-cts-hmac-sha384-192",
-		.enctype		= ENCTYPE_AES256_CTS_HMAC_SHA384_192,
-		.plaintext		= &rfc8009_enc_short_plaintext,
-		.confounder		= &rfc8009_enc_test6_confounder,
-		.base_key		= &aes256_cts_hmac_sha384_192_basekey,
-		.expected_result	= &rfc8009_enc_test6_expected_result,
-		.expected_hmac		= &rfc8009_enc_test6_expected_hmac,
-	},
-	{
-		.desc			= "Encrypt block plaintext with aes256-cts-hmac-sha384-192",
-		.enctype		= ENCTYPE_AES256_CTS_HMAC_SHA384_192,
-		.plaintext		= &rfc8009_enc_block_plaintext,
-		.confounder		= &rfc8009_enc_test7_confounder,
-		.base_key		= &aes256_cts_hmac_sha384_192_basekey,
-		.expected_result	= &rfc8009_enc_test7_expected_result,
-		.expected_hmac		= &rfc8009_enc_test7_expected_hmac,
-	},
-	{
-		.desc			= "Encrypt long plaintext with aes256-cts-hmac-sha384-192",
-		.enctype		= ENCTYPE_AES256_CTS_HMAC_SHA384_192,
-		.plaintext		= &rfc8009_enc_long_plaintext,
-		.confounder		= &rfc8009_enc_test8_confounder,
-		.base_key		= &aes256_cts_hmac_sha384_192_basekey,
-		.expected_result	= &rfc8009_enc_test8_expected_result,
-		.expected_hmac		= &rfc8009_enc_test8_expected_hmac,
-	},
-};
-
-/* Creates the function rfc8009_encrypt_gen_params */
-KUNIT_ARRAY_PARAM(rfc8009_encrypt, rfc8009_encrypt_test_params,
-		  gss_krb5_get_desc);
-
-static void rfc8009_encrypt_case(struct kunit *test)
-{
-	const struct gss_krb5_test_param *param = test->param_value;
-	struct crypto_sync_skcipher *cts_tfm, *cbc_tfm;
-	const struct gss_krb5_enctype *gk5e;
-	struct xdr_netobj Ke, Ki, checksum;
-	u8 usage_data[GSS_KRB5_K5CLENGTH];
-	struct xdr_netobj usage = {
-		.data = usage_data,
-		.len = sizeof(usage_data),
-	};
-	struct crypto_ahash *ahash_tfm;
-	struct xdr_buf buf;
-	void *text;
-	size_t len;
-	u32 err;
-
-	/* Arrange */
-	gk5e = gss_krb5_lookup_enctype(param->enctype);
-	if (!gk5e)
-		kunit_skip(test, "Encryption type is not available");
-
-	*(__be32 *)usage.data = cpu_to_be32(2);
-
-	Ke.len = gk5e->Ke_length;
-	Ke.data = kunit_kzalloc(test, Ke.len, GFP_KERNEL);
-	KUNIT_ASSERT_NOT_ERR_OR_NULL(test, Ke.data);
-	usage.data[4] = KEY_USAGE_SEED_ENCRYPTION;
-	err = gk5e->derive_key(gk5e, param->base_key, &Ke,
-			       &usage, GFP_KERNEL);
-	KUNIT_ASSERT_EQ(test, err, 0);
-
-	cbc_tfm = crypto_alloc_sync_skcipher(gk5e->aux_cipher, 0, 0);
-	KUNIT_ASSERT_NOT_ERR_OR_NULL(test, cbc_tfm);
-	err = crypto_sync_skcipher_setkey(cbc_tfm, Ke.data, Ke.len);
-	KUNIT_ASSERT_EQ(test, err, 0);
-
-	cts_tfm = crypto_alloc_sync_skcipher(gk5e->encrypt_name, 0, 0);
-	KUNIT_ASSERT_NOT_ERR_OR_NULL(test, cts_tfm);
-	err = crypto_sync_skcipher_setkey(cts_tfm, Ke.data, Ke.len);
-	KUNIT_ASSERT_EQ(test, err, 0);
-
-	len = param->confounder->len + param->plaintext->len;
-	text = kunit_kzalloc(test, len, GFP_KERNEL);
-	KUNIT_ASSERT_NOT_ERR_OR_NULL(test, text);
-	memcpy(text, param->confounder->data, param->confounder->len);
-	memcpy(text + param->confounder->len, param->plaintext->data,
-	       param->plaintext->len);
-
-	memset(&buf, 0, sizeof(buf));
-	buf.head[0].iov_base = text;
-	buf.head[0].iov_len = param->confounder->len + param->plaintext->len;
-	buf.len = buf.head[0].iov_len;
-
-	checksum.len = gk5e->cksumlength;
-	checksum.data = kunit_kzalloc(test, checksum.len, GFP_KERNEL);
-	KUNIT_ASSERT_NOT_ERR_OR_NULL(test, checksum.data);
-
-	Ki.len = gk5e->Ki_length;
-	Ki.data = kunit_kzalloc(test, Ki.len, GFP_KERNEL);
-	KUNIT_ASSERT_NOT_ERR_OR_NULL(test, Ki.data);
-	usage.data[4] = KEY_USAGE_SEED_INTEGRITY;
-	err = gk5e->derive_key(gk5e, param->base_key, &Ki,
-			       &usage, GFP_KERNEL);
-	KUNIT_ASSERT_EQ(test, err, 0);
-
-	ahash_tfm = crypto_alloc_ahash(gk5e->cksum_name, 0, CRYPTO_ALG_ASYNC);
-	KUNIT_ASSERT_NOT_ERR_OR_NULL(test, ahash_tfm);
-	err = crypto_ahash_setkey(ahash_tfm, Ki.data, Ki.len);
-	KUNIT_ASSERT_EQ(test, err, 0);
-
-	/* Act */
-	err = krb5_cbc_cts_encrypt(cts_tfm, cbc_tfm, 0, &buf, NULL, NULL, 0);
-	KUNIT_ASSERT_EQ(test, err, 0);
-	err = krb5_etm_checksum(cts_tfm, ahash_tfm, &buf, 0, &checksum);
-	KUNIT_ASSERT_EQ(test, err, 0);
-
-	/* Assert */
-	KUNIT_EXPECT_EQ_MSG(test,
-			    param->expected_result->len, buf.len,
-			    "ciphertext length mismatch");
-	KUNIT_EXPECT_MEMEQ_MSG(test,
-			       param->expected_result->data,
-			       buf.head[0].iov_base,
-			       param->expected_result->len,
-			       "ciphertext mismatch");
-	KUNIT_EXPECT_MEMEQ_MSG(test,
-			       param->expected_hmac->data,
-			       checksum.data,
-			       checksum.len,
-			       "HMAC mismatch");
-
-	crypto_free_ahash(ahash_tfm);
-	crypto_free_sync_skcipher(cts_tfm);
-	crypto_free_sync_skcipher(cbc_tfm);
-}
-
-static struct kunit_case rfc8009_test_cases[] = {
-	{
-		.name			= "RFC 8009 key derivation",
-		.run_case		= kdf_case,
-		.generate_params	= rfc8009_kdf_gen_params,
-	},
-	{
-		.name			= "RFC 8009 checksum",
-		.run_case		= checksum_case,
-		.generate_params	= rfc8009_checksum_gen_params,
-	},
-	{
-		.name			= "RFC 8009 encryption",
-		.run_case		= rfc8009_encrypt_case,
-		.generate_params	= rfc8009_encrypt_gen_params,
-	},
-	{}
-};
-
-static struct kunit_suite rfc8009_suite = {
-	.name			= "RFC 8009 suite",
-	.test_cases		= rfc8009_test_cases,
-};
-
-/*
- * Encryption self-tests
- */
-
-DEFINE_STR_XDR_NETOBJ(encrypt_selftest_plaintext,
-		      "This is the plaintext for the encryption self-test.");
-
-static const struct gss_krb5_test_param encrypt_selftest_params[] = {
-	{
-		.desc			= "aes128-cts-hmac-sha1-96 encryption self-test",
-		.enctype		= ENCTYPE_AES128_CTS_HMAC_SHA1_96,
-		.Ke			= &rfc3962_encryption_key,
-		.plaintext		= &encrypt_selftest_plaintext,
-	},
-	{
-		.desc			= "aes256-cts-hmac-sha1-96 encryption self-test",
-		.enctype		= ENCTYPE_AES256_CTS_HMAC_SHA1_96,
-		.Ke			= &rfc3962_encryption_key,
-		.plaintext		= &encrypt_selftest_plaintext,
-	},
-	{
-		.desc			= "camellia128-cts-cmac encryption self-test",
-		.enctype		= ENCTYPE_CAMELLIA128_CTS_CMAC,
-		.Ke			= &camellia128_cts_cmac_Ke,
-		.plaintext		= &encrypt_selftest_plaintext,
-	},
-	{
-		.desc			= "camellia256-cts-cmac encryption self-test",
-		.enctype		= ENCTYPE_CAMELLIA256_CTS_CMAC,
-		.Ke			= &camellia256_cts_cmac_Ke,
-		.plaintext		= &encrypt_selftest_plaintext,
-	},
-	{
-		.desc			= "aes128-cts-hmac-sha256-128 encryption self-test",
-		.enctype		= ENCTYPE_AES128_CTS_HMAC_SHA256_128,
-		.Ke			= &aes128_cts_hmac_sha256_128_Ke,
-		.plaintext		= &encrypt_selftest_plaintext,
-	},
-	{
-		.desc			= "aes256-cts-hmac-sha384-192 encryption self-test",
-		.enctype		= ENCTYPE_AES256_CTS_HMAC_SHA384_192,
-		.Ke			= &aes256_cts_hmac_sha384_192_Ke,
-		.plaintext		= &encrypt_selftest_plaintext,
-	},
-};
-
-/* Creates the function encrypt_selftest_gen_params */
-KUNIT_ARRAY_PARAM(encrypt_selftest, encrypt_selftest_params,
-		  gss_krb5_get_desc);
-
-/*
- * Encrypt and decrypt plaintext, and ensure the input plaintext
- * matches the output plaintext. A confounder is not added in this
- * case.
- */
-static void encrypt_selftest_case(struct kunit *test)
-{
-	const struct gss_krb5_test_param *param = test->param_value;
-	struct crypto_sync_skcipher *cts_tfm, *cbc_tfm;
-	const struct gss_krb5_enctype *gk5e;
-	struct xdr_buf buf;
-	void *text;
-	int err;
-
-	/* Arrange */
-	gk5e = gss_krb5_lookup_enctype(param->enctype);
-	if (!gk5e)
-		kunit_skip(test, "Encryption type is not available");
-
-	cbc_tfm = crypto_alloc_sync_skcipher(gk5e->aux_cipher, 0, 0);
-	KUNIT_ASSERT_NOT_ERR_OR_NULL(test, cbc_tfm);
-	err = crypto_sync_skcipher_setkey(cbc_tfm, param->Ke->data, param->Ke->len);
-	KUNIT_ASSERT_EQ(test, err, 0);
-
-	cts_tfm = crypto_alloc_sync_skcipher(gk5e->encrypt_name, 0, 0);
-	KUNIT_ASSERT_NOT_ERR_OR_NULL(test, cts_tfm);
-	err = crypto_sync_skcipher_setkey(cts_tfm, param->Ke->data, param->Ke->len);
-	KUNIT_ASSERT_EQ(test, err, 0);
-
-	text = kunit_kzalloc(test, roundup(param->plaintext->len,
-					   crypto_sync_skcipher_blocksize(cbc_tfm)),
-			     GFP_KERNEL);
-	KUNIT_ASSERT_NOT_ERR_OR_NULL(test, text);
-
-	memcpy(text, param->plaintext->data, param->plaintext->len);
-	memset(&buf, 0, sizeof(buf));
-	buf.head[0].iov_base = text;
-	buf.head[0].iov_len = param->plaintext->len;
-	buf.len = buf.head[0].iov_len;
-
-	/* Act */
-	err = krb5_cbc_cts_encrypt(cts_tfm, cbc_tfm, 0, &buf, NULL, NULL, 0);
-	KUNIT_ASSERT_EQ(test, err, 0);
-	err = krb5_cbc_cts_decrypt(cts_tfm, cbc_tfm, 0, &buf);
-	KUNIT_ASSERT_EQ(test, err, 0);
-
-	/* Assert */
-	KUNIT_EXPECT_EQ_MSG(test,
-			    param->plaintext->len, buf.len,
-			    "length mismatch");
-	KUNIT_EXPECT_MEMEQ_MSG(test,
-			       param->plaintext->data,
-			       buf.head[0].iov_base,
-			       buf.len,
-			       "plaintext mismatch");
-
-	crypto_free_sync_skcipher(cts_tfm);
-	crypto_free_sync_skcipher(cbc_tfm);
-}
-
-static struct kunit_case encryption_test_cases[] = {
-	{
-		.name			= "Encryption self-tests",
-		.run_case		= encrypt_selftest_case,
-		.generate_params	= encrypt_selftest_gen_params,
-	},
-	{}
-};
-
-static struct kunit_suite encryption_test_suite = {
-	.name			= "Encryption test suite",
-	.test_cases		= encryption_test_cases,
-};
-
-kunit_test_suites(&rfc3961_suite,
-		  &rfc3962_suite,
-		  &rfc6803_suite,
-		  &rfc8009_suite,
-		  &encryption_test_suite);
-
-MODULE_DESCRIPTION("Test RPCSEC GSS Kerberos 5 functions");
-MODULE_LICENSE("GPL");
diff --git a/net/sunrpc/xdr.c b/net/sunrpc/xdr.c
index 516833b4c114..6bd588dfbfc0 100644
--- a/net/sunrpc/xdr.c
+++ b/net/sunrpc/xdr.c
@@ -2348,73 +2348,6 @@ int xdr_encode_array2(const struct xdr_buf *buf, unsigned int base,
 }
 EXPORT_SYMBOL_GPL(xdr_encode_array2);
 
-int xdr_process_buf(const struct xdr_buf *buf, unsigned int offset,
-		    unsigned int len,
-		    int (*actor)(struct scatterlist *, void *), void *data)
-{
-	int i, ret = 0;
-	unsigned int page_len, thislen, page_offset;
-	struct scatterlist      sg[1];
-
-	sg_init_table(sg, 1);
-
-	if (offset >= buf->head[0].iov_len) {
-		offset -= buf->head[0].iov_len;
-	} else {
-		thislen = buf->head[0].iov_len - offset;
-		if (thislen > len)
-			thislen = len;
-		sg_set_buf(sg, buf->head[0].iov_base + offset, thislen);
-		ret = actor(sg, data);
-		if (ret)
-			goto out;
-		offset = 0;
-		len -= thislen;
-	}
-	if (len == 0)
-		goto out;
-
-	if (offset >= buf->page_len) {
-		offset -= buf->page_len;
-	} else {
-		page_len = buf->page_len - offset;
-		if (page_len > len)
-			page_len = len;
-		len -= page_len;
-		page_offset = (offset + buf->page_base) & (PAGE_SIZE - 1);
-		i = (offset + buf->page_base) >> PAGE_SHIFT;
-		thislen = PAGE_SIZE - page_offset;
-		do {
-			if (thislen > page_len)
-				thislen = page_len;
-			sg_set_page(sg, buf->pages[i], thislen, page_offset);
-			ret = actor(sg, data);
-			if (ret)
-				goto out;
-			page_len -= thislen;
-			i++;
-			page_offset = 0;
-			thislen = PAGE_SIZE;
-		} while (page_len != 0);
-		offset = 0;
-	}
-	if (len == 0)
-		goto out;
-	if (offset < buf->tail[0].iov_len) {
-		thislen = buf->tail[0].iov_len - offset;
-		if (thislen > len)
-			thislen = len;
-		sg_set_buf(sg, buf->tail[0].iov_base + offset, thislen);
-		ret = actor(sg, data);
-		len -= thislen;
-	}
-	if (len != 0)
-		ret = -EINVAL;
-out:
-	return ret;
-}
-EXPORT_SYMBOL_GPL(xdr_process_buf);
-
 /**
  * xdr_stream_decode_string_dup - Decode and duplicate variable length string
  * @xdr: pointer to xdr_stream

-- 
2.53.0


^ permalink raw reply related	[flat|nested] 21+ messages in thread

* [PATCH 16/18] SUNRPC: Remove per-enctype Kconfig options
  2026-04-27 13:50 [PATCH 00/18] Migrate rpcsec_gss_krb5 to the crypto/krb5 library Chuck Lever
                   ` (14 preceding siblings ...)
  2026-04-27 13:50 ` [PATCH 15/18] SUNRPC: Remove dead code from rpcsec_gss_krb5 Chuck Lever
@ 2026-04-27 13:51 ` Chuck Lever
  2026-04-27 13:51 ` [PATCH 17/18] SUNRPC: Remove redundant crypto Kconfig dependencies Chuck Lever
                   ` (2 subsequent siblings)
  18 siblings, 0 replies; 21+ messages in thread
From: Chuck Lever @ 2026-04-27 13:51 UTC (permalink / raw)
  To: Trond Myklebust, Anna Schumaker, Chuck Lever, Jeff Layton,
	NeilBrown, Olga Kornievskaia, Dai Ngo, Tom Talpey,
	David S. Miller, Eric Dumazet, Jakub Kicinski, Paolo Abeni,
	Simon Horman
  Cc: linux-nfs, netdev, linux-kernel, Herbert Xu, David Howells,
	Simo Sorce

From: Chuck Lever <chuck.lever@oracle.com>

The RPCSEC_GSS_KRB5_ENCTYPES_AES_SHA1,
RPCSEC_GSS_KRB5_ENCTYPES_CAMELLIA, and
RPCSEC_GSS_KRB5_ENCTYPES_AES_SHA2 Kconfig options
originally gated both algorithm availability and the
advertised enctype list. Now that per-message crypto
operations are routed through crypto/krb5, these options
control only which enctype numbers appear in the gssd
upcall string; the underlying algorithms are always
present.

Remove the per-enctype Kconfig options and replace the
ifdef-gated enctype table with a candidate list looked
up in the crypto/krb5 enctype table at module init
time. Each enctype is included in the advertised list
only if crypto_krb5_find_enctype() finds it in the
library's enctype table. When a new enctype is added
to crypto/krb5, adding its constant to the candidate
array is sufficient to begin advertising it.

Signed-off-by: Chuck Lever <chuck.lever@oracle.com>
---
 net/sunrpc/Kconfig                  | 38 -------------------------------------
 net/sunrpc/auth_gss/gss_krb5_mech.c | 30 ++++++++++++++---------------
 2 files changed, 14 insertions(+), 54 deletions(-)

diff --git a/net/sunrpc/Kconfig b/net/sunrpc/Kconfig
index 1c2e1fe9d365..305c55cdbd45 100644
--- a/net/sunrpc/Kconfig
+++ b/net/sunrpc/Kconfig
@@ -35,44 +35,6 @@ config RPCSEC_GSS_KRB5
 
 	  If unsure, say Y.
 
-config RPCSEC_GSS_KRB5_ENCTYPES_AES_SHA1
-	bool "Enable Kerberos enctypes based on AES and SHA-1"
-	depends on RPCSEC_GSS_KRB5
-	depends on CRYPTO_CBC && CRYPTO_CTS
-	depends on CRYPTO_HMAC && CRYPTO_SHA1
-	depends on CRYPTO_AES
-	default y
-	help
-	  Choose Y to enable the use of Kerberos 5 encryption types
-	  that utilize Advanced Encryption Standard (AES) ciphers and
-	  SHA-1 digests. These include aes128-cts-hmac-sha1-96 and
-	  aes256-cts-hmac-sha1-96.
-
-config RPCSEC_GSS_KRB5_ENCTYPES_CAMELLIA
-	bool "Enable Kerberos encryption types based on Camellia and CMAC"
-	depends on RPCSEC_GSS_KRB5
-	depends on CRYPTO_CBC && CRYPTO_CTS && CRYPTO_CAMELLIA
-	depends on CRYPTO_CMAC
-	default n
-	help
-	  Choose Y to enable the use of Kerberos 5 encryption types
-	  that utilize Camellia ciphers (RFC 3713) and CMAC digests
-	  (NIST Special Publication 800-38B). These include
-	  camellia128-cts-cmac and camellia256-cts-cmac.
-
-config RPCSEC_GSS_KRB5_ENCTYPES_AES_SHA2
-	bool "Enable Kerberos enctypes based on AES and SHA-2"
-	depends on RPCSEC_GSS_KRB5
-	depends on CRYPTO_CBC && CRYPTO_CTS
-	depends on CRYPTO_HMAC && CRYPTO_SHA256 && CRYPTO_SHA512
-	depends on CRYPTO_AES
-	default n
-	help
-	  Choose Y to enable the use of Kerberos 5 encryption types
-	  that utilize Advanced Encryption Standard (AES) ciphers and
-	  SHA-2 digests. These include aes128-cts-hmac-sha256-128 and
-	  aes256-cts-hmac-sha384-192.
-
 config SUNRPC_DEBUG
 	bool "RPC: Enable dprintk debugging"
 	depends on SUNRPC && SYSCTL
diff --git a/net/sunrpc/auth_gss/gss_krb5_mech.c b/net/sunrpc/auth_gss/gss_krb5_mech.c
index 5a52fd84f946..996e452b9b3c 100644
--- a/net/sunrpc/auth_gss/gss_krb5_mech.c
+++ b/net/sunrpc/auth_gss/gss_krb5_mech.c
@@ -28,27 +28,23 @@
 static struct gss_api_mech gss_kerberos_mech;
 
 /*
- * The list of advertised enctypes is specified in order of most
- * preferred to least.
+ * Candidate enctypes in order of most preferred to least.
+ * Each is probed against crypto/krb5 at module init; only
+ * enctypes that crypto/krb5 supports are advertised.
  */
+static const u32 gss_krb5_enctypes[] = {
+	ENCTYPE_AES256_CTS_HMAC_SHA384_192,
+	ENCTYPE_AES128_CTS_HMAC_SHA256_128,
+	ENCTYPE_CAMELLIA256_CTS_CMAC,
+	ENCTYPE_CAMELLIA128_CTS_CMAC,
+	ENCTYPE_AES256_CTS_HMAC_SHA1_96,
+	ENCTYPE_AES128_CTS_HMAC_SHA1_96,
+};
+
 static char gss_krb5_enctype_priority_list[64];
 
 static void gss_krb5_prepare_enctype_priority_list(void)
 {
-	static const u32 gss_krb5_enctypes[] = {
-#if defined(CONFIG_RPCSEC_GSS_KRB5_ENCTYPES_AES_SHA2)
-		ENCTYPE_AES256_CTS_HMAC_SHA384_192,
-		ENCTYPE_AES128_CTS_HMAC_SHA256_128,
-#endif
-#if defined(CONFIG_RPCSEC_GSS_KRB5_ENCTYPES_CAMELLIA)
-		ENCTYPE_CAMELLIA256_CTS_CMAC,
-		ENCTYPE_CAMELLIA128_CTS_CMAC,
-#endif
-#if defined(CONFIG_RPCSEC_GSS_KRB5_ENCTYPES_AES_SHA1)
-		ENCTYPE_AES256_CTS_HMAC_SHA1_96,
-		ENCTYPE_AES128_CTS_HMAC_SHA1_96,
-#endif
-	};
 	size_t total, i;
 	char buf[16];
 	char *sep;
@@ -57,6 +53,8 @@ static void gss_krb5_prepare_enctype_priority_list(void)
 	sep = "";
 	gss_krb5_enctype_priority_list[0] = '\0';
 	for (total = 0, i = 0; i < ARRAY_SIZE(gss_krb5_enctypes); i++) {
+		if (!crypto_krb5_find_enctype(gss_krb5_enctypes[i]))
+			continue;
 		n = sprintf(buf, "%s%u", sep, gss_krb5_enctypes[i]);
 		if (n < 0)
 			break;

-- 
2.53.0


^ permalink raw reply related	[flat|nested] 21+ messages in thread

* [PATCH 17/18] SUNRPC: Remove redundant crypto Kconfig dependencies
  2026-04-27 13:50 [PATCH 00/18] Migrate rpcsec_gss_krb5 to the crypto/krb5 library Chuck Lever
                   ` (15 preceding siblings ...)
  2026-04-27 13:51 ` [PATCH 16/18] SUNRPC: Remove per-enctype Kconfig options Chuck Lever
@ 2026-04-27 13:51 ` Chuck Lever
  2026-04-27 13:51 ` [PATCH 18/18] SUNRPC: Remove dead rpcsec_gss_krb5 definitions Chuck Lever
  2026-04-29  6:39 ` [PATCH 00/18] Migrate rpcsec_gss_krb5 to the crypto/krb5 library Jeff Layton
  18 siblings, 0 replies; 21+ messages in thread
From: Chuck Lever @ 2026-04-27 13:51 UTC (permalink / raw)
  To: Trond Myklebust, Anna Schumaker, Chuck Lever, Jeff Layton,
	NeilBrown, Olga Kornievskaia, Dai Ngo, Tom Talpey,
	David S. Miller, Eric Dumazet, Jakub Kicinski, Paolo Abeni,
	Simon Horman
  Cc: linux-nfs, netdev, linux-kernel, Herbert Xu, David Howells,
	Simo Sorce

From: Chuck Lever <chuck.lever@oracle.com>

With all per-message crypto operations now routed through
crypto/krb5, rpcsec_gss_krb5 no longer calls individual
crypto algorithms directly. The CRYPTO_KRB5 symbol already
selects CRYPTO_SKCIPHER and CRYPTO_HASH (the latter
transitively via CRYPTO_HMAC).

Drop the top-level select CRYPTO_SKCIPHER and select
CRYPTO_HASH from RPCSEC_GSS_KRB5, as these are redundant
with CRYPTO_KRB5's own dependencies.

Signed-off-by: Chuck Lever <chuck.lever@oracle.com>
---
 net/sunrpc/Kconfig | 2 --
 1 file changed, 2 deletions(-)

diff --git a/net/sunrpc/Kconfig b/net/sunrpc/Kconfig
index 305c55cdbd45..e7808e5714dc 100644
--- a/net/sunrpc/Kconfig
+++ b/net/sunrpc/Kconfig
@@ -22,8 +22,6 @@ config RPCSEC_GSS_KRB5
 	default y
 	select SUNRPC_GSS
 	select CRYPTO_KRB5
-	select CRYPTO_SKCIPHER
-	select CRYPTO_HASH
 	help
 	  Choose Y here to enable Secure RPC using the Kerberos version 5
 	  GSS-API mechanism (RFC 1964).

-- 
2.53.0


^ permalink raw reply related	[flat|nested] 21+ messages in thread

* [PATCH 18/18] SUNRPC: Remove dead rpcsec_gss_krb5 definitions
  2026-04-27 13:50 [PATCH 00/18] Migrate rpcsec_gss_krb5 to the crypto/krb5 library Chuck Lever
                   ` (16 preceding siblings ...)
  2026-04-27 13:51 ` [PATCH 17/18] SUNRPC: Remove redundant crypto Kconfig dependencies Chuck Lever
@ 2026-04-27 13:51 ` Chuck Lever
  2026-04-29  6:39 ` [PATCH 00/18] Migrate rpcsec_gss_krb5 to the crypto/krb5 library Jeff Layton
  18 siblings, 0 replies; 21+ messages in thread
From: Chuck Lever @ 2026-04-27 13:51 UTC (permalink / raw)
  To: Trond Myklebust, Anna Schumaker, Chuck Lever, Jeff Layton,
	NeilBrown, Olga Kornievskaia, Dai Ngo, Tom Talpey,
	David S. Miller, Eric Dumazet, Jakub Kicinski, Paolo Abeni,
	Simon Horman
  Cc: linux-nfs, netdev, linux-kernel, Herbert Xu, David Howells,
	Simo Sorce

From: Chuck Lever <chuck.lever@oracle.com>

The migration to crypto/krb5 eliminated the per-enctype
function dispatch and direct crypto API usage, leaving
behind a number of orphaned definitions.

Remove the following from gss_krb5.h:

 - GSS_KRB5_K5CLENGTH, used only by removed key derivation
 - KG_TOK_MIC_MSG and KG_TOK_WRAP_MSG (Kerberos v1 token
   types; v1 support was dropped earlier)
 - KG2_TOK_INITIAL and KG2_TOK_RESPONSE (context
   establishment token types; no remaining users)
 - KG2_RESP_FLAG_ERROR and KG2_RESP_FLAG_DELEG_OK
 - enum sgn_alg and enum seal_alg (v1 algorithm constants)
 - All CKSUMTYPE_* definitions, now duplicated by
   KRB5_CKSUMTYPE_* in <crypto/krb5.h>
 - The KG_ error constants from gssapi_err_krb5.h, which
   have no remaining users
 - The ENCTYPE_* constant block, replaced by KRB5_ENCTYPE_*
   from <crypto/krb5.h>
 - KG_USAGE_SEAL/SIGN/SEQ (3DES usage constants)
 - KEY_USAGE_SEED_CHECKSUM/ENCRYPTION/INTEGRITY, duplicated
   by <crypto/krb5.h>
 - #include <crypto/skcipher.h>, no longer needed

Remove the cksum[] field from struct krb5_ctx in
gss_krb5_internal.h; no code reads or writes it after the
key derivation removal.

Switch gss_krb5_enctypes[] in gss_krb5_mech.c to the
canonical KRB5_ENCTYPE_* names from <crypto/krb5.h>.

Remove stale #include directives:
 - <crypto/skcipher.h> from gss_krb5_wrap.c
 - <linux/random.h> and <linux/crypto.h> from
   gss_krb5_seal.c

Signed-off-by: Chuck Lever <chuck.lever@oracle.com>
---
 include/linux/sunrpc/gss_krb5.h         | 105 --------------------------------
 net/sunrpc/auth_gss/gss_krb5_internal.h |   1 -
 net/sunrpc/auth_gss/gss_krb5_mech.c     |  12 ++--
 net/sunrpc/auth_gss/gss_krb5_seal.c     |   2 -
 net/sunrpc/auth_gss/gss_krb5_wrap.c     |   1 -
 5 files changed, 6 insertions(+), 115 deletions(-)

diff --git a/include/linux/sunrpc/gss_krb5.h b/include/linux/sunrpc/gss_krb5.h
index 43950b5237c8..1cd452ed1db5 100644
--- a/include/linux/sunrpc/gss_krb5.h
+++ b/include/linux/sunrpc/gss_krb5.h
@@ -37,13 +37,9 @@
 #ifndef _LINUX_SUNRPC_GSS_KRB5_H
 #define _LINUX_SUNRPC_GSS_KRB5_H
 
-#include <crypto/skcipher.h>
 #include <linux/sunrpc/auth_gss.h>
 #include <linux/sunrpc/gss_err.h>
 
-/* Length of constant used in key derivation */
-#define GSS_KRB5_K5CLENGTH (5)
-
 /* Maximum key length (in bytes) for the supported crypto algorithms */
 #define GSS_KRB5_MAX_KEYLEN (32)
 
@@ -56,11 +52,6 @@
 /* The length of the Kerberos GSS token header */
 #define GSS_KRB5_TOK_HDR_LEN	(16)
 
-#define KG_TOK_MIC_MSG    0x0101
-#define KG_TOK_WRAP_MSG   0x0201
-
-#define KG2_TOK_INITIAL     0x0101
-#define KG2_TOK_RESPONSE    0x0202
 #define KG2_TOK_MIC         0x0404
 #define KG2_TOK_WRAP        0x0504
 
@@ -68,102 +59,6 @@
 #define KG2_TOKEN_FLAG_SEALED           0x02
 #define KG2_TOKEN_FLAG_ACCEPTORSUBKEY   0x04
 
-#define KG2_RESP_FLAG_ERROR             0x0001
-#define KG2_RESP_FLAG_DELEG_OK          0x0002
-
-enum sgn_alg {
-	SGN_ALG_DES_MAC_MD5 = 0x0000,
-	SGN_ALG_MD2_5 = 0x0001,
-	SGN_ALG_DES_MAC = 0x0002,
-	SGN_ALG_3 = 0x0003,		/* not published */
-	SGN_ALG_HMAC_SHA1_DES3_KD = 0x0004
-};
-enum seal_alg {
-	SEAL_ALG_NONE = 0xffff,
-	SEAL_ALG_DES = 0x0000,
-	SEAL_ALG_1 = 0x0001,		/* not published */
-	SEAL_ALG_DES3KD = 0x0002
-};
-
-/*
- * These values are assigned by IANA and published via the
- * subregistry at the link below:
- *
- * https://www.iana.org/assignments/kerberos-parameters/kerberos-parameters.xhtml#kerberos-parameters-2
- */
-#define CKSUMTYPE_CRC32			0x0001
-#define CKSUMTYPE_RSA_MD4		0x0002
-#define CKSUMTYPE_RSA_MD4_DES		0x0003
-#define CKSUMTYPE_DESCBC		0x0004
-#define CKSUMTYPE_RSA_MD5		0x0007
-#define CKSUMTYPE_RSA_MD5_DES		0x0008
-#define CKSUMTYPE_NIST_SHA		0x0009
-#define CKSUMTYPE_HMAC_SHA1_DES3	0x000c
-#define CKSUMTYPE_HMAC_SHA1_96_AES128   0x000f
-#define CKSUMTYPE_HMAC_SHA1_96_AES256   0x0010
-#define CKSUMTYPE_CMAC_CAMELLIA128	0x0011
-#define CKSUMTYPE_CMAC_CAMELLIA256	0x0012
-#define CKSUMTYPE_HMAC_SHA256_128_AES128	0x0013
-#define CKSUMTYPE_HMAC_SHA384_192_AES256	0x0014
-#define CKSUMTYPE_HMAC_MD5_ARCFOUR      -138 /* Microsoft md5 hmac cksumtype */
-
-/* from gssapi_err_krb5.h */
-#define KG_CCACHE_NOMATCH                        (39756032L)
-#define KG_KEYTAB_NOMATCH                        (39756033L)
-#define KG_TGT_MISSING                           (39756034L)
-#define KG_NO_SUBKEY                             (39756035L)
-#define KG_CONTEXT_ESTABLISHED                   (39756036L)
-#define KG_BAD_SIGN_TYPE                         (39756037L)
-#define KG_BAD_LENGTH                            (39756038L)
-#define KG_CTX_INCOMPLETE                        (39756039L)
-#define KG_CONTEXT                               (39756040L)
-#define KG_CRED                                  (39756041L)
-#define KG_ENC_DESC                              (39756042L)
-#define KG_BAD_SEQ                               (39756043L)
-#define KG_EMPTY_CCACHE                          (39756044L)
-#define KG_NO_CTYPES                             (39756045L)
-
-/* per Kerberos v5 protocol spec crypto types from the wire. 
- * these get mapped to linux kernel crypto routines.  
- *
- * These values are assigned by IANA and published via the
- * subregistry at the link below:
- *
- * https://www.iana.org/assignments/kerberos-parameters/kerberos-parameters.xhtml#kerberos-parameters-1
- */
-#define ENCTYPE_NULL            0x0000
-#define ENCTYPE_DES_CBC_CRC     0x0001	/* DES cbc mode with CRC-32 */
-#define ENCTYPE_DES_CBC_MD4     0x0002	/* DES cbc mode with RSA-MD4 */
-#define ENCTYPE_DES_CBC_MD5     0x0003	/* DES cbc mode with RSA-MD5 */
-#define ENCTYPE_DES_CBC_RAW     0x0004	/* DES cbc mode raw */
-/* XXX deprecated? */
-#define ENCTYPE_DES3_CBC_SHA    0x0005	/* DES-3 cbc mode with NIST-SHA */
-#define ENCTYPE_DES3_CBC_RAW    0x0006	/* DES-3 cbc mode raw */
-#define ENCTYPE_DES_HMAC_SHA1   0x0008
-#define ENCTYPE_DES3_CBC_SHA1   0x0010
-#define ENCTYPE_AES128_CTS_HMAC_SHA1_96 0x0011
-#define ENCTYPE_AES256_CTS_HMAC_SHA1_96 0x0012
-#define ENCTYPE_AES128_CTS_HMAC_SHA256_128	0x0013
-#define ENCTYPE_AES256_CTS_HMAC_SHA384_192	0x0014
-#define ENCTYPE_ARCFOUR_HMAC            0x0017
-#define ENCTYPE_ARCFOUR_HMAC_EXP        0x0018
-#define ENCTYPE_CAMELLIA128_CTS_CMAC	0x0019
-#define ENCTYPE_CAMELLIA256_CTS_CMAC	0x001A
-#define ENCTYPE_UNKNOWN         0x01ff
-
-/*
- * Constants used for key derivation
- */
-/* for 3DES */
-#define KG_USAGE_SEAL (22)
-#define KG_USAGE_SIGN (23)
-#define KG_USAGE_SEQ  (24)
-
-/* from rfc3961 */
-#define KEY_USAGE_SEED_CHECKSUM         (0x99)
-#define KEY_USAGE_SEED_ENCRYPTION       (0xAA)
-#define KEY_USAGE_SEED_INTEGRITY        (0x55)
-
 /* from rfc4121 */
 #define KG_USAGE_ACCEPTOR_SEAL  (22)
 #define KG_USAGE_ACCEPTOR_SIGN  (23)
diff --git a/net/sunrpc/auth_gss/gss_krb5_internal.h b/net/sunrpc/auth_gss/gss_krb5_internal.h
index 208f9df9ea96..3b392e96f25d 100644
--- a/net/sunrpc/auth_gss/gss_krb5_internal.h
+++ b/net/sunrpc/auth_gss/gss_krb5_internal.h
@@ -26,7 +26,6 @@ struct krb5_ctx {
 	struct crypto_shash	*initiator_sign_shash;
 	struct crypto_shash	*acceptor_sign_shash;
 	u8			Ksess[GSS_KRB5_MAX_KEYLEN]; /* session key */
-	u8			cksum[GSS_KRB5_MAX_KEYLEN];
 	atomic64_t		seq_send64;
 	time64_t		endtime;
 	struct xdr_netobj	mech_used;
diff --git a/net/sunrpc/auth_gss/gss_krb5_mech.c b/net/sunrpc/auth_gss/gss_krb5_mech.c
index 996e452b9b3c..c41b5f3e1789 100644
--- a/net/sunrpc/auth_gss/gss_krb5_mech.c
+++ b/net/sunrpc/auth_gss/gss_krb5_mech.c
@@ -33,12 +33,12 @@ static struct gss_api_mech gss_kerberos_mech;
  * enctypes that crypto/krb5 supports are advertised.
  */
 static const u32 gss_krb5_enctypes[] = {
-	ENCTYPE_AES256_CTS_HMAC_SHA384_192,
-	ENCTYPE_AES128_CTS_HMAC_SHA256_128,
-	ENCTYPE_CAMELLIA256_CTS_CMAC,
-	ENCTYPE_CAMELLIA128_CTS_CMAC,
-	ENCTYPE_AES256_CTS_HMAC_SHA1_96,
-	ENCTYPE_AES128_CTS_HMAC_SHA1_96,
+	KRB5_ENCTYPE_AES256_CTS_HMAC_SHA384_192,
+	KRB5_ENCTYPE_AES128_CTS_HMAC_SHA256_128,
+	KRB5_ENCTYPE_CAMELLIA256_CTS_CMAC,
+	KRB5_ENCTYPE_CAMELLIA128_CTS_CMAC,
+	KRB5_ENCTYPE_AES256_CTS_HMAC_SHA1_96,
+	KRB5_ENCTYPE_AES128_CTS_HMAC_SHA1_96,
 };
 
 static char gss_krb5_enctype_priority_list[64];
diff --git a/net/sunrpc/auth_gss/gss_krb5_seal.c b/net/sunrpc/auth_gss/gss_krb5_seal.c
index 66c179337029..cfe066e89f23 100644
--- a/net/sunrpc/auth_gss/gss_krb5_seal.c
+++ b/net/sunrpc/auth_gss/gss_krb5_seal.c
@@ -61,8 +61,6 @@
 #include <linux/types.h>
 #include <linux/jiffies.h>
 #include <linux/sunrpc/gss_krb5.h>
-#include <linux/random.h>
-#include <linux/crypto.h>
 #include <linux/atomic.h>
 #include <linux/scatterlist.h>
 #include <linux/slab.h>
diff --git a/net/sunrpc/auth_gss/gss_krb5_wrap.c b/net/sunrpc/auth_gss/gss_krb5_wrap.c
index 93aa7500d032..ac4b32df42b9 100644
--- a/net/sunrpc/auth_gss/gss_krb5_wrap.c
+++ b/net/sunrpc/auth_gss/gss_krb5_wrap.c
@@ -28,7 +28,6 @@
  * SUCH DAMAGES.
  */
 
-#include <crypto/skcipher.h>
 #include <linux/types.h>
 #include <linux/jiffies.h>
 #include <linux/sunrpc/gss_krb5.h>

-- 
2.53.0


^ permalink raw reply related	[flat|nested] 21+ messages in thread

* Re: [PATCH 00/18] Migrate rpcsec_gss_krb5 to the crypto/krb5 library
  2026-04-27 13:50 [PATCH 00/18] Migrate rpcsec_gss_krb5 to the crypto/krb5 library Chuck Lever
                   ` (17 preceding siblings ...)
  2026-04-27 13:51 ` [PATCH 18/18] SUNRPC: Remove dead rpcsec_gss_krb5 definitions Chuck Lever
@ 2026-04-29  6:39 ` Jeff Layton
  2026-04-29 15:17   ` Chuck Lever
  18 siblings, 1 reply; 21+ messages in thread
From: Jeff Layton @ 2026-04-29  6:39 UTC (permalink / raw)
  To: Chuck Lever, Trond Myklebust, Anna Schumaker, Chuck Lever,
	NeilBrown, Olga Kornievskaia, Dai Ngo, Tom Talpey,
	David S. Miller, Eric Dumazet, Jakub Kicinski, Paolo Abeni,
	Simon Horman
  Cc: linux-nfs, netdev, linux-kernel, Herbert Xu, David Howells,
	Simo Sorce

On Mon, 2026-04-27 at 09:50 -0400, Chuck Lever wrote:
> The rpcsec_gss_krb5 module carries its own Kerberos 5 crypto imple-
> mentation: key derivation, CBC-CTS encryption, HMAC checksumming,
> and the encrypt-then-MAC construction from RFC 8009. Keeping
> cryptographic code inside an RPC module means it receives review
> only from the SUNRPC maintainers, who lack deep crypto expertise.
> Vulnerabilities and algorithmic errors can persist unnoticed.
> 
> Replacing the private SunRPC Kerberos implementation eliminates
> this duplicated audit surface. A single implementation of Kerberos
> 5 key derivation and authenticated encryption is easier to verify
> than two independent copies. New encryption types and hardware
> offload added to crypto/krb5 will automatically become available
> to SunRPC Kerberos consumers.
> 
> The crypto/krb5 library handles enctype differences internally, so
> a single encrypt function and a single decrypt function serve all
> enctypes, eliminating the per-enctype dispatch table that previously
> existed in struct gss_krb5_enctype.
> 
> RFC 4121 Section 4.2.4 requires MIC checksums to cover the message
> body followed by the GSS token header. The crypto/krb5 get_mic/
> verify_mic API hashes optional metadata before the scatterlist
> data, which is the wrong order for the GSS header. The header is
> therefore placed at the end of the scatterlist rather than passed
> as the metadata parameter, and a dedicated gss_krb5_mic_build_sg()
> helper constructs this three-section layout (checksum area, message
> body, token header) with proper sg_mark_end() termination.
> 
> This implementation was available during the Spring 2026 NFS bake-
> a-thon, and received testing there.
> 
> ---
> Chuck Lever (18):
>       SUNRPC: Add Kconfig dependency on CRYPTO_KRB5
>       SUNRPC: Add crypto/krb5 enctype lookup to krb5_ctx
>       SUNRPC: Add helpers to convert xdr_buf byte ranges to scatterlists
>       SUNRPC: Add errno-to-GSS status conversion helper
>       SUNRPC: Prepare crypto/krb5 encryption and checksum handles
>       SUNRPC: Switch wrap token encryption to crypto/krb5
>       SUNRPC: Switch wrap token decryption to crypto/krb5
>       SUNRPC: Switch Camellia decrypt to crypto/krb5
>       SUNRPC: Switch MIC token generation to crypto/krb5
>       SUNRPC: Switch MIC token verification to crypto/krb5
>       SUNRPC: Remove get_mic/verify_mic function pointers from enctype table
>       SUNRPC: Remove wrap/unwrap function pointers from enctype table
>       SUNRPC: Remove encrypt/decrypt function pointers from enctype table
>       SUNRPC: Remove legacy skcipher/ahash handles from krb5_ctx
>       SUNRPC: Remove dead code from rpcsec_gss_krb5
>       SUNRPC: Remove per-enctype Kconfig options
>       SUNRPC: Remove redundant crypto Kconfig dependencies
>       SUNRPC: Remove dead rpcsec_gss_krb5 definitions
> 
>  include/linux/sunrpc/gss_krb5.h         |  105 --
>  include/linux/sunrpc/xdr.h              |   16 +-
>  net/sunrpc/.kunitconfig                 |   29 -
>  net/sunrpc/Kconfig                      |   56 +-
>  net/sunrpc/auth_gss/Makefile            |    4 +-
>  net/sunrpc/auth_gss/gss_krb5_crypto.c   | 1014 ++++-------------
>  net/sunrpc/auth_gss/gss_krb5_internal.h |  155 +--
>  net/sunrpc/auth_gss/gss_krb5_keys.c     |  546 ---------
>  net/sunrpc/auth_gss/gss_krb5_mech.c     |  441 ++------
>  net/sunrpc/auth_gss/gss_krb5_seal.c     |   47 +-
>  net/sunrpc/auth_gss/gss_krb5_test.c     | 1868 -------------------------------
>  net/sunrpc/auth_gss/gss_krb5_unseal.c   |   36 +-
>  net/sunrpc/auth_gss/gss_krb5_wrap.c     |   13 +-
>  net/sunrpc/xdr.c                        |  266 +++--
>  14 files changed, 573 insertions(+), 4023 deletions(-)
> ---
> base-commit: f3a96328282e8d41ba9f478d24ac122e4cbd2989
> change-id: 20260316-crypto-krb5-api-b9ee22636698
> 
> Best regards,
> --  
> Chuck Lever

Love that diffstat. Nice work! 

One comment in general: Do you need to add Assisted-by: tags to any of
this? You can add this to the set:

Reviewed-by: Jeff Layton <jlayton@kernel.org>

^ permalink raw reply	[flat|nested] 21+ messages in thread

* Re: [PATCH 00/18] Migrate rpcsec_gss_krb5 to the crypto/krb5 library
  2026-04-29  6:39 ` [PATCH 00/18] Migrate rpcsec_gss_krb5 to the crypto/krb5 library Jeff Layton
@ 2026-04-29 15:17   ` Chuck Lever
  0 siblings, 0 replies; 21+ messages in thread
From: Chuck Lever @ 2026-04-29 15:17 UTC (permalink / raw)
  To: Jeff Layton, Trond Myklebust, Anna Schumaker, Chuck Lever,
	NeilBrown, Olga Kornievskaia, Dai Ngo, Tom Talpey,
	David S. Miller, Eric Dumazet, Jakub Kicinski, Paolo Abeni,
	Simon Horman
  Cc: linux-nfs, netdev, linux-kernel, Herbert Xu, David Howells,
	Simo Sorce


On Wed, Apr 29, 2026, at 2:39 AM, Jeff Layton wrote:
> On Mon, 2026-04-27 at 09:50 -0400, Chuck Lever wrote:
>> The rpcsec_gss_krb5 module carries its own Kerberos 5 crypto imple-
>> mentation: key derivation, CBC-CTS encryption, HMAC checksumming,
>> and the encrypt-then-MAC construction from RFC 8009. Keeping
>> cryptographic code inside an RPC module means it receives review
>> only from the SUNRPC maintainers, who lack deep crypto expertise.
>> Vulnerabilities and algorithmic errors can persist unnoticed.
>> 
>> Replacing the private SunRPC Kerberos implementation eliminates
>> this duplicated audit surface. A single implementation of Kerberos
>> 5 key derivation and authenticated encryption is easier to verify
>> than two independent copies. New encryption types and hardware
>> offload added to crypto/krb5 will automatically become available
>> to SunRPC Kerberos consumers.
>> 
>> The crypto/krb5 library handles enctype differences internally, so
>> a single encrypt function and a single decrypt function serve all
>> enctypes, eliminating the per-enctype dispatch table that previously
>> existed in struct gss_krb5_enctype.
>> 
>> RFC 4121 Section 4.2.4 requires MIC checksums to cover the message
>> body followed by the GSS token header. The crypto/krb5 get_mic/
>> verify_mic API hashes optional metadata before the scatterlist
>> data, which is the wrong order for the GSS header. The header is
>> therefore placed at the end of the scatterlist rather than passed
>> as the metadata parameter, and a dedicated gss_krb5_mic_build_sg()
>> helper constructs this three-section layout (checksum area, message
>> body, token header) with proper sg_mark_end() termination.
>> 
>> This implementation was available during the Spring 2026 NFS bake-
>> a-thon, and received testing there.

>
> Love that diffstat. Nice work! 
>
> One comment in general: Do you need to add Assisted-by: tags to any of
> this? You can add this to the set:
>
> Reviewed-by: Jeff Layton <jlayton@kernel.org>

Thanks, applied to nfsd-testing. An Acked-by: from one of the NFS
client maintainers would be great too.


-- 
Chuck Lever

^ permalink raw reply	[flat|nested] 21+ messages in thread

end of thread, other threads:[~2026-04-29 15:18 UTC | newest]

Thread overview: 21+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-04-27 13:50 [PATCH 00/18] Migrate rpcsec_gss_krb5 to the crypto/krb5 library Chuck Lever
2026-04-27 13:50 ` [PATCH 01/18] SUNRPC: Add Kconfig dependency on CRYPTO_KRB5 Chuck Lever
2026-04-27 13:50 ` [PATCH 02/18] SUNRPC: Add crypto/krb5 enctype lookup to krb5_ctx Chuck Lever
2026-04-27 13:50 ` [PATCH 03/18] SUNRPC: Add helpers to convert xdr_buf byte ranges to scatterlists Chuck Lever
2026-04-27 13:50 ` [PATCH 04/18] SUNRPC: Add errno-to-GSS status conversion helper Chuck Lever
2026-04-27 13:50 ` [PATCH 05/18] SUNRPC: Prepare crypto/krb5 encryption and checksum handles Chuck Lever
2026-04-27 13:50 ` [PATCH 06/18] SUNRPC: Switch wrap token encryption to crypto/krb5 Chuck Lever
2026-04-27 13:50 ` [PATCH 07/18] SUNRPC: Switch wrap token decryption " Chuck Lever
2026-04-27 13:50 ` [PATCH 08/18] SUNRPC: Switch Camellia decrypt " Chuck Lever
2026-04-27 13:50 ` [PATCH 09/18] SUNRPC: Switch MIC token generation " Chuck Lever
2026-04-27 13:50 ` [PATCH 10/18] SUNRPC: Switch MIC token verification " Chuck Lever
2026-04-27 13:50 ` [PATCH 11/18] SUNRPC: Remove get_mic/verify_mic function pointers from enctype table Chuck Lever
2026-04-27 13:50 ` [PATCH 12/18] SUNRPC: Remove wrap/unwrap " Chuck Lever
2026-04-27 13:50 ` [PATCH 13/18] SUNRPC: Remove encrypt/decrypt " Chuck Lever
2026-04-27 13:50 ` [PATCH 14/18] SUNRPC: Remove legacy skcipher/ahash handles from krb5_ctx Chuck Lever
2026-04-27 13:50 ` [PATCH 15/18] SUNRPC: Remove dead code from rpcsec_gss_krb5 Chuck Lever
2026-04-27 13:51 ` [PATCH 16/18] SUNRPC: Remove per-enctype Kconfig options Chuck Lever
2026-04-27 13:51 ` [PATCH 17/18] SUNRPC: Remove redundant crypto Kconfig dependencies Chuck Lever
2026-04-27 13:51 ` [PATCH 18/18] SUNRPC: Remove dead rpcsec_gss_krb5 definitions Chuck Lever
2026-04-29  6:39 ` [PATCH 00/18] Migrate rpcsec_gss_krb5 to the crypto/krb5 library Jeff Layton
2026-04-29 15:17   ` Chuck Lever

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox