The purpose of this series is to improve/harden the security provided by the Linux kernel's RPCSEC GSS Kerberos 5 mechanism. There are lots of clean-ups in this series, but the pertinent feature is the addition of a clean deprecation path for the DES- and SHA1-based encryption types in accordance with Internet BCPs.
This series disables DES-based enctypes by default, provides a mechanism for disabling SHA1-based enctypes, and introduces two modern enctypes that do not use deprecated crypto algorithms.
Not only does that improve security for Kerberos 5 users, but it also prepares SunRPC for eventually switching to a shared common kernel Kerberos 5 implementation, which surely will not implement any deprecated encryption types (in particular, DES-based ones).
Today, MIT supports both of the newly-introduced enctypes, but Heimdal does not appear to. Thus distributions can enable and disable kernel enctype support to match the set of enctypes supported in their user space Kerberos libraries.
Scott has been kicking the tires -- we've found no regressions with the current SHA1-based enctypes, while the new ones are disabled by default until we have an opportunity for interop testing. The KUnit tests for the new enctypes pass and this implementation successfully interoperates with itself using these enctypes. Therefore I believe it to be safe to merge.
When this series gets merged, the Linux NFS community should select and announce a date-certain for removal of SunRPC's DES-based enctype code.
---
Changes since v1: - Addressed Simo's NAK on "SUNRPC: Improve Kerberos confounder generation" - Added Cc: linux-kselftest@ for review of the KUnit-related patches
Chuck Lever (41): SUNRPC: Add header ifdefs to linux/sunrpc/gss_krb5.h SUNRPC: Remove .blocksize field from struct gss_krb5_enctype SUNRPC: Remove .conflen field from struct gss_krb5_enctype SUNRPC: Improve Kerberos confounder generation SUNRPC: Obscure Kerberos session key SUNRPC: Refactor set-up for aux_cipher SUNRPC: Obscure Kerberos encryption keys SUNRPC: Obscure Kerberos signing keys SUNRPC: Obscure Kerberos integrity keys SUNRPC: Refactor the GSS-API Per Message calls in the Kerberos mechanism SUNRPC: Remove another switch on ctx->enctype SUNRPC: Add /proc/net/rpc/gss_krb5_enctypes file NFSD: Replace /proc/fs/nfsd/supported_krb5_enctypes with a symlink SUNRPC: Replace KRB5_SUPPORTED_ENCTYPES macro SUNRPC: Enable rpcsec_gss_krb5.ko to be built without CRYPTO_DES SUNRPC: Remove ->encrypt and ->decrypt methods from struct gss_krb5_enctype SUNRPC: Rename .encrypt_v2 and .decrypt_v2 methods SUNRPC: Hoist KDF into struct gss_krb5_enctype SUNRPC: Clean up cipher set up for v1 encryption types SUNRPC: Parametrize the key length passed to context_v2_alloc_cipher() SUNRPC: Add new subkey length fields SUNRPC: Refactor CBC with CTS into helpers SUNRPC: Add gk5e definitions for RFC 8009 encryption types SUNRPC: Add KDF-HMAC-SHA2 SUNRPC: Add RFC 8009 encryption and decryption functions SUNRPC: Advertise support for RFC 8009 encryption types SUNRPC: Support the Camellia enctypes SUNRPC: Add KDF_FEEDBACK_CMAC SUNRPC: Advertise support for the Camellia encryption types SUNRPC: Move remaining internal definitions to gss_krb5_internal.h SUNRPC: Add KUnit tests for rpcsec_krb5.ko SUNRPC: Export get_gss_krb5_enctype() SUNRPC: Add KUnit tests RFC 3961 Key Derivation SUNRPC: Add Kunit tests for RFC 3962-defined encryption/decryption SUNRPC: Add KDF KUnit tests for the RFC 6803 encryption types SUNRPC: Add checksum KUnit tests for the RFC 6803 encryption types SUNRPC: Add encryption KUnit tests for the RFC 6803 encryption types SUNRPC: Add KDF-HMAC-SHA2 Kunit tests SUNRPC: Add RFC 8009 checksum KUnit tests SUNRPC: Add RFC 8009 encryption KUnit tests SUNRPC: Add encryption self-tests
fs/nfsd/nfsctl.c | 74 +- include/linux/sunrpc/gss_krb5.h | 196 +-- include/linux/sunrpc/gss_krb5_enctypes.h | 41 - net/sunrpc/.kunitconfig | 30 + net/sunrpc/Kconfig | 96 +- net/sunrpc/auth_gss/Makefile | 2 + net/sunrpc/auth_gss/auth_gss.c | 17 + net/sunrpc/auth_gss/gss_krb5_crypto.c | 656 +++++-- net/sunrpc/auth_gss/gss_krb5_internal.h | 232 +++ net/sunrpc/auth_gss/gss_krb5_keys.c | 416 ++++- net/sunrpc/auth_gss/gss_krb5_mech.c | 730 +++++--- net/sunrpc/auth_gss/gss_krb5_seal.c | 122 +- net/sunrpc/auth_gss/gss_krb5_seqnum.c | 2 + net/sunrpc/auth_gss/gss_krb5_test.c | 2040 ++++++++++++++++++++++ net/sunrpc/auth_gss/gss_krb5_unseal.c | 63 +- net/sunrpc/auth_gss/gss_krb5_wrap.c | 124 +- net/sunrpc/auth_gss/svcauth_gss.c | 65 + 17 files changed, 4001 insertions(+), 905 deletions(-) delete mode 100644 include/linux/sunrpc/gss_krb5_enctypes.h create mode 100644 net/sunrpc/.kunitconfig create mode 100644 net/sunrpc/auth_gss/gss_krb5_internal.h create mode 100644 net/sunrpc/auth_gss/gss_krb5_test.c
-- Chuck Lever
From: Chuck Lever chuck.lever@oracle.com
Standard convention: Ensure the contents of the header are included only once per source file.
Tested-by: Scott Mayhew smayhew@redhat.com Signed-off-by: Chuck Lever chuck.lever@oracle.com --- include/linux/sunrpc/gss_krb5.h | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-)
diff --git a/include/linux/sunrpc/gss_krb5.h b/include/linux/sunrpc/gss_krb5.h index 91f43d86879d..0135139ddf20 100644 --- a/include/linux/sunrpc/gss_krb5.h +++ b/include/linux/sunrpc/gss_krb5.h @@ -1,6 +1,4 @@ /* - * linux/include/linux/sunrpc/gss_krb5_types.h - * * Adapted from MIT Kerberos 5-1.2.1 lib/include/krb5.h, * lib/gssapi/krb5/gssapiP_krb5.h, and others * @@ -36,6 +34,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> @@ -316,3 +317,5 @@ gss_krb5_aes_decrypt(struct krb5_ctx *kctx, u32 offset, u32 len,
void gss_krb5_make_confounder(char *p, u32 conflen); + +#endif /* _LINUX_SUNRPC_GSS_KRB5_H */
From: Chuck Lever chuck.lever@oracle.com
It is not clear from documenting comments, specifications, or code usage what value the gss_krb5_enctype.blocksize field is supposed to store. The "encryption blocksize" depends only on the cipher being used, so that value can be derived where it's needed instead of stored as a constant.
RFC 3961 Section 5.2 says:
cipher block size, c This is the block size of the block cipher underlying the encryption and decryption functions indicated above, used for key derivation and for the size of the message confounder and initial vector. (If a block cipher is not in use, some comparable parameter should be determined.) It must be at least 5 octets.
This is not actually an independent parameter; rather, it is a property of the functions E and D. It is listed here to clarify the distinction between it and the message block size, m.
In the Linux kernel's implemenation of the SunRPC RPCSEC GSS Kerberos 5 mechanism, the cipher block size, which is dependent on the encryption and decryption transforms, is used only in krb5_derive_key(), so it is straightforward to replace it.
Tested-by: Scott Mayhew smayhew@redhat.com Signed-off-by: Chuck Lever chuck.lever@oracle.com --- include/linux/sunrpc/gss_krb5.h | 1 - net/sunrpc/auth_gss/gss_krb5_keys.c | 4 +--- net/sunrpc/auth_gss/gss_krb5_mech.c | 4 ---- 3 files changed, 1 insertion(+), 8 deletions(-)
diff --git a/include/linux/sunrpc/gss_krb5.h b/include/linux/sunrpc/gss_krb5.h index 0135139ddf20..9a833825b55b 100644 --- a/include/linux/sunrpc/gss_krb5.h +++ b/include/linux/sunrpc/gss_krb5.h @@ -64,7 +64,6 @@ struct gss_krb5_enctype { const char *cksum_name; /* crypto checksum name */ const u16 signalg; /* signing algorithm */ const u16 sealalg; /* sealing algorithm */ - const u32 blocksize; /* encryption blocksize */ const u32 conflen; /* confounder length (normally the same as the blocksize) */ diff --git a/net/sunrpc/auth_gss/gss_krb5_keys.c b/net/sunrpc/auth_gss/gss_krb5_keys.c index 726c076950c0..554cfd23f288 100644 --- a/net/sunrpc/auth_gss/gss_krb5_keys.c +++ b/net/sunrpc/auth_gss/gss_krb5_keys.c @@ -150,7 +150,6 @@ u32 krb5_derive_key(const struct gss_krb5_enctype *gk5e, struct crypto_sync_skcipher *cipher; u32 ret = EINVAL;
- blocksize = gk5e->blocksize; keybytes = gk5e->keybytes; keylength = gk5e->keylength;
@@ -160,11 +159,10 @@ u32 krb5_derive_key(const struct gss_krb5_enctype *gk5e, 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_return;
- /* allocate and set up buffers */ - ret = ENOMEM; inblockdata = kmalloc(blocksize, gfp_mask); if (inblockdata == NULL) diff --git a/net/sunrpc/auth_gss/gss_krb5_mech.c b/net/sunrpc/auth_gss/gss_krb5_mech.c index 1c092b05c2bb..dd85fc9ca80b 100644 --- a/net/sunrpc/auth_gss/gss_krb5_mech.c +++ b/net/sunrpc/auth_gss/gss_krb5_mech.c @@ -47,7 +47,6 @@ static const struct gss_krb5_enctype supported_gss_krb5_enctypes[] = { .sealalg = SEAL_ALG_DES, .keybytes = 7, .keylength = 8, - .blocksize = 8, .conflen = 8, .cksumlength = 8, .keyed_cksum = 0, @@ -69,7 +68,6 @@ static const struct gss_krb5_enctype supported_gss_krb5_enctypes[] = { .sealalg = SEAL_ALG_DES3KD, .keybytes = 21, .keylength = 24, - .blocksize = 8, .conflen = 8, .cksumlength = 20, .keyed_cksum = 1, @@ -92,7 +90,6 @@ static const struct gss_krb5_enctype supported_gss_krb5_enctypes[] = { .sealalg = -1, .keybytes = 16, .keylength = 16, - .blocksize = 16, .conflen = 16, .cksumlength = 12, .keyed_cksum = 1, @@ -115,7 +112,6 @@ static const struct gss_krb5_enctype supported_gss_krb5_enctypes[] = { .sealalg = -1, .keybytes = 32, .keylength = 32, - .blocksize = 16, .conflen = 16, .cksumlength = 12, .keyed_cksum = 1,
From: Chuck Lever chuck.lever@oracle.com
Now that arcfour-hmac is gone, the confounder length is again the same as the cipher blocksize for every implemented enctype. The gss_krb5_enctype::conflen field is no longer necessary.
Tested-by: Scott Mayhew smayhew@redhat.com Signed-off-by: Chuck Lever chuck.lever@oracle.com --- include/linux/sunrpc/gss_krb5.h | 3 --- net/sunrpc/auth_gss/gss_krb5_crypto.c | 9 +++++---- net/sunrpc/auth_gss/gss_krb5_mech.c | 4 ---- net/sunrpc/auth_gss/gss_krb5_wrap.c | 4 ++-- 4 files changed, 7 insertions(+), 13 deletions(-)
diff --git a/include/linux/sunrpc/gss_krb5.h b/include/linux/sunrpc/gss_krb5.h index 9a833825b55b..51860e3a0216 100644 --- a/include/linux/sunrpc/gss_krb5.h +++ b/include/linux/sunrpc/gss_krb5.h @@ -64,9 +64,6 @@ struct gss_krb5_enctype { const char *cksum_name; /* crypto checksum name */ const u16 signalg; /* signing algorithm */ const u16 sealalg; /* sealing algorithm */ - const u32 conflen; /* confounder length - (normally the same as - the blocksize) */ const u32 cksumlength; /* checksum length */ const u32 keyed_cksum; /* is it a keyed cksum? */ const u32 keybytes; /* raw key len, in bytes */ diff --git a/net/sunrpc/auth_gss/gss_krb5_crypto.c b/net/sunrpc/auth_gss/gss_krb5_crypto.c index 3ea58175e159..8aa5610ef660 100644 --- a/net/sunrpc/auth_gss/gss_krb5_crypto.c +++ b/net/sunrpc/auth_gss/gss_krb5_crypto.c @@ -610,6 +610,7 @@ gss_krb5_aes_encrypt(struct krb5_ctx *kctx, u32 offset, struct encryptor_desc desc; u32 cbcbytes; unsigned int usage; + unsigned int conflen;
if (kctx->initiate) { cipher = kctx->initiator_enc; @@ -623,12 +624,13 @@ gss_krb5_aes_encrypt(struct krb5_ctx *kctx, u32 offset, usage = KG_USAGE_ACCEPTOR_SEAL; } blocksize = crypto_sync_skcipher_blocksize(cipher); + 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, kctx->gk5e->conflen)) + if (xdr_extend_head(buf, offset, conflen)) return GSS_S_FAILURE; - gss_krb5_make_confounder(buf->head[0].iov_base + offset, kctx->gk5e->conflen); + gss_krb5_make_confounder(buf->head[0].iov_base + offset, conflen); offset -= GSS_KRB5_TOK_HDR_LEN;
if (buf->tail[0].iov_base != NULL) { @@ -744,7 +746,6 @@ gss_krb5_aes_decrypt(struct krb5_ctx *kctx, u32 offset, u32 len, } blocksize = crypto_sync_skcipher_blocksize(cipher);
- /* 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 - @@ -801,7 +802,7 @@ gss_krb5_aes_decrypt(struct krb5_ctx *kctx, u32 offset, u32 len, ret = GSS_S_BAD_SIG; goto out_err; } - *headskip = kctx->gk5e->conflen; + *headskip = blocksize; *tailskip = kctx->gk5e->cksumlength; out_err: if (ret && ret != GSS_S_BAD_SIG) diff --git a/net/sunrpc/auth_gss/gss_krb5_mech.c b/net/sunrpc/auth_gss/gss_krb5_mech.c index dd85fc9ca80b..08a86ece665e 100644 --- a/net/sunrpc/auth_gss/gss_krb5_mech.c +++ b/net/sunrpc/auth_gss/gss_krb5_mech.c @@ -47,7 +47,6 @@ static const struct gss_krb5_enctype supported_gss_krb5_enctypes[] = { .sealalg = SEAL_ALG_DES, .keybytes = 7, .keylength = 8, - .conflen = 8, .cksumlength = 8, .keyed_cksum = 0, }, @@ -68,7 +67,6 @@ static const struct gss_krb5_enctype supported_gss_krb5_enctypes[] = { .sealalg = SEAL_ALG_DES3KD, .keybytes = 21, .keylength = 24, - .conflen = 8, .cksumlength = 20, .keyed_cksum = 1, }, @@ -90,7 +88,6 @@ static const struct gss_krb5_enctype supported_gss_krb5_enctypes[] = { .sealalg = -1, .keybytes = 16, .keylength = 16, - .conflen = 16, .cksumlength = 12, .keyed_cksum = 1, }, @@ -112,7 +109,6 @@ static const struct gss_krb5_enctype supported_gss_krb5_enctypes[] = { .sealalg = -1, .keybytes = 32, .keylength = 32, - .conflen = 16, .cksumlength = 12, .keyed_cksum = 1, }, diff --git a/net/sunrpc/auth_gss/gss_krb5_wrap.c b/net/sunrpc/auth_gss/gss_krb5_wrap.c index 48337687848c..bd068e936947 100644 --- a/net/sunrpc/auth_gss/gss_krb5_wrap.c +++ b/net/sunrpc/auth_gss/gss_krb5_wrap.c @@ -168,7 +168,7 @@ gss_wrap_kerberos_v1(struct krb5_ctx *kctx, int offset, struct page **tmp_pages; u32 seq_send; u8 *cksumkey; - u32 conflen = kctx->gk5e->conflen; + u32 conflen = crypto_sync_skcipher_blocksize(kctx->enc);
dprintk("RPC: %s\n", __func__);
@@ -261,7 +261,7 @@ gss_unwrap_kerberos_v1(struct krb5_ctx *kctx, int offset, int len, void *data_start, *orig_start; int data_len; int blocksize; - u32 conflen = kctx->gk5e->conflen; + u32 conflen = crypto_sync_skcipher_blocksize(kctx->enc); int crypt_offset; u8 *cksumkey; unsigned int saved_len = buf->len;
From: Chuck Lever chuck.lever@oracle.com
Other common Kerberos implementations use a fully random confounder for encryption. The reason for this is explained in the new comment added by this patch. The current get_random_bytes() implementation does not exhaust system entropy.
Since confounder generation is part of Kerberos itself rather than the GSS-API Kerberos mechanism, the function is renamed and moved.
Note that light top-down analysis shows that the SHA-1 transform is by far the most CPU-intensive part of encryption. Thus we do not expect this change to result in a significant performance impact. However, eventually it might be necessary to generate an independent stream of confounders for each Kerberos context to help improve I/O parallelism.
Signed-off-by: Chuck Lever chuck.lever@oracle.com --- include/linux/sunrpc/gss_krb5.h | 3 -- net/sunrpc/auth_gss/gss_krb5_crypto.c | 33 ++++++++++++++++++++++++++- net/sunrpc/auth_gss/gss_krb5_internal.h | 13 +++++++++++ net/sunrpc/auth_gss/gss_krb5_mech.c | 15 ++++++------ net/sunrpc/auth_gss/gss_krb5_wrap.c | 38 ++----------------------------- 5 files changed, 55 insertions(+), 47 deletions(-) create mode 100644 net/sunrpc/auth_gss/gss_krb5_internal.h
diff --git a/include/linux/sunrpc/gss_krb5.h b/include/linux/sunrpc/gss_krb5.h index 51860e3a0216..f0fac1e69731 100644 --- a/include/linux/sunrpc/gss_krb5.h +++ b/include/linux/sunrpc/gss_krb5.h @@ -311,7 +311,4 @@ gss_krb5_aes_decrypt(struct krb5_ctx *kctx, u32 offset, u32 len, struct xdr_buf *buf, u32 *plainoffset, u32 *plainlen);
-void -gss_krb5_make_confounder(char *p, u32 conflen); - #endif /* _LINUX_SUNRPC_GSS_KRB5_H */ diff --git a/net/sunrpc/auth_gss/gss_krb5_crypto.c b/net/sunrpc/auth_gss/gss_krb5_crypto.c index 8aa5610ef660..7c06c11e452c 100644 --- a/net/sunrpc/auth_gss/gss_krb5_crypto.c +++ b/net/sunrpc/auth_gss/gss_krb5_crypto.c @@ -47,10 +47,41 @@ #include <linux/sunrpc/gss_krb5.h> #include <linux/sunrpc/xdr.h>
+#include "gss_krb5_internal.h" + #if IS_ENABLED(CONFIG_SUNRPC_DEBUG) # 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); +} + u32 krb5_encrypt( struct crypto_sync_skcipher *tfm, @@ -630,7 +661,7 @@ gss_krb5_aes_encrypt(struct krb5_ctx *kctx, u32 offset, offset += GSS_KRB5_TOK_HDR_LEN; if (xdr_extend_head(buf, offset, conflen)) return GSS_S_FAILURE; - gss_krb5_make_confounder(buf->head[0].iov_base + offset, conflen); + krb5_make_confounder(buf->head[0].iov_base + offset, conflen); offset -= GSS_KRB5_TOK_HDR_LEN;
if (buf->tail[0].iov_base != NULL) { diff --git a/net/sunrpc/auth_gss/gss_krb5_internal.h b/net/sunrpc/auth_gss/gss_krb5_internal.h new file mode 100644 index 000000000000..16a83d507075 --- /dev/null +++ b/net/sunrpc/auth_gss/gss_krb5_internal.h @@ -0,0 +1,13 @@ +/* SPDX-License-Identifier: GPL-2.0 or BSD-3-Clause */ +/* + * SunRPC GSS Kerberos 5 mechanism internal definitions + * + * Copyright (c) 2022 Oracle and/or its affiliates. + */ + +#ifndef _NET_SUNRPC_AUTH_GSS_KRB5_INTERNAL_H +#define _NET_SUNRPC_AUTH_GSS_KRB5_INTERNAL_H + +void krb5_make_confounder(u8 *p, int conflen); + +#endif /* _NET_SUNRPC_AUTH_GSS_KRB5_INTERNAL_H */ diff --git a/net/sunrpc/auth_gss/gss_krb5_mech.c b/net/sunrpc/auth_gss/gss_krb5_mech.c index 08a86ece665e..76a0d83fe500 100644 --- a/net/sunrpc/auth_gss/gss_krb5_mech.c +++ b/net/sunrpc/auth_gss/gss_krb5_mech.c @@ -550,16 +550,15 @@ gss_import_sec_context_kerberos(const void *p, size_t len, ret = gss_import_v1_context(p, end, ctx); else ret = gss_import_v2_context(p, end, ctx, gfp_mask); - - if (ret == 0) { - ctx_id->internal_ctx_id = ctx; - if (endtime) - *endtime = ctx->endtime; - } else + if (ret) { kfree(ctx); + return ret; + }
- dprintk("RPC: %s: returning %d\n", __func__, ret); - return ret; + ctx_id->internal_ctx_id = ctx; + if (endtime) + *endtime = ctx->endtime; + return 0; }
static void diff --git a/net/sunrpc/auth_gss/gss_krb5_wrap.c b/net/sunrpc/auth_gss/gss_krb5_wrap.c index bd068e936947..66e65e4c6336 100644 --- a/net/sunrpc/auth_gss/gss_krb5_wrap.c +++ b/net/sunrpc/auth_gss/gss_krb5_wrap.c @@ -32,9 +32,10 @@ #include <linux/types.h> #include <linux/jiffies.h> #include <linux/sunrpc/gss_krb5.h> -#include <linux/random.h> #include <linux/pagemap.h>
+#include "gss_krb5_internal.h" + #if IS_ENABLED(CONFIG_SUNRPC_DEBUG) # define RPCDBG_FACILITY RPCDBG_AUTH #endif @@ -113,39 +114,6 @@ gss_krb5_remove_padding(struct xdr_buf *buf, int blocksize) return 0; }
-void -gss_krb5_make_confounder(char *p, u32 conflen) -{ - static u64 i = 0; - u64 *q = (u64 *)p; - - /* rfc1964 claims this should be "random". But all that's really - * necessary is that it be unique. And not even that is necessary in - * our case since our "gssapi" implementation exists only to support - * rpcsec_gss, so we know that the only buffers we will ever encrypt - * already begin with a unique sequence number. Just to hedge my bets - * I'll make a half-hearted attempt at something unique, but ensuring - * uniqueness would mean worrying about atomicity and rollover, and I - * don't care enough. */ - - /* initialize to random value */ - if (i == 0) { - i = get_random_u32(); - i = (i << 32) | get_random_u32(); - } - - switch (conflen) { - case 16: - *q++ = i++; - fallthrough; - case 8: - *q++ = i++; - break; - default: - BUG(); - } -} - /* Assumptions: the head and tail of inbuf are ours to play with. * The pages, however, may be real pages in the page cache and we replace * them with scratch pages from **pages before writing to them. */ @@ -211,7 +179,7 @@ gss_wrap_kerberos_v1(struct krb5_ctx *kctx, int offset, ptr[6] = 0xff; ptr[7] = 0xff;
- gss_krb5_make_confounder(msg_start, conflen); + krb5_make_confounder(msg_start, conflen);
if (kctx->gk5e->keyed_cksum) cksumkey = kctx->cksum;
From: Chuck Lever chuck.lever@oracle.com
ctx->Ksess is never used after import has completed. Obscure it immediately so it cannot be re-used or copied.
Tested-by: Scott Mayhew smayhew@redhat.com Signed-off-by: Chuck Lever chuck.lever@oracle.com --- net/sunrpc/auth_gss/gss_krb5_mech.c | 1 + 1 file changed, 1 insertion(+)
diff --git a/net/sunrpc/auth_gss/gss_krb5_mech.c b/net/sunrpc/auth_gss/gss_krb5_mech.c index 76a0d83fe500..b982c9d495f2 100644 --- a/net/sunrpc/auth_gss/gss_krb5_mech.c +++ b/net/sunrpc/auth_gss/gss_krb5_mech.c @@ -550,6 +550,7 @@ gss_import_sec_context_kerberos(const void *p, size_t len, ret = gss_import_v1_context(p, end, ctx); else ret = gss_import_v2_context(p, end, ctx, gfp_mask); + memzero_explicit(&ctx->Ksess, sizeof(ctx->Ksess)); if (ret) { kfree(ctx); return ret;
From: Chuck Lever chuck.lever@oracle.com
Hoist the name of the aux_cipher into struct gss_krb5_enctype to prepare for obscuring the encryption keys just after they are derived.
Tested-by: Scott Mayhew smayhew@redhat.com Signed-off-by: Chuck Lever chuck.lever@oracle.com --- include/linux/sunrpc/gss_krb5.h | 1 + net/sunrpc/auth_gss/gss_krb5_mech.c | 50 ++++++++++++++++++----------------- 2 files changed, 26 insertions(+), 25 deletions(-)
diff --git a/include/linux/sunrpc/gss_krb5.h b/include/linux/sunrpc/gss_krb5.h index f0fac1e69731..34d54714c6a3 100644 --- a/include/linux/sunrpc/gss_krb5.h +++ b/include/linux/sunrpc/gss_krb5.h @@ -61,6 +61,7 @@ struct gss_krb5_enctype { 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 */ diff --git a/net/sunrpc/auth_gss/gss_krb5_mech.c b/net/sunrpc/auth_gss/gss_krb5_mech.c index b982c9d495f2..afa6a692ccdd 100644 --- a/net/sunrpc/auth_gss/gss_krb5_mech.c +++ b/net/sunrpc/auth_gss/gss_krb5_mech.c @@ -78,6 +78,7 @@ static const struct gss_krb5_enctype supported_gss_krb5_enctypes[] = { .ctype = CKSUMTYPE_HMAC_SHA1_96_AES128, .name = "aes128-cts", .encrypt_name = "cts(cbc(aes))", + .aux_cipher = "cbc(aes)", .cksum_name = "hmac(sha1)", .encrypt = krb5_encrypt, .decrypt = krb5_decrypt, @@ -99,6 +100,7 @@ static const struct gss_krb5_enctype supported_gss_krb5_enctypes[] = { .ctype = CKSUMTYPE_HMAC_SHA1_96_AES256, .name = "aes256-cts", .encrypt_name = "cts(cbc(aes))", + .aux_cipher = "cbc(aes)", .cksum_name = "hmac(sha1)", .encrypt = krb5_encrypt, .decrypt = krb5_decrypt, @@ -373,6 +375,13 @@ context_derive_keys_new(struct krb5_ctx *ctx, gfp_t gfp_mask) ctx->initiator_seal); if (ctx->initiator_enc == NULL) goto out_err; + if (ctx->gk5e->aux_cipher) { + ctx->initiator_enc_aux = + context_v2_alloc_cipher(ctx, ctx->gk5e->aux_cipher, + ctx->initiator_seal); + if (ctx->initiator_enc_aux == NULL) + goto out_free; + }
/* acceptor seal encryption */ set_cdata(cdata, KG_USAGE_ACCEPTOR_SEAL, KEY_USAGE_SEED_ENCRYPTION); @@ -381,13 +390,20 @@ context_derive_keys_new(struct krb5_ctx *ctx, gfp_t gfp_mask) if (err) { dprintk("%s: Error %d deriving acceptor_seal key\n", __func__, err); - goto out_free_initiator_enc; + goto out_free; } ctx->acceptor_enc = context_v2_alloc_cipher(ctx, ctx->gk5e->encrypt_name, ctx->acceptor_seal); if (ctx->acceptor_enc == NULL) - goto out_free_initiator_enc; + goto out_free; + if (ctx->gk5e->aux_cipher) { + ctx->acceptor_enc_aux = + context_v2_alloc_cipher(ctx, ctx->gk5e->aux_cipher, + ctx->acceptor_seal); + if (ctx->acceptor_enc_aux == NULL) + goto out_free; + }
/* initiator sign checksum */ set_cdata(cdata, KG_USAGE_INITIATOR_SIGN, KEY_USAGE_SEED_CHECKSUM); @@ -396,7 +412,7 @@ context_derive_keys_new(struct krb5_ctx *ctx, gfp_t gfp_mask) if (err) { dprintk("%s: Error %d deriving initiator_sign key\n", __func__, err); - goto out_free_acceptor_enc; + goto out_free; }
/* acceptor sign checksum */ @@ -406,7 +422,7 @@ context_derive_keys_new(struct krb5_ctx *ctx, gfp_t gfp_mask) if (err) { dprintk("%s: Error %d deriving acceptor_sign key\n", __func__, err); - goto out_free_acceptor_enc; + goto out_free; }
/* initiator seal integrity */ @@ -416,7 +432,7 @@ context_derive_keys_new(struct krb5_ctx *ctx, gfp_t gfp_mask) if (err) { dprintk("%s: Error %d deriving initiator_integ key\n", __func__, err); - goto out_free_acceptor_enc; + goto out_free; }
/* acceptor seal integrity */ @@ -426,31 +442,15 @@ context_derive_keys_new(struct krb5_ctx *ctx, gfp_t gfp_mask) if (err) { dprintk("%s: Error %d deriving acceptor_integ key\n", __func__, err); - goto out_free_acceptor_enc; - } - - switch (ctx->enctype) { - case ENCTYPE_AES128_CTS_HMAC_SHA1_96: - case ENCTYPE_AES256_CTS_HMAC_SHA1_96: - ctx->initiator_enc_aux = - context_v2_alloc_cipher(ctx, "cbc(aes)", - ctx->initiator_seal); - if (ctx->initiator_enc_aux == NULL) - goto out_free_acceptor_enc; - ctx->acceptor_enc_aux = - context_v2_alloc_cipher(ctx, "cbc(aes)", - ctx->acceptor_seal); - if (ctx->acceptor_enc_aux == NULL) { - crypto_free_sync_skcipher(ctx->initiator_enc_aux); - goto out_free_acceptor_enc; - } + goto out_free; }
return 0;
-out_free_acceptor_enc: +out_free: + crypto_free_sync_skcipher(ctx->acceptor_enc_aux); crypto_free_sync_skcipher(ctx->acceptor_enc); -out_free_initiator_enc: + crypto_free_sync_skcipher(ctx->initiator_enc_aux); crypto_free_sync_skcipher(ctx->initiator_enc); out_err: return -EINVAL;
From: Chuck Lever chuck.lever@oracle.com
The encryption subkeys are not used after the cipher transforms have been allocated and keyed. There is no need to retain them in struct krb5_ctx.
Tested-by: Scott Mayhew smayhew@redhat.com Signed-off-by: Chuck Lever chuck.lever@oracle.com --- include/linux/sunrpc/gss_krb5.h | 2 -- net/sunrpc/auth_gss/gss_krb5_mech.c | 43 +++++++++++++++++++++-------------- 2 files changed, 26 insertions(+), 19 deletions(-)
diff --git a/include/linux/sunrpc/gss_krb5.h b/include/linux/sunrpc/gss_krb5.h index 34d54714c6a3..46eaa2ee9c21 100644 --- a/include/linux/sunrpc/gss_krb5.h +++ b/include/linux/sunrpc/gss_krb5.h @@ -110,8 +110,6 @@ struct krb5_ctx { struct xdr_netobj mech_used; u8 initiator_sign[GSS_KRB5_MAX_KEYLEN]; u8 acceptor_sign[GSS_KRB5_MAX_KEYLEN]; - u8 initiator_seal[GSS_KRB5_MAX_KEYLEN]; - u8 acceptor_seal[GSS_KRB5_MAX_KEYLEN]; u8 initiator_integ[GSS_KRB5_MAX_KEYLEN]; u8 acceptor_integ[GSS_KRB5_MAX_KEYLEN]; }; diff --git a/net/sunrpc/auth_gss/gss_krb5_mech.c b/net/sunrpc/auth_gss/gss_krb5_mech.c index afa6a692ccdd..8bc24c0684cb 100644 --- a/net/sunrpc/auth_gss/gss_krb5_mech.c +++ b/net/sunrpc/auth_gss/gss_krb5_mech.c @@ -350,42 +350,49 @@ context_derive_keys_des3(struct krb5_ctx *ctx, gfp_t gfp_mask) static int context_derive_keys_new(struct krb5_ctx *ctx, gfp_t gfp_mask) { - struct xdr_netobj c, keyin, keyout; u8 cdata[GSS_KRB5_K5CLENGTH]; + struct xdr_netobj c = { + .len = sizeof(cdata), + .data = cdata, + }; + struct xdr_netobj keyin = { + .len = ctx->gk5e->keylength, + .data = ctx->Ksess, + }; + struct xdr_netobj keyout; + int ret = -EINVAL; + void *subkey; u32 err;
- c.len = GSS_KRB5_K5CLENGTH; - c.data = cdata; - - keyin.data = ctx->Ksess; - keyin.len = ctx->gk5e->keylength; + subkey = kmalloc(ctx->gk5e->keylength, gfp_mask); + if (!subkey) + return -ENOMEM; keyout.len = ctx->gk5e->keylength; + keyout.data = subkey;
/* initiator seal encryption */ set_cdata(cdata, KG_USAGE_INITIATOR_SEAL, KEY_USAGE_SEED_ENCRYPTION); - keyout.data = ctx->initiator_seal; err = krb5_derive_key(ctx->gk5e, &keyin, &keyout, &c, gfp_mask); if (err) { dprintk("%s: Error %d deriving initiator_seal key\n", __func__, err); - goto out_err; + goto out; } ctx->initiator_enc = context_v2_alloc_cipher(ctx, ctx->gk5e->encrypt_name, - ctx->initiator_seal); + subkey); if (ctx->initiator_enc == NULL) - goto out_err; + goto out; if (ctx->gk5e->aux_cipher) { ctx->initiator_enc_aux = context_v2_alloc_cipher(ctx, ctx->gk5e->aux_cipher, - ctx->initiator_seal); + subkey); if (ctx->initiator_enc_aux == NULL) goto out_free; }
/* acceptor seal encryption */ set_cdata(cdata, KG_USAGE_ACCEPTOR_SEAL, KEY_USAGE_SEED_ENCRYPTION); - keyout.data = ctx->acceptor_seal; err = krb5_derive_key(ctx->gk5e, &keyin, &keyout, &c, gfp_mask); if (err) { dprintk("%s: Error %d deriving acceptor_seal key\n", @@ -394,13 +401,13 @@ context_derive_keys_new(struct krb5_ctx *ctx, gfp_t gfp_mask) } ctx->acceptor_enc = context_v2_alloc_cipher(ctx, ctx->gk5e->encrypt_name, - ctx->acceptor_seal); + subkey); if (ctx->acceptor_enc == NULL) goto out_free; if (ctx->gk5e->aux_cipher) { ctx->acceptor_enc_aux = context_v2_alloc_cipher(ctx, ctx->gk5e->aux_cipher, - ctx->acceptor_seal); + subkey); if (ctx->acceptor_enc_aux == NULL) goto out_free; } @@ -445,15 +452,17 @@ context_derive_keys_new(struct krb5_ctx *ctx, gfp_t gfp_mask) goto out_free; }
- return 0; + ret = 0; +out: + kfree_sensitive(subkey); + return ret;
out_free: 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); -out_err: - return -EINVAL; + goto out; }
static int
From: Chuck Lever chuck.lever@oracle.com
There's no need to keep the signing keys around if we instead allocate and key an ahash and keep that. This not only enables the subkeys to be destroyed immediately after deriving them, but it makes the Kerberos signing code path more efficient.
Tested-by: Scott Mayhew smayhew@redhat.com Signed-off-by: Chuck Lever chuck.lever@oracle.com --- include/linux/sunrpc/gss_krb5.h | 5 +- net/sunrpc/auth_gss/gss_krb5_crypto.c | 70 +++++++++++++++++++++++++++++++ net/sunrpc/auth_gss/gss_krb5_internal.h | 4 ++ net/sunrpc/auth_gss/gss_krb5_mech.c | 37 ++++++++++++---- net/sunrpc/auth_gss/gss_krb5_seal.c | 30 +++++-------- net/sunrpc/auth_gss/gss_krb5_unseal.c | 29 ++++++------- 6 files changed, 127 insertions(+), 48 deletions(-)
diff --git a/include/linux/sunrpc/gss_krb5.h b/include/linux/sunrpc/gss_krb5.h index 46eaa2ee9c21..9d897f1ac85a 100644 --- a/include/linux/sunrpc/gss_krb5.h +++ b/include/linux/sunrpc/gss_krb5.h @@ -102,14 +102,14 @@ struct krb5_ctx { 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; 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; - u8 initiator_sign[GSS_KRB5_MAX_KEYLEN]; - u8 acceptor_sign[GSS_KRB5_MAX_KEYLEN]; u8 initiator_integ[GSS_KRB5_MAX_KEYLEN]; u8 acceptor_integ[GSS_KRB5_MAX_KEYLEN]; }; @@ -252,7 +252,6 @@ u32 gss_unwrap_kerberos(struct gss_ctx *ctx_id, int offset, int len, struct xdr_buf *buf);
- u32 krb5_encrypt(struct crypto_sync_skcipher *key, void *iv, void *in, void *out, int length); diff --git a/net/sunrpc/auth_gss/gss_krb5_crypto.c b/net/sunrpc/auth_gss/gss_krb5_crypto.c index 7c06c11e452c..44dfcd5f6cbe 100644 --- a/net/sunrpc/auth_gss/gss_krb5_crypto.c +++ b/net/sunrpc/auth_gss/gss_krb5_crypto.c @@ -346,6 +346,76 @@ make_checksum_v2(struct krb5_ctx *kctx, char *header, int hdrlen, return err ? GSS_S_FAILURE : 0; }
+/** + * 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, cksumout->len); + +out_free_ahash: + ahash_request_free(req); +out_free_cksum: + kfree_sensitive(checksumdata); + return err ? GSS_S_FAILURE : GSS_S_COMPLETE; +} + struct encryptor_desc { u8 iv[GSS_KRB5_MAX_BLOCKSIZE]; struct skcipher_request *req; diff --git a/net/sunrpc/auth_gss/gss_krb5_internal.h b/net/sunrpc/auth_gss/gss_krb5_internal.h index 16a83d507075..42f7fd0bbf3a 100644 --- a/net/sunrpc/auth_gss/gss_krb5_internal.h +++ b/net/sunrpc/auth_gss/gss_krb5_internal.h @@ -10,4 +10,8 @@
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); + #endif /* _NET_SUNRPC_AUTH_GSS_KRB5_INTERNAL_H */ diff --git a/net/sunrpc/auth_gss/gss_krb5_mech.c b/net/sunrpc/auth_gss/gss_krb5_mech.c index 8bc24c0684cb..5478f741287e 100644 --- a/net/sunrpc/auth_gss/gss_krb5_mech.c +++ b/net/sunrpc/auth_gss/gss_krb5_mech.c @@ -347,6 +347,21 @@ context_derive_keys_des3(struct krb5_ctx *ctx, gfp_t gfp_mask) return -EINVAL; }
+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 context_derive_keys_new(struct krb5_ctx *ctx, gfp_t gfp_mask) { @@ -414,23 +429,21 @@ context_derive_keys_new(struct krb5_ctx *ctx, gfp_t gfp_mask)
/* initiator sign checksum */ set_cdata(cdata, KG_USAGE_INITIATOR_SIGN, KEY_USAGE_SEED_CHECKSUM); - keyout.data = ctx->initiator_sign; err = krb5_derive_key(ctx->gk5e, &keyin, &keyout, &c, gfp_mask); - if (err) { - dprintk("%s: Error %d deriving initiator_sign key\n", - __func__, err); + if (err) + goto out_free; + ctx->initiator_sign = gss_krb5_alloc_hash_v2(ctx, &keyout); + if (ctx->initiator_sign == NULL) goto out_free; - }
/* acceptor sign checksum */ set_cdata(cdata, KG_USAGE_ACCEPTOR_SIGN, KEY_USAGE_SEED_CHECKSUM); - keyout.data = ctx->acceptor_sign; err = krb5_derive_key(ctx->gk5e, &keyin, &keyout, &c, gfp_mask); - if (err) { - dprintk("%s: Error %d deriving acceptor_sign key\n", - __func__, err); + if (err) + goto out_free; + ctx->acceptor_sign = gss_krb5_alloc_hash_v2(ctx, &keyout); + if (ctx->acceptor_sign == NULL) goto out_free; - }
/* initiator seal integrity */ set_cdata(cdata, KG_USAGE_INITIATOR_SEAL, KEY_USAGE_SEED_INTEGRITY); @@ -458,6 +471,8 @@ context_derive_keys_new(struct krb5_ctx *ctx, gfp_t gfp_mask) return ret;
out_free: + 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); @@ -581,6 +596,8 @@ gss_delete_sec_context_kerberos(void *internal_ctx) { 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); kfree(kctx->mech_used.data); kfree(kctx); } diff --git a/net/sunrpc/auth_gss/gss_krb5_seal.c b/net/sunrpc/auth_gss/gss_krb5_seal.c index 33061417ec97..1d6f8a345354 100644 --- a/net/sunrpc/auth_gss/gss_krb5_seal.c +++ b/net/sunrpc/auth_gss/gss_krb5_seal.c @@ -65,6 +65,8 @@ #include <linux/crypto.h> #include <linux/atomic.h>
+#include "gss_krb5_internal.h" + #if IS_ENABLED(CONFIG_SUNRPC_DEBUG) # define RPCDBG_FACILITY RPCDBG_AUTH #endif @@ -166,14 +168,14 @@ static u32 gss_get_mic_v2(struct krb5_ctx *ctx, struct xdr_buf *text, struct xdr_netobj *token) { - char cksumdata[GSS_KRB5_MAX_CKSUM_LEN]; - struct xdr_netobj cksumobj = { .len = sizeof(cksumdata), - .data = cksumdata}; + struct crypto_ahash *tfm = ctx->initiate ? + ctx->initiator_sign : ctx->acceptor_sign; + struct xdr_netobj cksumobj = { + .len = ctx->gk5e->cksumlength, + }; + __be64 seq_send_be64; void *krb5_hdr; time64_t now; - u8 *cksumkey; - unsigned int cksum_usage; - __be64 seq_send_be64;
dprintk("RPC: %s\n", __func__);
@@ -184,22 +186,12 @@ gss_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);
- if (ctx->initiate) { - cksumkey = ctx->initiator_sign; - cksum_usage = KG_USAGE_INITIATOR_SIGN; - } else { - cksumkey = ctx->acceptor_sign; - cksum_usage = KG_USAGE_ACCEPTOR_SIGN; - } - - if (make_checksum_v2(ctx, krb5_hdr, GSS_KRB5_TOK_HDR_LEN, - text, 0, cksumkey, cksum_usage, &cksumobj)) + cksumobj.data = krb5_hdr + GSS_KRB5_TOK_HDR_LEN; + if (gss_krb5_checksum(tfm, krb5_hdr, GSS_KRB5_TOK_HDR_LEN, + text, 0, &cksumobj)) return GSS_S_FAILURE;
- memcpy(krb5_hdr + GSS_KRB5_TOK_HDR_LEN, cksumobj.data, cksumobj.len); - now = ktime_get_real_seconds(); - return (ctx->endtime < now) ? GSS_S_CONTEXT_EXPIRED : GSS_S_COMPLETE; }
diff --git a/net/sunrpc/auth_gss/gss_krb5_unseal.c b/net/sunrpc/auth_gss/gss_krb5_unseal.c index ba04e3ec970a..d52103f1203b 100644 --- a/net/sunrpc/auth_gss/gss_krb5_unseal.c +++ b/net/sunrpc/auth_gss/gss_krb5_unseal.c @@ -57,11 +57,14 @@ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. */
+#include <crypto/algapi.h> #include <linux/types.h> #include <linux/jiffies.h> #include <linux/sunrpc/gss_krb5.h> #include <linux/crypto.h>
+#include "gss_krb5_internal.h" + #if IS_ENABLED(CONFIG_SUNRPC_DEBUG) # define RPCDBG_FACILITY RPCDBG_AUTH #endif @@ -146,16 +149,18 @@ static u32 gss_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 = sizeof(cksumdata), - .data = cksumdata}; - time64_t now; + struct xdr_netobj cksumobj = { + .len = ctx->gk5e->cksumlength, + .data = cksumdata, + }; u8 *ptr = read_token->data; - u8 *cksumkey; + __be16 be16_ptr; + time64_t now; u8 flags; int i; - unsigned int cksum_usage; - __be16 be16_ptr;
dprintk("RPC: %s\n", __func__);
@@ -177,16 +182,8 @@ gss_verify_mic_v2(struct krb5_ctx *ctx, if (ptr[i] != 0xff) return GSS_S_DEFECTIVE_TOKEN;
- if (ctx->initiate) { - cksumkey = ctx->acceptor_sign; - cksum_usage = KG_USAGE_ACCEPTOR_SIGN; - } else { - cksumkey = ctx->initiator_sign; - cksum_usage = KG_USAGE_INITIATOR_SIGN; - } - - if (make_checksum_v2(ctx, ptr, GSS_KRB5_TOK_HDR_LEN, message_buffer, 0, - cksumkey, cksum_usage, &cksumobj)) + if (gss_krb5_checksum(tfm, ptr, GSS_KRB5_TOK_HDR_LEN, + message_buffer, 0, &cksumobj)) return GSS_S_FAILURE;
if (memcmp(cksumobj.data, ptr + GSS_KRB5_TOK_HDR_LEN,
From: Chuck Lever chuck.lever@oracle.com
There's no need to keep the integrity keys around if we instead allocate and key a pair of ahashes and keep those. This not only enables the subkeys to be destroyed immediately after deriving them, but it makes the Kerberos integrity code path more efficient.
Tested-by: Scott Mayhew smayhew@redhat.com Signed-off-by: Chuck Lever chuck.lever@oracle.com --- include/linux/sunrpc/gss_krb5.h | 9 +-- net/sunrpc/auth_gss/gss_krb5_crypto.c | 116 +++------------------------------ net/sunrpc/auth_gss/gss_krb5_mech.c | 22 +++--- 3 files changed, 23 insertions(+), 124 deletions(-)
diff --git a/include/linux/sunrpc/gss_krb5.h b/include/linux/sunrpc/gss_krb5.h index 9d897f1ac85a..85e65232bb61 100644 --- a/include/linux/sunrpc/gss_krb5.h +++ b/include/linux/sunrpc/gss_krb5.h @@ -104,14 +104,14 @@ struct krb5_ctx { 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; atomic64_t seq_send64; time64_t endtime; struct xdr_netobj mech_used; - u8 initiator_integ[GSS_KRB5_MAX_KEYLEN]; - u8 acceptor_integ[GSS_KRB5_MAX_KEYLEN]; };
/* The length of the Kerberos GSS token header */ @@ -233,11 +233,6 @@ make_checksum(struct krb5_ctx *kctx, char *header, int hdrlen, struct xdr_buf *body, int body_offset, u8 *cksumkey, unsigned int usage, struct xdr_netobj *cksumout);
-u32 -make_checksum_v2(struct krb5_ctx *, char *header, int hdrlen, - struct xdr_buf *body, int body_offset, u8 *key, - unsigned int usage, struct xdr_netobj *cksum); - u32 gss_get_mic_kerberos(struct gss_ctx *, struct xdr_buf *, struct xdr_netobj *);
diff --git a/net/sunrpc/auth_gss/gss_krb5_crypto.c b/net/sunrpc/auth_gss/gss_krb5_crypto.c index 44dfcd5f6cbe..098faaf02fe6 100644 --- a/net/sunrpc/auth_gss/gss_krb5_crypto.c +++ b/net/sunrpc/auth_gss/gss_krb5_crypto.c @@ -259,93 +259,6 @@ make_checksum(struct krb5_ctx *kctx, char *header, int hdrlen, return err ? GSS_S_FAILURE : 0; }
-/* - * checksum the plaintext data and hdrlen bytes of the token header - * Per rfc4121, sec. 4.2.4, the checksum is performed over the data - * body then over the first 16 octets of the MIC token - * Inclusion of the header data in the calculation of the - * checksum is optional. - */ -u32 -make_checksum_v2(struct krb5_ctx *kctx, char *header, int hdrlen, - struct xdr_buf *body, int body_offset, u8 *cksumkey, - unsigned int usage, struct xdr_netobj *cksumout) -{ - struct crypto_ahash *tfm; - struct ahash_request *req; - struct scatterlist sg[1]; - int err = -1; - u8 *checksumdata; - - if (kctx->gk5e->keyed_cksum == 0) { - dprintk("%s: expected keyed hash for %s\n", - __func__, kctx->gk5e->name); - return GSS_S_FAILURE; - } - if (cksumkey == NULL) { - dprintk("%s: no key supplied for %s\n", - __func__, kctx->gk5e->name); - return GSS_S_FAILURE; - } - - checksumdata = kmalloc(GSS_KRB5_MAX_CKSUM_LEN, GFP_KERNEL); - if (!checksumdata) - return GSS_S_FAILURE; - - tfm = crypto_alloc_ahash(kctx->gk5e->cksum_name, 0, CRYPTO_ALG_ASYNC); - if (IS_ERR(tfm)) - goto out_free_cksum; - - req = ahash_request_alloc(tfm, GFP_KERNEL); - if (!req) - goto out_free_ahash; - - ahash_request_set_callback(req, CRYPTO_TFM_REQ_MAY_SLEEP, NULL, NULL); - - err = crypto_ahash_setkey(tfm, cksumkey, kctx->gk5e->keylength); - if (err) - goto out; - - err = crypto_ahash_init(req); - if (err) - goto out; - err = xdr_process_buf(body, body_offset, body->len - body_offset, - checksummer, req); - if (err) - goto out; - if (header != NULL) { - sg_init_one(sg, header, hdrlen); - ahash_request_set_crypt(req, sg, NULL, hdrlen); - err = crypto_ahash_update(req); - if (err) - goto out; - } - ahash_request_set_crypt(req, NULL, checksumdata, 0); - err = crypto_ahash_final(req); - if (err) - goto out; - - cksumout->len = kctx->gk5e->cksumlength; - - switch (kctx->gk5e->ctype) { - case CKSUMTYPE_HMAC_SHA1_96_AES128: - case CKSUMTYPE_HMAC_SHA1_96_AES256: - /* note that this truncates the hash */ - memcpy(cksumout->data, checksumdata, kctx->gk5e->cksumlength); - break; - default: - BUG(); - break; - } -out: - ahash_request_free(req); -out_free_ahash: - crypto_free_ahash(tfm); -out_free_cksum: - kfree(checksumdata); - return err ? GSS_S_FAILURE : 0; -} - /** * gss_krb5_checksum - Compute the MAC for a GSS Wrap or MIC token * @tfm: an initialized hash transform @@ -702,27 +615,24 @@ gss_krb5_aes_encrypt(struct krb5_ctx *kctx, u32 offset, { u32 err; struct xdr_netobj hmac; - u8 *cksumkey; u8 *ecptr; struct crypto_sync_skcipher *cipher, *aux_cipher; + struct crypto_ahash *ahash; int blocksize; struct page **save_pages; int nblocks, nbytes; struct encryptor_desc desc; u32 cbcbytes; - unsigned int usage; unsigned int conflen;
if (kctx->initiate) { cipher = kctx->initiator_enc; aux_cipher = kctx->initiator_enc_aux; - cksumkey = kctx->initiator_integ; - usage = KG_USAGE_INITIATOR_SEAL; + ahash = kctx->initiator_integ; } else { cipher = kctx->acceptor_enc; aux_cipher = kctx->acceptor_enc_aux; - cksumkey = kctx->acceptor_integ; - usage = KG_USAGE_ACCEPTOR_SEAL; + ahash = kctx->acceptor_integ; } blocksize = crypto_sync_skcipher_blocksize(cipher); conflen = crypto_sync_skcipher_blocksize(cipher); @@ -762,9 +672,8 @@ gss_krb5_aes_encrypt(struct krb5_ctx *kctx, u32 offset, save_pages = buf->pages; buf->pages = pages;
- err = make_checksum_v2(kctx, NULL, 0, buf, - offset + GSS_KRB5_TOK_HDR_LEN, - cksumkey, usage, &hmac); + 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; @@ -825,25 +734,22 @@ gss_krb5_aes_decrypt(struct krb5_ctx *kctx, u32 offset, u32 len, { struct xdr_buf subbuf; u32 ret = 0; - u8 *cksum_key; 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]; int nblocks, blocksize, cbcbytes; struct decryptor_desc desc; - unsigned int usage;
if (kctx->initiate) { cipher = kctx->acceptor_enc; aux_cipher = kctx->acceptor_enc_aux; - cksum_key = kctx->acceptor_integ; - usage = KG_USAGE_ACCEPTOR_SEAL; + ahash = kctx->acceptor_integ; } else { cipher = kctx->initiator_enc; aux_cipher = kctx->initiator_enc_aux; - cksum_key = kctx->initiator_integ; - usage = KG_USAGE_INITIATOR_SEAL; + ahash = kctx->initiator_integ; } blocksize = crypto_sync_skcipher_blocksize(cipher);
@@ -883,13 +789,9 @@ gss_krb5_aes_decrypt(struct krb5_ctx *kctx, u32 offset, u32 len, if (ret) goto out_err;
- - /* Calculate our hmac over the plaintext data */ our_hmac_obj.len = sizeof(our_hmac); our_hmac_obj.data = our_hmac; - - ret = make_checksum_v2(kctx, NULL, 0, &subbuf, 0, - cksum_key, usage, &our_hmac_obj); + ret = gss_krb5_checksum(ahash, NULL, 0, &subbuf, 0, &our_hmac_obj); if (ret) goto out_err;
diff --git a/net/sunrpc/auth_gss/gss_krb5_mech.c b/net/sunrpc/auth_gss/gss_krb5_mech.c index 5478f741287e..2237f640cef4 100644 --- a/net/sunrpc/auth_gss/gss_krb5_mech.c +++ b/net/sunrpc/auth_gss/gss_krb5_mech.c @@ -447,23 +447,21 @@ context_derive_keys_new(struct krb5_ctx *ctx, gfp_t gfp_mask)
/* initiator seal integrity */ set_cdata(cdata, KG_USAGE_INITIATOR_SEAL, KEY_USAGE_SEED_INTEGRITY); - keyout.data = ctx->initiator_integ; err = krb5_derive_key(ctx->gk5e, &keyin, &keyout, &c, gfp_mask); - if (err) { - dprintk("%s: Error %d deriving initiator_integ key\n", - __func__, err); + if (err) + goto out_free; + ctx->initiator_integ = gss_krb5_alloc_hash_v2(ctx, &keyout); + if (ctx->initiator_integ == NULL) goto out_free; - }
/* acceptor seal integrity */ set_cdata(cdata, KG_USAGE_ACCEPTOR_SEAL, KEY_USAGE_SEED_INTEGRITY); - keyout.data = ctx->acceptor_integ; err = krb5_derive_key(ctx->gk5e, &keyin, &keyout, &c, gfp_mask); - if (err) { - dprintk("%s: Error %d deriving acceptor_integ key\n", - __func__, err); + if (err) + goto out_free; + ctx->acceptor_integ = gss_krb5_alloc_hash_v2(ctx, &keyout); + if (ctx->acceptor_integ == NULL) goto out_free; - }
ret = 0; out: @@ -471,6 +469,8 @@ context_derive_keys_new(struct krb5_ctx *ctx, gfp_t gfp_mask) return ret;
out_free: + 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); @@ -598,6 +598,8 @@ gss_delete_sec_context_kerberos(void *internal_ctx) { 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); }
From: Chuck Lever chuck.lever@oracle.com
Replace a number of switches on encryption type so that all of them don't have to be modified when adding or removing support for an enctype.
Tested-by: Scott Mayhew smayhew@redhat.com Signed-off-by: Chuck Lever chuck.lever@oracle.com --- include/linux/sunrpc/gss_krb5.h | 23 ++---- net/sunrpc/auth_gss/gss_krb5_internal.h | 30 +++++++ net/sunrpc/auth_gss/gss_krb5_mech.c | 126 ++++++++++++++++++++++++++++--- net/sunrpc/auth_gss/gss_krb5_seal.c | 30 +------ net/sunrpc/auth_gss/gss_krb5_unseal.c | 31 +------- net/sunrpc/auth_gss/gss_krb5_wrap.c | 66 +++------------- 6 files changed, 180 insertions(+), 126 deletions(-)
diff --git a/include/linux/sunrpc/gss_krb5.h b/include/linux/sunrpc/gss_krb5.h index 85e65232bb61..f1201478fdd5 100644 --- a/include/linux/sunrpc/gss_krb5.h +++ b/include/linux/sunrpc/gss_krb5.h @@ -84,6 +84,15 @@ struct gss_krb5_enctype { u32 (*decrypt_v2) (struct krb5_ctx *kctx, u32 offset, u32 len, struct xdr_buf *buf, u32 *headskip, u32 *tailskip); /* v2 decryption function */ + 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, + struct xdr_buf *buf, unsigned int *slack, + unsigned int *align); };
/* krb5_ctx flags definitions */ @@ -233,20 +242,6 @@ make_checksum(struct krb5_ctx *kctx, char *header, int hdrlen, struct xdr_buf *body, int body_offset, u8 *cksumkey, unsigned int usage, struct xdr_netobj *cksumout);
-u32 gss_get_mic_kerberos(struct gss_ctx *, struct xdr_buf *, - struct xdr_netobj *); - -u32 gss_verify_mic_kerberos(struct gss_ctx *, struct xdr_buf *, - struct xdr_netobj *); - -u32 -gss_wrap_kerberos(struct gss_ctx *ctx_id, int offset, - struct xdr_buf *outbuf, struct page **pages); - -u32 -gss_unwrap_kerberos(struct gss_ctx *ctx_id, int offset, int len, - struct xdr_buf *buf); - u32 krb5_encrypt(struct crypto_sync_skcipher *key, void *iv, void *in, void *out, int length); diff --git a/net/sunrpc/auth_gss/gss_krb5_internal.h b/net/sunrpc/auth_gss/gss_krb5_internal.h index 42f7fd0bbf3a..04d2781e2ce2 100644 --- a/net/sunrpc/auth_gss/gss_krb5_internal.h +++ b/net/sunrpc/auth_gss/gss_krb5_internal.h @@ -8,6 +8,36 @@ #ifndef _NET_SUNRPC_AUTH_GSS_KRB5_INTERNAL_H #define _NET_SUNRPC_AUTH_GSS_KRB5_INTERNAL_H
+/* + * GSS Kerberos 5 mechanism Per-Message calls. + */ + +u32 gss_krb5_get_mic_v1(struct krb5_ctx *ctx, struct xdr_buf *text, + struct xdr_netobj *token); +u32 gss_krb5_get_mic_v2(struct krb5_ctx *ctx, struct xdr_buf *text, + struct xdr_netobj *token); + +u32 gss_krb5_verify_mic_v1(struct krb5_ctx *ctx, struct xdr_buf *message_buffer, + struct xdr_netobj *read_token); +u32 gss_krb5_verify_mic_v2(struct krb5_ctx *ctx, struct xdr_buf *message_buffer, + struct xdr_netobj *read_token); + +u32 gss_krb5_wrap_v1(struct krb5_ctx *kctx, int offset, + struct xdr_buf *buf, struct page **pages); +u32 gss_krb5_wrap_v2(struct krb5_ctx *kctx, int offset, + struct xdr_buf *buf, struct page **pages); + +u32 gss_krb5_unwrap_v1(struct krb5_ctx *kctx, int offset, int len, + struct xdr_buf *buf, unsigned int *slack, + unsigned int *align); +u32 gss_krb5_unwrap_v2(struct krb5_ctx *kctx, int offset, int len, + struct xdr_buf *buf, unsigned int *slack, + unsigned int *align); + +/* + * Implementation internal functions + */ + void krb5_make_confounder(u8 *p, int conflen);
u32 gss_krb5_checksum(struct crypto_ahash *tfm, char *header, int hdrlen, diff --git a/net/sunrpc/auth_gss/gss_krb5_mech.c b/net/sunrpc/auth_gss/gss_krb5_mech.c index 2237f640cef4..0a831b5cea6b 100644 --- a/net/sunrpc/auth_gss/gss_krb5_mech.c +++ b/net/sunrpc/auth_gss/gss_krb5_mech.c @@ -22,6 +22,7 @@ #include <linux/sunrpc/gss_krb5_enctypes.h>
#include "auth_gss_internal.h" +#include "gss_krb5_internal.h"
#if IS_ENABLED(CONFIG_SUNRPC_DEBUG) # define RPCDBG_FACILITY RPCDBG_AUTH @@ -43,6 +44,10 @@ static const struct gss_krb5_enctype supported_gss_krb5_enctypes[] = { .encrypt = krb5_encrypt, .decrypt = krb5_decrypt, .mk_key = NULL, + .get_mic = gss_krb5_get_mic_v1, + .verify_mic = gss_krb5_verify_mic_v1, + .wrap = gss_krb5_wrap_v1, + .unwrap = gss_krb5_unwrap_v1, .signalg = SGN_ALG_DES_MAC_MD5, .sealalg = SEAL_ALG_DES, .keybytes = 7, @@ -63,6 +68,10 @@ static const struct gss_krb5_enctype supported_gss_krb5_enctypes[] = { .encrypt = krb5_encrypt, .decrypt = krb5_decrypt, .mk_key = gss_krb5_des3_make_key, + .get_mic = gss_krb5_get_mic_v1, + .verify_mic = gss_krb5_verify_mic_v1, + .wrap = gss_krb5_wrap_v1, + .unwrap = gss_krb5_unwrap_v1, .signalg = SGN_ALG_HMAC_SHA1_DES3_KD, .sealalg = SEAL_ALG_DES3KD, .keybytes = 21, @@ -85,6 +94,12 @@ static const struct gss_krb5_enctype supported_gss_krb5_enctypes[] = { .mk_key = gss_krb5_aes_make_key, .encrypt_v2 = gss_krb5_aes_encrypt, .decrypt_v2 = gss_krb5_aes_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, + .signalg = -1, .sealalg = -1, .keybytes = 16, @@ -107,6 +122,12 @@ static const struct gss_krb5_enctype supported_gss_krb5_enctypes[] = { .mk_key = gss_krb5_aes_make_key, .encrypt_v2 = gss_krb5_aes_encrypt, .decrypt_v2 = gss_krb5_aes_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, + .signalg = -1, .sealalg = -1, .keybytes = 32, @@ -557,10 +578,8 @@ gss_import_v2_context(const void *p, const void *end, struct krb5_ctx *ctx, }
static int -gss_import_sec_context_kerberos(const void *p, size_t len, - struct gss_ctx *ctx_id, - time64_t *endtime, - gfp_t gfp_mask) +gss_krb5_import_sec_context(const void *p, size_t len, struct gss_ctx *ctx_id, + time64_t *endtime, gfp_t gfp_mask) { const void *end = (const void *)((const char *)p + len); struct krb5_ctx *ctx; @@ -587,7 +606,8 @@ gss_import_sec_context_kerberos(const void *p, size_t len, }
static void -gss_delete_sec_context_kerberos(void *internal_ctx) { +gss_krb5_delete_sec_context(void *internal_ctx) +{ struct krb5_ctx *kctx = internal_ctx;
crypto_free_sync_skcipher(kctx->seq); @@ -604,13 +624,97 @@ gss_delete_sec_context_kerberos(void *internal_ctx) { kfree(kctx); }
+/** + * gss_krb5_get_mic - get_mic for the Kerberos GSS mechanism + * @gctx: GSS context + * @text: plaintext to checksum + * @token: buffer into which to write the computed checksum + * + * Return values: + * %GSS_S_COMPLETE - success, and @token is filled in + * %GSS_S_FAILURE - checksum could not be generated + * %GSS_S_CONTEXT_EXPIRED - Kerberos context is no longer valid + */ +static u32 gss_krb5_get_mic(struct gss_ctx *gctx, struct xdr_buf *text, + struct xdr_netobj *token) +{ + struct krb5_ctx *kctx = gctx->internal_ctx_id; + + return kctx->gk5e->get_mic(kctx, text, token); +} + +/** + * gss_krb5_verify_mic - verify_mic for the Kerberos GSS mechanism + * @gctx: GSS context + * @message_buffer: plaintext to check + * @read_token: received checksum to check + * + * Return values: + * %GSS_S_COMPLETE - computed and received checksums match + * %GSS_S_DEFECTIVE_TOKEN - received checksum is not valid + * %GSS_S_BAD_SIG - computed and received checksums do not match + * %GSS_S_FAILURE - received checksum could not be checked + * %GSS_S_CONTEXT_EXPIRED - Kerberos context is no longer valid + */ +static u32 gss_krb5_verify_mic(struct gss_ctx *gctx, + struct xdr_buf *message_buffer, + struct xdr_netobj *read_token) +{ + struct krb5_ctx *kctx = gctx->internal_ctx_id; + + return kctx->gk5e->verify_mic(kctx, message_buffer, read_token); +} + +/** + * gss_krb5_wrap - gss_wrap for the Kerberos GSS mechanism + * @gctx: initialized GSS context + * @offset: byte offset in @buf to start writing the cipher text + * @buf: OUT: send buffer + * @pages: plaintext to wrap + * + * Return values: + * %GSS_S_COMPLETE - success, @buf has been updated + * %GSS_S_FAILURE - @buf could not be wrapped + * %GSS_S_CONTEXT_EXPIRED - Kerberos context is no longer valid + */ +static u32 gss_krb5_wrap(struct gss_ctx *gctx, int offset, + struct xdr_buf *buf, struct page **pages) +{ + struct krb5_ctx *kctx = gctx->internal_ctx_id; + + return kctx->gk5e->wrap(kctx, offset, buf, pages); +} + +/** + * gss_krb5_unwrap - gss_unwrap for the Kerberos GSS mechanism + * @gctx: initialized GSS context + * @offset: starting byte offset into @buf + * @len: size of ciphertext to unwrap + * @buf: ciphertext to unwrap + * + * Return values: + * %GSS_S_COMPLETE - success, @buf has been updated + * %GSS_S_DEFECTIVE_TOKEN - received blob is not valid + * %GSS_S_BAD_SIG - computed and received checksums do not match + * %GSS_S_FAILURE - @buf could not be unwrapped + * %GSS_S_CONTEXT_EXPIRED - Kerberos context is no longer valid + */ +static u32 gss_krb5_unwrap(struct gss_ctx *gctx, int offset, + int len, struct xdr_buf *buf) +{ + struct krb5_ctx *kctx = gctx->internal_ctx_id; + + return kctx->gk5e->unwrap(kctx, offset, len, buf, + &gctx->slack, &gctx->align); +} + static const struct gss_api_ops gss_kerberos_ops = { - .gss_import_sec_context = gss_import_sec_context_kerberos, - .gss_get_mic = gss_get_mic_kerberos, - .gss_verify_mic = gss_verify_mic_kerberos, - .gss_wrap = gss_wrap_kerberos, - .gss_unwrap = gss_unwrap_kerberos, - .gss_delete_sec_context = gss_delete_sec_context_kerberos, + .gss_import_sec_context = gss_krb5_import_sec_context, + .gss_get_mic = gss_krb5_get_mic, + .gss_verify_mic = gss_krb5_verify_mic, + .gss_wrap = gss_krb5_wrap, + .gss_unwrap = gss_krb5_unwrap, + .gss_delete_sec_context = gss_krb5_delete_sec_context, };
static struct pf_desc gss_kerberos_pfs[] = { diff --git a/net/sunrpc/auth_gss/gss_krb5_seal.c b/net/sunrpc/auth_gss/gss_krb5_seal.c index 1d6f8a345354..f74125407588 100644 --- a/net/sunrpc/auth_gss/gss_krb5_seal.c +++ b/net/sunrpc/auth_gss/gss_krb5_seal.c @@ -125,9 +125,9 @@ setup_token_v2(struct krb5_ctx *ctx, struct xdr_netobj *token) return krb5_hdr; }
-static u32 -gss_get_mic_v1(struct krb5_ctx *ctx, struct xdr_buf *text, - struct xdr_netobj *token) +u32 +gss_krb5_get_mic_v1(struct krb5_ctx *ctx, struct xdr_buf *text, + struct xdr_netobj *token) { char cksumdata[GSS_KRB5_MAX_CKSUM_LEN]; struct xdr_netobj md5cksum = {.len = sizeof(cksumdata), @@ -164,9 +164,9 @@ gss_get_mic_v1(struct krb5_ctx *ctx, struct xdr_buf *text, return (ctx->endtime < now) ? GSS_S_CONTEXT_EXPIRED : GSS_S_COMPLETE; }
-static u32 -gss_get_mic_v2(struct krb5_ctx *ctx, struct xdr_buf *text, - struct xdr_netobj *token) +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; @@ -194,21 +194,3 @@ gss_get_mic_v2(struct krb5_ctx *ctx, struct xdr_buf *text, now = ktime_get_real_seconds(); return (ctx->endtime < now) ? GSS_S_CONTEXT_EXPIRED : GSS_S_COMPLETE; } - -u32 -gss_get_mic_kerberos(struct gss_ctx *gss_ctx, struct xdr_buf *text, - struct xdr_netobj *token) -{ - struct krb5_ctx *ctx = gss_ctx->internal_ctx_id; - - switch (ctx->enctype) { - default: - BUG(); - case ENCTYPE_DES_CBC_RAW: - case ENCTYPE_DES3_CBC_RAW: - return gss_get_mic_v1(ctx, text, token); - case ENCTYPE_AES128_CTS_HMAC_SHA1_96: - case ENCTYPE_AES256_CTS_HMAC_SHA1_96: - return gss_get_mic_v2(ctx, text, token); - } -} diff --git a/net/sunrpc/auth_gss/gss_krb5_unseal.c b/net/sunrpc/auth_gss/gss_krb5_unseal.c index d52103f1203b..939d199eb7b7 100644 --- a/net/sunrpc/auth_gss/gss_krb5_unseal.c +++ b/net/sunrpc/auth_gss/gss_krb5_unseal.c @@ -73,9 +73,9 @@ /* read_token is a mic token, and message_buffer is the data that the mic was * supposedly taken over. */
-static u32 -gss_verify_mic_v1(struct krb5_ctx *ctx, - struct xdr_buf *message_buffer, struct xdr_netobj *read_token) +u32 +gss_krb5_verify_mic_v1(struct krb5_ctx *ctx, struct xdr_buf *message_buffer, + struct xdr_netobj *read_token) { int signalg; int sealalg; @@ -145,9 +145,9 @@ gss_verify_mic_v1(struct krb5_ctx *ctx, return GSS_S_COMPLETE; }
-static u32 -gss_verify_mic_v2(struct krb5_ctx *ctx, - struct xdr_buf *message_buffer, struct xdr_netobj *read_token) +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; @@ -202,22 +202,3 @@ gss_verify_mic_v2(struct krb5_ctx *ctx,
return GSS_S_COMPLETE; } - -u32 -gss_verify_mic_kerberos(struct gss_ctx *gss_ctx, - struct xdr_buf *message_buffer, - struct xdr_netobj *read_token) -{ - struct krb5_ctx *ctx = gss_ctx->internal_ctx_id; - - switch (ctx->enctype) { - default: - BUG(); - case ENCTYPE_DES_CBC_RAW: - case ENCTYPE_DES3_CBC_RAW: - return gss_verify_mic_v1(ctx, message_buffer, read_token); - case ENCTYPE_AES128_CTS_HMAC_SHA1_96: - case ENCTYPE_AES256_CTS_HMAC_SHA1_96: - return gss_verify_mic_v2(ctx, message_buffer, read_token); - } -} diff --git a/net/sunrpc/auth_gss/gss_krb5_wrap.c b/net/sunrpc/auth_gss/gss_krb5_wrap.c index 66e65e4c6336..d983da6f9530 100644 --- a/net/sunrpc/auth_gss/gss_krb5_wrap.c +++ b/net/sunrpc/auth_gss/gss_krb5_wrap.c @@ -122,9 +122,9 @@ gss_krb5_remove_padding(struct xdr_buf *buf, int blocksize)
/* XXX factor out common code with seal/unseal. */
-static u32 -gss_wrap_kerberos_v1(struct krb5_ctx *kctx, int offset, - struct xdr_buf *buf, struct page **pages) +u32 +gss_krb5_wrap_v1(struct krb5_ctx *kctx, int offset, + struct xdr_buf *buf, struct page **pages) { char cksumdata[GSS_KRB5_MAX_CKSUM_LEN]; struct xdr_netobj md5cksum = {.len = sizeof(cksumdata), @@ -211,10 +211,10 @@ gss_wrap_kerberos_v1(struct krb5_ctx *kctx, int offset, return (kctx->endtime < now) ? GSS_S_CONTEXT_EXPIRED : GSS_S_COMPLETE; }
-static u32 -gss_unwrap_kerberos_v1(struct krb5_ctx *kctx, int offset, int len, - struct xdr_buf *buf, unsigned int *slack, - unsigned int *align) +u32 +gss_krb5_unwrap_v1(struct krb5_ctx *kctx, int offset, int len, + struct xdr_buf *buf, unsigned int *slack, + unsigned int *align) { int signalg; int sealalg; @@ -373,9 +373,9 @@ static void rotate_left(u32 base, struct xdr_buf *buf, unsigned int shift) _rotate_left(&subbuf, shift); }
-static u32 -gss_wrap_kerberos_v2(struct krb5_ctx *kctx, u32 offset, - struct xdr_buf *buf, struct page **pages) +u32 +gss_krb5_wrap_v2(struct krb5_ctx *kctx, int offset, + struct xdr_buf *buf, struct page **pages) { u8 *ptr; time64_t now; @@ -424,10 +424,10 @@ gss_wrap_kerberos_v2(struct krb5_ctx *kctx, u32 offset, return (kctx->endtime < now) ? GSS_S_CONTEXT_EXPIRED : GSS_S_COMPLETE; }
-static u32 -gss_unwrap_kerberos_v2(struct krb5_ctx *kctx, int offset, int len, - struct xdr_buf *buf, unsigned int *slack, - unsigned int *align) +u32 +gss_krb5_unwrap_v2(struct krb5_ctx *kctx, int offset, int len, + struct xdr_buf *buf, unsigned int *slack, + unsigned int *align) { time64_t now; u8 *ptr; @@ -524,41 +524,3 @@ gss_unwrap_kerberos_v2(struct krb5_ctx *kctx, int offset, int len, *slack = *align + XDR_QUADLEN(ec + GSS_KRB5_TOK_HDR_LEN + tailskip); return GSS_S_COMPLETE; } - -u32 -gss_wrap_kerberos(struct gss_ctx *gctx, int offset, - struct xdr_buf *buf, struct page **pages) -{ - struct krb5_ctx *kctx = gctx->internal_ctx_id; - - switch (kctx->enctype) { - default: - BUG(); - case ENCTYPE_DES_CBC_RAW: - case ENCTYPE_DES3_CBC_RAW: - return gss_wrap_kerberos_v1(kctx, offset, buf, pages); - case ENCTYPE_AES128_CTS_HMAC_SHA1_96: - case ENCTYPE_AES256_CTS_HMAC_SHA1_96: - return gss_wrap_kerberos_v2(kctx, offset, buf, pages); - } -} - -u32 -gss_unwrap_kerberos(struct gss_ctx *gctx, int offset, - int len, struct xdr_buf *buf) -{ - struct krb5_ctx *kctx = gctx->internal_ctx_id; - - switch (kctx->enctype) { - default: - BUG(); - case ENCTYPE_DES_CBC_RAW: - case ENCTYPE_DES3_CBC_RAW: - return gss_unwrap_kerberos_v1(kctx, offset, len, buf, - &gctx->slack, &gctx->align); - case ENCTYPE_AES128_CTS_HMAC_SHA1_96: - case ENCTYPE_AES256_CTS_HMAC_SHA1_96: - return gss_unwrap_kerberos_v2(kctx, offset, len, buf, - &gctx->slack, &gctx->align); - } -}
From: Chuck Lever chuck.lever@oracle.com
Replace another switch on encryption type so that it does not have to be modified when adding or removing support for an enctype.
Tested-by: Scott Mayhew smayhew@redhat.com Signed-off-by: Chuck Lever chuck.lever@oracle.com --- include/linux/sunrpc/gss_krb5.h | 1 + net/sunrpc/auth_gss/gss_krb5_mech.c | 30 ++++++++++++++++++------------ 2 files changed, 19 insertions(+), 12 deletions(-)
diff --git a/include/linux/sunrpc/gss_krb5.h b/include/linux/sunrpc/gss_krb5.h index f1201478fdd5..68ae0c3d4cf7 100644 --- a/include/linux/sunrpc/gss_krb5.h +++ b/include/linux/sunrpc/gss_krb5.h @@ -75,6 +75,7 @@ struct gss_krb5_enctype { u32 (*decrypt) (struct crypto_sync_skcipher *tfm, void *iv, void *in, void *out, int length); /* decryption function */ + int (*import_ctx)(struct krb5_ctx *ctx, gfp_t gfp_mask); u32 (*mk_key) (const struct gss_krb5_enctype *gk5e, struct xdr_netobj *in, struct xdr_netobj *out); /* complete key generation */ diff --git a/net/sunrpc/auth_gss/gss_krb5_mech.c b/net/sunrpc/auth_gss/gss_krb5_mech.c index 0a831b5cea6b..e33575216a01 100644 --- a/net/sunrpc/auth_gss/gss_krb5_mech.c +++ b/net/sunrpc/auth_gss/gss_krb5_mech.c @@ -28,7 +28,11 @@ # define RPCDBG_FACILITY RPCDBG_AUTH #endif
-static struct gss_api_mech gss_kerberos_mech; /* forward declaration */ +static struct gss_api_mech gss_kerberos_mech; + +static int gss_krb5_import_ctx_des(struct krb5_ctx *ctx, gfp_t gfp_mask); +static int gss_krb5_import_ctx_v1(struct krb5_ctx *ctx, gfp_t gfp_mask); +static int gss_krb5_import_ctx_v2(struct krb5_ctx *ctx, gfp_t gfp_mask);
static const struct gss_krb5_enctype supported_gss_krb5_enctypes[] = { #ifndef CONFIG_SUNRPC_DISABLE_INSECURE_ENCTYPES @@ -43,6 +47,7 @@ static const struct gss_krb5_enctype supported_gss_krb5_enctypes[] = { .cksum_name = "md5", .encrypt = krb5_encrypt, .decrypt = krb5_decrypt, + .import_ctx = gss_krb5_import_ctx_des, .mk_key = NULL, .get_mic = gss_krb5_get_mic_v1, .verify_mic = gss_krb5_verify_mic_v1, @@ -67,6 +72,7 @@ static const struct gss_krb5_enctype supported_gss_krb5_enctypes[] = { .cksum_name = "hmac(sha1)", .encrypt = krb5_encrypt, .decrypt = krb5_decrypt, + .import_ctx = gss_krb5_import_ctx_v1, .mk_key = gss_krb5_des3_make_key, .get_mic = gss_krb5_get_mic_v1, .verify_mic = gss_krb5_verify_mic_v1, @@ -91,6 +97,7 @@ static const struct gss_krb5_enctype supported_gss_krb5_enctypes[] = { .cksum_name = "hmac(sha1)", .encrypt = krb5_encrypt, .decrypt = krb5_decrypt, + .import_ctx = gss_krb5_import_ctx_v2, .mk_key = gss_krb5_aes_make_key, .encrypt_v2 = gss_krb5_aes_encrypt, .decrypt_v2 = gss_krb5_aes_decrypt, @@ -119,6 +126,7 @@ static const struct gss_krb5_enctype supported_gss_krb5_enctypes[] = { .cksum_name = "hmac(sha1)", .encrypt = krb5_encrypt, .decrypt = krb5_decrypt, + .import_ctx = gss_krb5_import_ctx_v2, .mk_key = gss_krb5_aes_make_key, .encrypt_v2 = gss_krb5_aes_encrypt, .decrypt_v2 = gss_krb5_aes_decrypt, @@ -324,7 +332,13 @@ set_cdata(u8 cdata[GSS_KRB5_K5CLENGTH], u32 usage, u8 seed) }
static int -context_derive_keys_des3(struct krb5_ctx *ctx, gfp_t gfp_mask) +gss_krb5_import_ctx_des(struct krb5_ctx *ctx, gfp_t gfp_mask) +{ + return -EINVAL; +} + +static int +gss_krb5_import_ctx_v1(struct krb5_ctx *ctx, gfp_t gfp_mask) { struct xdr_netobj c, keyin, keyout; u8 cdata[GSS_KRB5_K5CLENGTH]; @@ -384,7 +398,7 @@ gss_krb5_alloc_hash_v2(struct krb5_ctx *kctx, const struct xdr_netobj *key) }
static int -context_derive_keys_new(struct krb5_ctx *ctx, gfp_t gfp_mask) +gss_krb5_import_ctx_v2(struct krb5_ctx *ctx, gfp_t gfp_mask) { u8 cdata[GSS_KRB5_K5CLENGTH]; struct xdr_netobj c = { @@ -563,15 +577,7 @@ gss_import_v2_context(const void *p, const void *end, struct krb5_ctx *ctx, } ctx->mech_used.len = gss_kerberos_mech.gm_oid.len;
- switch (ctx->enctype) { - case ENCTYPE_DES3_CBC_RAW: - return context_derive_keys_des3(ctx, gfp_mask); - case ENCTYPE_AES128_CTS_HMAC_SHA1_96: - case ENCTYPE_AES256_CTS_HMAC_SHA1_96: - return context_derive_keys_new(ctx, gfp_mask); - default: - return -EINVAL; - } + return ctx->gk5e->import_ctx(ctx, gfp_mask);
out_err: return PTR_ERR(p);
From: Chuck Lever chuck.lever@oracle.com
I would like to replace the KRB5_SUPPORTED_ENCTYPES macro so that there is finer granularity about what enctype support is built in to the kernel and then advertised by it.
The /proc/fs/nfsd/supported_krb5_enctypes file is a legacy API that advertises supported enctypes to rpc.svcgssd (I think?). It simply prints the value of the KRB5_SUPPORTED_ENCTYPES macro, so it will need to be replaced with something that can instead display exactly which enctypes are configured and built into the SunRPC layer.
Completely decommissioning such APIs is hard. Instead, add a file that is managed by SunRPC's GSS Kerberos mechanism, which is authoritative about enctype support status. A subsequent patch will replace /proc/fs/nfsd/supported_krb5_enctypes with a symlink to this new file.
Tested-by: Scott Mayhew smayhew@redhat.com Signed-off-by: Chuck Lever chuck.lever@oracle.com --- net/sunrpc/auth_gss/svcauth_gss.c | 65 +++++++++++++++++++++++++++++++++++++ 1 file changed, 65 insertions(+)
diff --git a/net/sunrpc/auth_gss/svcauth_gss.c b/net/sunrpc/auth_gss/svcauth_gss.c index 28e977c89a5a..19f0190a0b97 100644 --- a/net/sunrpc/auth_gss/svcauth_gss.c +++ b/net/sunrpc/auth_gss/svcauth_gss.c @@ -1494,6 +1494,55 @@ static void destroy_use_gss_proxy_proc_entry(struct net *net) clear_gssp_clnt(sn); } } + +static ssize_t read_gss_krb5_enctypes(struct file *file, char __user *buf, + size_t count, loff_t *ppos) +{ + struct rpcsec_gss_oid oid = { + .len = 9, + .data = "\x2a\x86\x48\x86\xf7\x12\x01\x02\x02", + }; + struct gss_api_mech *mech; + ssize_t ret; + + mech = gss_mech_get_by_OID(&oid); + if (!mech) + return 0; + if (!mech->gm_upcall_enctypes) { + gss_mech_put(mech); + return 0; + } + + ret = simple_read_from_buffer(buf, count, ppos, + mech->gm_upcall_enctypes, + strlen(mech->gm_upcall_enctypes)); + gss_mech_put(mech); + return ret; +} + +static const struct proc_ops gss_krb5_enctypes_proc_ops = { + .proc_open = nonseekable_open, + .proc_read = read_gss_krb5_enctypes, +}; + +static int create_krb5_enctypes_proc_entry(struct net *net) +{ + struct sunrpc_net *sn = net_generic(net, sunrpc_net_id); + + if (!proc_create_data("gss_krb5_enctypes", S_IFREG | 0444, + sn->proc_net_rpc, + &gss_krb5_enctypes_proc_ops, net)) + return -ENOMEM; + return 0; +} + +static void destroy_krb5_enctypes_proc_entry(struct net *net) +{ + struct sunrpc_net *sn = net_generic(net, sunrpc_net_id); + + remove_proc_entry("gss_krb5_enctypes", sn->proc_net_rpc); +} + #else /* CONFIG_PROC_FS */
static int create_use_gss_proxy_proc_entry(struct net *net) @@ -1503,6 +1552,13 @@ static int create_use_gss_proxy_proc_entry(struct net *net)
static void destroy_use_gss_proxy_proc_entry(struct net *net) {}
+static int create_krb5_enctypes_proc_entry(struct net *net) +{ + return 0; +} + +static void destroy_krb5_enctypes_proc_entry(struct net *net) {} + #endif /* CONFIG_PROC_FS */
/* @@ -2042,7 +2098,15 @@ gss_svc_init_net(struct net *net) rv = create_use_gss_proxy_proc_entry(net); if (rv) goto out2; + + rv = create_krb5_enctypes_proc_entry(net); + if (rv) + goto out3; + return 0; + +out3: + destroy_use_gss_proxy_proc_entry(net); out2: rsi_cache_destroy_net(net); out1: @@ -2053,6 +2117,7 @@ gss_svc_init_net(struct net *net) void gss_svc_shutdown_net(struct net *net) { + destroy_krb5_enctypes_proc_entry(net); destroy_use_gss_proxy_proc_entry(net); rsi_cache_destroy_net(net); rsc_cache_destroy_net(net);
From: Chuck Lever chuck.lever@oracle.com
Now that I've added a file under /proc/net/rpc that is managed by the SunRPC's Kerberos mechanism, replace NFSD's supported_krb5_enctypes file with a symlink to the new SunRPC proc file, which contains exactly the same content.
Remarkably, commit b0b0c0a26e84 ("nfsd: add proc file listing kernel's gss_krb5 enctypes") added the nfsd_supported_krb5_enctypes file in 2011, but this file has never been documented in nfsd(7).
Tested-by: Scott Mayhew smayhew@redhat.com Signed-off-by: Chuck Lever chuck.lever@oracle.com --- fs/nfsd/nfsctl.c | 74 ++++++++++++++++++++++++++++++++++++++++++------------ 1 file changed, 58 insertions(+), 16 deletions(-)
diff --git a/fs/nfsd/nfsctl.c b/fs/nfsd/nfsctl.c index f2a0d6ac88df..04474b8ccf0a 100644 --- a/fs/nfsd/nfsctl.c +++ b/fs/nfsd/nfsctl.c @@ -14,7 +14,6 @@ #include <linux/lockd/lockd.h> #include <linux/sunrpc/addr.h> #include <linux/sunrpc/gss_api.h> -#include <linux/sunrpc/gss_krb5_enctypes.h> #include <linux/sunrpc/rpc_pipe_fs.h> #include <linux/module.h> #include <linux/fsnotify.h> @@ -47,7 +46,6 @@ enum { NFSD_MaxBlkSize, NFSD_MaxConnections, NFSD_Filecache, - NFSD_SupportedEnctypes, /* * The below MUST come last. Otherwise we leave a hole in nfsd_files[] * with !CONFIG_NFSD_V4 and simple_fill_super() goes oops @@ -187,16 +185,6 @@ static int export_features_show(struct seq_file *m, void *v)
DEFINE_SHOW_ATTRIBUTE(export_features);
-#if defined(CONFIG_SUNRPC_GSS) || defined(CONFIG_SUNRPC_GSS_MODULE) -static int supported_enctypes_show(struct seq_file *m, void *v) -{ - seq_printf(m, KRB5_SUPPORTED_ENCTYPES); - return 0; -} - -DEFINE_SHOW_ATTRIBUTE(supported_enctypes); -#endif /* CONFIG_SUNRPC_GSS or CONFIG_SUNRPC_GSS_MODULE */ - static const struct file_operations pool_stats_operations = { .open = nfsd_pool_stats_open, .read = seq_read, @@ -1150,6 +1138,9 @@ static struct inode *nfsd_get_inode(struct super_block *sb, umode_t mode) inode->i_op = &simple_dir_inode_operations; inc_nlink(inode); break; + case S_IFLNK: + inode->i_op = &simple_symlink_inode_operations; + break; default: break; } @@ -1195,6 +1186,59 @@ static struct dentry *nfsd_mkdir(struct dentry *parent, struct nfsdfs_client *nc goto out; }
+#if IS_ENABLED(CONFIG_SUNRPC_GSS) +static int __nfsd_symlink(struct inode *dir, struct dentry *dentry, + umode_t mode, const char *content) +{ + struct inode *inode; + + inode = nfsd_get_inode(dir->i_sb, mode); + if (!inode) + return -ENOMEM; + + inode->i_link = (char *)content; + inode->i_size = strlen(content); + + d_add(dentry, inode); + inc_nlink(dir); + fsnotify_create(dir, dentry); + return 0; +} + +/* + * @content is assumed to be a NUL-terminated string that lives + * longer than the symlink itself. + */ +static void nfsd_symlink(struct dentry *parent, const char *name, + const char *content) +{ + struct inode *dir = parent->d_inode; + struct dentry *dentry; + int ret = -ENOMEM; + + inode_lock(dir); + dentry = d_alloc_name(parent, name); + if (!dentry) + goto out_err; + ret = __nfsd_symlink(d_inode(parent), dentry, S_IFLNK | 0777, content); + if (ret) + goto out_err; +out: + inode_unlock(dir); + return; +out_err: + dput(dentry); + dentry = ERR_PTR(ret); + goto out; +} +#else +static inline void nfsd_symlink(struct dentry *parent, const char *name, + const char *content) +{ +} + +#endif + static void clear_ncl(struct inode *inode) { struct nfsdfs_client *ncl = inode->i_private; @@ -1355,10 +1399,6 @@ static int nfsd_fill_super(struct super_block *sb, struct fs_context *fc) [NFSD_MaxBlkSize] = {"max_block_size", &transaction_ops, S_IWUSR|S_IRUGO}, [NFSD_MaxConnections] = {"max_connections", &transaction_ops, S_IWUSR|S_IRUGO}, [NFSD_Filecache] = {"filecache", &nfsd_file_cache_stats_fops, S_IRUGO}, -#if defined(CONFIG_SUNRPC_GSS) || defined(CONFIG_SUNRPC_GSS_MODULE) - [NFSD_SupportedEnctypes] = {"supported_krb5_enctypes", - &supported_enctypes_fops, S_IRUGO}, -#endif /* CONFIG_SUNRPC_GSS or CONFIG_SUNRPC_GSS_MODULE */ #ifdef CONFIG_NFSD_V4 [NFSD_Leasetime] = {"nfsv4leasetime", &transaction_ops, S_IWUSR|S_IRUSR}, [NFSD_Gracetime] = {"nfsv4gracetime", &transaction_ops, S_IWUSR|S_IRUSR}, @@ -1371,6 +1411,8 @@ static int nfsd_fill_super(struct super_block *sb, struct fs_context *fc) ret = simple_fill_super(sb, 0x6e667364, nfsd_files); if (ret) return ret; + nfsd_symlink(sb->s_root, "supported_krb5_enctypes", + "/proc/net/rpc/gss_krb5_enctypes"); dentry = nfsd_mkdir(sb->s_root, NULL, "clients"); if (IS_ERR(dentry)) return PTR_ERR(dentry);
From: Chuck Lever chuck.lever@oracle.com
Now that all consumers of the KRB5_SUPPORTED_ENCTYPES macro are within the SunRPC layer, the macro can be replaced with something private and more flexible.
Tested-by: Scott Mayhew smayhew@redhat.com Signed-off-by: Chuck Lever chuck.lever@oracle.com --- include/linux/sunrpc/gss_krb5_enctypes.h | 41 ------------------------------ net/sunrpc/auth_gss/gss_krb5_mech.c | 41 +++++++++++++++++++++++++++++- 2 files changed, 39 insertions(+), 43 deletions(-) delete mode 100644 include/linux/sunrpc/gss_krb5_enctypes.h
diff --git a/include/linux/sunrpc/gss_krb5_enctypes.h b/include/linux/sunrpc/gss_krb5_enctypes.h deleted file mode 100644 index 87eea679d750..000000000000 --- a/include/linux/sunrpc/gss_krb5_enctypes.h +++ /dev/null @@ -1,41 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0 */ -/* - * Define the string that exports the set of kernel-supported - * Kerberos enctypes. This list is sent via upcall to gssd, and - * is also exposed via the nfsd /proc API. The consumers generally - * treat this as an ordered list, where the first item in the list - * is the most preferred. - */ - -#ifndef _LINUX_SUNRPC_GSS_KRB5_ENCTYPES_H -#define _LINUX_SUNRPC_GSS_KRB5_ENCTYPES_H - -#ifdef CONFIG_SUNRPC_DISABLE_INSECURE_ENCTYPES - -/* - * NB: This list includes DES3_CBC_SHA1, which was deprecated by RFC 8429. - * - * ENCTYPE_AES256_CTS_HMAC_SHA1_96 - * ENCTYPE_AES128_CTS_HMAC_SHA1_96 - * ENCTYPE_DES3_CBC_SHA1 - */ -#define KRB5_SUPPORTED_ENCTYPES "18,17,16" - -#else /* CONFIG_SUNRPC_DISABLE_INSECURE_ENCTYPES */ - -/* - * NB: This list includes encryption types that were deprecated - * by RFC 8429 and RFC 6649. - * - * ENCTYPE_AES256_CTS_HMAC_SHA1_96 - * ENCTYPE_AES128_CTS_HMAC_SHA1_96 - * ENCTYPE_DES3_CBC_SHA1 - * ENCTYPE_DES_CBC_MD5 - * ENCTYPE_DES_CBC_CRC - * ENCTYPE_DES_CBC_MD4 - */ -#define KRB5_SUPPORTED_ENCTYPES "18,17,16,3,1,2" - -#endif /* CONFIG_SUNRPC_DISABLE_INSECURE_ENCTYPES */ - -#endif /* _LINUX_SUNRPC_GSS_KRB5_ENCTYPES_H */ diff --git a/net/sunrpc/auth_gss/gss_krb5_mech.c b/net/sunrpc/auth_gss/gss_krb5_mech.c index e33575216a01..2553d18fd288 100644 --- a/net/sunrpc/auth_gss/gss_krb5_mech.c +++ b/net/sunrpc/auth_gss/gss_krb5_mech.c @@ -19,7 +19,6 @@ #include <linux/sunrpc/auth.h> #include <linux/sunrpc/gss_krb5.h> #include <linux/sunrpc/xdr.h> -#include <linux/sunrpc/gss_krb5_enctypes.h>
#include "auth_gss_internal.h" #include "gss_krb5_internal.h" @@ -145,6 +144,43 @@ static const struct gss_krb5_enctype supported_gss_krb5_enctypes[] = { }, };
+/* + * The list of advertised enctypes is specified in order of most + * preferred to least. + */ +static char gss_krb5_enctype_priority_list[64]; + +static void gss_krb5_prepare_enctype_priority_list(void) +{ + static const u32 gss_krb5_enctypes[] = { + ENCTYPE_AES256_CTS_HMAC_SHA1_96, + ENCTYPE_AES128_CTS_HMAC_SHA1_96, + ENCTYPE_DES3_CBC_SHA1, +#ifndef CONFIG_SUNRPC_DISABLE_INSECURE_ENCTYPES + ENCTYPE_DES_CBC_MD5, + ENCTYPE_DES_CBC_CRC, + ENCTYPE_DES_CBC_MD4, +#endif + }; + size_t total, i; + char buf[16]; + char *sep; + int n; + + sep = ""; + gss_krb5_enctype_priority_list[0] = '\0'; + for (total = 0, i = 0; i < ARRAY_SIZE(gss_krb5_enctypes); i++) { + n = sprintf(buf, "%s%u", sep, gss_krb5_enctypes[i]); + if (n < 0) + break; + if (total + n >= sizeof(gss_krb5_enctype_priority_list)) + break; + strcat(gss_krb5_enctype_priority_list, buf); + sep = ","; + total += n; + } +} + static const int num_supported_enctypes = ARRAY_SIZE(supported_gss_krb5_enctypes);
@@ -761,13 +797,14 @@ static struct gss_api_mech gss_kerberos_mech = { .gm_ops = &gss_kerberos_ops, .gm_pf_num = ARRAY_SIZE(gss_kerberos_pfs), .gm_pfs = gss_kerberos_pfs, - .gm_upcall_enctypes = KRB5_SUPPORTED_ENCTYPES, + .gm_upcall_enctypes = gss_krb5_enctype_priority_list, };
static int __init init_kerberos_module(void) { int status;
+ gss_krb5_prepare_enctype_priority_list(); status = gss_mech_register(&gss_kerberos_mech); if (status) printk("Failed to register kerberos gss mechanism!\n");
From: Chuck Lever chuck.lever@oracle.com
Because the DES block cipher has been deprecated by Internet standard, highly secure configurations might require that DES support be blacklisted or not installed. NFS Kerberos should still be able to work correctly with only the AES-based enctypes in that situation.
Also note that MIT Kerberos has begun a deprecation process for DES encryption types. Their README for 1.19.3 states:
Beginning with the krb5-1.19 release, a warning will be issued if initial credentials are acquired using the des3-cbc-sha1 encryption type. In future releases, this encryption type will be disabled by default and eventually removed.
Beginning with the krb5-1.18 release, single-DES encryption types have been removed.
Aside from the CONFIG option name change, there are two important policy changes:
1. The 'insecure enctype' group is now disabled by default. Distributors have to take action to enable support for deprecated enctypes. Implementation of these enctypes will be removed in a future kernel release.
2. des3-cbc-sha1 is now considered part of the 'insecure enctype' group, having been deprecated by RFC 8429, and is thus disabled by default
After this patch is applied, SunRPC support can be built with Kerberos 5 support but without CRYPTO_DES enabled in the kernel. And, when these enctypes are disabled, the Linux kernel's SunRPC RPCSEC GSS implementation fully complies with BCP 179 / RFC 6649 and BCP 218 / RFC 8429.
Tested-by: Scott Mayhew smayhew@redhat.com Signed-off-by: Chuck Lever chuck.lever@oracle.com --- net/sunrpc/Kconfig | 54 +++++++++++++++++++++-------- net/sunrpc/auth_gss/gss_krb5_mech.c | 27 +++++++++++--- net/sunrpc/auth_gss/gss_krb5_seal.c | 62 ++++++++++++++++++--------------- net/sunrpc/auth_gss/gss_krb5_unseal.c | 3 +- net/sunrpc/auth_gss/gss_krb5_wrap.c | 4 ++ 5 files changed, 101 insertions(+), 49 deletions(-)
diff --git a/net/sunrpc/Kconfig b/net/sunrpc/Kconfig index bbbb5af0af13..1135ff362132 100644 --- a/net/sunrpc/Kconfig +++ b/net/sunrpc/Kconfig @@ -19,10 +19,10 @@ config SUNRPC_SWAP config RPCSEC_GSS_KRB5 tristate "Secure RPC: Kerberos V mechanism" depends on SUNRPC && CRYPTO - depends on CRYPTO_MD5 && CRYPTO_DES && CRYPTO_CBC && CRYPTO_CTS - depends on CRYPTO_ECB && CRYPTO_HMAC && CRYPTO_SHA1 && CRYPTO_AES default y select SUNRPC_GSS + select CRYPTO_SKCIPHER + select CRYPTO_HASH help Choose Y here to enable Secure RPC using the Kerberos version 5 GSS-API mechanism (RFC 1964). @@ -34,21 +34,47 @@ config RPCSEC_GSS_KRB5
If unsure, say Y.
-config SUNRPC_DISABLE_INSECURE_ENCTYPES - bool "Secure RPC: Disable insecure Kerberos encryption types" +config RPCSEC_GSS_KRB5_SIMPLIFIED + bool + depends on RPCSEC_GSS_KRB5 + +config RPCSEC_GSS_KRB5_CRYPTOSYSTEM + bool + depends on RPCSEC_GSS_KRB5 + +config RPCSEC_GSS_KRB5_ENCTYPES_DES + bool "Enable Kerberos enctypes based on DES (deprecated)" depends on RPCSEC_GSS_KRB5 + depends on CRYPTO_CBC && CRYPTO_CTS && CRYPTO_ECB + depends on CRYPTO_HMAC && CRYPTO_MD5 && CRYPTO_SHA1 + depends on CRYPTO_DES default n + select RPCSEC_GSS_KRB5_SIMPLIFIED + help + Choose Y to enable the use of deprecated Kerberos 5 + encryption types that utilize Data Encryption Standard + (DES) based ciphers. These include des-cbc-md5, + des-cbc-crc, and des-cbc-md4, which were deprecated by + RFC 6649, and des3-cbc-sha1, which was deprecated by RFC + 8429. + + Support for these encryption types is available for + compatibility with legacy NFS client and server + implementations. The default is N which is more secure. + +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 + select RPCSEC_GSS_KRB5_CRYPTOSYSTEM help - Choose Y here to disable the use of deprecated encryption types - with the Kerberos version 5 GSS-API mechanism (RFC 1964). The - deprecated encryption types include DES-CBC-MD5, DES-CBC-CRC, - and DES-CBC-MD4. These types were deprecated by RFC 6649 because - they were found to be insecure. - - N is the default because many sites have deployed KDCs and - keytabs that contain only these deprecated encryption types. - Choosing Y prevents the use of known-insecure encryption types - but might result in compatibility problems. + 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 SUNRPC_DEBUG bool "RPC: Enable dprintk debugging" diff --git a/net/sunrpc/auth_gss/gss_krb5_mech.c b/net/sunrpc/auth_gss/gss_krb5_mech.c index 2553d18fd288..9ddc6fc7077f 100644 --- a/net/sunrpc/auth_gss/gss_krb5_mech.c +++ b/net/sunrpc/auth_gss/gss_krb5_mech.c @@ -29,12 +29,16 @@
static struct gss_api_mech gss_kerberos_mech;
+#if defined(CONFIG_RPCSEC_GSS_KRB5_SIMPLIFIED) static int gss_krb5_import_ctx_des(struct krb5_ctx *ctx, gfp_t gfp_mask); static int gss_krb5_import_ctx_v1(struct krb5_ctx *ctx, gfp_t gfp_mask); +#endif +#if defined(CONFIG_RPCSEC_GSS_KRB5_CRYPTOSYSTEM) static int gss_krb5_import_ctx_v2(struct krb5_ctx *ctx, gfp_t gfp_mask); +#endif
static const struct gss_krb5_enctype supported_gss_krb5_enctypes[] = { -#ifndef CONFIG_SUNRPC_DISABLE_INSECURE_ENCTYPES +#if defined(CONFIG_RPCSEC_GSS_KRB5_ENCTYPES_DES) /* * DES (All DES enctypes are mapped to the same gss functionality) */ @@ -59,7 +63,6 @@ static const struct gss_krb5_enctype supported_gss_krb5_enctypes[] = { .cksumlength = 8, .keyed_cksum = 0, }, -#endif /* CONFIG_SUNRPC_DISABLE_INSECURE_ENCTYPES */ /* * 3DES */ @@ -84,8 +87,11 @@ static const struct gss_krb5_enctype supported_gss_krb5_enctypes[] = { .cksumlength = 20, .keyed_cksum = 1, }, +#endif + +#if defined(CONFIG_RPCSEC_GSS_KRB5_ENCTYPES_AES_SHA1) /* - * AES128 + * AES-128 with SHA-1 (RFC 3962) */ { .etype = ENCTYPE_AES128_CTS_HMAC_SHA1_96, @@ -114,7 +120,7 @@ static const struct gss_krb5_enctype supported_gss_krb5_enctypes[] = { .keyed_cksum = 1, }, /* - * AES256 + * AES-256 with SHA-1 (RFC 3962) */ { .etype = ENCTYPE_AES256_CTS_HMAC_SHA1_96, @@ -142,6 +148,7 @@ static const struct gss_krb5_enctype supported_gss_krb5_enctypes[] = { .cksumlength = 12, .keyed_cksum = 1, }, +#endif };
/* @@ -153,10 +160,12 @@ 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_SHA1) ENCTYPE_AES256_CTS_HMAC_SHA1_96, ENCTYPE_AES128_CTS_HMAC_SHA1_96, +#endif +#if defined(CONFIG_RPCSEC_GSS_KRB5_ENCTYPES_DES) ENCTYPE_DES3_CBC_SHA1, -#ifndef CONFIG_SUNRPC_DISABLE_INSECURE_ENCTYPES ENCTYPE_DES_CBC_MD5, ENCTYPE_DES_CBC_CRC, ENCTYPE_DES_CBC_MD4, @@ -337,7 +346,7 @@ gss_import_v1_context(const void *p, const void *end, struct krb5_ctx *ctx) return PTR_ERR(p); }
-static struct crypto_sync_skcipher * +static inline struct crypto_sync_skcipher * context_v2_alloc_cipher(struct krb5_ctx *ctx, const char *cname, u8 *key) { struct crypto_sync_skcipher *cp; @@ -367,6 +376,7 @@ set_cdata(u8 cdata[GSS_KRB5_K5CLENGTH], u32 usage, u8 seed) cdata[4] = seed; }
+#if defined(CONFIG_RPCSEC_GSS_KRB5_SIMPLIFIED) static int gss_krb5_import_ctx_des(struct krb5_ctx *ctx, gfp_t gfp_mask) { @@ -417,6 +427,9 @@ gss_krb5_import_ctx_v1(struct krb5_ctx *ctx, gfp_t gfp_mask) out_err: return -EINVAL; } +#endif + +#if defined(CONFIG_RPCSEC_GSS_KRB5_CRYPTOSYSTEM)
static struct crypto_ahash * gss_krb5_alloc_hash_v2(struct krb5_ctx *kctx, const struct xdr_netobj *key) @@ -551,6 +564,8 @@ gss_krb5_import_ctx_v2(struct krb5_ctx *ctx, gfp_t gfp_mask) goto out; }
+#endif + static int gss_import_v2_context(const void *p, const void *end, struct krb5_ctx *ctx, gfp_t gfp_mask) diff --git a/net/sunrpc/auth_gss/gss_krb5_seal.c b/net/sunrpc/auth_gss/gss_krb5_seal.c index f74125407588..146aa755f07d 100644 --- a/net/sunrpc/auth_gss/gss_krb5_seal.c +++ b/net/sunrpc/auth_gss/gss_krb5_seal.c @@ -71,6 +71,8 @@ # define RPCDBG_FACILITY RPCDBG_AUTH #endif
+#if defined(CONFIG_RPCSEC_GSS_KRB5_SIMPLIFIED) + static void * setup_token(struct krb5_ctx *ctx, struct xdr_netobj *token) { @@ -97,34 +99,6 @@ setup_token(struct krb5_ctx *ctx, struct xdr_netobj *token) return krb5_hdr; }
-static void * -setup_token_v2(struct krb5_ctx *ctx, struct xdr_netobj *token) -{ - u16 *ptr; - void *krb5_hdr; - u8 *p, flags = 0x00; - - if ((ctx->flags & KRB5_CTX_FLAG_INITIATOR) == 0) - flags |= 0x01; - if (ctx->flags & KRB5_CTX_FLAG_ACCEPTOR_SUBKEY) - flags |= 0x04; - - /* Per rfc 4121, sec 4.2.6.1, there is no header, - * just start the token */ - krb5_hdr = ptr = (u16 *)token->data; - - *ptr++ = KG2_TOK_MIC; - p = (u8 *)ptr; - *p++ = flags; - *p++ = 0xff; - ptr = (u16 *)p; - *ptr++ = 0xffff; - *ptr = 0xffff; - - token->len = GSS_KRB5_TOK_HDR_LEN + ctx->gk5e->cksumlength; - return krb5_hdr; -} - u32 gss_krb5_get_mic_v1(struct krb5_ctx *ctx, struct xdr_buf *text, struct xdr_netobj *token) @@ -164,6 +138,38 @@ gss_krb5_get_mic_v1(struct krb5_ctx *ctx, struct xdr_buf *text, return (ctx->endtime < now) ? GSS_S_CONTEXT_EXPIRED : GSS_S_COMPLETE; }
+#endif + +static void * +setup_token_v2(struct krb5_ctx *ctx, struct xdr_netobj *token) +{ + u16 *ptr; + void *krb5_hdr; + u8 *p, flags = 0x00; + + if ((ctx->flags & KRB5_CTX_FLAG_INITIATOR) == 0) + flags |= 0x01; + if (ctx->flags & KRB5_CTX_FLAG_ACCEPTOR_SUBKEY) + flags |= 0x04; + + /* Per rfc 4121, sec 4.2.6.1, there is no header, + * just start the token. + */ + krb5_hdr = (u16 *)token->data; + ptr = krb5_hdr; + + *ptr++ = KG2_TOK_MIC; + p = (u8 *)ptr; + *p++ = flags; + *p++ = 0xff; + ptr = (u16 *)p; + *ptr++ = 0xffff; + *ptr = 0xffff; + + token->len = GSS_KRB5_TOK_HDR_LEN + ctx->gk5e->cksumlength; + return krb5_hdr; +} + u32 gss_krb5_get_mic_v2(struct krb5_ctx *ctx, struct xdr_buf *text, struct xdr_netobj *token) diff --git a/net/sunrpc/auth_gss/gss_krb5_unseal.c b/net/sunrpc/auth_gss/gss_krb5_unseal.c index 939d199eb7b7..7d6d4ae4a3c9 100644 --- a/net/sunrpc/auth_gss/gss_krb5_unseal.c +++ b/net/sunrpc/auth_gss/gss_krb5_unseal.c @@ -70,9 +70,9 @@ #endif
+#if defined(CONFIG_RPCSEC_GSS_KRB5_SIMPLIFIED) /* read_token is a mic token, and message_buffer is the data that the mic was * supposedly taken over. */ - u32 gss_krb5_verify_mic_v1(struct krb5_ctx *ctx, struct xdr_buf *message_buffer, struct xdr_netobj *read_token) @@ -144,6 +144,7 @@ gss_krb5_verify_mic_v1(struct krb5_ctx *ctx, struct xdr_buf *message_buffer,
return GSS_S_COMPLETE; } +#endif
u32 gss_krb5_verify_mic_v2(struct krb5_ctx *ctx, struct xdr_buf *message_buffer, diff --git a/net/sunrpc/auth_gss/gss_krb5_wrap.c b/net/sunrpc/auth_gss/gss_krb5_wrap.c index d983da6f9530..7dabf379406b 100644 --- a/net/sunrpc/auth_gss/gss_krb5_wrap.c +++ b/net/sunrpc/auth_gss/gss_krb5_wrap.c @@ -40,6 +40,8 @@ # define RPCDBG_FACILITY RPCDBG_AUTH #endif
+#if defined(CONFIG_RPCSEC_GSS_KRB5_SIMPLIFIED) + static inline int gss_krb5_padding(int blocksize, int length) { @@ -323,6 +325,8 @@ gss_krb5_unwrap_v1(struct krb5_ctx *kctx, int offset, int len, return GSS_S_COMPLETE; }
+#endif + /* * We can shift data by up to LOCAL_BUF_LEN bytes in a pass. If we need * to do more than that, we shift repeatedly. Kevin Coffman reports
Hi Chuck,
On Sun, 15 Jan 2023, Chuck Lever wrote:
From: Chuck Lever chuck.lever@oracle.com
Because the DES block cipher has been deprecated by Internet standard, highly secure configurations might require that DES support be blacklisted or not installed. NFS Kerberos should still be able to work correctly with only the AES-based enctypes in that situation.
Also note that MIT Kerberos has begun a deprecation process for DES encryption types. Their README for 1.19.3 states:
Beginning with the krb5-1.19 release, a warning will be issued if initial credentials are acquired using the des3-cbc-sha1 encryption type. In future releases, this encryption type will be disabled by default and eventually removed.
Beginning with the krb5-1.18 release, single-DES encryption types have been removed.
Aside from the CONFIG option name change, there are two important policy changes:
- The 'insecure enctype' group is now disabled by default.
Distributors have to take action to enable support for deprecated enctypes. Implementation of these enctypes will be removed in a future kernel release.
- des3-cbc-sha1 is now considered part of the 'insecure enctype'
group, having been deprecated by RFC 8429, and is thus disabled by default
After this patch is applied, SunRPC support can be built with Kerberos 5 support but without CRYPTO_DES enabled in the kernel. And, when these enctypes are disabled, the Linux kernel's SunRPC RPCSEC GSS implementation fully complies with BCP 179 / RFC 6649 and BCP 218 / RFC 8429.
Tested-by: Scott Mayhew smayhew@redhat.com Signed-off-by: Chuck Lever chuck.lever@oracle.com
Thanks for your patch, which is now commit dfe9a123451a6e73 ("SUNRPC: Enable rpcsec_gss_krb5.ko to be built without CRYPTO_DES") in v6.3-rc1.
--- a/net/sunrpc/Kconfig +++ b/net/sunrpc/Kconfig @@ -19,10 +19,10 @@ config SUNRPC_SWAP config RPCSEC_GSS_KRB5 tristate "Secure RPC: Kerberos V mechanism" depends on SUNRPC && CRYPTO
- depends on CRYPTO_MD5 && CRYPTO_DES && CRYPTO_CBC && CRYPTO_CTS
- depends on CRYPTO_ECB && CRYPTO_HMAC && CRYPTO_SHA1 && CRYPTO_AES default y select SUNRPC_GSS
- select CRYPTO_SKCIPHER
- select CRYPTO_HASH help Choose Y here to enable Secure RPC using the Kerberos version 5 GSS-API mechanism (RFC 1964).
While updating my defconfigs for v6.3-rc1, I noticed this change has an interesting side-effect: if any of the CRYPTO_* algorithms were modular before, RPCSEC_GSS_KRB5 was modular, too. After this change, RPCSEC_GSS_KRB5 is promoted to builtin.
This is not necessarily bad in-se, but you might want to be aware of it, and perhaps change the "default y".
Gr{oetje,eeting}s,
Geert
-- Geert Uytterhoeven -- There's lots of Linux beyond ia32 -- geert@linux-m68k.org
In personal conversations with technical people, I call myself a hacker. But when I'm talking to journalists I just say "programmer" or something like that. -- Linus Torvalds
On Mar 6, 2023, at 3:16 AM, Geert Uytterhoeven geert@linux-m68k.org wrote:
Hi Chuck,
On Sun, 15 Jan 2023, Chuck Lever wrote:
From: Chuck Lever chuck.lever@oracle.com
Because the DES block cipher has been deprecated by Internet standard, highly secure configurations might require that DES support be blacklisted or not installed. NFS Kerberos should still be able to work correctly with only the AES-based enctypes in that situation.
Also note that MIT Kerberos has begun a deprecation process for DES encryption types. Their README for 1.19.3 states:
Beginning with the krb5-1.19 release, a warning will be issued if initial credentials are acquired using the des3-cbc-sha1 encryption type. In future releases, this encryption type will be disabled by default and eventually removed.
Beginning with the krb5-1.18 release, single-DES encryption types have been removed.
Aside from the CONFIG option name change, there are two important policy changes:
- The 'insecure enctype' group is now disabled by default.
Distributors have to take action to enable support for deprecated enctypes. Implementation of these enctypes will be removed in a future kernel release.
- des3-cbc-sha1 is now considered part of the 'insecure enctype'
group, having been deprecated by RFC 8429, and is thus disabled by default
After this patch is applied, SunRPC support can be built with Kerberos 5 support but without CRYPTO_DES enabled in the kernel. And, when these enctypes are disabled, the Linux kernel's SunRPC RPCSEC GSS implementation fully complies with BCP 179 / RFC 6649 and BCP 218 / RFC 8429.
Tested-by: Scott Mayhew smayhew@redhat.com Signed-off-by: Chuck Lever chuck.lever@oracle.com
Thanks for your patch, which is now commit dfe9a123451a6e73 ("SUNRPC: Enable rpcsec_gss_krb5.ko to be built without CRYPTO_DES") in v6.3-rc1.
--- a/net/sunrpc/Kconfig +++ b/net/sunrpc/Kconfig @@ -19,10 +19,10 @@ config SUNRPC_SWAP config RPCSEC_GSS_KRB5 tristate "Secure RPC: Kerberos V mechanism" depends on SUNRPC && CRYPTO
- depends on CRYPTO_MD5 && CRYPTO_DES && CRYPTO_CBC && CRYPTO_CTS
- depends on CRYPTO_ECB && CRYPTO_HMAC && CRYPTO_SHA1 && CRYPTO_AES default y select SUNRPC_GSS
- select CRYPTO_SKCIPHER
- select CRYPTO_HASH help Choose Y here to enable Secure RPC using the Kerberos version 5 GSS-API mechanism (RFC 1964).
While updating my defconfigs for v6.3-rc1, I noticed this change has an interesting side-effect: if any of the CRYPTO_* algorithms were modular before, RPCSEC_GSS_KRB5 was modular, too. After this change, RPCSEC_GSS_KRB5 is promoted to builtin.
I'm not following. Which CRYPTO_ options trigger the behavior? On my test system, CONFIG_RPCSEC_GSS_KRB5=m and the CRYPTO stuff is all =y.
This is not necessarily bad in-se, but you might want to be aware of it, and perhaps change the "default y".
Well that might be there to address the need for GSS to be enabled if NFSv4 support is built. See commit df486a25900f ("NFS: Fix the selection of security flavours in Kconfig")
I'm not claiming I understand exactly how that fix works.
-- Chuck Lever
Hi Chuck,
On Mon, Mar 6, 2023 at 5:17 PM Chuck Lever III chuck.lever@oracle.com wrote:
On Mar 6, 2023, at 3:16 AM, Geert Uytterhoeven geert@linux-m68k.org wrote: On Sun, 15 Jan 2023, Chuck Lever wrote:
From: Chuck Lever chuck.lever@oracle.com
Because the DES block cipher has been deprecated by Internet standard, highly secure configurations might require that DES support be blacklisted or not installed. NFS Kerberos should still be able to work correctly with only the AES-based enctypes in that situation.
Also note that MIT Kerberos has begun a deprecation process for DES encryption types. Their README for 1.19.3 states:
Beginning with the krb5-1.19 release, a warning will be issued if initial credentials are acquired using the des3-cbc-sha1 encryption type. In future releases, this encryption type will be disabled by default and eventually removed.
Beginning with the krb5-1.18 release, single-DES encryption types have been removed.
Aside from the CONFIG option name change, there are two important policy changes:
- The 'insecure enctype' group is now disabled by default.
Distributors have to take action to enable support for deprecated enctypes. Implementation of these enctypes will be removed in a future kernel release.
- des3-cbc-sha1 is now considered part of the 'insecure enctype'
group, having been deprecated by RFC 8429, and is thus disabled by default
After this patch is applied, SunRPC support can be built with Kerberos 5 support but without CRYPTO_DES enabled in the kernel. And, when these enctypes are disabled, the Linux kernel's SunRPC RPCSEC GSS implementation fully complies with BCP 179 / RFC 6649 and BCP 218 / RFC 8429.
Tested-by: Scott Mayhew smayhew@redhat.com Signed-off-by: Chuck Lever chuck.lever@oracle.com
Thanks for your patch, which is now commit dfe9a123451a6e73 ("SUNRPC: Enable rpcsec_gss_krb5.ko to be built without CRYPTO_DES") in v6.3-rc1.
--- a/net/sunrpc/Kconfig +++ b/net/sunrpc/Kconfig @@ -19,10 +19,10 @@ config SUNRPC_SWAP config RPCSEC_GSS_KRB5 tristate "Secure RPC: Kerberos V mechanism" depends on SUNRPC && CRYPTO
- depends on CRYPTO_MD5 && CRYPTO_DES && CRYPTO_CBC && CRYPTO_CTS
- depends on CRYPTO_ECB && CRYPTO_HMAC && CRYPTO_SHA1 && CRYPTO_AES default y select SUNRPC_GSS
- select CRYPTO_SKCIPHER
- select CRYPTO_HASH help Choose Y here to enable Secure RPC using the Kerberos version 5 GSS-API mechanism (RFC 1964).
While updating my defconfigs for v6.3-rc1, I noticed this change has an interesting side-effect: if any of the CRYPTO_* algorithms were modular before, RPCSEC_GSS_KRB5 was modular, too. After this change, RPCSEC_GSS_KRB5 is promoted to builtin.
I'm not following. Which CRYPTO_ options trigger the behavior? On my test system, CONFIG_RPCSEC_GSS_KRB5=m and the CRYPTO stuff is all =y.
On v6.2, "make ARCH=m68k defconfig" gives you CONFIG_RPCSEC_GSS_KRB5=m On v6.3, it became builtin, due to dropping the dependencies on the individual crypto modules.
$ grep -E "CRYPTO_(MD5|DES|CBC|CTS|ECB|HMAC|SHA1|AES)" .config CONFIG_CRYPTO_AES=y CONFIG_CRYPTO_AES_TI=m CONFIG_CRYPTO_DES=m CONFIG_CRYPTO_CBC=m CONFIG_CRYPTO_CTS=m CONFIG_CRYPTO_ECB=m CONFIG_CRYPTO_HMAC=m CONFIG_CRYPTO_MD5=m CONFIG_CRYPTO_SHA1=m
This is not necessarily bad in-se, but you might want to be aware of it, and perhaps change the "default y".
Well that might be there to address the need for GSS to be enabled if NFSv4 support is built. See commit df486a25900f ("NFS: Fix the selection of security flavours in Kconfig")
I'm not claiming I understand exactly how that fix works.
And that was changed again a little bit later in commit e3b2854faabd1043 ("SUNRPC: Fix the SUNRPC Kerberos V RPCSEC_GSS module dependencies").
Gr{oetje,eeting}s,
Geert
From: Chuck Lever chuck.lever@oracle.com
Clean up: ->encrypt is set to only one value. Replace the two remaining call sites with direct calls to krb5_encrypt().
There have never been any call sites for the ->decrypt() method.
Tested-by: Scott Mayhew smayhew@redhat.com Signed-off-by: Chuck Lever chuck.lever@oracle.com --- include/linux/sunrpc/gss_krb5.h | 14 ------------ net/sunrpc/auth_gss/gss_krb5_crypto.c | 36 +++++++++++++++++++++++++++++-- net/sunrpc/auth_gss/gss_krb5_internal.h | 6 +++++ net/sunrpc/auth_gss/gss_krb5_keys.c | 6 +++-- net/sunrpc/auth_gss/gss_krb5_mech.c | 8 ------- net/sunrpc/auth_gss/gss_krb5_seqnum.c | 2 ++ 6 files changed, 46 insertions(+), 26 deletions(-)
diff --git a/include/linux/sunrpc/gss_krb5.h b/include/linux/sunrpc/gss_krb5.h index 68ae0c3d4cf7..a0646df12beb 100644 --- a/include/linux/sunrpc/gss_krb5.h +++ b/include/linux/sunrpc/gss_krb5.h @@ -69,12 +69,6 @@ struct gss_krb5_enctype { const u32 keyed_cksum; /* is it a keyed cksum? */ const u32 keybytes; /* raw key len, in bytes */ const u32 keylength; /* final key len, in bytes */ - u32 (*encrypt) (struct crypto_sync_skcipher *tfm, - void *iv, void *in, void *out, - int length); /* encryption function */ - u32 (*decrypt) (struct crypto_sync_skcipher *tfm, - void *iv, void *in, void *out, - int length); /* decryption function */ int (*import_ctx)(struct krb5_ctx *ctx, gfp_t gfp_mask); u32 (*mk_key) (const struct gss_krb5_enctype *gk5e, struct xdr_netobj *in, @@ -243,14 +237,6 @@ make_checksum(struct krb5_ctx *kctx, char *header, int hdrlen, struct xdr_buf *body, int body_offset, u8 *cksumkey, unsigned int usage, struct xdr_netobj *cksumout);
-u32 -krb5_encrypt(struct crypto_sync_skcipher *key, - void *iv, void *in, void *out, int length); - -u32 -krb5_decrypt(struct crypto_sync_skcipher *key, - void *iv, void *in, void *out, int length); - int gss_encrypt_xdr_buf(struct crypto_sync_skcipher *tfm, struct xdr_buf *outbuf, int offset, struct page **pages); diff --git a/net/sunrpc/auth_gss/gss_krb5_crypto.c b/net/sunrpc/auth_gss/gss_krb5_crypto.c index 098faaf02fe6..c5845fdda527 100644 --- a/net/sunrpc/auth_gss/gss_krb5_crypto.c +++ b/net/sunrpc/auth_gss/gss_krb5_crypto.c @@ -82,6 +82,22 @@ 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, @@ -121,6 +137,22 @@ krb5_encrypt( return ret; }
+/** + * krb5_decrypt - simple decryption of an RPCSEC GSS payload + * @tfm: initialized cipher transform + * @iv: pointer to an IV + * @in: ciphertext to decrypt + * @out: OUT: plaintext + * @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 decrypted into @out + * negative errno: @in not decrypted + */ u32 krb5_decrypt( struct crypto_sync_skcipher *tfm, @@ -234,8 +266,8 @@ make_checksum(struct krb5_ctx *kctx, char *header, int hdrlen,
switch (kctx->gk5e->ctype) { case CKSUMTYPE_RSA_MD5: - err = kctx->gk5e->encrypt(kctx->seq, NULL, checksumdata, - checksumdata, checksumlen); + err = krb5_encrypt(kctx->seq, NULL, checksumdata, + checksumdata, checksumlen); if (err) goto out; memcpy(cksumout->data, diff --git a/net/sunrpc/auth_gss/gss_krb5_internal.h b/net/sunrpc/auth_gss/gss_krb5_internal.h index 04d2781e2ce2..a4b752af6951 100644 --- a/net/sunrpc/auth_gss/gss_krb5_internal.h +++ b/net/sunrpc/auth_gss/gss_krb5_internal.h @@ -44,4 +44,10 @@ 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); + +u32 krb5_decrypt(struct crypto_sync_skcipher *key, void *iv, void *in, + void *out, int length); + #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 index 554cfd23f288..a7c6866dad96 100644 --- a/net/sunrpc/auth_gss/gss_krb5_keys.c +++ b/net/sunrpc/auth_gss/gss_krb5_keys.c @@ -61,6 +61,8 @@ #include <linux/sunrpc/xdr.h> #include <linux/lcm.h>
+#include "gss_krb5_internal.h" + #if IS_ENABLED(CONFIG_SUNRPC_DEBUG) # define RPCDBG_FACILITY RPCDBG_AUTH #endif @@ -195,8 +197,8 @@ u32 krb5_derive_key(const struct gss_krb5_enctype *gk5e,
n = 0; while (n < keybytes) { - (*(gk5e->encrypt))(cipher, NULL, inblock.data, - outblock.data, inblock.len); + krb5_encrypt(cipher, NULL, inblock.data, outblock.data, + inblock.len);
if ((keybytes - n) <= outblock.len) { memcpy(rawkey + n, outblock.data, (keybytes - n)); diff --git a/net/sunrpc/auth_gss/gss_krb5_mech.c b/net/sunrpc/auth_gss/gss_krb5_mech.c index 9ddc6fc7077f..47c065aa4a14 100644 --- a/net/sunrpc/auth_gss/gss_krb5_mech.c +++ b/net/sunrpc/auth_gss/gss_krb5_mech.c @@ -48,8 +48,6 @@ static const struct gss_krb5_enctype supported_gss_krb5_enctypes[] = { .name = "des-cbc-crc", .encrypt_name = "cbc(des)", .cksum_name = "md5", - .encrypt = krb5_encrypt, - .decrypt = krb5_decrypt, .import_ctx = gss_krb5_import_ctx_des, .mk_key = NULL, .get_mic = gss_krb5_get_mic_v1, @@ -72,8 +70,6 @@ static const struct gss_krb5_enctype supported_gss_krb5_enctypes[] = { .name = "des3-hmac-sha1", .encrypt_name = "cbc(des3_ede)", .cksum_name = "hmac(sha1)", - .encrypt = krb5_encrypt, - .decrypt = krb5_decrypt, .import_ctx = gss_krb5_import_ctx_v1, .mk_key = gss_krb5_des3_make_key, .get_mic = gss_krb5_get_mic_v1, @@ -100,8 +96,6 @@ static const struct gss_krb5_enctype supported_gss_krb5_enctypes[] = { .encrypt_name = "cts(cbc(aes))", .aux_cipher = "cbc(aes)", .cksum_name = "hmac(sha1)", - .encrypt = krb5_encrypt, - .decrypt = krb5_decrypt, .import_ctx = gss_krb5_import_ctx_v2, .mk_key = gss_krb5_aes_make_key, .encrypt_v2 = gss_krb5_aes_encrypt, @@ -129,8 +123,6 @@ static const struct gss_krb5_enctype supported_gss_krb5_enctypes[] = { .encrypt_name = "cts(cbc(aes))", .aux_cipher = "cbc(aes)", .cksum_name = "hmac(sha1)", - .encrypt = krb5_encrypt, - .decrypt = krb5_decrypt, .import_ctx = gss_krb5_import_ctx_v2, .mk_key = gss_krb5_aes_make_key, .encrypt_v2 = gss_krb5_aes_encrypt, diff --git a/net/sunrpc/auth_gss/gss_krb5_seqnum.c b/net/sunrpc/auth_gss/gss_krb5_seqnum.c index 3200b971a814..1babc3474e10 100644 --- a/net/sunrpc/auth_gss/gss_krb5_seqnum.c +++ b/net/sunrpc/auth_gss/gss_krb5_seqnum.c @@ -35,6 +35,8 @@ #include <linux/types.h> #include <linux/sunrpc/gss_krb5.h>
+#include "gss_krb5_internal.h" + #if IS_ENABLED(CONFIG_SUNRPC_DEBUG) # define RPCDBG_FACILITY RPCDBG_AUTH #endif
From: Chuck Lever chuck.lever@oracle.com
Clean up: there is now only one encrypt and only one decrypt method, thus there is no longer a need for the v2-suffixed method names.
Tested-by: Scott Mayhew smayhew@redhat.com Signed-off-by: Chuck Lever chuck.lever@oracle.com --- include/linux/sunrpc/gss_krb5.h | 20 ++++---------------- net/sunrpc/auth_gss/gss_krb5_internal.h | 6 ++++++ net/sunrpc/auth_gss/gss_krb5_mech.c | 8 ++++---- net/sunrpc/auth_gss/gss_krb5_wrap.c | 12 +++--------- 4 files changed, 17 insertions(+), 29 deletions(-)
diff --git a/include/linux/sunrpc/gss_krb5.h b/include/linux/sunrpc/gss_krb5.h index a0646df12beb..85fce36c242d 100644 --- a/include/linux/sunrpc/gss_krb5.h +++ b/include/linux/sunrpc/gss_krb5.h @@ -73,12 +73,10 @@ struct gss_krb5_enctype { u32 (*mk_key) (const struct gss_krb5_enctype *gk5e, struct xdr_netobj *in, struct xdr_netobj *out); /* complete key generation */ - u32 (*encrypt_v2) (struct krb5_ctx *kctx, u32 offset, - struct xdr_buf *buf, - struct page **pages); /* v2 encryption function */ - u32 (*decrypt_v2) (struct krb5_ctx *kctx, u32 offset, u32 len, - struct xdr_buf *buf, u32 *headskip, - u32 *tailskip); /* v2 decryption function */ + 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); 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, @@ -276,14 +274,4 @@ gss_krb5_aes_make_key(const struct gss_krb5_enctype *gk5e, struct xdr_netobj *randombits, struct xdr_netobj *key);
-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); - #endif /* _LINUX_SUNRPC_GSS_KRB5_H */ diff --git a/net/sunrpc/auth_gss/gss_krb5_internal.h b/net/sunrpc/auth_gss/gss_krb5_internal.h index a4b752af6951..837bcfa3742f 100644 --- a/net/sunrpc/auth_gss/gss_krb5_internal.h +++ b/net/sunrpc/auth_gss/gss_krb5_internal.h @@ -50,4 +50,10 @@ u32 krb5_encrypt(struct crypto_sync_skcipher *key, void *iv, void *in, u32 krb5_decrypt(struct crypto_sync_skcipher *key, void *iv, void *in, void *out, int length);
+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); + #endif /* _NET_SUNRPC_AUTH_GSS_KRB5_INTERNAL_H */ diff --git a/net/sunrpc/auth_gss/gss_krb5_mech.c b/net/sunrpc/auth_gss/gss_krb5_mech.c index 47c065aa4a14..9f393175a276 100644 --- a/net/sunrpc/auth_gss/gss_krb5_mech.c +++ b/net/sunrpc/auth_gss/gss_krb5_mech.c @@ -98,8 +98,8 @@ static const struct gss_krb5_enctype supported_gss_krb5_enctypes[] = { .cksum_name = "hmac(sha1)", .import_ctx = gss_krb5_import_ctx_v2, .mk_key = gss_krb5_aes_make_key, - .encrypt_v2 = gss_krb5_aes_encrypt, - .decrypt_v2 = gss_krb5_aes_decrypt, + .encrypt = gss_krb5_aes_encrypt, + .decrypt = gss_krb5_aes_decrypt,
.get_mic = gss_krb5_get_mic_v2, .verify_mic = gss_krb5_verify_mic_v2, @@ -125,8 +125,8 @@ static const struct gss_krb5_enctype supported_gss_krb5_enctypes[] = { .cksum_name = "hmac(sha1)", .import_ctx = gss_krb5_import_ctx_v2, .mk_key = gss_krb5_aes_make_key, - .encrypt_v2 = gss_krb5_aes_encrypt, - .decrypt_v2 = gss_krb5_aes_decrypt, + .encrypt = gss_krb5_aes_encrypt, + .decrypt = gss_krb5_aes_decrypt,
.get_mic = gss_krb5_get_mic_v2, .verify_mic = gss_krb5_verify_mic_v2, diff --git a/net/sunrpc/auth_gss/gss_krb5_wrap.c b/net/sunrpc/auth_gss/gss_krb5_wrap.c index 7dabf379406b..6d6b082380b2 100644 --- a/net/sunrpc/auth_gss/gss_krb5_wrap.c +++ b/net/sunrpc/auth_gss/gss_krb5_wrap.c @@ -390,9 +390,6 @@ gss_krb5_wrap_v2(struct krb5_ctx *kctx, int offset,
dprintk("RPC: %s\n", __func__);
- if (kctx->gk5e->encrypt_v2 == NULL) - return GSS_S_FAILURE; - /* make room for gss token header */ if (xdr_extend_head(buf, offset, GSS_KRB5_TOK_HDR_LEN)) return GSS_S_FAILURE; @@ -420,7 +417,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_v2)(kctx, offset, buf, pages); + err = (*kctx->gk5e->encrypt)(kctx, offset, buf, pages); if (err) return err;
@@ -445,9 +442,6 @@ gss_krb5_unwrap_v2(struct krb5_ctx *kctx, int offset, int len,
dprintk("RPC: %s\n", __func__);
- if (kctx->gk5e->decrypt_v2 == NULL) - return GSS_S_FAILURE; - ptr = buf->head[0].iov_base + offset;
if (be16_to_cpu(*((__be16 *)ptr)) != KG2_TOK_WRAP) @@ -477,8 +471,8 @@ 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_v2)(kctx, offset, len, buf, - &headskip, &tailskip); + err = (*kctx->gk5e->decrypt)(kctx, offset, len, buf, + &headskip, &tailskip); if (err) return GSS_S_FAILURE;
From: Chuck Lever chuck.lever@oracle.com
Each Kerberos enctype can have a different KDF. Refactor the key derivation path to support different KDFs for the enctypes introduced in subsequent patches.
In particular, expose the key derivation function in struct gss_krb5_enctype instead of the enctype's preferred random-to-key function. The latter is usually the identity function and is only ever called during key derivation, so have each KDF call it directly.
A couple of extra clean-ups: - Deduplicate the set_cdata() helper - Have ->derive_key return negative errnos, in accordance with usual kernel coding conventions
This patch is a little bigger than I'd like, but these are all mechanical changes and they are all to the same areas of code. No behavior change is intended.
Tested-by: Scott Mayhew smayhew@redhat.com Signed-off-by: Chuck Lever chuck.lever@oracle.com --- include/linux/sunrpc/gss_krb5.h | 25 +----- net/sunrpc/auth_gss/gss_krb5_internal.h | 46 +++++++++++ net/sunrpc/auth_gss/gss_krb5_keys.c | 131 ++++++++++++++++++++----------- net/sunrpc/auth_gss/gss_krb5_mech.c | 76 ++++-------------- 4 files changed, 156 insertions(+), 122 deletions(-)
diff --git a/include/linux/sunrpc/gss_krb5.h b/include/linux/sunrpc/gss_krb5.h index 85fce36c242d..04addef79177 100644 --- a/include/linux/sunrpc/gss_krb5.h +++ b/include/linux/sunrpc/gss_krb5.h @@ -70,9 +70,11 @@ struct gss_krb5_enctype { const u32 keybytes; /* raw key len, in bytes */ const u32 keylength; /* final key len, in bytes */ int (*import_ctx)(struct krb5_ctx *ctx, gfp_t gfp_mask); - u32 (*mk_key) (const struct gss_krb5_enctype *gk5e, - struct xdr_netobj *in, - struct xdr_netobj *out); /* complete key generation */ + 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); 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, @@ -257,21 +259,4 @@ krb5_get_seq_num(struct krb5_ctx *kctx, int xdr_extend_head(struct xdr_buf *buf, unsigned int base, unsigned int shiftlen);
-u32 -krb5_derive_key(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); - -u32 -gss_krb5_des3_make_key(const struct gss_krb5_enctype *gk5e, - struct xdr_netobj *randombits, - struct xdr_netobj *key); - -u32 -gss_krb5_aes_make_key(const struct gss_krb5_enctype *gk5e, - struct xdr_netobj *randombits, - struct xdr_netobj *key); - #endif /* _LINUX_SUNRPC_GSS_KRB5_H */ diff --git a/net/sunrpc/auth_gss/gss_krb5_internal.h b/net/sunrpc/auth_gss/gss_krb5_internal.h index 837bcfa3742f..c7580026adc7 100644 --- a/net/sunrpc/auth_gss/gss_krb5_internal.h +++ b/net/sunrpc/auth_gss/gss_krb5_internal.h @@ -38,6 +38,52 @@ u32 gss_krb5_unwrap_v2(struct krb5_ctx *kctx, int offset, int len, * Implementation internal functions */
+/* Key Derivation Functions */ + +int krb5_derive_key_v1(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_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); + +/** + * 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, diff --git a/net/sunrpc/auth_gss/gss_krb5_keys.c b/net/sunrpc/auth_gss/gss_krb5_keys.c index a7c6866dad96..f6de4fdd63ae 100644 --- a/net/sunrpc/auth_gss/gss_krb5_keys.c +++ b/net/sunrpc/auth_gss/gss_krb5_keys.c @@ -139,23 +139,20 @@ static void krb5_nfold(u32 inbits, const u8 *in, * This is the DK (derive_key) function as described in rfc3961, sec 5.1 * Taken from MIT Kerberos and modified. */ - -u32 krb5_derive_key(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) +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, *rawkey; + unsigned char *inblockdata, *outblockdata; struct xdr_netobj inblock, outblock; struct crypto_sync_skcipher *cipher; - u32 ret = EINVAL; + int ret = -EINVAL;
keybytes = gk5e->keybytes; keylength = gk5e->keylength;
- if ((inkey->len != keylength) || (outkey->len != keylength)) + if (inkey->len != keylength) goto err_return;
cipher = crypto_alloc_sync_skcipher(gk5e->encrypt_name, 0, 0); @@ -165,7 +162,7 @@ u32 krb5_derive_key(const struct gss_krb5_enctype *gk5e, if (crypto_sync_skcipher_setkey(cipher, inkey->data, inkey->len)) goto err_return;
- ret = ENOMEM; + ret = -ENOMEM; inblockdata = kmalloc(blocksize, gfp_mask); if (inblockdata == NULL) goto err_free_cipher; @@ -174,10 +171,6 @@ u32 krb5_derive_key(const struct gss_krb5_enctype *gk5e, if (outblockdata == NULL) goto err_free_in;
- rawkey = kmalloc(keybytes, gfp_mask); - if (rawkey == NULL) - goto err_free_out; - inblock.data = (char *) inblockdata; inblock.len = blocksize;
@@ -210,26 +203,8 @@ u32 krb5_derive_key(const struct gss_krb5_enctype *gk5e, n += outblock.len; }
- /* postprocess the key */ - - inblock.data = (char *) rawkey; - inblock.len = keybytes; - - BUG_ON(gk5e->mk_key == NULL); - ret = (*(gk5e->mk_key))(gk5e, &inblock, outkey); - if (ret) { - dprintk("%s: got %d from mk_key function for '%s'\n", - __func__, ret, gk5e->encrypt_name); - goto err_free_raw; - } - - /* clean memory, free resources and exit */ - ret = 0;
-err_free_raw: - kfree_sensitive(rawkey); -err_free_out: kfree_sensitive(outblockdata); err_free_in: kfree_sensitive(inblockdata); @@ -252,15 +227,11 @@ static void mit_des_fixup_key_parity(u8 key[8]) } }
-/* - * This is the des3 key derivation postprocess function - */ -u32 gss_krb5_des3_make_key(const struct gss_krb5_enctype *gk5e, - struct xdr_netobj *randombits, - struct xdr_netobj *key) +static int krb5_random_to_key_v1(const struct gss_krb5_enctype *gk5e, + struct xdr_netobj *randombits, + struct xdr_netobj *key) { - int i; - u32 ret = EINVAL; + int i, ret = -EINVAL;
if (key->len != 24) { dprintk("%s: key->len is %d\n", __func__, key->len); @@ -292,14 +263,49 @@ u32 gss_krb5_des3_make_key(const struct gss_krb5_enctype *gk5e, return ret; }
+/** + * krb5_derive_key_v1 - Derive a subkey for an RFC 3961 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_v1(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_v1(gk5e, &inblock, outkey); + + kfree_sensitive(inblock.data); + return ret; +} + /* - * This is the aes key derivation postprocess function + * This is the identity function, with some sanity checking. */ -u32 gss_krb5_aes_make_key(const struct gss_krb5_enctype *gk5e, - struct xdr_netobj *randombits, - struct xdr_netobj *key) +static int krb5_random_to_key_v2(const struct gss_krb5_enctype *gk5e, + struct xdr_netobj *randombits, + struct xdr_netobj *key) { - u32 ret = EINVAL; + int ret = -EINVAL;
if (key->len != 16 && key->len != 32) { dprintk("%s: key->len is %d\n", __func__, key->len); @@ -320,3 +326,38 @@ u32 gss_krb5_aes_make_key(const struct gss_krb5_enctype *gk5e, 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; +} diff --git a/net/sunrpc/auth_gss/gss_krb5_mech.c b/net/sunrpc/auth_gss/gss_krb5_mech.c index 9f393175a276..9e9551b224f6 100644 --- a/net/sunrpc/auth_gss/gss_krb5_mech.c +++ b/net/sunrpc/auth_gss/gss_krb5_mech.c @@ -49,7 +49,6 @@ static const struct gss_krb5_enctype supported_gss_krb5_enctypes[] = { .encrypt_name = "cbc(des)", .cksum_name = "md5", .import_ctx = gss_krb5_import_ctx_des, - .mk_key = NULL, .get_mic = gss_krb5_get_mic_v1, .verify_mic = gss_krb5_verify_mic_v1, .wrap = gss_krb5_wrap_v1, @@ -71,7 +70,7 @@ static const struct gss_krb5_enctype supported_gss_krb5_enctypes[] = { .encrypt_name = "cbc(des3_ede)", .cksum_name = "hmac(sha1)", .import_ctx = gss_krb5_import_ctx_v1, - .mk_key = gss_krb5_des3_make_key, + .derive_key = krb5_derive_key_v1, .get_mic = gss_krb5_get_mic_v1, .verify_mic = gss_krb5_verify_mic_v1, .wrap = gss_krb5_wrap_v1, @@ -97,7 +96,7 @@ static const struct gss_krb5_enctype supported_gss_krb5_enctypes[] = { .aux_cipher = "cbc(aes)", .cksum_name = "hmac(sha1)", .import_ctx = gss_krb5_import_ctx_v2, - .mk_key = gss_krb5_aes_make_key, + .derive_key = krb5_derive_key_v2, .encrypt = gss_krb5_aes_encrypt, .decrypt = gss_krb5_aes_decrypt,
@@ -124,7 +123,7 @@ static const struct gss_krb5_enctype supported_gss_krb5_enctypes[] = { .aux_cipher = "cbc(aes)", .cksum_name = "hmac(sha1)", .import_ctx = gss_krb5_import_ctx_v2, - .mk_key = gss_krb5_aes_make_key, + .derive_key = krb5_derive_key_v2, .encrypt = gss_krb5_aes_encrypt, .decrypt = gss_krb5_aes_decrypt,
@@ -358,16 +357,6 @@ context_v2_alloc_cipher(struct krb5_ctx *ctx, const char *cname, u8 *key) return cp; }
-static inline void -set_cdata(u8 cdata[GSS_KRB5_K5CLENGTH], u32 usage, u8 seed) -{ - cdata[0] = (usage>>24)&0xff; - cdata[1] = (usage>>16)&0xff; - cdata[2] = (usage>>8)&0xff; - cdata[3] = usage&0xff; - cdata[4] = seed; -} - #if defined(CONFIG_RPCSEC_GSS_KRB5_SIMPLIFIED) static int gss_krb5_import_ctx_des(struct krb5_ctx *ctx, gfp_t gfp_mask) @@ -378,16 +367,10 @@ gss_krb5_import_ctx_des(struct krb5_ctx *ctx, gfp_t gfp_mask) static int gss_krb5_import_ctx_v1(struct krb5_ctx *ctx, gfp_t gfp_mask) { - struct xdr_netobj c, keyin, keyout; - u8 cdata[GSS_KRB5_K5CLENGTH]; - u32 err; - - c.len = GSS_KRB5_K5CLENGTH; - c.data = cdata; + struct xdr_netobj keyin, keyout;
keyin.data = ctx->Ksess; keyin.len = ctx->gk5e->keylength; - keyout.len = ctx->gk5e->keylength;
/* seq uses the raw key */ ctx->seq = context_v2_alloc_cipher(ctx, ctx->gk5e->encrypt_name, @@ -401,14 +384,11 @@ gss_krb5_import_ctx_v1(struct krb5_ctx *ctx, gfp_t gfp_mask) goto out_free_seq;
/* derive cksum */ - set_cdata(cdata, KG_USAGE_SIGN, KEY_USAGE_SEED_CHECKSUM); keyout.data = ctx->cksum; - err = krb5_derive_key(ctx->gk5e, &keyin, &keyout, &c, gfp_mask); - if (err) { - dprintk("%s: Error %d deriving cksum key\n", - __func__, err); + keyout.len = ctx->gk5e->keylength; + if (krb5_derive_key(ctx, &keyin, &keyout, KG_USAGE_SIGN, + KEY_USAGE_SEED_CHECKSUM, gfp_mask)) goto out_free_enc; - }
return 0;
@@ -441,11 +421,6 @@ gss_krb5_alloc_hash_v2(struct krb5_ctx *kctx, const struct xdr_netobj *key) static int gss_krb5_import_ctx_v2(struct krb5_ctx *ctx, gfp_t gfp_mask) { - u8 cdata[GSS_KRB5_K5CLENGTH]; - struct xdr_netobj c = { - .len = sizeof(cdata), - .data = cdata, - }; struct xdr_netobj keyin = { .len = ctx->gk5e->keylength, .data = ctx->Ksess, @@ -453,7 +428,6 @@ gss_krb5_import_ctx_v2(struct krb5_ctx *ctx, gfp_t gfp_mask) struct xdr_netobj keyout; int ret = -EINVAL; void *subkey; - u32 err;
subkey = kmalloc(ctx->gk5e->keylength, gfp_mask); if (!subkey) @@ -462,13 +436,9 @@ gss_krb5_import_ctx_v2(struct krb5_ctx *ctx, gfp_t gfp_mask) keyout.data = subkey;
/* initiator seal encryption */ - set_cdata(cdata, KG_USAGE_INITIATOR_SEAL, KEY_USAGE_SEED_ENCRYPTION); - err = krb5_derive_key(ctx->gk5e, &keyin, &keyout, &c, gfp_mask); - if (err) { - dprintk("%s: Error %d deriving initiator_seal key\n", - __func__, err); + if (krb5_derive_key(ctx, &keyin, &keyout, KG_USAGE_INITIATOR_SEAL, + KEY_USAGE_SEED_ENCRYPTION, gfp_mask)) goto out; - } ctx->initiator_enc = context_v2_alloc_cipher(ctx, ctx->gk5e->encrypt_name, subkey); @@ -483,13 +453,9 @@ gss_krb5_import_ctx_v2(struct krb5_ctx *ctx, gfp_t gfp_mask) }
/* acceptor seal encryption */ - set_cdata(cdata, KG_USAGE_ACCEPTOR_SEAL, KEY_USAGE_SEED_ENCRYPTION); - err = krb5_derive_key(ctx->gk5e, &keyin, &keyout, &c, gfp_mask); - if (err) { - dprintk("%s: Error %d deriving acceptor_seal key\n", - __func__, err); + if (krb5_derive_key(ctx, &keyin, &keyout, KG_USAGE_ACCEPTOR_SEAL, + KEY_USAGE_SEED_ENCRYPTION, gfp_mask)) goto out_free; - } ctx->acceptor_enc = context_v2_alloc_cipher(ctx, ctx->gk5e->encrypt_name, subkey); @@ -504,36 +470,32 @@ gss_krb5_import_ctx_v2(struct krb5_ctx *ctx, gfp_t gfp_mask) }
/* initiator sign checksum */ - set_cdata(cdata, KG_USAGE_INITIATOR_SIGN, KEY_USAGE_SEED_CHECKSUM); - err = krb5_derive_key(ctx->gk5e, &keyin, &keyout, &c, gfp_mask); - if (err) + 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 */ - set_cdata(cdata, KG_USAGE_ACCEPTOR_SIGN, KEY_USAGE_SEED_CHECKSUM); - err = krb5_derive_key(ctx->gk5e, &keyin, &keyout, &c, gfp_mask); - if (err) + 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 */ - set_cdata(cdata, KG_USAGE_INITIATOR_SEAL, KEY_USAGE_SEED_INTEGRITY); - err = krb5_derive_key(ctx->gk5e, &keyin, &keyout, &c, gfp_mask); - if (err) + 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 */ - set_cdata(cdata, KG_USAGE_ACCEPTOR_SEAL, KEY_USAGE_SEED_INTEGRITY); - err = krb5_derive_key(ctx->gk5e, &keyin, &keyout, &c, gfp_mask); - if (err) + 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)
From: Chuck Lever chuck.lever@oracle.com
De-duplicate some common code.
Tested-by: Scott Mayhew smayhew@redhat.com Signed-off-by: Chuck Lever chuck.lever@oracle.com --- net/sunrpc/auth_gss/gss_krb5_mech.c | 58 ++++++++++++++++++----------------- 1 file changed, 29 insertions(+), 29 deletions(-)
diff --git a/net/sunrpc/auth_gss/gss_krb5_mech.c b/net/sunrpc/auth_gss/gss_krb5_mech.c index 9e9551b224f6..9575fb291d33 100644 --- a/net/sunrpc/auth_gss/gss_krb5_mech.c +++ b/net/sunrpc/auth_gss/gss_krb5_mech.c @@ -204,17 +204,32 @@ get_gss_krb5_enctype(int etype) return NULL; }
+static struct crypto_sync_skcipher * +gss_krb5_alloc_cipher_v1(struct krb5_ctx *ctx, struct xdr_netobj *key) +{ + struct crypto_sync_skcipher *tfm; + + tfm = crypto_alloc_sync_skcipher(ctx->gk5e->encrypt_name, 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 inline const void * get_key(const void *p, const void *end, struct krb5_ctx *ctx, struct crypto_sync_skcipher **res) { + struct crypto_sync_skcipher *tfm; struct xdr_netobj key; int alg;
p = simple_get_bytes(p, end, &alg, sizeof(alg)); if (IS_ERR(p)) goto out_err; - switch (alg) { case ENCTYPE_DES_CBC_CRC: case ENCTYPE_DES_CBC_MD4: @@ -223,37 +238,26 @@ get_key(const void *p, const void *end, alg = ENCTYPE_DES_CBC_RAW; break; } - if (!supported_gss_krb5_enctype(alg)) { - printk(KERN_WARNING "gss_kerberos_mech: unsupported " - "encryption key algorithm %d\n", alg); - p = ERR_PTR(-EINVAL); - goto out_err; + pr_warn("gss_krb5: unsupported enctype: %d\n", alg); + goto out_err_inval; } + p = simple_get_netobj(p, end, &key); if (IS_ERR(p)) goto out_err; - - *res = crypto_alloc_sync_skcipher(ctx->gk5e->encrypt_name, 0, 0); - if (IS_ERR(*res)) { - printk(KERN_WARNING "gss_kerberos_mech: unable to initialize " - "crypto algorithm %s\n", ctx->gk5e->encrypt_name); - *res = NULL; - goto out_err_free_key; - } - if (crypto_sync_skcipher_setkey(*res, key.data, key.len)) { - printk(KERN_WARNING "gss_kerberos_mech: error setting key for " - "crypto algorithm %s\n", ctx->gk5e->encrypt_name); - goto out_err_free_tfm; + tfm = gss_krb5_alloc_cipher_v1(ctx, &key); + kfree(key.data); + if (!tfm) { + pr_warn("gss_krb5: failed to initialize cipher '%s'\n", + ctx->gk5e->encrypt_name); + goto out_err_inval; } + *res = tfm;
- kfree(key.data); return p;
-out_err_free_tfm: - crypto_free_sync_skcipher(*res); -out_err_free_key: - kfree(key.data); +out_err_inval: p = ERR_PTR(-EINVAL); out_err: return p; @@ -372,14 +376,10 @@ gss_krb5_import_ctx_v1(struct krb5_ctx *ctx, gfp_t gfp_mask) keyin.data = ctx->Ksess; keyin.len = ctx->gk5e->keylength;
- /* seq uses the raw key */ - ctx->seq = context_v2_alloc_cipher(ctx, ctx->gk5e->encrypt_name, - ctx->Ksess); + ctx->seq = gss_krb5_alloc_cipher_v1(ctx, &keyin); if (ctx->seq == NULL) goto out_err; - - ctx->enc = context_v2_alloc_cipher(ctx, ctx->gk5e->encrypt_name, - ctx->Ksess); + ctx->enc = gss_krb5_alloc_cipher_v1(ctx, &keyin); if (ctx->enc == NULL) goto out_free_seq;
From: Chuck Lever chuck.lever@oracle.com
Although the Kerberos specs have always listed separate subkey lengths, the Linux kernel's SunRPC GSS Kerberos enctype profiles assume the base key and the derived keys have identical lengths.
The aes256-cts-hmac-sha384-192 enctype specifies the length of its checksum and integrity subkeys as 192 bits, but the length of its encryption subkey (Ke) as 256 bits.
To support that enctype, parametrize context_v2_alloc_cipher() so that each of its call sites can pass in its desired key length. For now it will be the same length as before (gk5e->keylength), but a subsequent patch will change this.
Tested-by: Scott Mayhew smayhew@redhat.com Signed-off-by: Chuck Lever chuck.lever@oracle.com --- net/sunrpc/auth_gss/gss_krb5_mech.c | 61 +++++++++++++++-------------------- 1 file changed, 26 insertions(+), 35 deletions(-)
diff --git a/net/sunrpc/auth_gss/gss_krb5_mech.c b/net/sunrpc/auth_gss/gss_krb5_mech.c index 9575fb291d33..45f461f9b5ba 100644 --- a/net/sunrpc/auth_gss/gss_krb5_mech.c +++ b/net/sunrpc/auth_gss/gss_krb5_mech.c @@ -341,26 +341,6 @@ gss_import_v1_context(const void *p, const void *end, struct krb5_ctx *ctx) return PTR_ERR(p); }
-static inline struct crypto_sync_skcipher * -context_v2_alloc_cipher(struct krb5_ctx *ctx, const char *cname, u8 *key) -{ - struct crypto_sync_skcipher *cp; - - cp = crypto_alloc_sync_skcipher(cname, 0, 0); - if (IS_ERR(cp)) { - dprintk("gss_kerberos_mech: unable to initialize " - "crypto algorithm %s\n", cname); - return NULL; - } - if (crypto_sync_skcipher_setkey(cp, key, ctx->gk5e->keylength)) { - dprintk("gss_kerberos_mech: error setting key for " - "crypto algorithm %s\n", cname); - crypto_free_sync_skcipher(cp); - return NULL; - } - return cp; -} - #if defined(CONFIG_RPCSEC_GSS_KRB5_SIMPLIFIED) static int gss_krb5_import_ctx_des(struct krb5_ctx *ctx, gfp_t gfp_mask) @@ -403,6 +383,21 @@ gss_krb5_import_ctx_v1(struct krb5_ctx *ctx, gfp_t gfp_mask)
#if defined(CONFIG_RPCSEC_GSS_KRB5_CRYPTOSYSTEM)
+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) { @@ -427,27 +422,24 @@ gss_krb5_import_ctx_v2(struct krb5_ctx *ctx, gfp_t gfp_mask) }; struct xdr_netobj keyout; int ret = -EINVAL; - void *subkey;
- subkey = kmalloc(ctx->gk5e->keylength, gfp_mask); - if (!subkey) + keyout.data = kmalloc(ctx->gk5e->keylength, gfp_mask); + if (!keyout.data) return -ENOMEM; keyout.len = ctx->gk5e->keylength; - keyout.data = subkey;
/* initiator seal encryption */ if (krb5_derive_key(ctx, &keyin, &keyout, KG_USAGE_INITIATOR_SEAL, KEY_USAGE_SEED_ENCRYPTION, gfp_mask)) goto out; - ctx->initiator_enc = context_v2_alloc_cipher(ctx, - ctx->gk5e->encrypt_name, - subkey); + 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 = - context_v2_alloc_cipher(ctx, ctx->gk5e->aux_cipher, - subkey); + gss_krb5_alloc_cipher_v2(ctx->gk5e->aux_cipher, + &keyout); if (ctx->initiator_enc_aux == NULL) goto out_free; } @@ -456,15 +448,14 @@ gss_krb5_import_ctx_v2(struct krb5_ctx *ctx, gfp_t gfp_mask) if (krb5_derive_key(ctx, &keyin, &keyout, KG_USAGE_ACCEPTOR_SEAL, KEY_USAGE_SEED_ENCRYPTION, gfp_mask)) goto out_free; - ctx->acceptor_enc = context_v2_alloc_cipher(ctx, - ctx->gk5e->encrypt_name, - subkey); + 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 = - context_v2_alloc_cipher(ctx, ctx->gk5e->aux_cipher, - subkey); + gss_krb5_alloc_cipher_v2(ctx->gk5e->aux_cipher, + &keyout); if (ctx->acceptor_enc_aux == NULL) goto out_free; } @@ -503,7 +494,7 @@ gss_krb5_import_ctx_v2(struct krb5_ctx *ctx, gfp_t gfp_mask)
ret = 0; out: - kfree_sensitive(subkey); + kfree_sensitive(keyout.data); return ret;
out_free:
From: Chuck Lever chuck.lever@oracle.com
The aes256-cts-hmac-sha384-192 enctype specifies the length of its checksum and integrity subkeys as 192 bits, but the length of its encryption subkey (Ke) as 256 bits. Add new fields to struct gss_krb5_enctype that specify the key lengths individually, and where needed, use the correct new field instead of ->keylength.
Tested-by: Scott Mayhew smayhew@redhat.com Signed-off-by: Chuck Lever chuck.lever@oracle.com --- include/linux/sunrpc/gss_krb5.h | 14 ++++++++++++-- net/sunrpc/auth_gss/gss_krb5_mech.c | 20 ++++++++++++++------ 2 files changed, 26 insertions(+), 8 deletions(-)
diff --git a/include/linux/sunrpc/gss_krb5.h b/include/linux/sunrpc/gss_krb5.h index 04addef79177..3e97d2a7c87d 100644 --- a/include/linux/sunrpc/gss_krb5.h +++ b/include/linux/sunrpc/gss_krb5.h @@ -42,10 +42,16 @@ #include <linux/sunrpc/gss_err.h> #include <linux/sunrpc/gss_asn1.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) + /* Length of constant used in key derivation */ #define GSS_KRB5_K5CLENGTH (5)
-/* Maximum key length (in bytes) for the supported crypto algorithms*/ +/* Maximum key length (in bytes) for the supported crypto algorithms */ #define GSS_KRB5_MAX_KEYLEN (32)
/* Maximum checksum function output for the supported crypto algorithms */ @@ -68,7 +74,11 @@ struct gss_krb5_enctype { 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; /* final 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 (*import_ctx)(struct krb5_ctx *ctx, gfp_t gfp_mask); int (*derive_key)(const struct gss_krb5_enctype *gk5e, const struct xdr_netobj *in, diff --git a/net/sunrpc/auth_gss/gss_krb5_mech.c b/net/sunrpc/auth_gss/gss_krb5_mech.c index 45f461f9b5ba..ec3cca8fadc5 100644 --- a/net/sunrpc/auth_gss/gss_krb5_mech.c +++ b/net/sunrpc/auth_gss/gss_krb5_mech.c @@ -108,8 +108,11 @@ static const struct gss_krb5_enctype supported_gss_krb5_enctypes[] = { .signalg = -1, .sealalg = -1, .keybytes = 16, - .keylength = 16, - .cksumlength = 12, + .keylength = BITS2OCTETS(128), + .Kc_length = BITS2OCTETS(128), + .Ke_length = BITS2OCTETS(128), + .Ki_length = BITS2OCTETS(128), + .cksumlength = BITS2OCTETS(96), .keyed_cksum = 1, }, /* @@ -135,8 +138,11 @@ static const struct gss_krb5_enctype supported_gss_krb5_enctypes[] = { .signalg = -1, .sealalg = -1, .keybytes = 32, - .keylength = 32, - .cksumlength = 12, + .keylength = BITS2OCTETS(256), + .Kc_length = BITS2OCTETS(256), + .Ke_length = BITS2OCTETS(256), + .Ki_length = BITS2OCTETS(256), + .cksumlength = BITS2OCTETS(96), .keyed_cksum = 1, }, #endif @@ -423,12 +429,12 @@ gss_krb5_import_ctx_v2(struct krb5_ctx *ctx, gfp_t gfp_mask) struct xdr_netobj keyout; int ret = -EINVAL;
- keyout.data = kmalloc(ctx->gk5e->keylength, gfp_mask); + keyout.data = kmalloc(GSS_KRB5_MAX_KEYLEN, gfp_mask); if (!keyout.data) return -ENOMEM; - keyout.len = ctx->gk5e->keylength;
/* 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; @@ -461,6 +467,7 @@ gss_krb5_import_ctx_v2(struct krb5_ctx *ctx, gfp_t gfp_mask) }
/* 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; @@ -477,6 +484,7 @@ gss_krb5_import_ctx_v2(struct krb5_ctx *ctx, gfp_t gfp_mask) 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;
From: Chuck Lever chuck.lever@oracle.com
Cryptosystem profile enctypes all use cipher block chaining with ciphertext steal (CBC-with-CTS). However enctypes that are currently supported in the Linux kernel SunRPC implementation use only the encrypt-&-MAC approach. The RFC 8009 enctypes use encrypt-then-MAC, which performs encryption and checksumming in a different order.
Refactor to make it possible to share the CBC with CTS encryption and decryption mechanisms between e&M and etM enctypes.
Tested-by: Scott Mayhew smayhew@redhat.com Signed-off-by: Chuck Lever chuck.lever@oracle.com --- net/sunrpc/auth_gss/gss_krb5_crypto.c | 187 +++++++++++++++++++-------------- 1 file changed, 105 insertions(+), 82 deletions(-)
diff --git a/net/sunrpc/auth_gss/gss_krb5_crypto.c b/net/sunrpc/auth_gss/gss_krb5_crypto.c index c5845fdda527..65c8b6982729 100644 --- a/net/sunrpc/auth_gss/gss_krb5_crypto.c +++ b/net/sunrpc/auth_gss/gss_krb5_crypto.c @@ -641,6 +641,100 @@ gss_krb5_cts_crypt(struct crypto_sync_skcipher *cipher, struct xdr_buf *buf, return ret; }
+/* + * To provide confidentiality, encrypt using cipher block chaining + * with ciphertext stealing. Message integrity is handled separately. + */ +static 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) +{ + 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; + + return 0; +} + +static 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); +} + u32 gss_krb5_aes_encrypt(struct krb5_ctx *kctx, u32 offset, struct xdr_buf *buf, struct page **pages) @@ -650,11 +744,7 @@ gss_krb5_aes_encrypt(struct krb5_ctx *kctx, u32 offset, u8 *ecptr; struct crypto_sync_skcipher *cipher, *aux_cipher; struct crypto_ahash *ahash; - int blocksize; struct page **save_pages; - int nblocks, nbytes; - struct encryptor_desc desc; - u32 cbcbytes; unsigned int conflen;
if (kctx->initiate) { @@ -666,7 +756,6 @@ gss_krb5_aes_encrypt(struct krb5_ctx *kctx, u32 offset, aux_cipher = kctx->acceptor_enc_aux; ahash = kctx->acceptor_integ; } - blocksize = crypto_sync_skcipher_blocksize(cipher); conflen = crypto_sync_skcipher_blocksize(cipher);
/* hide the gss token header and insert the confounder */ @@ -710,69 +799,30 @@ gss_krb5_aes_encrypt(struct krb5_ctx *kctx, u32 offset, if (err) return GSS_S_FAILURE;
- nbytes = buf->len - offset - GSS_KRB5_TOK_HDR_LEN; - nblocks = (nbytes + blocksize - 1) / blocksize; - cbcbytes = 0; - if (nblocks > 2) - cbcbytes = (nblocks - 2) * blocksize; - - memset(desc.iv, 0, sizeof(desc.iv)); - - if (cbcbytes) { - SYNC_SKCIPHER_REQUEST_ON_STACK(req, aux_cipher); - - desc.pos = offset + GSS_KRB5_TOK_HDR_LEN; - desc.fragno = 0; - desc.fraglen = 0; - desc.pages = pages; - desc.outbuf = buf; - desc.req = req; - - skcipher_request_set_sync_tfm(req, aux_cipher); - 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 + GSS_KRB5_TOK_HDR_LEN, - cbcbytes, encryptor, &desc); - skcipher_request_zero(req); - if (err) - goto out_err; - } - - /* Make sure IV carries forward from any CBC results. */ - err = gss_krb5_cts_crypt(cipher, buf, - offset + GSS_KRB5_TOK_HDR_LEN + cbcbytes, - desc.iv, pages, 1); - if (err) { - err = GSS_S_FAILURE; - goto out_err; - } + err = krb5_cbc_cts_encrypt(cipher, aux_cipher, + offset + GSS_KRB5_TOK_HDR_LEN, + buf, pages); + 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;
-out_err: - if (err) - err = GSS_S_FAILURE; - return err; + 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 xdr_buf subbuf; - u32 ret = 0; 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]; - int nblocks, blocksize, cbcbytes; - struct decryptor_desc desc; + struct xdr_buf subbuf; + u32 ret = 0;
if (kctx->initiate) { cipher = kctx->acceptor_enc; @@ -783,44 +833,17 @@ gss_krb5_aes_decrypt(struct krb5_ctx *kctx, u32 offset, u32 len, aux_cipher = kctx->initiator_enc_aux; ahash = kctx->initiator_integ; } - blocksize = crypto_sync_skcipher_blocksize(cipher);
/* 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));
- nblocks = (subbuf.len + blocksize - 1) / blocksize; - - cbcbytes = 0; - if (nblocks > 2) - cbcbytes = (nblocks - 2) * blocksize; - - memset(desc.iv, 0, sizeof(desc.iv)); - - if (cbcbytes) { - SYNC_SKCIPHER_REQUEST_ON_STACK(req, aux_cipher); - - desc.fragno = 0; - desc.fraglen = 0; - desc.req = req; - - skcipher_request_set_sync_tfm(req, aux_cipher); - skcipher_request_set_callback(req, 0, NULL, NULL); - - sg_init_table(desc.frags, 4); - - ret = xdr_process_buf(&subbuf, 0, cbcbytes, decryptor, &desc); - skcipher_request_zero(req); - if (ret) - goto out_err; - } - - /* Make sure IV carries forward from any CBC results. */ - ret = gss_krb5_cts_crypt(cipher, &subbuf, cbcbytes, desc.iv, NULL, 0); + ret = krb5_cbc_cts_decrypt(cipher, aux_cipher, 0, &subbuf); if (ret) goto out_err;
+ /* Calculate our hmac over the plaintext data */ our_hmac_obj.len = sizeof(our_hmac); our_hmac_obj.data = our_hmac; ret = gss_krb5_checksum(ahash, NULL, 0, &subbuf, 0, &our_hmac_obj); @@ -837,7 +860,7 @@ gss_krb5_aes_decrypt(struct krb5_ctx *kctx, u32 offset, u32 len, ret = GSS_S_BAD_SIG; goto out_err; } - *headskip = blocksize; + *headskip = crypto_sync_skcipher_blocksize(cipher); *tailskip = kctx->gk5e->cksumlength; out_err: if (ret && ret != GSS_S_BAD_SIG)
From: Chuck Lever chuck.lever@oracle.com
Fill in entries in the supported_gss_krb5_enctypes array for the encryption types defined in RFC 8009. These new enctypes use the SHA-256 and SHA-384 message digest algorithms (as defined in FIPS-180) instead of the deprecated SHA-1 algorithm, and are thus more secure.
Note that NIST has scheduled SHA-1 for deprecation:
https://www.nist.gov/news-events/news/2022/12/nist-retires-sha-1-cryptograph...
Thus these new encryption types are placed under a separate CONFIG option to enable distributors to separately introduce support for the AES-SHA2 enctypes and deprecate support for the current set of AES-SHA1 encryption types as their user space allows.
As this implementation is still a "beta", the default is to not build it automatically.
Tested-by: Scott Mayhew smayhew@redhat.com Signed-off-by: Chuck Lever chuck.lever@oracle.com --- include/linux/sunrpc/gss_krb5.h | 19 ++++++++++++- net/sunrpc/Kconfig | 14 ++++++++++ net/sunrpc/auth_gss/gss_krb5_mech.c | 51 +++++++++++++++++++++++++++++++++++ 3 files changed, 82 insertions(+), 2 deletions(-)
diff --git a/include/linux/sunrpc/gss_krb5.h b/include/linux/sunrpc/gss_krb5.h index 3e97d2a7c87d..8ff397b5c04b 100644 --- a/include/linux/sunrpc/gss_krb5.h +++ b/include/linux/sunrpc/gss_krb5.h @@ -54,8 +54,8 @@ /* Maximum key length (in bytes) for the supported crypto algorithms */ #define GSS_KRB5_MAX_KEYLEN (32)
-/* Maximum checksum function output for the supported crypto algorithms */ -#define GSS_KRB5_MAX_CKSUM_LEN (20) +/* Maximum checksum function output for the supported enctypes */ +#define GSS_KRB5_MAX_CKSUM_LEN (24)
/* Maximum blocksize for the supported crypto algorithms */ #define GSS_KRB5_MAX_BLOCKSIZE (16) @@ -160,6 +160,12 @@ enum seal_alg { 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.xht... + */ #define CKSUMTYPE_CRC32 0x0001 #define CKSUMTYPE_RSA_MD4 0x0002 #define CKSUMTYPE_RSA_MD4_DES 0x0003 @@ -170,6 +176,8 @@ enum seal_alg { #define CKSUMTYPE_HMAC_SHA1_DES3 0x000c #define CKSUMTYPE_HMAC_SHA1_96_AES128 0x000f #define CKSUMTYPE_HMAC_SHA1_96_AES256 0x0010 +#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 */ @@ -190,6 +198,11 @@ enum seal_alg {
/* 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.xht... */ #define ENCTYPE_NULL 0x0000 #define ENCTYPE_DES_CBC_CRC 0x0001 /* DES cbc mode with CRC-32 */ @@ -203,6 +216,8 @@ enum seal_alg { #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_UNKNOWN 0x01ff diff --git a/net/sunrpc/Kconfig b/net/sunrpc/Kconfig index 1135ff362132..b1aa2318e1dc 100644 --- a/net/sunrpc/Kconfig +++ b/net/sunrpc/Kconfig @@ -76,6 +76,20 @@ config RPCSEC_GSS_KRB5_ENCTYPES_AES_SHA1 SHA-1 digests. These include aes128-cts-hmac-sha1-96 and aes256-cts-hmac-sha1-96.
+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 + select RPCSEC_GSS_KRB5_CRYPTOSYSTEM + 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 ec3cca8fadc5..1951867f3fa8 100644 --- a/net/sunrpc/auth_gss/gss_krb5_mech.c +++ b/net/sunrpc/auth_gss/gss_krb5_mech.c @@ -146,6 +146,57 @@ static const struct gss_krb5_enctype supported_gss_krb5_enctypes[] = { .keyed_cksum = 1, }, #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), + + .import_ctx = gss_krb5_import_ctx_v2, + + .get_mic = gss_krb5_get_mic_v2, + .verify_mic = gss_krb5_verify_mic_v2, + .wrap = gss_krb5_wrap_v2, + .unwrap = gss_krb5_unwrap_v2, + }, + /* + * 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), + + .import_ctx = gss_krb5_import_ctx_v2, + + .get_mic = gss_krb5_get_mic_v2, + .verify_mic = gss_krb5_verify_mic_v2, + .wrap = gss_krb5_wrap_v2, + .unwrap = gss_krb5_unwrap_v2, + }, +#endif };
/*
Hi Chuck
On Sun, Jan 15, 2023 at 12:23 PM Chuck Lever cel@kernel.org wrote:
From: Chuck Lever chuck.lever@oracle.com
Fill in entries in the supported_gss_krb5_enctypes array for the encryption types defined in RFC 8009. These new enctypes use the SHA-256 and SHA-384 message digest algorithms (as defined in FIPS-180) instead of the deprecated SHA-1 algorithm, and are thus more secure.
Note that NIST has scheduled SHA-1 for deprecation:
https://www.nist.gov/news-events/news/2022/12/nist-retires-sha-1-cryptograph...
Thus these new encryption types are placed under a separate CONFIG option to enable distributors to separately introduce support for the AES-SHA2 enctypes and deprecate support for the current set of AES-SHA1 encryption types as their user space allows.
As this implementation is still a "beta", the default is to not build it automatically.
Tested-by: Scott Mayhew smayhew@redhat.com Signed-off-by: Chuck Lever chuck.lever@oracle.com
include/linux/sunrpc/gss_krb5.h | 19 ++++++++++++- net/sunrpc/Kconfig | 14 ++++++++++ net/sunrpc/auth_gss/gss_krb5_mech.c | 51 +++++++++++++++++++++++++++++++++++ 3 files changed, 82 insertions(+), 2 deletions(-)
diff --git a/include/linux/sunrpc/gss_krb5.h b/include/linux/sunrpc/gss_krb5.h index 3e97d2a7c87d..8ff397b5c04b 100644 --- a/include/linux/sunrpc/gss_krb5.h +++ b/include/linux/sunrpc/gss_krb5.h @@ -54,8 +54,8 @@ /* Maximum key length (in bytes) for the supported crypto algorithms */ #define GSS_KRB5_MAX_KEYLEN (32)
-/* Maximum checksum function output for the supported crypto algorithms */ -#define GSS_KRB5_MAX_CKSUM_LEN (20) +/* Maximum checksum function output for the supported enctypes */ +#define GSS_KRB5_MAX_CKSUM_LEN (24)
I'm having some problems that I bisected to this patch, specifically this change to GSS_KRB5_MAX_CKSUM_LEN. KASAN reports it as a slab-out-of-bounds in gss_krb5_checksum(), and it can cause my client to panic when running cthon basic tests with krb5p. I was wondering if you've seen this?
Anna
Here is what kasan tells me:
[ 35.725366] ================================================================== [ 35.725373] BUG: KASAN: slab-out-of-bounds in gss_krb5_checksum+0x4b6/0x630 [rpcsec_gss_krb5] [ 35.725383] Read of size 24 at addr ffff888110cfc1a0 by task mount.nfs/853
[ 35.725390] CPU: 2 PID: 853 Comm: mount.nfs Not tainted 6.2.0-ga40cf7530d31+ #37820 4b7d53453529728aac4e973d4ba6a17952148f02 [ 35.725395] Hardware name: QEMU Standard PC (Q35 + ICH9, 2009), BIOS 0.0.0 02/06/2015 [ 35.725399] Call Trace: [ 35.725401] <TASK> [ 35.725404] dump_stack_lvl+0x48/0x60 [ 35.725409] print_report+0x184/0x4a8 [ 35.725414] ? memcpy+0x3c/0x60 [ 35.725419] ? gss_krb5_checksum+0x4b6/0x630 [rpcsec_gss_krb5 2fd8c249acfdf3162b23b30d5eb7af0425d84960] [ 35.725426] kasan_report+0xc9/0x150 [ 35.725431] ? gss_krb5_checksum+0x4b6/0x630 [rpcsec_gss_krb5 2fd8c249acfdf3162b23b30d5eb7af0425d84960] [ 35.725439] kasan_check_range+0x13e/0x1c0 [ 35.725447] memcpy+0x23/0x60 [ 35.725451] gss_krb5_checksum+0x4b6/0x630 [rpcsec_gss_krb5 2fd8c249acfdf3162b23b30d5eb7af0425d84960] [ 35.725460] ? __pfx_gss_krb5_checksum+0x10/0x10 [rpcsec_gss_krb5 2fd8c249acfdf3162b23b30d5eb7af0425d84960] [ 35.725467] ? memmove+0x3c/0x60 [ 35.725472] gss_krb5_aes_encrypt+0x388/0x7c0 [rpcsec_gss_krb5 2fd8c249acfdf3162b23b30d5eb7af0425d84960] [ 35.725480] ? __pfx_gss_krb5_aes_encrypt+0x10/0x10 [rpcsec_gss_krb5 2fd8c249acfdf3162b23b30d5eb7af0425d84960] [ 35.725487] ? memmove+0x3c/0x60 [ 35.725491] gss_krb5_wrap_v2+0x28e/0x3a0 [rpcsec_gss_krb5 2fd8c249acfdf3162b23b30d5eb7af0425d84960] [ 35.725500] gss_wrap_req_priv+0x3d7/0x1090 [auth_rpcgss 9532107bdb7719d1a30fdcf239028e9e54e0c27c] [ 35.725517] gss_wrap_req+0x1df/0x250 [auth_rpcgss 9532107bdb7719d1a30fdcf239028e9e54e0c27c] [ 35.725572] call_encode+0x75a/0x1000 [sunrpc 807a235f89c5b6b32dbda9261e96d6b1ac9ed4f5] [ 35.725626] ? __pfx_call_encode+0x10/0x10 [sunrpc 807a235f89c5b6b32dbda9261e96d6b1ac9ed4f5] [ 35.725671] ? __kasan_kmalloc+0xad/0xb0 [ 35.725676] ? xprt_alloc_slot+0x1ca/0x590 [sunrpc 807a235f89c5b6b32dbda9261e96d6b1ac9ed4f5] [ 35.725724] ? call_allocate+0x30d/0x6b0 [sunrpc 807a235f89c5b6b32dbda9261e96d6b1ac9ed4f5] [ 35.725779] ? __pfx_call_encode+0x10/0x10 [sunrpc 807a235f89c5b6b32dbda9261e96d6b1ac9ed4f5] [ 35.725829] __rpc_execute+0x29b/0xcf0 [sunrpc 807a235f89c5b6b32dbda9261e96d6b1ac9ed4f5] [ 35.725885] ? __pfx___rpc_execute+0x10/0x10 [sunrpc 807a235f89c5b6b32dbda9261e96d6b1ac9ed4f5] [ 35.725936] ? __pfx_wake_up_bit+0x10/0x10 [ 35.725941] ? _raw_spin_lock+0x85/0xe0 [ 35.725945] rpc_execute+0x21d/0x320 [sunrpc 807a235f89c5b6b32dbda9261e96d6b1ac9ed4f5] [ 35.725997] rpc_run_task+0x467/0x650 [sunrpc 807a235f89c5b6b32dbda9261e96d6b1ac9ed4f5] [ 35.726044] nfs4_call_sync_sequence+0x17e/0x2a0 [nfsv4 d67fe18359c6743dcd6788d44186185ed97423ee] [ 35.726095] ? unwind_get_return_address+0x5e/0xa0 [ 35.726100] ? __pfx_nfs4_call_sync_sequence+0x10/0x10 [nfsv4 d67fe18359c6743dcd6788d44186185ed97423ee] [ 35.726146] ? stack_trace_save+0x95/0xd0 [ 35.726151] ? __stack_depot_save+0x3f/0x4c0 [ 35.726157] _nfs4_lookup_root.isra.0+0x193/0x200 [nfsv4 d67fe18359c6743dcd6788d44186185ed97423ee] [ 35.726202] ? __pfx__nfs4_lookup_root.isra.0+0x10/0x10 [nfsv4 d67fe18359c6743dcd6788d44186185ed97423ee] [ 35.726246] ? kasan_save_stack+0x45/0x60 [ 35.726251] ? nfs_alloc_fattr+0x44/0x210 [nfs 1894ec9cbdec354be2bcab1be6e5e8ab9f92de62] [ 35.726290] ? nfs4_get_rootfh+0x92/0x290 [nfsv4 d67fe18359c6743dcd6788d44186185ed97423ee] [ 35.726341] ? nfs4_server_common_setup+0xa4/0x680 [nfsv4 d67fe18359c6743dcd6788d44186185ed97423ee] [ 35.726391] ? nfs4_create_server+0x8d7/0xf00 [nfsv4 d67fe18359c6743dcd6788d44186185ed97423ee] [ 35.726440] ? nfs4_try_get_tree+0xd1/0x250 [nfsv4 d67fe18359c6743dcd6788d44186185ed97423ee] [ 35.726488] ? entry_SYSCALL_64_after_hwframe+0x72/0xdc [ 35.726496] nfs4_lookup_root+0xeb/0x260 [nfsv4 d67fe18359c6743dcd6788d44186185ed97423ee] [ 35.726542] ? __pfx_nfs4_lookup_root+0x10/0x10 [nfsv4 d67fe18359c6743dcd6788d44186185ed97423ee] [ 35.726589] nfs4_proc_get_rootfh+0xdc/0x110 [nfsv4 d67fe18359c6743dcd6788d44186185ed97423ee] [ 35.726636] nfs4_get_rootfh+0xb4/0x290 [nfsv4 d67fe18359c6743dcd6788d44186185ed97423ee] [ 35.726685] ? __pfx_nfs4_get_rootfh+0x10/0x10 [nfsv4 d67fe18359c6743dcd6788d44186185ed97423ee] [ 35.726733] ? nfs4_set_client+0x2d8/0x430 [nfsv4 d67fe18359c6743dcd6788d44186185ed97423ee] [ 35.726785] nfs4_server_common_setup+0xa4/0x680 [nfsv4 d67fe18359c6743dcd6788d44186185ed97423ee] [ 35.726834] nfs4_create_server+0x8d7/0xf00 [nfsv4 d67fe18359c6743dcd6788d44186185ed97423ee] [ 35.726884] ? _raw_spin_lock+0x85/0xe0 [ 35.726888] ? __pfx_nfs4_create_server+0x10/0x10 [nfsv4 d67fe18359c6743dcd6788d44186185ed97423ee] [ 35.726937] ? __module_get+0x31/0xf0 [ 35.726942] nfs4_try_get_tree+0xd1/0x250 [nfsv4 d67fe18359c6743dcd6788d44186185ed97423ee] [ 35.726991] vfs_get_tree+0x84/0x2c0 [ 35.726996] path_mount+0xa9f/0x1a20 [ 35.727001] ? __pfx_path_mount+0x10/0x10 [ 35.727005] ? user_path_at_empty+0x44/0x60 [ 35.727008] ? kmem_cache_free+0x19e/0x320 [ 35.727013] __x64_sys_mount+0x214/0x280 [ 35.727017] ? __pfx___x64_sys_mount+0x10/0x10 [ 35.727020] ? _raw_spin_lock+0x85/0xe0 [ 35.727024] do_syscall_64+0x5c/0x90 [ 35.727029] ? syscall_exit_to_user_mode+0x1b/0x40 [ 35.727032] ? do_syscall_64+0x6b/0x90 [ 35.727036] entry_SYSCALL_64_after_hwframe+0x72/0xdc [ 35.727040] RIP: 0033:0x7f1291a5afde [ 35.727044] Code: 48 8b 0d 95 ed 0c 00 f7 d8 64 89 01 48 83 c8 ff c3 66 2e 0f 1f 84 00 00 00 00 00 90 f3 0f 1e fa 49 89 ca b8 a5 00 00 00 0f 05 <48> 3d 01 f0 ff ff 73 01 c3 48 8b 0d 62 ed 0c 00 f7 d8 64 89 01 48 [ 35.727047] RSP: 002b:00007ffd02e479e8 EFLAGS: 00000246 ORIG_RAX: 00000000000000a5 [ 35.727055] RAX: ffffffffffffffda RBX: 00007ffd02e47b90 RCX: 00007f1291a5afde [ 35.727058] RDX: 00005565e507c3b0 RSI: 00005565e507b500 RDI: 00005565e507b550 [ 35.727060] RBP: 00005565e50824f0 R08: 00005565e50824f0 R09: 0000000000000060 [ 35.727062] R10: 0000000000000000 R11: 0000000000000246 R12: 00007ffd02e47b90 [ 35.727065] R13: 00005565e5082210 R14: 0000000000000003 R15: 00005565e42168f8 [ 35.727069] </TASK>
[ 35.727073] Allocated by task 853: [ 35.727075] kasan_save_stack+0x33/0x60 [ 35.727079] kasan_set_track+0x25/0x30 [ 35.727082] __kasan_kmalloc+0xad/0xb0 [ 35.727086] __kmalloc+0x5e/0x160 [ 35.727088] gss_krb5_checksum+0xcf/0x630 [rpcsec_gss_krb5] [ 35.727095] gss_krb5_aes_encrypt+0x388/0x7c0 [rpcsec_gss_krb5] [ 35.727101] gss_krb5_wrap_v2+0x28e/0x3a0 [rpcsec_gss_krb5] [ 35.727107] gss_wrap_req_priv+0x3d7/0x1090 [auth_rpcgss] [ 35.727119] gss_wrap_req+0x1df/0x250 [auth_rpcgss] [ 35.727131] call_encode+0x75a/0x1000 [sunrpc] [ 35.727175] __rpc_execute+0x29b/0xcf0 [sunrpc] [ 35.727227] rpc_execute+0x21d/0x320 [sunrpc] [ 35.727277] rpc_run_task+0x467/0x650 [sunrpc] [ 35.727321] nfs4_call_sync_sequence+0x17e/0x2a0 [nfsv4] [ 35.727365] _nfs4_lookup_root.isra.0+0x193/0x200 [nfsv4] [ 35.727408] nfs4_lookup_root+0xeb/0x260 [nfsv4] [ 35.727453] nfs4_proc_get_rootfh+0xdc/0x110 [nfsv4] [ 35.727498] nfs4_get_rootfh+0xb4/0x290 [nfsv4] [ 35.727546] nfs4_server_common_setup+0xa4/0x680 [nfsv4] [ 35.727595] nfs4_create_server+0x8d7/0xf00 [nfsv4] [ 35.727643] nfs4_try_get_tree+0xd1/0x250 [nfsv4] [ 35.727690] vfs_get_tree+0x84/0x2c0 [ 35.727694] path_mount+0xa9f/0x1a20 [ 35.727697] __x64_sys_mount+0x214/0x280 [ 35.727701] do_syscall_64+0x5c/0x90 [ 35.727704] entry_SYSCALL_64_after_hwframe+0x72/0xdc
[ 35.727709] The buggy address belongs to the object at ffff888110cfc1a0 which belongs to the cache kmalloc-32 of size 32 [ 35.727712] The buggy address is located 0 bytes inside of 32-byte region [ffff888110cfc1a0, ffff888110cfc1c0)
[ 35.727717] The buggy address belongs to the physical page: [ 35.727721] page:ffffea0004433f00 refcount:1 mapcount:0 mapping:0000000000000000 index:0xffff888110cfce60 pfn:0x110cfc [ 35.727726] flags: 0x2ffff0000000200(slab|node=0|zone=2|lastcpupid=0xffff) [ 35.727731] raw: 02ffff0000000200 ffff888100042740 ffffea00044274d0 ffff888100040450 [ 35.727734] raw: ffff888110cfce60 0000000000150012 00000001ffffffff 0000000000000000 [ 35.727736] page dumped because: kasan: bad access detected [ 35.727740] page_owner tracks the page as allocated [ 35.727741] page last allocated via order 0, migratetype Unmovable, gfp_mask 0x12c40(GFP_NOFS|__GFP_NOWARN|__GFP_NORETRY), pid 715, tgid 715 (test2), ts 24589446140, free_ts 24535345796 [ 35.727747] post_alloc_hook+0x118/0x250 [ 35.727750] get_page_from_freelist+0x11ef/0x3a20 [ 35.727754] __alloc_pages+0x1d5/0x440 [ 35.727757] allocate_slab+0x346/0x4a0 [ 35.727760] ___slab_alloc+0x39a/0x9a0 [ 35.727763] __kmem_cache_alloc_node+0x143/0x3d0 [ 35.727766] __kmalloc+0x4d/0x160 [ 35.727768] gss_krb5_checksum+0xcf/0x630 [rpcsec_gss_krb5] [ 35.727775] gss_krb5_verify_mic_v2+0x2d2/0x4f0 [rpcsec_gss_krb5] [ 35.727780] gss_validate+0x360/0x700 [auth_rpcgss] [ 35.727792] rpc_decode_header+0x288/0xcb0 [sunrpc] [ 35.727836] call_decode+0x3a7/0x780 [sunrpc] [ 35.727880] __rpc_execute+0x29b/0xcf0 [sunrpc] [ 35.727932] rpc_execute+0x21d/0x320 [sunrpc] [ 35.727982] rpc_run_task+0x467/0x650 [sunrpc] [ 35.728026] nfs4_call_sync_sequence+0x17e/0x2a0 [nfsv4] [ 35.728070] page last free stack trace: [ 35.728072] free_pcp_prepare+0x66c/0x10e0 [ 35.728075] free_unref_page+0x4e/0x3c0 [ 35.728078] tlb_remove_table_rcu+0x77/0xc0 [ 35.728081] rcu_do_batch+0x34c/0xd00 [ 35.728084] rcu_core+0x447/0xf20 [ 35.728086] __do_softirq+0x1d6/0x5ed
[ 35.728091] Memory state around the buggy address: [ 35.728093] ffff888110cfc080: fc fc fc fc fc fc fc fc fc fc fc fc fa fb fb fb [ 35.728096] ffff888110cfc100: fc fc fc fc fc fc fc fc fc fc fc fc fc fc fc fc [ 35.728098] >ffff888110cfc180: fc fc fc fc 00 00 04 fc fc fc fc fc fc fc fc fc [ 35.728100] ^ [ 35.728102] ffff888110cfc200: fc fc fc fc fc fc fc fc fc fc fc fc 00 00 00 00 [ 35.728104] ffff888110cfc280: fc fc fc fc fc fc fc fc fc fc fc fc fc fc fc fc [ 35.728106] ==================================================================
/* Maximum blocksize for the supported crypto algorithms */ #define GSS_KRB5_MAX_BLOCKSIZE (16) @@ -160,6 +160,12 @@ enum seal_alg { SEAL_ALG_DES3KD = 0x0002 };
+/*
- These values are assigned by IANA and published via the
- subregistry at the link below:
- */
#define CKSUMTYPE_CRC32 0x0001 #define CKSUMTYPE_RSA_MD4 0x0002 #define CKSUMTYPE_RSA_MD4_DES 0x0003 @@ -170,6 +176,8 @@ enum seal_alg { #define CKSUMTYPE_HMAC_SHA1_DES3 0x000c #define CKSUMTYPE_HMAC_SHA1_96_AES128 0x000f #define CKSUMTYPE_HMAC_SHA1_96_AES256 0x0010 +#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 */ @@ -190,6 +198,11 @@ enum seal_alg {
/* 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:
- */
#define ENCTYPE_NULL 0x0000 #define ENCTYPE_DES_CBC_CRC 0x0001 /* DES cbc mode with CRC-32 */ @@ -203,6 +216,8 @@ enum seal_alg { #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_UNKNOWN 0x01ff diff --git a/net/sunrpc/Kconfig b/net/sunrpc/Kconfig index 1135ff362132..b1aa2318e1dc 100644 --- a/net/sunrpc/Kconfig +++ b/net/sunrpc/Kconfig @@ -76,6 +76,20 @@ config RPCSEC_GSS_KRB5_ENCTYPES_AES_SHA1 SHA-1 digests. These include aes128-cts-hmac-sha1-96 and aes256-cts-hmac-sha1-96.
+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
select RPCSEC_GSS_KRB5_CRYPTOSYSTEM
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 ec3cca8fadc5..1951867f3fa8 100644 --- a/net/sunrpc/auth_gss/gss_krb5_mech.c +++ b/net/sunrpc/auth_gss/gss_krb5_mech.c @@ -146,6 +146,57 @@ static const struct gss_krb5_enctype supported_gss_krb5_enctypes[] = { .keyed_cksum = 1, }, #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),
.import_ctx = gss_krb5_import_ctx_v2,
.get_mic = gss_krb5_get_mic_v2,
.verify_mic = gss_krb5_verify_mic_v2,
.wrap = gss_krb5_wrap_v2,
.unwrap = gss_krb5_unwrap_v2,
},
/*
* 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),
.import_ctx = gss_krb5_import_ctx_v2,
.get_mic = gss_krb5_get_mic_v2,
.verify_mic = gss_krb5_verify_mic_v2,
.wrap = gss_krb5_wrap_v2,
.unwrap = gss_krb5_unwrap_v2,
},
+#endif };
/*
On Mar 22, 2023, at 11:49 AM, Anna Schumaker schumaker.anna@gmail.com wrote:
Hi Chuck
On Sun, Jan 15, 2023 at 12:23 PM Chuck Lever cel@kernel.org wrote:
From: Chuck Lever chuck.lever@oracle.com
Fill in entries in the supported_gss_krb5_enctypes array for the encryption types defined in RFC 8009. These new enctypes use the SHA-256 and SHA-384 message digest algorithms (as defined in FIPS-180) instead of the deprecated SHA-1 algorithm, and are thus more secure.
Note that NIST has scheduled SHA-1 for deprecation:
https://www.nist.gov/news-events/news/2022/12/nist-retires-sha-1-cryptograph...
Thus these new encryption types are placed under a separate CONFIG option to enable distributors to separately introduce support for the AES-SHA2 enctypes and deprecate support for the current set of AES-SHA1 encryption types as their user space allows.
As this implementation is still a "beta", the default is to not build it automatically.
Tested-by: Scott Mayhew smayhew@redhat.com Signed-off-by: Chuck Lever chuck.lever@oracle.com
include/linux/sunrpc/gss_krb5.h | 19 ++++++++++++- net/sunrpc/Kconfig | 14 ++++++++++ net/sunrpc/auth_gss/gss_krb5_mech.c | 51 +++++++++++++++++++++++++++++++++++ 3 files changed, 82 insertions(+), 2 deletions(-)
diff --git a/include/linux/sunrpc/gss_krb5.h b/include/linux/sunrpc/gss_krb5.h index 3e97d2a7c87d..8ff397b5c04b 100644 --- a/include/linux/sunrpc/gss_krb5.h +++ b/include/linux/sunrpc/gss_krb5.h @@ -54,8 +54,8 @@ /* Maximum key length (in bytes) for the supported crypto algorithms */ #define GSS_KRB5_MAX_KEYLEN (32)
-/* Maximum checksum function output for the supported crypto algorithms */ -#define GSS_KRB5_MAX_CKSUM_LEN (20) +/* Maximum checksum function output for the supported enctypes */ +#define GSS_KRB5_MAX_CKSUM_LEN (24)
I'm having some problems that I bisected to this patch, specifically this change to GSS_KRB5_MAX_CKSUM_LEN. KASAN reports it as a slab-out-of-bounds in gss_krb5_checksum(), and it can cause my client to panic when running cthon basic tests with krb5p. I was wondering if you've seen this?
I have not. Scott reported a similar problem that was addressed before merge, so this one is new to me. It looks like there's something in gss_krb5_checksum() that assumes the value of the maximum checksum size.
Can you run "gss_krb5_checksum+0x4b6" through faddr2line for me?
Anna
Here is what kasan tells me:
[ 35.725366] ================================================================== [ 35.725373] BUG: KASAN: slab-out-of-bounds in gss_krb5_checksum+0x4b6/0x630 [rpcsec_gss_krb5] [ 35.725383] Read of size 24 at addr ffff888110cfc1a0 by task mount.nfs/853
[ 35.725390] CPU: 2 PID: 853 Comm: mount.nfs Not tainted 6.2.0-ga40cf7530d31+ #37820 4b7d53453529728aac4e973d4ba6a17952148f02 [ 35.725395] Hardware name: QEMU Standard PC (Q35 + ICH9, 2009), BIOS 0.0.0 02/06/2015 [ 35.725399] Call Trace: [ 35.725401] <TASK> [ 35.725404] dump_stack_lvl+0x48/0x60 [ 35.725409] print_report+0x184/0x4a8 [ 35.725414] ? memcpy+0x3c/0x60 [ 35.725419] ? gss_krb5_checksum+0x4b6/0x630 [rpcsec_gss_krb5 2fd8c249acfdf3162b23b30d5eb7af0425d84960] [ 35.725426] kasan_report+0xc9/0x150 [ 35.725431] ? gss_krb5_checksum+0x4b6/0x630 [rpcsec_gss_krb5 2fd8c249acfdf3162b23b30d5eb7af0425d84960] [ 35.725439] kasan_check_range+0x13e/0x1c0 [ 35.725447] memcpy+0x23/0x60 [ 35.725451] gss_krb5_checksum+0x4b6/0x630 [rpcsec_gss_krb5 2fd8c249acfdf3162b23b30d5eb7af0425d84960] [ 35.725460] ? __pfx_gss_krb5_checksum+0x10/0x10 [rpcsec_gss_krb5 2fd8c249acfdf3162b23b30d5eb7af0425d84960] [ 35.725467] ? memmove+0x3c/0x60 [ 35.725472] gss_krb5_aes_encrypt+0x388/0x7c0 [rpcsec_gss_krb5 2fd8c249acfdf3162b23b30d5eb7af0425d84960] [ 35.725480] ? __pfx_gss_krb5_aes_encrypt+0x10/0x10 [rpcsec_gss_krb5 2fd8c249acfdf3162b23b30d5eb7af0425d84960] [ 35.725487] ? memmove+0x3c/0x60 [ 35.725491] gss_krb5_wrap_v2+0x28e/0x3a0 [rpcsec_gss_krb5 2fd8c249acfdf3162b23b30d5eb7af0425d84960] [ 35.725500] gss_wrap_req_priv+0x3d7/0x1090 [auth_rpcgss 9532107bdb7719d1a30fdcf239028e9e54e0c27c] [ 35.725517] gss_wrap_req+0x1df/0x250 [auth_rpcgss 9532107bdb7719d1a30fdcf239028e9e54e0c27c] [ 35.725572] call_encode+0x75a/0x1000 [sunrpc 807a235f89c5b6b32dbda9261e96d6b1ac9ed4f5] [ 35.725626] ? __pfx_call_encode+0x10/0x10 [sunrpc 807a235f89c5b6b32dbda9261e96d6b1ac9ed4f5] [ 35.725671] ? __kasan_kmalloc+0xad/0xb0 [ 35.725676] ? xprt_alloc_slot+0x1ca/0x590 [sunrpc 807a235f89c5b6b32dbda9261e96d6b1ac9ed4f5] [ 35.725724] ? call_allocate+0x30d/0x6b0 [sunrpc 807a235f89c5b6b32dbda9261e96d6b1ac9ed4f5] [ 35.725779] ? __pfx_call_encode+0x10/0x10 [sunrpc 807a235f89c5b6b32dbda9261e96d6b1ac9ed4f5] [ 35.725829] __rpc_execute+0x29b/0xcf0 [sunrpc 807a235f89c5b6b32dbda9261e96d6b1ac9ed4f5] [ 35.725885] ? __pfx___rpc_execute+0x10/0x10 [sunrpc 807a235f89c5b6b32dbda9261e96d6b1ac9ed4f5] [ 35.725936] ? __pfx_wake_up_bit+0x10/0x10 [ 35.725941] ? _raw_spin_lock+0x85/0xe0 [ 35.725945] rpc_execute+0x21d/0x320 [sunrpc 807a235f89c5b6b32dbda9261e96d6b1ac9ed4f5] [ 35.725997] rpc_run_task+0x467/0x650 [sunrpc 807a235f89c5b6b32dbda9261e96d6b1ac9ed4f5] [ 35.726044] nfs4_call_sync_sequence+0x17e/0x2a0 [nfsv4 d67fe18359c6743dcd6788d44186185ed97423ee] [ 35.726095] ? unwind_get_return_address+0x5e/0xa0 [ 35.726100] ? __pfx_nfs4_call_sync_sequence+0x10/0x10 [nfsv4 d67fe18359c6743dcd6788d44186185ed97423ee] [ 35.726146] ? stack_trace_save+0x95/0xd0 [ 35.726151] ? __stack_depot_save+0x3f/0x4c0 [ 35.726157] _nfs4_lookup_root.isra.0+0x193/0x200 [nfsv4 d67fe18359c6743dcd6788d44186185ed97423ee] [ 35.726202] ? __pfx__nfs4_lookup_root.isra.0+0x10/0x10 [nfsv4 d67fe18359c6743dcd6788d44186185ed97423ee] [ 35.726246] ? kasan_save_stack+0x45/0x60 [ 35.726251] ? nfs_alloc_fattr+0x44/0x210 [nfs 1894ec9cbdec354be2bcab1be6e5e8ab9f92de62] [ 35.726290] ? nfs4_get_rootfh+0x92/0x290 [nfsv4 d67fe18359c6743dcd6788d44186185ed97423ee] [ 35.726341] ? nfs4_server_common_setup+0xa4/0x680 [nfsv4 d67fe18359c6743dcd6788d44186185ed97423ee] [ 35.726391] ? nfs4_create_server+0x8d7/0xf00 [nfsv4 d67fe18359c6743dcd6788d44186185ed97423ee] [ 35.726440] ? nfs4_try_get_tree+0xd1/0x250 [nfsv4 d67fe18359c6743dcd6788d44186185ed97423ee] [ 35.726488] ? entry_SYSCALL_64_after_hwframe+0x72/0xdc [ 35.726496] nfs4_lookup_root+0xeb/0x260 [nfsv4 d67fe18359c6743dcd6788d44186185ed97423ee] [ 35.726542] ? __pfx_nfs4_lookup_root+0x10/0x10 [nfsv4 d67fe18359c6743dcd6788d44186185ed97423ee] [ 35.726589] nfs4_proc_get_rootfh+0xdc/0x110 [nfsv4 d67fe18359c6743dcd6788d44186185ed97423ee] [ 35.726636] nfs4_get_rootfh+0xb4/0x290 [nfsv4 d67fe18359c6743dcd6788d44186185ed97423ee] [ 35.726685] ? __pfx_nfs4_get_rootfh+0x10/0x10 [nfsv4 d67fe18359c6743dcd6788d44186185ed97423ee] [ 35.726733] ? nfs4_set_client+0x2d8/0x430 [nfsv4 d67fe18359c6743dcd6788d44186185ed97423ee] [ 35.726785] nfs4_server_common_setup+0xa4/0x680 [nfsv4 d67fe18359c6743dcd6788d44186185ed97423ee] [ 35.726834] nfs4_create_server+0x8d7/0xf00 [nfsv4 d67fe18359c6743dcd6788d44186185ed97423ee] [ 35.726884] ? _raw_spin_lock+0x85/0xe0 [ 35.726888] ? __pfx_nfs4_create_server+0x10/0x10 [nfsv4 d67fe18359c6743dcd6788d44186185ed97423ee] [ 35.726937] ? __module_get+0x31/0xf0 [ 35.726942] nfs4_try_get_tree+0xd1/0x250 [nfsv4 d67fe18359c6743dcd6788d44186185ed97423ee] [ 35.726991] vfs_get_tree+0x84/0x2c0 [ 35.726996] path_mount+0xa9f/0x1a20 [ 35.727001] ? __pfx_path_mount+0x10/0x10 [ 35.727005] ? user_path_at_empty+0x44/0x60 [ 35.727008] ? kmem_cache_free+0x19e/0x320 [ 35.727013] __x64_sys_mount+0x214/0x280 [ 35.727017] ? __pfx___x64_sys_mount+0x10/0x10 [ 35.727020] ? _raw_spin_lock+0x85/0xe0 [ 35.727024] do_syscall_64+0x5c/0x90 [ 35.727029] ? syscall_exit_to_user_mode+0x1b/0x40 [ 35.727032] ? do_syscall_64+0x6b/0x90 [ 35.727036] entry_SYSCALL_64_after_hwframe+0x72/0xdc [ 35.727040] RIP: 0033:0x7f1291a5afde [ 35.727044] Code: 48 8b 0d 95 ed 0c 00 f7 d8 64 89 01 48 83 c8 ff c3 66 2e 0f 1f 84 00 00 00 00 00 90 f3 0f 1e fa 49 89 ca b8 a5 00 00 00 0f 05 <48> 3d 01 f0 ff ff 73 01 c3 48 8b 0d 62 ed 0c 00 f7 d8 64 89 01 48 [ 35.727047] RSP: 002b:00007ffd02e479e8 EFLAGS: 00000246 ORIG_RAX: 00000000000000a5 [ 35.727055] RAX: ffffffffffffffda RBX: 00007ffd02e47b90 RCX: 00007f1291a5afde [ 35.727058] RDX: 00005565e507c3b0 RSI: 00005565e507b500 RDI: 00005565e507b550 [ 35.727060] RBP: 00005565e50824f0 R08: 00005565e50824f0 R09: 0000000000000060 [ 35.727062] R10: 0000000000000000 R11: 0000000000000246 R12: 00007ffd02e47b90 [ 35.727065] R13: 00005565e5082210 R14: 0000000000000003 R15: 00005565e42168f8 [ 35.727069] </TASK>
[ 35.727073] Allocated by task 853: [ 35.727075] kasan_save_stack+0x33/0x60 [ 35.727079] kasan_set_track+0x25/0x30 [ 35.727082] __kasan_kmalloc+0xad/0xb0 [ 35.727086] __kmalloc+0x5e/0x160 [ 35.727088] gss_krb5_checksum+0xcf/0x630 [rpcsec_gss_krb5] [ 35.727095] gss_krb5_aes_encrypt+0x388/0x7c0 [rpcsec_gss_krb5] [ 35.727101] gss_krb5_wrap_v2+0x28e/0x3a0 [rpcsec_gss_krb5] [ 35.727107] gss_wrap_req_priv+0x3d7/0x1090 [auth_rpcgss] [ 35.727119] gss_wrap_req+0x1df/0x250 [auth_rpcgss] [ 35.727131] call_encode+0x75a/0x1000 [sunrpc] [ 35.727175] __rpc_execute+0x29b/0xcf0 [sunrpc] [ 35.727227] rpc_execute+0x21d/0x320 [sunrpc] [ 35.727277] rpc_run_task+0x467/0x650 [sunrpc] [ 35.727321] nfs4_call_sync_sequence+0x17e/0x2a0 [nfsv4] [ 35.727365] _nfs4_lookup_root.isra.0+0x193/0x200 [nfsv4] [ 35.727408] nfs4_lookup_root+0xeb/0x260 [nfsv4] [ 35.727453] nfs4_proc_get_rootfh+0xdc/0x110 [nfsv4] [ 35.727498] nfs4_get_rootfh+0xb4/0x290 [nfsv4] [ 35.727546] nfs4_server_common_setup+0xa4/0x680 [nfsv4] [ 35.727595] nfs4_create_server+0x8d7/0xf00 [nfsv4] [ 35.727643] nfs4_try_get_tree+0xd1/0x250 [nfsv4] [ 35.727690] vfs_get_tree+0x84/0x2c0 [ 35.727694] path_mount+0xa9f/0x1a20 [ 35.727697] __x64_sys_mount+0x214/0x280 [ 35.727701] do_syscall_64+0x5c/0x90 [ 35.727704] entry_SYSCALL_64_after_hwframe+0x72/0xdc
[ 35.727709] The buggy address belongs to the object at ffff888110cfc1a0 which belongs to the cache kmalloc-32 of size 32 [ 35.727712] The buggy address is located 0 bytes inside of 32-byte region [ffff888110cfc1a0, ffff888110cfc1c0)
[ 35.727717] The buggy address belongs to the physical page: [ 35.727721] page:ffffea0004433f00 refcount:1 mapcount:0 mapping:0000000000000000 index:0xffff888110cfce60 pfn:0x110cfc [ 35.727726] flags: 0x2ffff0000000200(slab|node=0|zone=2|lastcpupid=0xffff) [ 35.727731] raw: 02ffff0000000200 ffff888100042740 ffffea00044274d0 ffff888100040450 [ 35.727734] raw: ffff888110cfce60 0000000000150012 00000001ffffffff 0000000000000000 [ 35.727736] page dumped because: kasan: bad access detected [ 35.727740] page_owner tracks the page as allocated [ 35.727741] page last allocated via order 0, migratetype Unmovable, gfp_mask 0x12c40(GFP_NOFS|__GFP_NOWARN|__GFP_NORETRY), pid 715, tgid 715 (test2), ts 24589446140, free_ts 24535345796 [ 35.727747] post_alloc_hook+0x118/0x250 [ 35.727750] get_page_from_freelist+0x11ef/0x3a20 [ 35.727754] __alloc_pages+0x1d5/0x440 [ 35.727757] allocate_slab+0x346/0x4a0 [ 35.727760] ___slab_alloc+0x39a/0x9a0 [ 35.727763] __kmem_cache_alloc_node+0x143/0x3d0 [ 35.727766] __kmalloc+0x4d/0x160 [ 35.727768] gss_krb5_checksum+0xcf/0x630 [rpcsec_gss_krb5] [ 35.727775] gss_krb5_verify_mic_v2+0x2d2/0x4f0 [rpcsec_gss_krb5] [ 35.727780] gss_validate+0x360/0x700 [auth_rpcgss] [ 35.727792] rpc_decode_header+0x288/0xcb0 [sunrpc] [ 35.727836] call_decode+0x3a7/0x780 [sunrpc] [ 35.727880] __rpc_execute+0x29b/0xcf0 [sunrpc] [ 35.727932] rpc_execute+0x21d/0x320 [sunrpc] [ 35.727982] rpc_run_task+0x467/0x650 [sunrpc] [ 35.728026] nfs4_call_sync_sequence+0x17e/0x2a0 [nfsv4] [ 35.728070] page last free stack trace: [ 35.728072] free_pcp_prepare+0x66c/0x10e0 [ 35.728075] free_unref_page+0x4e/0x3c0 [ 35.728078] tlb_remove_table_rcu+0x77/0xc0 [ 35.728081] rcu_do_batch+0x34c/0xd00 [ 35.728084] rcu_core+0x447/0xf20 [ 35.728086] __do_softirq+0x1d6/0x5ed
[ 35.728091] Memory state around the buggy address: [ 35.728093] ffff888110cfc080: fc fc fc fc fc fc fc fc fc fc fc fc fa fb fb fb [ 35.728096] ffff888110cfc100: fc fc fc fc fc fc fc fc fc fc fc fc fc fc fc fc [ 35.728098] >ffff888110cfc180: fc fc fc fc 00 00 04 fc fc fc fc fc fc fc fc fc [ 35.728100] ^ [ 35.728102] ffff888110cfc200: fc fc fc fc fc fc fc fc fc fc fc fc 00 00 00 00 [ 35.728104] ffff888110cfc280: fc fc fc fc fc fc fc fc fc fc fc fc fc fc fc fc [ 35.728106] ==================================================================
/* Maximum blocksize for the supported crypto algorithms */ #define GSS_KRB5_MAX_BLOCKSIZE (16) @@ -160,6 +160,12 @@ enum seal_alg { SEAL_ALG_DES3KD = 0x0002 };
+/*
- These values are assigned by IANA and published via the
- subregistry at the link below:
- */
#define CKSUMTYPE_CRC32 0x0001 #define CKSUMTYPE_RSA_MD4 0x0002 #define CKSUMTYPE_RSA_MD4_DES 0x0003 @@ -170,6 +176,8 @@ enum seal_alg { #define CKSUMTYPE_HMAC_SHA1_DES3 0x000c #define CKSUMTYPE_HMAC_SHA1_96_AES128 0x000f #define CKSUMTYPE_HMAC_SHA1_96_AES256 0x0010 +#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 */ @@ -190,6 +198,11 @@ enum seal_alg {
/* 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:
*/ #define ENCTYPE_NULL 0x0000 #define ENCTYPE_DES_CBC_CRC 0x0001 /* DES cbc mode with CRC-32 */ @@ -203,6 +216,8 @@ enum seal_alg { #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_UNKNOWN 0x01ff diff --git a/net/sunrpc/Kconfig b/net/sunrpc/Kconfig index 1135ff362132..b1aa2318e1dc 100644 --- a/net/sunrpc/Kconfig +++ b/net/sunrpc/Kconfig @@ -76,6 +76,20 @@ config RPCSEC_GSS_KRB5_ENCTYPES_AES_SHA1 SHA-1 digests. These include aes128-cts-hmac-sha1-96 and aes256-cts-hmac-sha1-96.
+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
select RPCSEC_GSS_KRB5_CRYPTOSYSTEM
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 ec3cca8fadc5..1951867f3fa8 100644 --- a/net/sunrpc/auth_gss/gss_krb5_mech.c +++ b/net/sunrpc/auth_gss/gss_krb5_mech.c @@ -146,6 +146,57 @@ static const struct gss_krb5_enctype supported_gss_krb5_enctypes[] = { .keyed_cksum = 1, }, #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),
.import_ctx = gss_krb5_import_ctx_v2,
.get_mic = gss_krb5_get_mic_v2,
.verify_mic = gss_krb5_verify_mic_v2,
.wrap = gss_krb5_wrap_v2,
.unwrap = gss_krb5_unwrap_v2,
},
/*
* 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),
.import_ctx = gss_krb5_import_ctx_v2,
.get_mic = gss_krb5_get_mic_v2,
.verify_mic = gss_krb5_verify_mic_v2,
.wrap = gss_krb5_wrap_v2,
.unwrap = gss_krb5_unwrap_v2,
},
+#endif };
/*
-- Chuck Lever
On Wed, Mar 22, 2023 at 12:31 PM Chuck Lever III chuck.lever@oracle.com wrote:
On Mar 22, 2023, at 11:49 AM, Anna Schumaker schumaker.anna@gmail.com wrote:
Hi Chuck
On Sun, Jan 15, 2023 at 12:23 PM Chuck Lever cel@kernel.org wrote:
From: Chuck Lever chuck.lever@oracle.com
Fill in entries in the supported_gss_krb5_enctypes array for the encryption types defined in RFC 8009. These new enctypes use the SHA-256 and SHA-384 message digest algorithms (as defined in FIPS-180) instead of the deprecated SHA-1 algorithm, and are thus more secure.
Note that NIST has scheduled SHA-1 for deprecation:
https://www.nist.gov/news-events/news/2022/12/nist-retires-sha-1-cryptograph...
Thus these new encryption types are placed under a separate CONFIG option to enable distributors to separately introduce support for the AES-SHA2 enctypes and deprecate support for the current set of AES-SHA1 encryption types as their user space allows.
As this implementation is still a "beta", the default is to not build it automatically.
Tested-by: Scott Mayhew smayhew@redhat.com Signed-off-by: Chuck Lever chuck.lever@oracle.com
include/linux/sunrpc/gss_krb5.h | 19 ++++++++++++- net/sunrpc/Kconfig | 14 ++++++++++ net/sunrpc/auth_gss/gss_krb5_mech.c | 51 +++++++++++++++++++++++++++++++++++ 3 files changed, 82 insertions(+), 2 deletions(-)
diff --git a/include/linux/sunrpc/gss_krb5.h b/include/linux/sunrpc/gss_krb5.h index 3e97d2a7c87d..8ff397b5c04b 100644 --- a/include/linux/sunrpc/gss_krb5.h +++ b/include/linux/sunrpc/gss_krb5.h @@ -54,8 +54,8 @@ /* Maximum key length (in bytes) for the supported crypto algorithms */ #define GSS_KRB5_MAX_KEYLEN (32)
-/* Maximum checksum function output for the supported crypto algorithms */ -#define GSS_KRB5_MAX_CKSUM_LEN (20) +/* Maximum checksum function output for the supported enctypes */ +#define GSS_KRB5_MAX_CKSUM_LEN (24)
I'm having some problems that I bisected to this patch, specifically this change to GSS_KRB5_MAX_CKSUM_LEN. KASAN reports it as a slab-out-of-bounds in gss_krb5_checksum(), and it can cause my client to panic when running cthon basic tests with krb5p. I was wondering if you've seen this?
I have not. Scott reported a similar problem that was addressed before merge, so this one is new to me. It looks like there's something in gss_krb5_checksum() that assumes the value of the maximum checksum size.
Can you run "gss_krb5_checksum+0x4b6" through faddr2line for me?
Running faddr2line gives me:
gss_krb5_checksum+0x4b6/0x630: ahash_request_free at /home/anna/Programs/linux-nfs.git/./include/crypto/hash.h:619 (inlined by) gss_krb5_checksum at /home/anna/Programs/linux-nfs.git/net/sunrpc/auth_gss/gss_krb5_crypto.c:358
I hope this helps! Anna
Anna
Here is what kasan tells me:
[ 35.725366] ================================================================== [ 35.725373] BUG: KASAN: slab-out-of-bounds in gss_krb5_checksum+0x4b6/0x630 [rpcsec_gss_krb5] [ 35.725383] Read of size 24 at addr ffff888110cfc1a0 by task mount.nfs/853
[ 35.725390] CPU: 2 PID: 853 Comm: mount.nfs Not tainted 6.2.0-ga40cf7530d31+ #37820 4b7d53453529728aac4e973d4ba6a17952148f02 [ 35.725395] Hardware name: QEMU Standard PC (Q35 + ICH9, 2009), BIOS 0.0.0 02/06/2015 [ 35.725399] Call Trace: [ 35.725401] <TASK> [ 35.725404] dump_stack_lvl+0x48/0x60 [ 35.725409] print_report+0x184/0x4a8 [ 35.725414] ? memcpy+0x3c/0x60 [ 35.725419] ? gss_krb5_checksum+0x4b6/0x630 [rpcsec_gss_krb5 2fd8c249acfdf3162b23b30d5eb7af0425d84960] [ 35.725426] kasan_report+0xc9/0x150 [ 35.725431] ? gss_krb5_checksum+0x4b6/0x630 [rpcsec_gss_krb5 2fd8c249acfdf3162b23b30d5eb7af0425d84960] [ 35.725439] kasan_check_range+0x13e/0x1c0 [ 35.725447] memcpy+0x23/0x60 [ 35.725451] gss_krb5_checksum+0x4b6/0x630 [rpcsec_gss_krb5 2fd8c249acfdf3162b23b30d5eb7af0425d84960] [ 35.725460] ? __pfx_gss_krb5_checksum+0x10/0x10 [rpcsec_gss_krb5 2fd8c249acfdf3162b23b30d5eb7af0425d84960] [ 35.725467] ? memmove+0x3c/0x60 [ 35.725472] gss_krb5_aes_encrypt+0x388/0x7c0 [rpcsec_gss_krb5 2fd8c249acfdf3162b23b30d5eb7af0425d84960] [ 35.725480] ? __pfx_gss_krb5_aes_encrypt+0x10/0x10 [rpcsec_gss_krb5 2fd8c249acfdf3162b23b30d5eb7af0425d84960] [ 35.725487] ? memmove+0x3c/0x60 [ 35.725491] gss_krb5_wrap_v2+0x28e/0x3a0 [rpcsec_gss_krb5 2fd8c249acfdf3162b23b30d5eb7af0425d84960] [ 35.725500] gss_wrap_req_priv+0x3d7/0x1090 [auth_rpcgss 9532107bdb7719d1a30fdcf239028e9e54e0c27c] [ 35.725517] gss_wrap_req+0x1df/0x250 [auth_rpcgss 9532107bdb7719d1a30fdcf239028e9e54e0c27c] [ 35.725572] call_encode+0x75a/0x1000 [sunrpc 807a235f89c5b6b32dbda9261e96d6b1ac9ed4f5] [ 35.725626] ? __pfx_call_encode+0x10/0x10 [sunrpc 807a235f89c5b6b32dbda9261e96d6b1ac9ed4f5] [ 35.725671] ? __kasan_kmalloc+0xad/0xb0 [ 35.725676] ? xprt_alloc_slot+0x1ca/0x590 [sunrpc 807a235f89c5b6b32dbda9261e96d6b1ac9ed4f5] [ 35.725724] ? call_allocate+0x30d/0x6b0 [sunrpc 807a235f89c5b6b32dbda9261e96d6b1ac9ed4f5] [ 35.725779] ? __pfx_call_encode+0x10/0x10 [sunrpc 807a235f89c5b6b32dbda9261e96d6b1ac9ed4f5] [ 35.725829] __rpc_execute+0x29b/0xcf0 [sunrpc 807a235f89c5b6b32dbda9261e96d6b1ac9ed4f5] [ 35.725885] ? __pfx___rpc_execute+0x10/0x10 [sunrpc 807a235f89c5b6b32dbda9261e96d6b1ac9ed4f5] [ 35.725936] ? __pfx_wake_up_bit+0x10/0x10 [ 35.725941] ? _raw_spin_lock+0x85/0xe0 [ 35.725945] rpc_execute+0x21d/0x320 [sunrpc 807a235f89c5b6b32dbda9261e96d6b1ac9ed4f5] [ 35.725997] rpc_run_task+0x467/0x650 [sunrpc 807a235f89c5b6b32dbda9261e96d6b1ac9ed4f5] [ 35.726044] nfs4_call_sync_sequence+0x17e/0x2a0 [nfsv4 d67fe18359c6743dcd6788d44186185ed97423ee] [ 35.726095] ? unwind_get_return_address+0x5e/0xa0 [ 35.726100] ? __pfx_nfs4_call_sync_sequence+0x10/0x10 [nfsv4 d67fe18359c6743dcd6788d44186185ed97423ee] [ 35.726146] ? stack_trace_save+0x95/0xd0 [ 35.726151] ? __stack_depot_save+0x3f/0x4c0 [ 35.726157] _nfs4_lookup_root.isra.0+0x193/0x200 [nfsv4 d67fe18359c6743dcd6788d44186185ed97423ee] [ 35.726202] ? __pfx__nfs4_lookup_root.isra.0+0x10/0x10 [nfsv4 d67fe18359c6743dcd6788d44186185ed97423ee] [ 35.726246] ? kasan_save_stack+0x45/0x60 [ 35.726251] ? nfs_alloc_fattr+0x44/0x210 [nfs 1894ec9cbdec354be2bcab1be6e5e8ab9f92de62] [ 35.726290] ? nfs4_get_rootfh+0x92/0x290 [nfsv4 d67fe18359c6743dcd6788d44186185ed97423ee] [ 35.726341] ? nfs4_server_common_setup+0xa4/0x680 [nfsv4 d67fe18359c6743dcd6788d44186185ed97423ee] [ 35.726391] ? nfs4_create_server+0x8d7/0xf00 [nfsv4 d67fe18359c6743dcd6788d44186185ed97423ee] [ 35.726440] ? nfs4_try_get_tree+0xd1/0x250 [nfsv4 d67fe18359c6743dcd6788d44186185ed97423ee] [ 35.726488] ? entry_SYSCALL_64_after_hwframe+0x72/0xdc [ 35.726496] nfs4_lookup_root+0xeb/0x260 [nfsv4 d67fe18359c6743dcd6788d44186185ed97423ee] [ 35.726542] ? __pfx_nfs4_lookup_root+0x10/0x10 [nfsv4 d67fe18359c6743dcd6788d44186185ed97423ee] [ 35.726589] nfs4_proc_get_rootfh+0xdc/0x110 [nfsv4 d67fe18359c6743dcd6788d44186185ed97423ee] [ 35.726636] nfs4_get_rootfh+0xb4/0x290 [nfsv4 d67fe18359c6743dcd6788d44186185ed97423ee] [ 35.726685] ? __pfx_nfs4_get_rootfh+0x10/0x10 [nfsv4 d67fe18359c6743dcd6788d44186185ed97423ee] [ 35.726733] ? nfs4_set_client+0x2d8/0x430 [nfsv4 d67fe18359c6743dcd6788d44186185ed97423ee] [ 35.726785] nfs4_server_common_setup+0xa4/0x680 [nfsv4 d67fe18359c6743dcd6788d44186185ed97423ee] [ 35.726834] nfs4_create_server+0x8d7/0xf00 [nfsv4 d67fe18359c6743dcd6788d44186185ed97423ee] [ 35.726884] ? _raw_spin_lock+0x85/0xe0 [ 35.726888] ? __pfx_nfs4_create_server+0x10/0x10 [nfsv4 d67fe18359c6743dcd6788d44186185ed97423ee] [ 35.726937] ? __module_get+0x31/0xf0 [ 35.726942] nfs4_try_get_tree+0xd1/0x250 [nfsv4 d67fe18359c6743dcd6788d44186185ed97423ee] [ 35.726991] vfs_get_tree+0x84/0x2c0 [ 35.726996] path_mount+0xa9f/0x1a20 [ 35.727001] ? __pfx_path_mount+0x10/0x10 [ 35.727005] ? user_path_at_empty+0x44/0x60 [ 35.727008] ? kmem_cache_free+0x19e/0x320 [ 35.727013] __x64_sys_mount+0x214/0x280 [ 35.727017] ? __pfx___x64_sys_mount+0x10/0x10 [ 35.727020] ? _raw_spin_lock+0x85/0xe0 [ 35.727024] do_syscall_64+0x5c/0x90 [ 35.727029] ? syscall_exit_to_user_mode+0x1b/0x40 [ 35.727032] ? do_syscall_64+0x6b/0x90 [ 35.727036] entry_SYSCALL_64_after_hwframe+0x72/0xdc [ 35.727040] RIP: 0033:0x7f1291a5afde [ 35.727044] Code: 48 8b 0d 95 ed 0c 00 f7 d8 64 89 01 48 83 c8 ff c3 66 2e 0f 1f 84 00 00 00 00 00 90 f3 0f 1e fa 49 89 ca b8 a5 00 00 00 0f 05 <48> 3d 01 f0 ff ff 73 01 c3 48 8b 0d 62 ed 0c 00 f7 d8 64 89 01 48 [ 35.727047] RSP: 002b:00007ffd02e479e8 EFLAGS: 00000246 ORIG_RAX: 00000000000000a5 [ 35.727055] RAX: ffffffffffffffda RBX: 00007ffd02e47b90 RCX: 00007f1291a5afde [ 35.727058] RDX: 00005565e507c3b0 RSI: 00005565e507b500 RDI: 00005565e507b550 [ 35.727060] RBP: 00005565e50824f0 R08: 00005565e50824f0 R09: 0000000000000060 [ 35.727062] R10: 0000000000000000 R11: 0000000000000246 R12: 00007ffd02e47b90 [ 35.727065] R13: 00005565e5082210 R14: 0000000000000003 R15: 00005565e42168f8 [ 35.727069] </TASK>
[ 35.727073] Allocated by task 853: [ 35.727075] kasan_save_stack+0x33/0x60 [ 35.727079] kasan_set_track+0x25/0x30 [ 35.727082] __kasan_kmalloc+0xad/0xb0 [ 35.727086] __kmalloc+0x5e/0x160 [ 35.727088] gss_krb5_checksum+0xcf/0x630 [rpcsec_gss_krb5] [ 35.727095] gss_krb5_aes_encrypt+0x388/0x7c0 [rpcsec_gss_krb5] [ 35.727101] gss_krb5_wrap_v2+0x28e/0x3a0 [rpcsec_gss_krb5] [ 35.727107] gss_wrap_req_priv+0x3d7/0x1090 [auth_rpcgss] [ 35.727119] gss_wrap_req+0x1df/0x250 [auth_rpcgss] [ 35.727131] call_encode+0x75a/0x1000 [sunrpc] [ 35.727175] __rpc_execute+0x29b/0xcf0 [sunrpc] [ 35.727227] rpc_execute+0x21d/0x320 [sunrpc] [ 35.727277] rpc_run_task+0x467/0x650 [sunrpc] [ 35.727321] nfs4_call_sync_sequence+0x17e/0x2a0 [nfsv4] [ 35.727365] _nfs4_lookup_root.isra.0+0x193/0x200 [nfsv4] [ 35.727408] nfs4_lookup_root+0xeb/0x260 [nfsv4] [ 35.727453] nfs4_proc_get_rootfh+0xdc/0x110 [nfsv4] [ 35.727498] nfs4_get_rootfh+0xb4/0x290 [nfsv4] [ 35.727546] nfs4_server_common_setup+0xa4/0x680 [nfsv4] [ 35.727595] nfs4_create_server+0x8d7/0xf00 [nfsv4] [ 35.727643] nfs4_try_get_tree+0xd1/0x250 [nfsv4] [ 35.727690] vfs_get_tree+0x84/0x2c0 [ 35.727694] path_mount+0xa9f/0x1a20 [ 35.727697] __x64_sys_mount+0x214/0x280 [ 35.727701] do_syscall_64+0x5c/0x90 [ 35.727704] entry_SYSCALL_64_after_hwframe+0x72/0xdc
[ 35.727709] The buggy address belongs to the object at ffff888110cfc1a0 which belongs to the cache kmalloc-32 of size 32 [ 35.727712] The buggy address is located 0 bytes inside of 32-byte region [ffff888110cfc1a0, ffff888110cfc1c0)
[ 35.727717] The buggy address belongs to the physical page: [ 35.727721] page:ffffea0004433f00 refcount:1 mapcount:0 mapping:0000000000000000 index:0xffff888110cfce60 pfn:0x110cfc [ 35.727726] flags: 0x2ffff0000000200(slab|node=0|zone=2|lastcpupid=0xffff) [ 35.727731] raw: 02ffff0000000200 ffff888100042740 ffffea00044274d0 ffff888100040450 [ 35.727734] raw: ffff888110cfce60 0000000000150012 00000001ffffffff 0000000000000000 [ 35.727736] page dumped because: kasan: bad access detected [ 35.727740] page_owner tracks the page as allocated [ 35.727741] page last allocated via order 0, migratetype Unmovable, gfp_mask 0x12c40(GFP_NOFS|__GFP_NOWARN|__GFP_NORETRY), pid 715, tgid 715 (test2), ts 24589446140, free_ts 24535345796 [ 35.727747] post_alloc_hook+0x118/0x250 [ 35.727750] get_page_from_freelist+0x11ef/0x3a20 [ 35.727754] __alloc_pages+0x1d5/0x440 [ 35.727757] allocate_slab+0x346/0x4a0 [ 35.727760] ___slab_alloc+0x39a/0x9a0 [ 35.727763] __kmem_cache_alloc_node+0x143/0x3d0 [ 35.727766] __kmalloc+0x4d/0x160 [ 35.727768] gss_krb5_checksum+0xcf/0x630 [rpcsec_gss_krb5] [ 35.727775] gss_krb5_verify_mic_v2+0x2d2/0x4f0 [rpcsec_gss_krb5] [ 35.727780] gss_validate+0x360/0x700 [auth_rpcgss] [ 35.727792] rpc_decode_header+0x288/0xcb0 [sunrpc] [ 35.727836] call_decode+0x3a7/0x780 [sunrpc] [ 35.727880] __rpc_execute+0x29b/0xcf0 [sunrpc] [ 35.727932] rpc_execute+0x21d/0x320 [sunrpc] [ 35.727982] rpc_run_task+0x467/0x650 [sunrpc] [ 35.728026] nfs4_call_sync_sequence+0x17e/0x2a0 [nfsv4] [ 35.728070] page last free stack trace: [ 35.728072] free_pcp_prepare+0x66c/0x10e0 [ 35.728075] free_unref_page+0x4e/0x3c0 [ 35.728078] tlb_remove_table_rcu+0x77/0xc0 [ 35.728081] rcu_do_batch+0x34c/0xd00 [ 35.728084] rcu_core+0x447/0xf20 [ 35.728086] __do_softirq+0x1d6/0x5ed
[ 35.728091] Memory state around the buggy address: [ 35.728093] ffff888110cfc080: fc fc fc fc fc fc fc fc fc fc fc fc fa fb fb fb [ 35.728096] ffff888110cfc100: fc fc fc fc fc fc fc fc fc fc fc fc fc fc fc fc [ 35.728098] >ffff888110cfc180: fc fc fc fc 00 00 04 fc fc fc fc fc fc fc fc fc [ 35.728100] ^ [ 35.728102] ffff888110cfc200: fc fc fc fc fc fc fc fc fc fc fc fc 00 00 00 00 [ 35.728104] ffff888110cfc280: fc fc fc fc fc fc fc fc fc fc fc fc fc fc fc fc [ 35.728106] ==================================================================
/* Maximum blocksize for the supported crypto algorithms */ #define GSS_KRB5_MAX_BLOCKSIZE (16) @@ -160,6 +160,12 @@ enum seal_alg { SEAL_ALG_DES3KD = 0x0002 };
+/*
- These values are assigned by IANA and published via the
- subregistry at the link below:
- */
#define CKSUMTYPE_CRC32 0x0001 #define CKSUMTYPE_RSA_MD4 0x0002 #define CKSUMTYPE_RSA_MD4_DES 0x0003 @@ -170,6 +176,8 @@ enum seal_alg { #define CKSUMTYPE_HMAC_SHA1_DES3 0x000c #define CKSUMTYPE_HMAC_SHA1_96_AES128 0x000f #define CKSUMTYPE_HMAC_SHA1_96_AES256 0x0010 +#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 */ @@ -190,6 +198,11 @@ enum seal_alg {
/* 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:
*/ #define ENCTYPE_NULL 0x0000 #define ENCTYPE_DES_CBC_CRC 0x0001 /* DES cbc mode with CRC-32 */ @@ -203,6 +216,8 @@ enum seal_alg { #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_UNKNOWN 0x01ff diff --git a/net/sunrpc/Kconfig b/net/sunrpc/Kconfig index 1135ff362132..b1aa2318e1dc 100644 --- a/net/sunrpc/Kconfig +++ b/net/sunrpc/Kconfig @@ -76,6 +76,20 @@ config RPCSEC_GSS_KRB5_ENCTYPES_AES_SHA1 SHA-1 digests. These include aes128-cts-hmac-sha1-96 and aes256-cts-hmac-sha1-96.
+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
select RPCSEC_GSS_KRB5_CRYPTOSYSTEM
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 ec3cca8fadc5..1951867f3fa8 100644 --- a/net/sunrpc/auth_gss/gss_krb5_mech.c +++ b/net/sunrpc/auth_gss/gss_krb5_mech.c @@ -146,6 +146,57 @@ static const struct gss_krb5_enctype supported_gss_krb5_enctypes[] = { .keyed_cksum = 1, }, #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),
.import_ctx = gss_krb5_import_ctx_v2,
.get_mic = gss_krb5_get_mic_v2,
.verify_mic = gss_krb5_verify_mic_v2,
.wrap = gss_krb5_wrap_v2,
.unwrap = gss_krb5_unwrap_v2,
},
/*
* 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),
.import_ctx = gss_krb5_import_ctx_v2,
.get_mic = gss_krb5_get_mic_v2,
.verify_mic = gss_krb5_verify_mic_v2,
.wrap = gss_krb5_wrap_v2,
.unwrap = gss_krb5_unwrap_v2,
},
+#endif };
/*
-- Chuck Lever
On Wed, Mar 22, 2023 at 1:06 PM Anna Schumaker schumaker.anna@gmail.com wrote:
On Wed, Mar 22, 2023 at 12:31 PM Chuck Lever III chuck.lever@oracle.com wrote:
On Mar 22, 2023, at 11:49 AM, Anna Schumaker schumaker.anna@gmail.com wrote:
Hi Chuck
On Sun, Jan 15, 2023 at 12:23 PM Chuck Lever cel@kernel.org wrote:
From: Chuck Lever chuck.lever@oracle.com
Fill in entries in the supported_gss_krb5_enctypes array for the encryption types defined in RFC 8009. These new enctypes use the SHA-256 and SHA-384 message digest algorithms (as defined in FIPS-180) instead of the deprecated SHA-1 algorithm, and are thus more secure.
Note that NIST has scheduled SHA-1 for deprecation:
https://www.nist.gov/news-events/news/2022/12/nist-retires-sha-1-cryptograph...
Thus these new encryption types are placed under a separate CONFIG option to enable distributors to separately introduce support for the AES-SHA2 enctypes and deprecate support for the current set of AES-SHA1 encryption types as their user space allows.
As this implementation is still a "beta", the default is to not build it automatically.
Tested-by: Scott Mayhew smayhew@redhat.com Signed-off-by: Chuck Lever chuck.lever@oracle.com
include/linux/sunrpc/gss_krb5.h | 19 ++++++++++++- net/sunrpc/Kconfig | 14 ++++++++++ net/sunrpc/auth_gss/gss_krb5_mech.c | 51 +++++++++++++++++++++++++++++++++++ 3 files changed, 82 insertions(+), 2 deletions(-)
diff --git a/include/linux/sunrpc/gss_krb5.h b/include/linux/sunrpc/gss_krb5.h index 3e97d2a7c87d..8ff397b5c04b 100644 --- a/include/linux/sunrpc/gss_krb5.h +++ b/include/linux/sunrpc/gss_krb5.h @@ -54,8 +54,8 @@ /* Maximum key length (in bytes) for the supported crypto algorithms */ #define GSS_KRB5_MAX_KEYLEN (32)
-/* Maximum checksum function output for the supported crypto algorithms */ -#define GSS_KRB5_MAX_CKSUM_LEN (20) +/* Maximum checksum function output for the supported enctypes */ +#define GSS_KRB5_MAX_CKSUM_LEN (24)
I'm having some problems that I bisected to this patch, specifically this change to GSS_KRB5_MAX_CKSUM_LEN. KASAN reports it as a slab-out-of-bounds in gss_krb5_checksum(), and it can cause my client to panic when running cthon basic tests with krb5p. I was wondering if you've seen this?
I have not. Scott reported a similar problem that was addressed before merge, so this one is new to me. It looks like there's something in gss_krb5_checksum() that assumes the value of the maximum checksum size.
Can you run "gss_krb5_checksum+0x4b6" through faddr2line for me?
Running faddr2line gives me:
gss_krb5_checksum+0x4b6/0x630: ahash_request_free at /home/anna/Programs/linux-nfs.git/./include/crypto/hash.h:619 (inlined by) gss_krb5_checksum at /home/anna/Programs/linux-nfs.git/net/sunrpc/auth_gss/gss_krb5_crypto.c:358
Oh, on -rc3 it panics before kasan is triggered. Here is the top part of the stack trace:
[ 35.550547] detected buffer overflow in memcpy [ 35.551669] ------------[ cut here ]------------ [ 35.551672] kernel BUG at lib/string_helpers.c:1027! [ 35.551685] invalid opcode: 0000 [#1] PREEMPT SMP KASAN PTI [ 35.552164] CPU: 0 PID: 843 Comm: mount.nfs Not tainted 6.3.0-rc3-g2c019977ca17+ #37825 6715e14f5cddf0578c9eda83d59769c55d24257d [ 35.553119] Hardware name: QEMU Standard PC (Q35 + ICH9, 2009), BIOS 0.0.0 02/06/2015 [ 35.553739] RIP: 0010:fortify_panic+0x13/0x20 [ 35.554100] Code: a3 ba 8c ff eb d7 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 f3 0f 1e fa 48 89 fe 48 c7 c7 c0 63 ea ac e8 5d 56 27 ff <0f> 0b 66 66 2e 0f 1f 84 00 00 00 00 00 90 90 90 90 90 90 90 90 90 [ 35.555563] RSP: 0018:ffffc90000c3f180 EFLAGS: 00010246 [ 35.556039] RAX: 0000000000000022 RBX: 1ffff92000187e36 RCX: ffffffffab2b2bfe [ 35.556609] RDX: 0000000000000000 RSI: 0000000000000008 RDI: ffff888156434a8c [ 35.557177] RBP: ffff888124148560 R08: 0000000000000001 R09: ffffc90000c3ef6f [ 35.557745] R10: fffff52000187ded R11: ffffffffad942a30 R12: ffff88811ecf4528 [ 35.558314] R13: ffff88811ecf4518 R14: ffff88811ecf44e8 R15: ffff88811ecf4508 [ 35.558882] FS: 00007f12ce4dc740(0000) GS:ffff888156400000(0000) knlGS:0000000000000000 [ 35.559525] CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033 [ 35.559987] CR2: 00007f02b0ff9d58 CR3: 00000001145d0002 CR4: 0000000000370ef0 [ 35.560557] DR0: 0000000000000000 DR1: 0000000000000000 DR2: 0000000000000000 [ 35.561125] DR3: 0000000000000000 DR6: 00000000fffe0ff0 DR7: 0000000000000400 [ 35.561694] Call Trace: [ 35.561901] <TASK> [ 35.562084] gss_krb5_checksum+0x591/0x650 [rpcsec_gss_krb5 1524c9c037fd463ba1ee0a2a5b4157ea3136b1b2] [ 35.562946] ? __pfx_gss_krb5_checksum+0x10/0x10 [rpcsec_gss_krb5 1524c9c037fd463ba1ee0a2a5b4157ea3136b1b2] [ 35.563987] ? encode_sequence+0x184/0x640 [nfsv4 b57133408187f0f88ce764a210a7bb097813c617] [ 35.564963] gss_krb5_aes_encrypt+0x388/0x7c0 [rpcsec_gss_krb5 1524c9c037fd463ba1ee0a2a5b4157ea3136b1b2] [ 35.565892] ? __pfx_gss_krb5_aes_encrypt+0x10/0x10 [rpcsec_gss_krb5 1524c9c037fd463ba1ee0a2a5b4157ea3136b1b2] [ 35.566696] gss_krb5_wrap_v2+0x28f/0x3c0 [rpcsec_gss_krb5 1524c9c037fd463ba1ee0a2a5b4157ea3136b1b2] [ 35.567428] gss_wrap_req_priv+0x3d7/0x1090 [auth_rpcgss ea31c14c10f9562df68baa20a41bd10d3236fb09] [ 35.568157] gss_wrap_req+0x1df/0x250 [auth_rpcgss ea31c14c10f9562df68baa20a41bd10d3236fb09] [ 35.568843] call_encode+0x75a/0x1000 [sunrpc 9537ccf71f30f72cd19b32523261d8120f993009]
Running faddr2line with "gss_krb5_checksum+0x591" gives me:
gss_krb5_checksum+0x591/0x650: ahash_request_set_crypt at /home/anna/Programs/linux-nfs.git/./include/crypto/hash.h:687 (inlined by) gss_krb5_checksum at /home/anna/Programs/linux-nfs.git/net/sunrpc/auth_gss/gss_krb5_crypto.c:346
Anna
I hope this helps! Anna
Anna
Here is what kasan tells me:
[ 35.725366] ================================================================== [ 35.725373] BUG: KASAN: slab-out-of-bounds in gss_krb5_checksum+0x4b6/0x630 [rpcsec_gss_krb5] [ 35.725383] Read of size 24 at addr ffff888110cfc1a0 by task mount.nfs/853
[ 35.725390] CPU: 2 PID: 853 Comm: mount.nfs Not tainted 6.2.0-ga40cf7530d31+ #37820 4b7d53453529728aac4e973d4ba6a17952148f02 [ 35.725395] Hardware name: QEMU Standard PC (Q35 + ICH9, 2009), BIOS 0.0.0 02/06/2015 [ 35.725399] Call Trace: [ 35.725401] <TASK> [ 35.725404] dump_stack_lvl+0x48/0x60 [ 35.725409] print_report+0x184/0x4a8 [ 35.725414] ? memcpy+0x3c/0x60 [ 35.725419] ? gss_krb5_checksum+0x4b6/0x630 [rpcsec_gss_krb5 2fd8c249acfdf3162b23b30d5eb7af0425d84960] [ 35.725426] kasan_report+0xc9/0x150 [ 35.725431] ? gss_krb5_checksum+0x4b6/0x630 [rpcsec_gss_krb5 2fd8c249acfdf3162b23b30d5eb7af0425d84960] [ 35.725439] kasan_check_range+0x13e/0x1c0 [ 35.725447] memcpy+0x23/0x60 [ 35.725451] gss_krb5_checksum+0x4b6/0x630 [rpcsec_gss_krb5 2fd8c249acfdf3162b23b30d5eb7af0425d84960] [ 35.725460] ? __pfx_gss_krb5_checksum+0x10/0x10 [rpcsec_gss_krb5 2fd8c249acfdf3162b23b30d5eb7af0425d84960] [ 35.725467] ? memmove+0x3c/0x60 [ 35.725472] gss_krb5_aes_encrypt+0x388/0x7c0 [rpcsec_gss_krb5 2fd8c249acfdf3162b23b30d5eb7af0425d84960] [ 35.725480] ? __pfx_gss_krb5_aes_encrypt+0x10/0x10 [rpcsec_gss_krb5 2fd8c249acfdf3162b23b30d5eb7af0425d84960] [ 35.725487] ? memmove+0x3c/0x60 [ 35.725491] gss_krb5_wrap_v2+0x28e/0x3a0 [rpcsec_gss_krb5 2fd8c249acfdf3162b23b30d5eb7af0425d84960] [ 35.725500] gss_wrap_req_priv+0x3d7/0x1090 [auth_rpcgss 9532107bdb7719d1a30fdcf239028e9e54e0c27c] [ 35.725517] gss_wrap_req+0x1df/0x250 [auth_rpcgss 9532107bdb7719d1a30fdcf239028e9e54e0c27c] [ 35.725572] call_encode+0x75a/0x1000 [sunrpc 807a235f89c5b6b32dbda9261e96d6b1ac9ed4f5] [ 35.725626] ? __pfx_call_encode+0x10/0x10 [sunrpc 807a235f89c5b6b32dbda9261e96d6b1ac9ed4f5] [ 35.725671] ? __kasan_kmalloc+0xad/0xb0 [ 35.725676] ? xprt_alloc_slot+0x1ca/0x590 [sunrpc 807a235f89c5b6b32dbda9261e96d6b1ac9ed4f5] [ 35.725724] ? call_allocate+0x30d/0x6b0 [sunrpc 807a235f89c5b6b32dbda9261e96d6b1ac9ed4f5] [ 35.725779] ? __pfx_call_encode+0x10/0x10 [sunrpc 807a235f89c5b6b32dbda9261e96d6b1ac9ed4f5] [ 35.725829] __rpc_execute+0x29b/0xcf0 [sunrpc 807a235f89c5b6b32dbda9261e96d6b1ac9ed4f5] [ 35.725885] ? __pfx___rpc_execute+0x10/0x10 [sunrpc 807a235f89c5b6b32dbda9261e96d6b1ac9ed4f5] [ 35.725936] ? __pfx_wake_up_bit+0x10/0x10 [ 35.725941] ? _raw_spin_lock+0x85/0xe0 [ 35.725945] rpc_execute+0x21d/0x320 [sunrpc 807a235f89c5b6b32dbda9261e96d6b1ac9ed4f5] [ 35.725997] rpc_run_task+0x467/0x650 [sunrpc 807a235f89c5b6b32dbda9261e96d6b1ac9ed4f5] [ 35.726044] nfs4_call_sync_sequence+0x17e/0x2a0 [nfsv4 d67fe18359c6743dcd6788d44186185ed97423ee] [ 35.726095] ? unwind_get_return_address+0x5e/0xa0 [ 35.726100] ? __pfx_nfs4_call_sync_sequence+0x10/0x10 [nfsv4 d67fe18359c6743dcd6788d44186185ed97423ee] [ 35.726146] ? stack_trace_save+0x95/0xd0 [ 35.726151] ? __stack_depot_save+0x3f/0x4c0 [ 35.726157] _nfs4_lookup_root.isra.0+0x193/0x200 [nfsv4 d67fe18359c6743dcd6788d44186185ed97423ee] [ 35.726202] ? __pfx__nfs4_lookup_root.isra.0+0x10/0x10 [nfsv4 d67fe18359c6743dcd6788d44186185ed97423ee] [ 35.726246] ? kasan_save_stack+0x45/0x60 [ 35.726251] ? nfs_alloc_fattr+0x44/0x210 [nfs 1894ec9cbdec354be2bcab1be6e5e8ab9f92de62] [ 35.726290] ? nfs4_get_rootfh+0x92/0x290 [nfsv4 d67fe18359c6743dcd6788d44186185ed97423ee] [ 35.726341] ? nfs4_server_common_setup+0xa4/0x680 [nfsv4 d67fe18359c6743dcd6788d44186185ed97423ee] [ 35.726391] ? nfs4_create_server+0x8d7/0xf00 [nfsv4 d67fe18359c6743dcd6788d44186185ed97423ee] [ 35.726440] ? nfs4_try_get_tree+0xd1/0x250 [nfsv4 d67fe18359c6743dcd6788d44186185ed97423ee] [ 35.726488] ? entry_SYSCALL_64_after_hwframe+0x72/0xdc [ 35.726496] nfs4_lookup_root+0xeb/0x260 [nfsv4 d67fe18359c6743dcd6788d44186185ed97423ee] [ 35.726542] ? __pfx_nfs4_lookup_root+0x10/0x10 [nfsv4 d67fe18359c6743dcd6788d44186185ed97423ee] [ 35.726589] nfs4_proc_get_rootfh+0xdc/0x110 [nfsv4 d67fe18359c6743dcd6788d44186185ed97423ee] [ 35.726636] nfs4_get_rootfh+0xb4/0x290 [nfsv4 d67fe18359c6743dcd6788d44186185ed97423ee] [ 35.726685] ? __pfx_nfs4_get_rootfh+0x10/0x10 [nfsv4 d67fe18359c6743dcd6788d44186185ed97423ee] [ 35.726733] ? nfs4_set_client+0x2d8/0x430 [nfsv4 d67fe18359c6743dcd6788d44186185ed97423ee] [ 35.726785] nfs4_server_common_setup+0xa4/0x680 [nfsv4 d67fe18359c6743dcd6788d44186185ed97423ee] [ 35.726834] nfs4_create_server+0x8d7/0xf00 [nfsv4 d67fe18359c6743dcd6788d44186185ed97423ee] [ 35.726884] ? _raw_spin_lock+0x85/0xe0 [ 35.726888] ? __pfx_nfs4_create_server+0x10/0x10 [nfsv4 d67fe18359c6743dcd6788d44186185ed97423ee] [ 35.726937] ? __module_get+0x31/0xf0 [ 35.726942] nfs4_try_get_tree+0xd1/0x250 [nfsv4 d67fe18359c6743dcd6788d44186185ed97423ee] [ 35.726991] vfs_get_tree+0x84/0x2c0 [ 35.726996] path_mount+0xa9f/0x1a20 [ 35.727001] ? __pfx_path_mount+0x10/0x10 [ 35.727005] ? user_path_at_empty+0x44/0x60 [ 35.727008] ? kmem_cache_free+0x19e/0x320 [ 35.727013] __x64_sys_mount+0x214/0x280 [ 35.727017] ? __pfx___x64_sys_mount+0x10/0x10 [ 35.727020] ? _raw_spin_lock+0x85/0xe0 [ 35.727024] do_syscall_64+0x5c/0x90 [ 35.727029] ? syscall_exit_to_user_mode+0x1b/0x40 [ 35.727032] ? do_syscall_64+0x6b/0x90 [ 35.727036] entry_SYSCALL_64_after_hwframe+0x72/0xdc [ 35.727040] RIP: 0033:0x7f1291a5afde [ 35.727044] Code: 48 8b 0d 95 ed 0c 00 f7 d8 64 89 01 48 83 c8 ff c3 66 2e 0f 1f 84 00 00 00 00 00 90 f3 0f 1e fa 49 89 ca b8 a5 00 00 00 0f 05 <48> 3d 01 f0 ff ff 73 01 c3 48 8b 0d 62 ed 0c 00 f7 d8 64 89 01 48 [ 35.727047] RSP: 002b:00007ffd02e479e8 EFLAGS: 00000246 ORIG_RAX: 00000000000000a5 [ 35.727055] RAX: ffffffffffffffda RBX: 00007ffd02e47b90 RCX: 00007f1291a5afde [ 35.727058] RDX: 00005565e507c3b0 RSI: 00005565e507b500 RDI: 00005565e507b550 [ 35.727060] RBP: 00005565e50824f0 R08: 00005565e50824f0 R09: 0000000000000060 [ 35.727062] R10: 0000000000000000 R11: 0000000000000246 R12: 00007ffd02e47b90 [ 35.727065] R13: 00005565e5082210 R14: 0000000000000003 R15: 00005565e42168f8 [ 35.727069] </TASK>
[ 35.727073] Allocated by task 853: [ 35.727075] kasan_save_stack+0x33/0x60 [ 35.727079] kasan_set_track+0x25/0x30 [ 35.727082] __kasan_kmalloc+0xad/0xb0 [ 35.727086] __kmalloc+0x5e/0x160 [ 35.727088] gss_krb5_checksum+0xcf/0x630 [rpcsec_gss_krb5] [ 35.727095] gss_krb5_aes_encrypt+0x388/0x7c0 [rpcsec_gss_krb5] [ 35.727101] gss_krb5_wrap_v2+0x28e/0x3a0 [rpcsec_gss_krb5] [ 35.727107] gss_wrap_req_priv+0x3d7/0x1090 [auth_rpcgss] [ 35.727119] gss_wrap_req+0x1df/0x250 [auth_rpcgss] [ 35.727131] call_encode+0x75a/0x1000 [sunrpc] [ 35.727175] __rpc_execute+0x29b/0xcf0 [sunrpc] [ 35.727227] rpc_execute+0x21d/0x320 [sunrpc] [ 35.727277] rpc_run_task+0x467/0x650 [sunrpc] [ 35.727321] nfs4_call_sync_sequence+0x17e/0x2a0 [nfsv4] [ 35.727365] _nfs4_lookup_root.isra.0+0x193/0x200 [nfsv4] [ 35.727408] nfs4_lookup_root+0xeb/0x260 [nfsv4] [ 35.727453] nfs4_proc_get_rootfh+0xdc/0x110 [nfsv4] [ 35.727498] nfs4_get_rootfh+0xb4/0x290 [nfsv4] [ 35.727546] nfs4_server_common_setup+0xa4/0x680 [nfsv4] [ 35.727595] nfs4_create_server+0x8d7/0xf00 [nfsv4] [ 35.727643] nfs4_try_get_tree+0xd1/0x250 [nfsv4] [ 35.727690] vfs_get_tree+0x84/0x2c0 [ 35.727694] path_mount+0xa9f/0x1a20 [ 35.727697] __x64_sys_mount+0x214/0x280 [ 35.727701] do_syscall_64+0x5c/0x90 [ 35.727704] entry_SYSCALL_64_after_hwframe+0x72/0xdc
[ 35.727709] The buggy address belongs to the object at ffff888110cfc1a0 which belongs to the cache kmalloc-32 of size 32 [ 35.727712] The buggy address is located 0 bytes inside of 32-byte region [ffff888110cfc1a0, ffff888110cfc1c0)
[ 35.727717] The buggy address belongs to the physical page: [ 35.727721] page:ffffea0004433f00 refcount:1 mapcount:0 mapping:0000000000000000 index:0xffff888110cfce60 pfn:0x110cfc [ 35.727726] flags: 0x2ffff0000000200(slab|node=0|zone=2|lastcpupid=0xffff) [ 35.727731] raw: 02ffff0000000200 ffff888100042740 ffffea00044274d0 ffff888100040450 [ 35.727734] raw: ffff888110cfce60 0000000000150012 00000001ffffffff 0000000000000000 [ 35.727736] page dumped because: kasan: bad access detected [ 35.727740] page_owner tracks the page as allocated [ 35.727741] page last allocated via order 0, migratetype Unmovable, gfp_mask 0x12c40(GFP_NOFS|__GFP_NOWARN|__GFP_NORETRY), pid 715, tgid 715 (test2), ts 24589446140, free_ts 24535345796 [ 35.727747] post_alloc_hook+0x118/0x250 [ 35.727750] get_page_from_freelist+0x11ef/0x3a20 [ 35.727754] __alloc_pages+0x1d5/0x440 [ 35.727757] allocate_slab+0x346/0x4a0 [ 35.727760] ___slab_alloc+0x39a/0x9a0 [ 35.727763] __kmem_cache_alloc_node+0x143/0x3d0 [ 35.727766] __kmalloc+0x4d/0x160 [ 35.727768] gss_krb5_checksum+0xcf/0x630 [rpcsec_gss_krb5] [ 35.727775] gss_krb5_verify_mic_v2+0x2d2/0x4f0 [rpcsec_gss_krb5] [ 35.727780] gss_validate+0x360/0x700 [auth_rpcgss] [ 35.727792] rpc_decode_header+0x288/0xcb0 [sunrpc] [ 35.727836] call_decode+0x3a7/0x780 [sunrpc] [ 35.727880] __rpc_execute+0x29b/0xcf0 [sunrpc] [ 35.727932] rpc_execute+0x21d/0x320 [sunrpc] [ 35.727982] rpc_run_task+0x467/0x650 [sunrpc] [ 35.728026] nfs4_call_sync_sequence+0x17e/0x2a0 [nfsv4] [ 35.728070] page last free stack trace: [ 35.728072] free_pcp_prepare+0x66c/0x10e0 [ 35.728075] free_unref_page+0x4e/0x3c0 [ 35.728078] tlb_remove_table_rcu+0x77/0xc0 [ 35.728081] rcu_do_batch+0x34c/0xd00 [ 35.728084] rcu_core+0x447/0xf20 [ 35.728086] __do_softirq+0x1d6/0x5ed
[ 35.728091] Memory state around the buggy address: [ 35.728093] ffff888110cfc080: fc fc fc fc fc fc fc fc fc fc fc fc fa fb fb fb [ 35.728096] ffff888110cfc100: fc fc fc fc fc fc fc fc fc fc fc fc fc fc fc fc [ 35.728098] >ffff888110cfc180: fc fc fc fc 00 00 04 fc fc fc fc fc fc fc fc fc [ 35.728100] ^ [ 35.728102] ffff888110cfc200: fc fc fc fc fc fc fc fc fc fc fc fc 00 00 00 00 [ 35.728104] ffff888110cfc280: fc fc fc fc fc fc fc fc fc fc fc fc fc fc fc fc [ 35.728106] ==================================================================
/* Maximum blocksize for the supported crypto algorithms */ #define GSS_KRB5_MAX_BLOCKSIZE (16) @@ -160,6 +160,12 @@ enum seal_alg { SEAL_ALG_DES3KD = 0x0002 };
+/*
- These values are assigned by IANA and published via the
- subregistry at the link below:
- */
#define CKSUMTYPE_CRC32 0x0001 #define CKSUMTYPE_RSA_MD4 0x0002 #define CKSUMTYPE_RSA_MD4_DES 0x0003 @@ -170,6 +176,8 @@ enum seal_alg { #define CKSUMTYPE_HMAC_SHA1_DES3 0x000c #define CKSUMTYPE_HMAC_SHA1_96_AES128 0x000f #define CKSUMTYPE_HMAC_SHA1_96_AES256 0x0010 +#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 */ @@ -190,6 +198,11 @@ enum seal_alg {
/* 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:
*/ #define ENCTYPE_NULL 0x0000 #define ENCTYPE_DES_CBC_CRC 0x0001 /* DES cbc mode with CRC-32 */ @@ -203,6 +216,8 @@ enum seal_alg { #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_UNKNOWN 0x01ff diff --git a/net/sunrpc/Kconfig b/net/sunrpc/Kconfig index 1135ff362132..b1aa2318e1dc 100644 --- a/net/sunrpc/Kconfig +++ b/net/sunrpc/Kconfig @@ -76,6 +76,20 @@ config RPCSEC_GSS_KRB5_ENCTYPES_AES_SHA1 SHA-1 digests. These include aes128-cts-hmac-sha1-96 and aes256-cts-hmac-sha1-96.
+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
select RPCSEC_GSS_KRB5_CRYPTOSYSTEM
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 ec3cca8fadc5..1951867f3fa8 100644 --- a/net/sunrpc/auth_gss/gss_krb5_mech.c +++ b/net/sunrpc/auth_gss/gss_krb5_mech.c @@ -146,6 +146,57 @@ static const struct gss_krb5_enctype supported_gss_krb5_enctypes[] = { .keyed_cksum = 1, }, #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),
.import_ctx = gss_krb5_import_ctx_v2,
.get_mic = gss_krb5_get_mic_v2,
.verify_mic = gss_krb5_verify_mic_v2,
.wrap = gss_krb5_wrap_v2,
.unwrap = gss_krb5_unwrap_v2,
},
/*
* 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),
.import_ctx = gss_krb5_import_ctx_v2,
.get_mic = gss_krb5_get_mic_v2,
.verify_mic = gss_krb5_verify_mic_v2,
.wrap = gss_krb5_wrap_v2,
.unwrap = gss_krb5_unwrap_v2,
},
+#endif };
/*
-- Chuck Lever
From: Chuck Lever chuck.lever@oracle.com
The RFC 8009 encryption types use a different key derivation function than the RFC 3962 encryption types. The new key derivation function is defined in Section 3 of RFC 8009.
Tested-by: Scott Mayhew smayhew@redhat.com Signed-off-by: Chuck Lever chuck.lever@oracle.com --- net/sunrpc/auth_gss/gss_krb5_internal.h | 6 ++ net/sunrpc/auth_gss/gss_krb5_keys.c | 117 +++++++++++++++++++++++++++++++ net/sunrpc/auth_gss/gss_krb5_mech.c | 2 + 3 files changed, 125 insertions(+)
diff --git a/net/sunrpc/auth_gss/gss_krb5_internal.h b/net/sunrpc/auth_gss/gss_krb5_internal.h index c7580026adc7..33abf9ee9508 100644 --- a/net/sunrpc/auth_gss/gss_krb5_internal.h +++ b/net/sunrpc/auth_gss/gss_krb5_internal.h @@ -52,6 +52,12 @@ int krb5_derive_key_v2(const struct gss_krb5_enctype *gk5e, 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); + /** * krb5_derive_key - Derive a subkey from a protocol key * @kctx: Kerberos 5 context diff --git a/net/sunrpc/auth_gss/gss_krb5_keys.c b/net/sunrpc/auth_gss/gss_krb5_keys.c index f6de4fdd63ae..724be20f5417 100644 --- a/net/sunrpc/auth_gss/gss_krb5_keys.c +++ b/net/sunrpc/auth_gss/gss_krb5_keys.c @@ -60,6 +60,7 @@ #include <linux/sunrpc/gss_krb5.h> #include <linux/sunrpc/xdr.h> #include <linux/lcm.h> +#include <crypto/hash.h>
#include "gss_krb5_internal.h"
@@ -361,3 +362,119 @@ int krb5_derive_key_v2(const struct gss_krb5_enctype *gk5e, kfree_sensitive(inblock.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 1951867f3fa8..b55897cac459 100644 --- a/net/sunrpc/auth_gss/gss_krb5_mech.c +++ b/net/sunrpc/auth_gss/gss_krb5_mech.c @@ -166,6 +166,7 @@ static const struct gss_krb5_enctype supported_gss_krb5_enctypes[] = { .Ki_length = BITS2OCTETS(128),
.import_ctx = gss_krb5_import_ctx_v2, + .derive_key = krb5_kdf_hmac_sha2,
.get_mic = gss_krb5_get_mic_v2, .verify_mic = gss_krb5_verify_mic_v2, @@ -190,6 +191,7 @@ static const struct gss_krb5_enctype supported_gss_krb5_enctypes[] = { .Ki_length = BITS2OCTETS(192),
.import_ctx = gss_krb5_import_ctx_v2, + .derive_key = krb5_kdf_hmac_sha2,
.get_mic = gss_krb5_get_mic_v2, .verify_mic = gss_krb5_verify_mic_v2,
From: Chuck Lever chuck.lever@oracle.com
RFC 8009 enctypes use different crypt formulae than previous Kerberos 5 encryption types. Section 1 of RFC 8009 explains the reason for this change:
The new types conform to the framework specified in [RFC3961], but do not use the simplified profile, as the simplified profile is not compliant with modern cryptographic best practices such as calculating Message Authentication Codes (MACs) over ciphertext rather than plaintext.
Add new .encrypt and .decrypt functions to handle this variation.
The new approach described above is referred to as Encrypt-then-MAC (or EtM). Hence the names of the new functions added here are prefixed with "krb5_etm_".
A critical second difference with previous crypt formulae is that the cipher state is included in the computed HMAC. Note however that for RPCSEC, the initial cipher state is easy to compute on both initiator and acceptor because it is always all zeroes.
Tested-by: Scott Mayhew smayhew@redhat.com Signed-off-by: Chuck Lever chuck.lever@oracle.com --- net/sunrpc/auth_gss/gss_krb5_crypto.c | 227 +++++++++++++++++++++++++++++++ net/sunrpc/auth_gss/gss_krb5_internal.h | 6 + net/sunrpc/auth_gss/gss_krb5_mech.c | 4 + 3 files changed, 237 insertions(+)
diff --git a/net/sunrpc/auth_gss/gss_krb5_crypto.c b/net/sunrpc/auth_gss/gss_krb5_crypto.c index 65c8b6982729..4f29216d414a 100644 --- a/net/sunrpc/auth_gss/gss_krb5_crypto.c +++ b/net/sunrpc/auth_gss/gss_krb5_crypto.c @@ -867,3 +867,230 @@ gss_krb5_aes_decrypt(struct krb5_ctx *kctx, u32 offset, u32 len, ret = GSS_S_FAILURE; return ret; } + +static 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; +} + +/** + * 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); + 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: + * @buf: + * @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; +} diff --git a/net/sunrpc/auth_gss/gss_krb5_internal.h b/net/sunrpc/auth_gss/gss_krb5_internal.h index 33abf9ee9508..fd2ae11c5067 100644 --- a/net/sunrpc/auth_gss/gss_krb5_internal.h +++ b/net/sunrpc/auth_gss/gss_krb5_internal.h @@ -108,4 +108,10 @@ u32 gss_krb5_aes_encrypt(struct krb5_ctx *kctx, u32 offset, 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); + #endif /* _NET_SUNRPC_AUTH_GSS_KRB5_INTERNAL_H */ diff --git a/net/sunrpc/auth_gss/gss_krb5_mech.c b/net/sunrpc/auth_gss/gss_krb5_mech.c index b55897cac459..7fe39e47c84f 100644 --- a/net/sunrpc/auth_gss/gss_krb5_mech.c +++ b/net/sunrpc/auth_gss/gss_krb5_mech.c @@ -167,6 +167,8 @@ static const struct gss_krb5_enctype supported_gss_krb5_enctypes[] = {
.import_ctx = gss_krb5_import_ctx_v2, .derive_key = krb5_kdf_hmac_sha2, + .encrypt = krb5_etm_encrypt, + .decrypt = krb5_etm_decrypt,
.get_mic = gss_krb5_get_mic_v2, .verify_mic = gss_krb5_verify_mic_v2, @@ -192,6 +194,8 @@ static const struct gss_krb5_enctype supported_gss_krb5_enctypes[] = {
.import_ctx = gss_krb5_import_ctx_v2, .derive_key = krb5_kdf_hmac_sha2, + .encrypt = krb5_etm_encrypt, + .decrypt = krb5_etm_decrypt,
.get_mic = gss_krb5_get_mic_v2, .verify_mic = gss_krb5_verify_mic_v2,
From: Chuck Lever chuck.lever@oracle.com
Add the RFC 8009 encryption types to the string of integers that is reported to gssd during upcalls. This enables gssd to utilize keys with these encryption types when support for them is built into the kernel.
Link: https://bugzilla.linux-nfs.org/show_bug.cgi?id=400 Tested-by: Scott Mayhew smayhew@redhat.com Signed-off-by: Chuck Lever chuck.lever@oracle.com --- net/sunrpc/auth_gss/gss_krb5_mech.c | 4 ++++ 1 file changed, 4 insertions(+)
diff --git a/net/sunrpc/auth_gss/gss_krb5_mech.c b/net/sunrpc/auth_gss/gss_krb5_mech.c index 7fe39e47c84f..97a365608233 100644 --- a/net/sunrpc/auth_gss/gss_krb5_mech.c +++ b/net/sunrpc/auth_gss/gss_krb5_mech.c @@ -214,6 +214,10 @@ 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_AES_SHA1) ENCTYPE_AES256_CTS_HMAC_SHA1_96, ENCTYPE_AES128_CTS_HMAC_SHA1_96,
From: Chuck Lever chuck.lever@oracle.com
RFC 6803 defines two encryption types that use Camellia ciphers (RFC 3713) and CMAC digests. Implement support for those in SunRPC's GSS Kerberos 5 mechanism.
There has not been an explicit request to support these enctypes. However, this new set of enctypes provides a good alternative to the AES-SHA1 enctypes that are to be deprecated at some point.
As this implementation is still a "beta", the default is to not build it automatically.
Tested-by: Scott Mayhew smayhew@redhat.com Signed-off-by: Chuck Lever chuck.lever@oracle.com --- include/linux/sunrpc/gss_krb5.h | 4 +++ net/sunrpc/Kconfig | 13 ++++++++ net/sunrpc/auth_gss/gss_krb5_mech.c | 55 +++++++++++++++++++++++++++++++++++ 3 files changed, 72 insertions(+)
diff --git a/include/linux/sunrpc/gss_krb5.h b/include/linux/sunrpc/gss_krb5.h index 8ff397b5c04b..cbb6c8192890 100644 --- a/include/linux/sunrpc/gss_krb5.h +++ b/include/linux/sunrpc/gss_krb5.h @@ -176,6 +176,8 @@ enum seal_alg { #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 */ @@ -220,6 +222,8 @@ enum seal_alg { #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
/* diff --git a/net/sunrpc/Kconfig b/net/sunrpc/Kconfig index b1aa2318e1dc..def7e1ce348b 100644 --- a/net/sunrpc/Kconfig +++ b/net/sunrpc/Kconfig @@ -76,6 +76,19 @@ config RPCSEC_GSS_KRB5_ENCTYPES_AES_SHA1 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 + select RPCSEC_GSS_KRB5_CRYPTOSYSTEM + 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 diff --git a/net/sunrpc/auth_gss/gss_krb5_mech.c b/net/sunrpc/auth_gss/gss_krb5_mech.c index 97a365608233..4e7cb49a06de 100644 --- a/net/sunrpc/auth_gss/gss_krb5_mech.c +++ b/net/sunrpc/auth_gss/gss_krb5_mech.c @@ -147,6 +147,61 @@ static const struct gss_krb5_enctype supported_gss_krb5_enctypes[] = { }, #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), + + .import_ctx = gss_krb5_import_ctx_v2, + .encrypt = gss_krb5_aes_encrypt, + .decrypt = gss_krb5_aes_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, + }, + /* + * 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), + + .import_ctx = gss_krb5_import_ctx_v2, + .encrypt = gss_krb5_aes_encrypt, + .decrypt = gss_krb5_aes_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, + }, +#endif + #if defined(CONFIG_RPCSEC_GSS_KRB5_ENCTYPES_AES_SHA2) /* * AES-128 with SHA-256 (RFC 8009)
From: Chuck Lever chuck.lever@oracle.com
The Camellia enctypes use the KDF_FEEDBACK_CMAC Key Derivation Function defined in RFC 6803 Section 3.
Tested-by: Scott Mayhew smayhew@redhat.com Signed-off-by: Chuck Lever chuck.lever@oracle.com --- net/sunrpc/auth_gss/gss_krb5_internal.h | 6 + net/sunrpc/auth_gss/gss_krb5_keys.c | 143 +++++++++++++++++++++++++++++++ net/sunrpc/auth_gss/gss_krb5_mech.c | 2 3 files changed, 151 insertions(+)
diff --git a/net/sunrpc/auth_gss/gss_krb5_internal.h b/net/sunrpc/auth_gss/gss_krb5_internal.h index fd2ae11c5067..c955e7b76c4d 100644 --- a/net/sunrpc/auth_gss/gss_krb5_internal.h +++ b/net/sunrpc/auth_gss/gss_krb5_internal.h @@ -58,6 +58,12 @@ int krb5_kdf_hmac_sha2(const struct gss_krb5_enctype *gk5e, 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); + /** * krb5_derive_key - Derive a subkey from a protocol key * @kctx: Kerberos 5 context diff --git a/net/sunrpc/auth_gss/gss_krb5_keys.c b/net/sunrpc/auth_gss/gss_krb5_keys.c index 724be20f5417..99251f15723a 100644 --- a/net/sunrpc/auth_gss/gss_krb5_keys.c +++ b/net/sunrpc/auth_gss/gss_krb5_keys.c @@ -363,6 +363,149 @@ int krb5_derive_key_v2(const struct gss_krb5_enctype *gk5e, 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) * diff --git a/net/sunrpc/auth_gss/gss_krb5_mech.c b/net/sunrpc/auth_gss/gss_krb5_mech.c index 4e7cb49a06de..e616ec536265 100644 --- a/net/sunrpc/auth_gss/gss_krb5_mech.c +++ b/net/sunrpc/auth_gss/gss_krb5_mech.c @@ -166,6 +166,7 @@ static const struct gss_krb5_enctype supported_gss_krb5_enctypes[] = { .Ki_length = BITS2OCTETS(128),
.import_ctx = gss_krb5_import_ctx_v2, + .derive_key = krb5_kdf_feedback_cmac, .encrypt = gss_krb5_aes_encrypt, .decrypt = gss_krb5_aes_decrypt,
@@ -192,6 +193,7 @@ static const struct gss_krb5_enctype supported_gss_krb5_enctypes[] = { .Ki_length = BITS2OCTETS(256),
.import_ctx = gss_krb5_import_ctx_v2, + .derive_key = krb5_kdf_feedback_cmac, .encrypt = gss_krb5_aes_encrypt, .decrypt = gss_krb5_aes_decrypt,
From: Chuck Lever chuck.lever@oracle.com
Add the RFC 6803 encryption types to the string of integers that is reported to gssd during upcalls. This enables gssd to utilize keys with these encryption types when support for them is built into the kernel.
Tested-by: Scott Mayhew smayhew@redhat.com Signed-off-by: Chuck Lever chuck.lever@oracle.com --- net/sunrpc/auth_gss/gss_krb5_mech.c | 4 ++++ 1 file changed, 4 insertions(+)
diff --git a/net/sunrpc/auth_gss/gss_krb5_mech.c b/net/sunrpc/auth_gss/gss_krb5_mech.c index e616ec536265..5909fef97d27 100644 --- a/net/sunrpc/auth_gss/gss_krb5_mech.c +++ b/net/sunrpc/auth_gss/gss_krb5_mech.c @@ -275,6 +275,10 @@ static void gss_krb5_prepare_enctype_priority_list(void) 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,
From: Chuck Lever chuck.lever@oracle.com
The goal is to leave only protocol-defined items in gss_krb5.h so that it can be easily replaced by a generic header. Implementation specific items are moved to the new internal header.
Tested-by: Scott Mayhew smayhew@redhat.com Signed-off-by: Chuck Lever chuck.lever@oracle.com --- include/linux/sunrpc/gss_krb5.h | 117 ------------------------------- net/sunrpc/auth_gss/auth_gss.c | 17 +++++ net/sunrpc/auth_gss/gss_krb5_crypto.c | 1 net/sunrpc/auth_gss/gss_krb5_internal.h | 94 +++++++++++++++++++++++++ 4 files changed, 111 insertions(+), 118 deletions(-)
diff --git a/include/linux/sunrpc/gss_krb5.h b/include/linux/sunrpc/gss_krb5.h index cbb6c8192890..78a80bf3fdcb 100644 --- a/include/linux/sunrpc/gss_krb5.h +++ b/include/linux/sunrpc/gss_krb5.h @@ -42,12 +42,6 @@ #include <linux/sunrpc/gss_err.h> #include <linux/sunrpc/gss_asn1.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) - /* Length of constant used in key derivation */ #define GSS_KRB5_K5CLENGTH (5)
@@ -60,74 +54,6 @@ /* Maximum blocksize for the supported crypto algorithms */ #define GSS_KRB5_MAX_BLOCKSIZE (16)
-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 (*import_ctx)(struct krb5_ctx *ctx, gfp_t gfp_mask); - 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); - 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); - 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, - struct xdr_buf *buf, unsigned int *slack, - unsigned int *align); -}; - -/* krb5_ctx flags definitions */ -#define KRB5_CTX_FLAG_INITIATOR 0x00000001 -#define KRB5_CTX_FLAG_CFX 0x00000002 -#define KRB5_CTX_FLAG_ACCEPTOR_SUBKEY 0x00000004 - -struct krb5_ctx { - int initiate; /* 1 = initiating, 0 = accepting */ - u32 enctype; - u32 flags; - const struct gss_krb5_enctype *gk5e; /* enctype-specific info */ - 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; - atomic64_t seq_send64; - time64_t endtime; - struct xdr_netobj mech_used; -}; - /* The length of the Kerberos GSS token header */ #define GSS_KRB5_TOK_HDR_LEN (16)
@@ -245,47 +171,4 @@ enum seal_alg { #define KG_USAGE_INITIATOR_SEAL (24) #define KG_USAGE_INITIATOR_SIGN (25)
-/* - * This compile-time check verifies that we will not exceed the - * slack space allotted by the client and server auth_gss code - * before they call gss_wrap(). - */ -#define GSS_KRB5_MAX_SLACK_NEEDED \ - (GSS_KRB5_TOK_HDR_LEN /* gss token header */ \ - + GSS_KRB5_MAX_CKSUM_LEN /* gss token checksum */ \ - + GSS_KRB5_MAX_BLOCKSIZE /* confounder */ \ - + GSS_KRB5_MAX_BLOCKSIZE /* possible padding */ \ - + GSS_KRB5_TOK_HDR_LEN /* encrypted hdr in v2 token */\ - + GSS_KRB5_MAX_CKSUM_LEN /* encryption hmac */ \ - + 4 + 4 /* RPC verifier */ \ - + GSS_KRB5_TOK_HDR_LEN \ - + GSS_KRB5_MAX_CKSUM_LEN) - -u32 -make_checksum(struct krb5_ctx *kctx, char *header, int hdrlen, - struct xdr_buf *body, int body_offset, u8 *cksumkey, - unsigned int usage, struct xdr_netobj *cksumout); - -int -gss_encrypt_xdr_buf(struct crypto_sync_skcipher *tfm, struct xdr_buf *outbuf, - int offset, struct page **pages); - -int -gss_decrypt_xdr_buf(struct crypto_sync_skcipher *tfm, struct xdr_buf *inbuf, - int offset); - -s32 -krb5_make_seq_num(struct krb5_ctx *kctx, - struct crypto_sync_skcipher *key, - int direction, - u32 seqnum, unsigned char *cksum, unsigned char *buf); - -s32 -krb5_get_seq_num(struct krb5_ctx *kctx, - unsigned char *cksum, - unsigned char *buf, int *direction, u32 *seqnum); - -int -xdr_extend_head(struct xdr_buf *buf, unsigned int base, unsigned int shiftlen); - #endif /* _LINUX_SUNRPC_GSS_KRB5_H */ diff --git a/net/sunrpc/auth_gss/auth_gss.c b/net/sunrpc/auth_gss/auth_gss.c index 2d7b1e03110a..1af71fbb0d80 100644 --- a/net/sunrpc/auth_gss/auth_gss.c +++ b/net/sunrpc/auth_gss/auth_gss.c @@ -49,6 +49,22 @@ static unsigned int gss_key_expire_timeo = GSS_KEY_EXPIRE_TIMEO; # define RPCDBG_FACILITY RPCDBG_AUTH #endif
+/* + * This compile-time check verifies that we will not exceed the + * slack space allotted by the client and server auth_gss code + * before they call gss_wrap(). + */ +#define GSS_KRB5_MAX_SLACK_NEEDED \ + (GSS_KRB5_TOK_HDR_LEN /* gss token header */ \ + + GSS_KRB5_MAX_CKSUM_LEN /* gss token checksum */ \ + + GSS_KRB5_MAX_BLOCKSIZE /* confounder */ \ + + GSS_KRB5_MAX_BLOCKSIZE /* possible padding */ \ + + GSS_KRB5_TOK_HDR_LEN /* encrypted hdr in v2 token */ \ + + GSS_KRB5_MAX_CKSUM_LEN /* encryption hmac */ \ + + XDR_UNIT * 2 /* RPC verifier */ \ + + GSS_KRB5_TOK_HDR_LEN \ + + GSS_KRB5_MAX_CKSUM_LEN) + #define GSS_CRED_SLACK (RPC_MAX_AUTH_SIZE * 2) /* length of a krb5 verifier (48), plus data added before arguments when * using integrity (two 4-byte integers): */ @@ -1042,6 +1058,7 @@ gss_create_new(const struct rpc_auth_create_args *args, struct rpc_clnt *clnt) goto err_put_mech; auth = &gss_auth->rpc_auth; auth->au_cslack = GSS_CRED_SLACK >> 2; + BUILD_BUG_ON(GSS_KRB5_MAX_SLACK_NEEDED > RPC_MAX_AUTH_SIZE); auth->au_rslack = GSS_KRB5_MAX_SLACK_NEEDED >> 2; auth->au_verfsize = GSS_VERF_SLACK >> 2; auth->au_ralign = GSS_VERF_SLACK >> 2; diff --git a/net/sunrpc/auth_gss/gss_krb5_crypto.c b/net/sunrpc/auth_gss/gss_krb5_crypto.c index 4f29216d414a..5c811b554fd1 100644 --- a/net/sunrpc/auth_gss/gss_krb5_crypto.c +++ b/net/sunrpc/auth_gss/gss_krb5_crypto.c @@ -572,7 +572,6 @@ xdr_extend_head(struct xdr_buf *buf, unsigned int base, unsigned int shiftlen) if (shiftlen == 0) return 0;
- BUILD_BUG_ON(GSS_KRB5_MAX_SLACK_NEEDED > RPC_MAX_AUTH_SIZE); BUG_ON(shiftlen > RPC_MAX_AUTH_SIZE);
p = buf->head[0].iov_base + base; diff --git a/net/sunrpc/auth_gss/gss_krb5_internal.h b/net/sunrpc/auth_gss/gss_krb5_internal.h index c955e7b76c4d..850748f6733a 100644 --- a/net/sunrpc/auth_gss/gss_krb5_internal.h +++ b/net/sunrpc/auth_gss/gss_krb5_internal.h @@ -8,6 +8,79 @@ #ifndef _NET_SUNRPC_AUTH_GSS_KRB5_INTERNAL_H #define _NET_SUNRPC_AUTH_GSS_KRB5_INTERNAL_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 (*import_ctx)(struct krb5_ctx *ctx, gfp_t gfp_mask); + 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); + 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); + 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, + struct xdr_buf *buf, unsigned int *slack, + unsigned int *align); +}; + +/* krb5_ctx flags definitions */ +#define KRB5_CTX_FLAG_INITIATOR 0x00000001 +#define KRB5_CTX_FLAG_ACCEPTOR_SUBKEY 0x00000004 + +struct krb5_ctx { + int initiate; /* 1 = initiating, 0 = accepting */ + u32 enctype; + u32 flags; + const struct gss_krb5_enctype *gk5e; /* enctype-specific info */ + 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; + atomic64_t seq_send64; + time64_t endtime; + struct xdr_netobj mech_used; +}; + /* * GSS Kerberos 5 mechanism Per-Message calls. */ @@ -96,8 +169,19 @@ static inline int krb5_derive_key(struct krb5_ctx *kctx, return gk5e->derive_key(gk5e, inkey, outkey, &label, gfp_mask); }
+s32 krb5_make_seq_num(struct krb5_ctx *kctx, struct crypto_sync_skcipher *key, + int direction, u32 seqnum, unsigned char *cksum, + unsigned char *buf); + +s32 krb5_get_seq_num(struct krb5_ctx *kctx, unsigned char *cksum, + unsigned char *buf, int *direction, u32 *seqnum); + void krb5_make_confounder(u8 *p, int conflen);
+u32 make_checksum(struct krb5_ctx *kctx, char *header, int hdrlen, + struct xdr_buf *body, int body_offset, u8 *cksumkey, + unsigned int usage, struct xdr_netobj *cksumout); + u32 gss_krb5_checksum(struct crypto_ahash *tfm, char *header, int hdrlen, const struct xdr_buf *body, int body_offset, struct xdr_netobj *cksumout); @@ -108,6 +192,16 @@ u32 krb5_encrypt(struct crypto_sync_skcipher *key, void *iv, void *in, u32 krb5_decrypt(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); + +int gss_encrypt_xdr_buf(struct crypto_sync_skcipher *tfm, + struct xdr_buf *outbuf, int offset, + struct page **pages); + +int gss_decrypt_xdr_buf(struct crypto_sync_skcipher *tfm, + struct xdr_buf *inbuf, int offset); + u32 gss_krb5_aes_encrypt(struct krb5_ctx *kctx, u32 offset, struct xdr_buf *buf, struct page **pages);
From: Chuck Lever chuck.lever@oracle.com
The Kerberos RFCs provide test vectors to verify the operation of an implementation. Introduce a KUnit test framework to exercise the Linux kernel's implementation of Kerberos.
Start with test cases for the RFC 3961-defined n-fold function. The sample vectors for that are found in RFC 3961 Section 10.
Run the GSS Kerberos 5 mechanism's unit tests with this command:
$ ./tools/testing/kunit/kunit.py run \ --kunitconfig ./net/sunrpc/.kunitconfig
Tested-by: Scott Mayhew smayhew@redhat.com Signed-off-by: Chuck Lever chuck.lever@oracle.com --- net/sunrpc/.kunitconfig | 22 +++ net/sunrpc/Kconfig | 15 ++ net/sunrpc/auth_gss/Makefile | 2 net/sunrpc/auth_gss/gss_krb5_internal.h | 4 + net/sunrpc/auth_gss/gss_krb5_keys.c | 15 +- net/sunrpc/auth_gss/gss_krb5_test.c | 244 +++++++++++++++++++++++++++++++ 6 files changed, 298 insertions(+), 4 deletions(-) create mode 100644 net/sunrpc/.kunitconfig create mode 100644 net/sunrpc/auth_gss/gss_krb5_test.c
diff --git a/net/sunrpc/.kunitconfig b/net/sunrpc/.kunitconfig new file mode 100644 index 000000000000..dc9abe4faa4f --- /dev/null +++ b/net/sunrpc/.kunitconfig @@ -0,0 +1,22 @@ +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_MD5=y +CONFIG_CRYPTO_SHA1=y +CONFIG_CRYPTO_DES=y +CONFIG_NFS_FS=y +CONFIG_SUNRPC=y +CONFIG_SUNRPC_GSS=y +CONFIG_RPCSEC_GSS_KRB5=y +CONFIG_RPCSEC_GSS_KRB5_ENCTYPES_DES=y +CONFIG_RPCSEC_GSS_KRB5_KUNIT_TEST=y diff --git a/net/sunrpc/Kconfig b/net/sunrpc/Kconfig index def7e1ce348b..214e07e39f7b 100644 --- a/net/sunrpc/Kconfig +++ b/net/sunrpc/Kconfig @@ -103,6 +103,21 @@ 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 4a29f4c5dac4..012ae1720689 100644 --- a/net/sunrpc/auth_gss/Makefile +++ b/net/sunrpc/auth_gss/Makefile @@ -13,3 +13,5 @@ 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_seqnum.o gss_krb5_wrap.o gss_krb5_crypto.o gss_krb5_keys.o + +obj-$(CONFIG_RPCSEC_GSS_KRB5_KUNIT_TEST) += gss_krb5_test.o diff --git a/net/sunrpc/auth_gss/gss_krb5_internal.h b/net/sunrpc/auth_gss/gss_krb5_internal.h index 850748f6733a..9aba1647c205 100644 --- a/net/sunrpc/auth_gss/gss_krb5_internal.h +++ b/net/sunrpc/auth_gss/gss_krb5_internal.h @@ -214,4 +214,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);
+#if IS_ENABLED(CONFIG_KUNIT) +void krb5_nfold(u32 inbits, const u8 *in, u32 outbits, u8 *out); +#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 index 99251f15723a..5347fe1cc93f 100644 --- a/net/sunrpc/auth_gss/gss_krb5_keys.c +++ b/net/sunrpc/auth_gss/gss_krb5_keys.c @@ -61,6 +61,7 @@ #include <linux/sunrpc/xdr.h> #include <linux/lcm.h> #include <crypto/hash.h> +#include <kunit/visibility.h>
#include "gss_krb5_internal.h"
@@ -68,13 +69,18 @@ # 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. */ - -static void krb5_nfold(u32 inbits, const u8 *in, - u32 outbits, u8 *out) +VISIBLE_IF_KUNIT +void krb5_nfold(u32 inbits, const u8 *in, u32 outbits, u8 *out) { unsigned long ulcm; int byte, i, msbit; @@ -135,6 +141,7 @@ static void krb5_nfold(u32 inbits, const u8 *in, } } } +EXPORT_SYMBOL_IF_KUNIT(krb5_nfold);
/* * This is the DK (derive_key) function as described in rfc3961, sec 5.1 diff --git a/net/sunrpc/auth_gss/gss_krb5_test.c b/net/sunrpc/auth_gss/gss_krb5_test.c new file mode 100644 index 000000000000..f67dbf7c8af4 --- /dev/null +++ b/net/sunrpc/auth_gss/gss_krb5_test.c @@ -0,0 +1,244 @@ +// 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 <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 nfold; + const struct xdr_netobj *plaintext; + const struct xdr_netobj *expected_result; +}; + +static inline void gss_krb5_get_desc(const struct gss_krb5_test_param *param, + char *desc) +{ + strscpy(desc, param->desc, KUNIT_PARAM_DESC_SIZE); +} + +#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), \ + } + +/* + * 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_EQ_MSG(test, + memcmp(param->expected_result->data, + result, param->expected_result->len), 0, + "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, +}; + +kunit_test_suites(&rfc3961_suite); + +MODULE_DESCRIPTION("Test RPCSEC GSS Kerberos 5 functions"); +MODULE_LICENSE("GPL");
From: Chuck Lever chuck.lever@oracle.com
I plan to add KUnit tests that will need enctype profile information. Export the enctype profile lookup function.
Tested-by: Scott Mayhew smayhew@redhat.com Signed-off-by: Chuck Lever chuck.lever@oracle.com --- net/sunrpc/auth_gss/gss_krb5_internal.h | 1 + net/sunrpc/auth_gss/gss_krb5_mech.c | 35 ++++++++++++++----------------- 2 files changed, 17 insertions(+), 19 deletions(-)
diff --git a/net/sunrpc/auth_gss/gss_krb5_internal.h b/net/sunrpc/auth_gss/gss_krb5_internal.h index 9aba1647c205..cca4026f986d 100644 --- a/net/sunrpc/auth_gss/gss_krb5_internal.h +++ b/net/sunrpc/auth_gss/gss_krb5_internal.h @@ -216,6 +216,7 @@ u32 krb5_etm_decrypt(struct krb5_ctx *kctx, u32 offset, u32 len,
#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); #endif
#endif /* _NET_SUNRPC_AUTH_GSS_KRB5_INTERNAL_H */ diff --git a/net/sunrpc/auth_gss/gss_krb5_mech.c b/net/sunrpc/auth_gss/gss_krb5_mech.c index 5909fef97d27..20e21d08badb 100644 --- a/net/sunrpc/auth_gss/gss_krb5_mech.c +++ b/net/sunrpc/auth_gss/gss_krb5_mech.c @@ -19,6 +19,7 @@ #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" @@ -309,28 +310,24 @@ static void gss_krb5_prepare_enctype_priority_list(void) } }
-static const int num_supported_enctypes = - ARRAY_SIZE(supported_gss_krb5_enctypes); - -static int -supported_gss_krb5_enctype(int etype) +/** + * 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) { - int i; - for (i = 0; i < num_supported_enctypes; i++) - if (supported_gss_krb5_enctypes[i].etype == etype) - return 1; - return 0; -} + size_t i;
-static const struct gss_krb5_enctype * -get_gss_krb5_enctype(int etype) -{ - int i; - for (i = 0; i < num_supported_enctypes; 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 struct crypto_sync_skcipher * gss_krb5_alloc_cipher_v1(struct krb5_ctx *ctx, struct xdr_netobj *key) @@ -366,7 +363,7 @@ get_key(const void *p, const void *end, alg = ENCTYPE_DES_CBC_RAW; break; } - if (!supported_gss_krb5_enctype(alg)) { + if (!gss_krb5_lookup_enctype(alg)) { pr_warn("gss_krb5: unsupported enctype: %d\n", alg); goto out_err_inval; } @@ -405,7 +402,7 @@ gss_import_v1_context(const void *p, const void *end, struct krb5_ctx *ctx) /* Old format supports only DES! Any other enctype uses new format */ ctx->enctype = ENCTYPE_DES_CBC_RAW;
- ctx->gk5e = get_gss_krb5_enctype(ctx->enctype); + ctx->gk5e = gss_krb5_lookup_enctype(ctx->enctype); if (ctx->gk5e == NULL) { p = ERR_PTR(-EINVAL); goto out_err; @@ -677,7 +674,7 @@ gss_import_v2_context(const void *p, const void *end, struct krb5_ctx *ctx, /* Map ENCTYPE_DES3_CBC_SHA1 to ENCTYPE_DES3_CBC_RAW */ if (ctx->enctype == ENCTYPE_DES3_CBC_SHA1) ctx->enctype = ENCTYPE_DES3_CBC_RAW; - ctx->gk5e = get_gss_krb5_enctype(ctx->enctype); + ctx->gk5e = gss_krb5_lookup_enctype(ctx->enctype); if (ctx->gk5e == NULL) { dprintk("gss_kerberos_mech: unsupported krb5 enctype %u\n", ctx->enctype);
From: Chuck Lever chuck.lever@oracle.com
RFC 3961 Appendix A provides tests for the KDF specified in that document as well as other parts of Kerberos. The other three usage scenarios in Section 10 are not implemented by the Linux kernel's RPCSEC GSS Kerberos 5 mechanism, so tests are not added for those.
Tested-by: Scott Mayhew smayhew@redhat.com Signed-off-by: Chuck Lever chuck.lever@oracle.com --- net/sunrpc/auth_gss/gss_krb5_test.c | 227 +++++++++++++++++++++++++++++++++++ 1 file changed, 227 insertions(+)
diff --git a/net/sunrpc/auth_gss/gss_krb5_test.c b/net/sunrpc/auth_gss/gss_krb5_test.c index f67dbf7c8af4..550f1b3a11a3 100644 --- a/net/sunrpc/auth_gss/gss_krb5_test.c +++ b/net/sunrpc/auth_gss/gss_krb5_test.c @@ -20,7 +20,10 @@ MODULE_IMPORT_NS(EXPORTED_FOR_KUNIT_TESTING);
struct gss_krb5_test_param { const char *desc; + u32 enctype; u32 nfold; + const struct xdr_netobj *base_key; + const struct xdr_netobj *usage; const struct xdr_netobj *plaintext; const struct xdr_netobj *expected_result; }; @@ -31,6 +34,34 @@ static inline void gss_krb5_get_desc(const struct gss_krb5_test_param *param, 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); + KUNIT_ASSERT_NOT_NULL(test, gk5e); + + 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_EQ_MSG(test, + memcmp(param->expected_result->data, + derivedkey.data, derivedkey.len), 0, + "key mismatch"); +} + #define DEFINE_HEX_XDR_NETOBJ(name, hex_array...) \ static const u8 name ## _data[] = { hex_array }; \ static const struct xdr_netobj name = { \ @@ -225,12 +256,208 @@ static void rfc3961_nfold_case(struct kunit *test) "result mismatch"); }
+/* + * RFC 3961 Appendix A.3. DES3 DR and DK + * + * These tests show the derived-random and derived-key values for the + * des3-hmac-sha1-kd encryption scheme, using the DR and DK functions + * defined in section 6.3.1. The input keys were randomly generated; + * the usage values are from this specification. + * + * This test material is copyright (C) The Internet Society (2005). + */ + +DEFINE_HEX_XDR_NETOBJ(des3_dk_usage_155, + 0x00, 0x00, 0x00, 0x01, 0x55 +); + +DEFINE_HEX_XDR_NETOBJ(des3_dk_usage_1aa, + 0x00, 0x00, 0x00, 0x01, 0xaa +); + +DEFINE_HEX_XDR_NETOBJ(des3_dk_usage_kerberos, + 0x6b, 0x65, 0x72, 0x62, 0x65, 0x72, 0x6f, 0x73 +); + +DEFINE_HEX_XDR_NETOBJ(des3_dk_test1_base_key, + 0xdc, 0xe0, 0x6b, 0x1f, 0x64, 0xc8, 0x57, 0xa1, + 0x1c, 0x3d, 0xb5, 0x7c, 0x51, 0x89, 0x9b, 0x2c, + 0xc1, 0x79, 0x10, 0x08, 0xce, 0x97, 0x3b, 0x92 +); +DEFINE_HEX_XDR_NETOBJ(des3_dk_test1_derived_key, + 0x92, 0x51, 0x79, 0xd0, 0x45, 0x91, 0xa7, 0x9b, + 0x5d, 0x31, 0x92, 0xc4, 0xa7, 0xe9, 0xc2, 0x89, + 0xb0, 0x49, 0xc7, 0x1f, 0x6e, 0xe6, 0x04, 0xcd +); + +DEFINE_HEX_XDR_NETOBJ(des3_dk_test2_base_key, + 0x5e, 0x13, 0xd3, 0x1c, 0x70, 0xef, 0x76, 0x57, + 0x46, 0x57, 0x85, 0x31, 0xcb, 0x51, 0xc1, 0x5b, + 0xf1, 0x1c, 0xa8, 0x2c, 0x97, 0xce, 0xe9, 0xf2 +); +DEFINE_HEX_XDR_NETOBJ(des3_dk_test2_derived_key, + 0x9e, 0x58, 0xe5, 0xa1, 0x46, 0xd9, 0x94, 0x2a, + 0x10, 0x1c, 0x46, 0x98, 0x45, 0xd6, 0x7a, 0x20, + 0xe3, 0xc4, 0x25, 0x9e, 0xd9, 0x13, 0xf2, 0x07 +); + +DEFINE_HEX_XDR_NETOBJ(des3_dk_test3_base_key, + 0x98, 0xe6, 0xfd, 0x8a, 0x04, 0xa4, 0xb6, 0x85, + 0x9b, 0x75, 0xa1, 0x76, 0x54, 0x0b, 0x97, 0x52, + 0xba, 0xd3, 0xec, 0xd6, 0x10, 0xa2, 0x52, 0xbc +); +DEFINE_HEX_XDR_NETOBJ(des3_dk_test3_derived_key, + 0x13, 0xfe, 0xf8, 0x0d, 0x76, 0x3e, 0x94, 0xec, + 0x6d, 0x13, 0xfd, 0x2c, 0xa1, 0xd0, 0x85, 0x07, + 0x02, 0x49, 0xda, 0xd3, 0x98, 0x08, 0xea, 0xbf +); + +DEFINE_HEX_XDR_NETOBJ(des3_dk_test4_base_key, + 0x62, 0x2a, 0xec, 0x25, 0xa2, 0xfe, 0x2c, 0xad, + 0x70, 0x94, 0x68, 0x0b, 0x7c, 0x64, 0x94, 0x02, + 0x80, 0x08, 0x4c, 0x1a, 0x7c, 0xec, 0x92, 0xb5 +); +DEFINE_HEX_XDR_NETOBJ(des3_dk_test4_derived_key, + 0xf8, 0xdf, 0xbf, 0x04, 0xb0, 0x97, 0xe6, 0xd9, + 0xdc, 0x07, 0x02, 0x68, 0x6b, 0xcb, 0x34, 0x89, + 0xd9, 0x1f, 0xd9, 0xa4, 0x51, 0x6b, 0x70, 0x3e +); + +DEFINE_HEX_XDR_NETOBJ(des3_dk_test5_base_key, + 0xd3, 0xf8, 0x29, 0x8c, 0xcb, 0x16, 0x64, 0x38, + 0xdc, 0xb9, 0xb9, 0x3e, 0xe5, 0xa7, 0x62, 0x92, + 0x86, 0xa4, 0x91, 0xf8, 0x38, 0xf8, 0x02, 0xfb +); +DEFINE_HEX_XDR_NETOBJ(des3_dk_test5_derived_key, + 0x23, 0x70, 0xda, 0x57, 0x5d, 0x2a, 0x3d, 0xa8, + 0x64, 0xce, 0xbf, 0xdc, 0x52, 0x04, 0xd5, 0x6d, + 0xf7, 0x79, 0xa7, 0xdf, 0x43, 0xd9, 0xda, 0x43 +); + +DEFINE_HEX_XDR_NETOBJ(des3_dk_test6_base_key, + 0xc1, 0x08, 0x16, 0x49, 0xad, 0xa7, 0x43, 0x62, + 0xe6, 0xa1, 0x45, 0x9d, 0x01, 0xdf, 0xd3, 0x0d, + 0x67, 0xc2, 0x23, 0x4c, 0x94, 0x07, 0x04, 0xda +); +DEFINE_HEX_XDR_NETOBJ(des3_dk_test6_derived_key, + 0x34, 0x80, 0x57, 0xec, 0x98, 0xfd, 0xc4, 0x80, + 0x16, 0x16, 0x1c, 0x2a, 0x4c, 0x7a, 0x94, 0x3e, + 0x92, 0xae, 0x49, 0x2c, 0x98, 0x91, 0x75, 0xf7 +); + +DEFINE_HEX_XDR_NETOBJ(des3_dk_test7_base_key, + 0x5d, 0x15, 0x4a, 0xf2, 0x38, 0xf4, 0x67, 0x13, + 0x15, 0x57, 0x19, 0xd5, 0x5e, 0x2f, 0x1f, 0x79, + 0x0d, 0xd6, 0x61, 0xf2, 0x79, 0xa7, 0x91, 0x7c +); +DEFINE_HEX_XDR_NETOBJ(des3_dk_test7_derived_key, + 0xa8, 0x80, 0x8a, 0xc2, 0x67, 0xda, 0xda, 0x3d, + 0xcb, 0xe9, 0xa7, 0xc8, 0x46, 0x26, 0xfb, 0xc7, + 0x61, 0xc2, 0x94, 0xb0, 0x13, 0x15, 0xe5, 0xc1 +); + +DEFINE_HEX_XDR_NETOBJ(des3_dk_test8_base_key, + 0x79, 0x85, 0x62, 0xe0, 0x49, 0x85, 0x2f, 0x57, + 0xdc, 0x8c, 0x34, 0x3b, 0xa1, 0x7f, 0x2c, 0xa1, + 0xd9, 0x73, 0x94, 0xef, 0xc8, 0xad, 0xc4, 0x43 +); +DEFINE_HEX_XDR_NETOBJ(des3_dk_test8_derived_key, + 0xc8, 0x13, 0xf8, 0x8a, 0x3b, 0xe3, 0xb3, 0x34, + 0xf7, 0x54, 0x25, 0xce, 0x91, 0x75, 0xfb, 0xe3, + 0xc8, 0x49, 0x3b, 0x89, 0xc8, 0x70, 0x3b, 0x49 +); + +DEFINE_HEX_XDR_NETOBJ(des3_dk_test9_base_key, + 0x26, 0xdc, 0xe3, 0x34, 0xb5, 0x45, 0x29, 0x2f, + 0x2f, 0xea, 0xb9, 0xa8, 0x70, 0x1a, 0x89, 0xa4, + 0xb9, 0x9e, 0xb9, 0x94, 0x2c, 0xec, 0xd0, 0x16 +); +DEFINE_HEX_XDR_NETOBJ(des3_dk_test9_derived_key, + 0xf4, 0x8f, 0xfd, 0x6e, 0x83, 0xf8, 0x3e, 0x73, + 0x54, 0xe6, 0x94, 0xfd, 0x25, 0x2c, 0xf8, 0x3b, + 0xfe, 0x58, 0xf7, 0xd5, 0xba, 0x37, 0xec, 0x5d +); + +static const struct gss_krb5_test_param rfc3961_kdf_test_params[] = { + { + .desc = "des3-hmac-sha1 key derivation case 1", + .enctype = ENCTYPE_DES3_CBC_RAW, + .base_key = &des3_dk_test1_base_key, + .usage = &des3_dk_usage_155, + .expected_result = &des3_dk_test1_derived_key, + }, + { + .desc = "des3-hmac-sha1 key derivation case 2", + .enctype = ENCTYPE_DES3_CBC_RAW, + .base_key = &des3_dk_test2_base_key, + .usage = &des3_dk_usage_1aa, + .expected_result = &des3_dk_test2_derived_key, + }, + { + .desc = "des3-hmac-sha1 key derivation case 3", + .enctype = ENCTYPE_DES3_CBC_RAW, + .base_key = &des3_dk_test3_base_key, + .usage = &des3_dk_usage_155, + .expected_result = &des3_dk_test3_derived_key, + }, + { + .desc = "des3-hmac-sha1 key derivation case 4", + .enctype = ENCTYPE_DES3_CBC_RAW, + .base_key = &des3_dk_test4_base_key, + .usage = &des3_dk_usage_1aa, + .expected_result = &des3_dk_test4_derived_key, + }, + { + .desc = "des3-hmac-sha1 key derivation case 5", + .enctype = ENCTYPE_DES3_CBC_RAW, + .base_key = &des3_dk_test5_base_key, + .usage = &des3_dk_usage_kerberos, + .expected_result = &des3_dk_test5_derived_key, + }, + { + .desc = "des3-hmac-sha1 key derivation case 6", + .enctype = ENCTYPE_DES3_CBC_RAW, + .base_key = &des3_dk_test6_base_key, + .usage = &des3_dk_usage_155, + .expected_result = &des3_dk_test6_derived_key, + }, + { + .desc = "des3-hmac-sha1 key derivation case 7", + .enctype = ENCTYPE_DES3_CBC_RAW, + .base_key = &des3_dk_test7_base_key, + .usage = &des3_dk_usage_1aa, + .expected_result = &des3_dk_test7_derived_key, + }, + { + .desc = "des3-hmac-sha1 key derivation case 8", + .enctype = ENCTYPE_DES3_CBC_RAW, + .base_key = &des3_dk_test8_base_key, + .usage = &des3_dk_usage_155, + .expected_result = &des3_dk_test8_derived_key, + }, + { + .desc = "des3-hmac-sha1 key derivation case 9", + .enctype = ENCTYPE_DES3_CBC_RAW, + .base_key = &des3_dk_test9_base_key, + .usage = &des3_dk_usage_1aa, + .expected_result = &des3_dk_test9_derived_key, + }, +}; + +/* Creates the function rfc3961_kdf_gen_params */ +KUNIT_ARRAY_PARAM(rfc3961_kdf, rfc3961_kdf_test_params, gss_krb5_get_desc); + static struct kunit_case rfc3961_test_cases[] = { { .name = "RFC 3961 n-fold", .run_case = rfc3961_nfold_case, .generate_params = rfc3961_nfold_gen_params, }, + { + .name = "RFC 3961 key derivation", + .run_case = kdf_case, + .generate_params = rfc3961_kdf_gen_params, + }, };
static struct kunit_suite rfc3961_suite = {
From: Chuck Lever chuck.lever@oracle.com
Add Kunit tests for ENCTYPE_AES128_CTS_HMAC_SHA1_96. The test vectors come from RFC 3962 Appendix B.
Tested-by: Scott Mayhew smayhew@redhat.com Signed-off-by: Chuck Lever chuck.lever@oracle.com --- net/sunrpc/.kunitconfig | 2 net/sunrpc/auth_gss/gss_krb5_crypto.c | 32 +++- net/sunrpc/auth_gss/gss_krb5_internal.h | 4 net/sunrpc/auth_gss/gss_krb5_test.c | 267 +++++++++++++++++++++++++++++++ 4 files changed, 296 insertions(+), 9 deletions(-)
diff --git a/net/sunrpc/.kunitconfig b/net/sunrpc/.kunitconfig index dc9abe4faa4f..01e12729f465 100644 --- a/net/sunrpc/.kunitconfig +++ b/net/sunrpc/.kunitconfig @@ -14,9 +14,11 @@ CONFIG_CRYPTO_HMAC=y CONFIG_CRYPTO_MD5=y CONFIG_CRYPTO_SHA1=y CONFIG_CRYPTO_DES=y +CONFIG_CRYPTO_AES=y CONFIG_NFS_FS=y CONFIG_SUNRPC=y CONFIG_SUNRPC_GSS=y CONFIG_RPCSEC_GSS_KRB5=y CONFIG_RPCSEC_GSS_KRB5_ENCTYPES_DES=y +CONFIG_RPCSEC_GSS_KRB5_ENCTYPES_AES_SHA1=y CONFIG_RPCSEC_GSS_KRB5_KUNIT_TEST=y diff --git a/net/sunrpc/auth_gss/gss_krb5_crypto.c b/net/sunrpc/auth_gss/gss_krb5_crypto.c index 5c811b554fd1..5d8dff65d014 100644 --- a/net/sunrpc/auth_gss/gss_krb5_crypto.c +++ b/net/sunrpc/auth_gss/gss_krb5_crypto.c @@ -46,6 +46,7 @@ #include <linux/random.h> #include <linux/sunrpc/gss_krb5.h> #include <linux/sunrpc/xdr.h> +#include <kunit/visibility.h>
#include "gss_krb5_internal.h"
@@ -640,14 +641,28 @@ gss_krb5_cts_crypt(struct crypto_sync_skcipher *cipher, struct xdr_buf *buf, 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 */ -static 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) +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; @@ -691,8 +706,11 @@ krb5_cbc_cts_encrypt(struct crypto_sync_skcipher *cts_tfm, if (err) return err;
+ if (unlikely(iv)) + memcpy(iv, desc.iv, ivsize); return 0; } +EXPORT_SYMBOL_IF_KUNIT(krb5_cbc_cts_encrypt);
static int krb5_cbc_cts_decrypt(struct crypto_sync_skcipher *cts_tfm, @@ -800,7 +818,7 @@ gss_krb5_aes_encrypt(struct krb5_ctx *kctx, u32 offset,
err = krb5_cbc_cts_encrypt(cipher, aux_cipher, offset + GSS_KRB5_TOK_HDR_LEN, - buf, pages); + buf, pages, NULL, 0); if (err) return GSS_S_FAILURE;
@@ -992,7 +1010,7 @@ krb5_etm_encrypt(struct krb5_ctx *kctx, u32 offset,
err = krb5_cbc_cts_encrypt(cipher, aux_cipher, offset + GSS_KRB5_TOK_HDR_LEN, - buf, pages); + buf, pages, NULL, 0); if (err) return GSS_S_FAILURE;
diff --git a/net/sunrpc/auth_gss/gss_krb5_internal.h b/net/sunrpc/auth_gss/gss_krb5_internal.h index cca4026f986d..bebe1ec2f507 100644 --- a/net/sunrpc/auth_gss/gss_krb5_internal.h +++ b/net/sunrpc/auth_gss/gss_krb5_internal.h @@ -217,6 +217,10 @@ u32 krb5_etm_decrypt(struct krb5_ctx *kctx, u32 offset, u32 len, #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); #endif
#endif /* _NET_SUNRPC_AUTH_GSS_KRB5_INTERNAL_H */ diff --git a/net/sunrpc/auth_gss/gss_krb5_test.c b/net/sunrpc/auth_gss/gss_krb5_test.c index 550f1b3a11a3..2f7e31b8004e 100644 --- a/net/sunrpc/auth_gss/gss_krb5_test.c +++ b/net/sunrpc/auth_gss/gss_krb5_test.c @@ -23,9 +23,11 @@ struct gss_krb5_test_param { u32 enctype; u32 nfold; 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 *plaintext; const struct xdr_netobj *expected_result; + const struct xdr_netobj *next_iv; };
static inline void gss_krb5_get_desc(const struct gss_krb5_test_param *param, @@ -465,7 +467,268 @@ static struct kunit_suite rfc3961_suite = { .test_cases = rfc3961_test_cases, };
-kunit_test_suites(&rfc3961_suite); +/* + * 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); + KUNIT_ASSERT_NOT_NULL(test, gk5e); + + 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_EQ_MSG(test, + memcmp(param->expected_result->data, + text, param->expected_result->len), 0, + "ciphertext mismatch"); + KUNIT_EXPECT_EQ_MSG(test, + memcmp(param->next_iv->data, iv, + param->next_iv->len), 0, + "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, +}; + +kunit_test_suites(&rfc3961_suite, + &rfc3962_suite);
MODULE_DESCRIPTION("Test RPCSEC GSS Kerberos 5 functions"); MODULE_LICENSE("GPL");
From: Chuck Lever chuck.lever@oracle.com
The Camellia enctypes use a new KDF, so add some tests to ensure it is working properly.
Tested-by: Scott Mayhew smayhew@redhat.com Signed-off-by: Chuck Lever chuck.lever@oracle.com --- net/sunrpc/.kunitconfig | 3 + net/sunrpc/auth_gss/gss_krb5_test.c | 125 +++++++++++++++++++++++++++++++++++ 2 files changed, 127 insertions(+), 1 deletion(-)
diff --git a/net/sunrpc/.kunitconfig b/net/sunrpc/.kunitconfig index 01e12729f465..90d0ad430e7e 100644 --- a/net/sunrpc/.kunitconfig +++ b/net/sunrpc/.kunitconfig @@ -11,14 +11,17 @@ 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_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_DES=y CONFIG_RPCSEC_GSS_KRB5_ENCTYPES_AES_SHA1=y +CONFIG_RPCSEC_GSS_KRB5_ENCTYPES_CAMELLIA=y CONFIG_RPCSEC_GSS_KRB5_KUNIT_TEST=y diff --git a/net/sunrpc/auth_gss/gss_krb5_test.c b/net/sunrpc/auth_gss/gss_krb5_test.c index 2f7e31b8004e..c80a8f6588c0 100644 --- a/net/sunrpc/auth_gss/gss_krb5_test.c +++ b/net/sunrpc/auth_gss/gss_krb5_test.c @@ -727,8 +727,131 @@ static struct kunit_suite rfc3962_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); + +static struct kunit_case rfc6803_test_cases[] = { + { + .name = "RFC 6803 key derivation", + .run_case = kdf_case, + .generate_params = rfc6803_kdf_gen_params, + }, +}; + +static struct kunit_suite rfc6803_suite = { + .name = "RFC 6803 suite", + .test_cases = rfc6803_test_cases, +}; + kunit_test_suites(&rfc3961_suite, - &rfc3962_suite); + &rfc3962_suite, + &rfc6803_suite);
MODULE_DESCRIPTION("Test RPCSEC GSS Kerberos 5 functions"); MODULE_LICENSE("GPL");
From: Chuck Lever chuck.lever@oracle.com
Test the new-to-RPCSEC CMAC digest algorithm.
Tested-by: Scott Mayhew smayhew@redhat.com Signed-off-by: Chuck Lever chuck.lever@oracle.com --- net/sunrpc/auth_gss/gss_krb5_crypto.c | 1 net/sunrpc/auth_gss/gss_krb5_test.c | 168 +++++++++++++++++++++++++++++++++ 2 files changed, 169 insertions(+)
diff --git a/net/sunrpc/auth_gss/gss_krb5_crypto.c b/net/sunrpc/auth_gss/gss_krb5_crypto.c index 5d8dff65d014..c4e76a51203b 100644 --- a/net/sunrpc/auth_gss/gss_krb5_crypto.c +++ b/net/sunrpc/auth_gss/gss_krb5_crypto.c @@ -361,6 +361,7 @@ gss_krb5_checksum(struct crypto_ahash *tfm, char *header, int hdrlen, 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]; diff --git a/net/sunrpc/auth_gss/gss_krb5_test.c b/net/sunrpc/auth_gss/gss_krb5_test.c index c80a8f6588c0..ea8cba8c3eb3 100644 --- a/net/sunrpc/auth_gss/gss_krb5_test.c +++ b/net/sunrpc/auth_gss/gss_krb5_test.c @@ -10,6 +10,7 @@ #include <kunit/visibility.h>
#include <linux/kernel.h> +#include <crypto/hash.h>
#include <linux/sunrpc/xdr.h> #include <linux/sunrpc/gss_krb5.h> @@ -64,6 +65,52 @@ static void kdf_case(struct kunit *test) "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_base = param->plaintext->data, + .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); + KUNIT_ASSERT_NOT_NULL(test, gk5e); + + 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); + + 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_EQ_MSG(test, + memcmp(param->expected_result->data, + checksum.data, checksum.len), 0, + "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 = { \ @@ -71,6 +118,13 @@ static void kdf_case(struct kunit *test) .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 * @@ -836,12 +890,126 @@ static const struct gss_krb5_test_param rfc6803_kdf_test_params[] = { /* 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); + 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, + }, };
static struct kunit_suite rfc6803_suite = {
From: Chuck Lever chuck.lever@oracle.com
Add tests for the new-to-RPCSEC Camellia cipher.
Tested-by: Scott Mayhew smayhew@redhat.com Signed-off-by: Chuck Lever chuck.lever@oracle.com --- net/sunrpc/auth_gss/gss_krb5_test.c | 400 +++++++++++++++++++++++++++++++++++ 1 file changed, 400 insertions(+)
diff --git a/net/sunrpc/auth_gss/gss_krb5_test.c b/net/sunrpc/auth_gss/gss_krb5_test.c index ea8cba8c3eb3..3d8d41aab5fe 100644 --- a/net/sunrpc/auth_gss/gss_krb5_test.c +++ b/net/sunrpc/auth_gss/gss_krb5_test.c @@ -23,10 +23,12 @@ 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 *next_iv; }; @@ -999,6 +1001,399 @@ static const struct gss_krb5_test_param rfc6803_checksum_test_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); + KUNIT_ASSERT_NOT_NULL(test, gk5e); + + 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_EQ_MSG(test, + memcmp(param->expected_result->data, + buf.head[0].iov_base, buf.len), 0, + "encrypted result mismatch"); + KUNIT_EXPECT_EQ_MSG(test, + memcmp(param->expected_result->data + + (param->expected_result->len - checksum.len), + checksum.data, checksum.len), 0, + "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", @@ -1010,6 +1405,11 @@ static struct kunit_case rfc6803_test_cases[] = { .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 = {
From: Chuck Lever chuck.lever@oracle.com
RFC 8009 provides sample key derivation results, so Kunit tests are added to ensure our implementation derives the expected keys for the provided sample input.
Tested-by: Scott Mayhew smayhew@redhat.com Signed-off-by: Chuck Lever chuck.lever@oracle.com --- net/sunrpc/.kunitconfig | 3 + net/sunrpc/auth_gss/gss_krb5_test.c | 113 +++++++++++++++++++++++++++++++++++ 2 files changed, 115 insertions(+), 1 deletion(-)
diff --git a/net/sunrpc/.kunitconfig b/net/sunrpc/.kunitconfig index 90d0ad430e7e..a55a00fa649b 100644 --- a/net/sunrpc/.kunitconfig +++ b/net/sunrpc/.kunitconfig @@ -14,6 +14,8 @@ 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 @@ -24,4 +26,5 @@ CONFIG_RPCSEC_GSS_KRB5=y CONFIG_RPCSEC_GSS_KRB5_ENCTYPES_DES=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/auth_gss/gss_krb5_test.c b/net/sunrpc/auth_gss/gss_krb5_test.c index 3d8d41aab5fe..ad4737b60b56 100644 --- a/net/sunrpc/auth_gss/gss_krb5_test.c +++ b/net/sunrpc/auth_gss/gss_krb5_test.c @@ -1417,9 +1417,120 @@ static struct kunit_suite rfc6803_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); + +static struct kunit_case rfc8009_test_cases[] = { + { + .name = "RFC 8009 key derivation", + .run_case = kdf_case, + .generate_params = rfc8009_kdf_gen_params, + }, +}; + +static struct kunit_suite rfc8009_suite = { + .name = "RFC 8009 suite", + .test_cases = rfc8009_test_cases, +}; + kunit_test_suites(&rfc3961_suite, &rfc3962_suite, - &rfc6803_suite); + &rfc6803_suite, + &rfc8009_suite);
MODULE_DESCRIPTION("Test RPCSEC GSS Kerberos 5 functions"); MODULE_LICENSE("GPL");
From: Chuck Lever chuck.lever@oracle.com
RFC 8009 provides sample checksum results. Add KUnit tests to ensure our implementation derives the expected results for the provided sample input.
Tested-by: Scott Mayhew smayhew@redhat.com Signed-off-by: Chuck Lever chuck.lever@oracle.com --- net/sunrpc/auth_gss/gss_krb5_test.c | 53 +++++++++++++++++++++++++++++++++++ 1 file changed, 53 insertions(+)
diff --git a/net/sunrpc/auth_gss/gss_krb5_test.c b/net/sunrpc/auth_gss/gss_krb5_test.c index ad4737b60b56..0399f8338066 100644 --- a/net/sunrpc/auth_gss/gss_krb5_test.c +++ b/net/sunrpc/auth_gss/gss_krb5_test.c @@ -1514,12 +1514,65 @@ static const struct gss_krb5_test_param rfc8009_kdf_test_params[] = { /* 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); + 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, + }, };
static struct kunit_suite rfc8009_suite = {
From: Chuck Lever chuck.lever@oracle.com
RFC 8009 provides sample encryption results. Add KUnit tests to ensure our implementation derives the expected results for the provided sample input.
I hate how large this test is, but using non-standard key usage values means rfc8009_encrypt_case() can't simply reuse ->import_ctx to allocate and key its ciphers; and the test provides its own confounders, which means krb5_etm_encrypt() can't be used directly.
Tested-by: Scott Mayhew smayhew@redhat.com Signed-off-by: Chuck Lever chuck.lever@oracle.com --- net/sunrpc/auth_gss/gss_krb5_crypto.c | 26 ++ net/sunrpc/auth_gss/gss_krb5_internal.h | 3 net/sunrpc/auth_gss/gss_krb5_test.c | 329 +++++++++++++++++++++++++++++++ 3 files changed, 354 insertions(+), 4 deletions(-)
diff --git a/net/sunrpc/auth_gss/gss_krb5_crypto.c b/net/sunrpc/auth_gss/gss_krb5_crypto.c index c4e76a51203b..d0879a4d3122 100644 --- a/net/sunrpc/auth_gss/gss_krb5_crypto.c +++ b/net/sunrpc/auth_gss/gss_krb5_crypto.c @@ -886,10 +886,27 @@ gss_krb5_aes_decrypt(struct krb5_ctx *kctx, u32 offset, u32 len, return ret; }
-static 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) +/** + * 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; @@ -936,6 +953,7 @@ krb5_etm_checksum(struct crypto_sync_skcipher *cipher, kfree_sensitive(checksumdata); return err ? GSS_S_FAILURE : GSS_S_COMPLETE; } +EXPORT_SYMBOL_IF_KUNIT(krb5_etm_checksum);
/** * krb5_etm_encrypt - Encrypt using the RFC 8009 rules diff --git a/net/sunrpc/auth_gss/gss_krb5_internal.h b/net/sunrpc/auth_gss/gss_krb5_internal.h index bebe1ec2f507..c907eda2ad72 100644 --- a/net/sunrpc/auth_gss/gss_krb5_internal.h +++ b/net/sunrpc/auth_gss/gss_krb5_internal.h @@ -221,6 +221,9 @@ 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 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_test.c b/net/sunrpc/auth_gss/gss_krb5_test.c index 0399f8338066..fe3e4b81221a 100644 --- a/net/sunrpc/auth_gss/gss_krb5_test.c +++ b/net/sunrpc/auth_gss/gss_krb5_test.c @@ -30,6 +30,7 @@ struct gss_krb5_test_param { 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; };
@@ -1562,6 +1563,329 @@ static const struct gss_krb5_test_param rfc8009_checksum_test_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); + KUNIT_ASSERT_NOT_NULL(test, gk5e); + + *(__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_EQ_MSG(test, + memcmp(param->expected_result->data, + buf.head[0].iov_base, + param->expected_result->len), 0, + "ciphertext mismatch"); + KUNIT_EXPECT_EQ_MSG(test, memcmp(param->expected_hmac->data, + checksum.data, + checksum.len), 0, + "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", @@ -1573,6 +1897,11 @@ static struct kunit_case rfc8009_test_cases[] = { .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 = {
From: Chuck Lever chuck.lever@oracle.com
With the KUnit infrastructure recently added, we are free to define other unit tests particular to our implementation. As an example, I've added a self-test that encrypts then decrypts a string, and checks the result.
Tested-by: Scott Mayhew smayhew@redhat.com Signed-off-by: Chuck Lever chuck.lever@oracle.com --- net/sunrpc/auth_gss/gss_krb5_crypto.c | 20 ++++- net/sunrpc/auth_gss/gss_krb5_internal.h | 3 + net/sunrpc/auth_gss/gss_krb5_test.c | 124 +++++++++++++++++++++++++++++++ 3 files changed, 142 insertions(+), 5 deletions(-)
diff --git a/net/sunrpc/auth_gss/gss_krb5_crypto.c b/net/sunrpc/auth_gss/gss_krb5_crypto.c index d0879a4d3122..6c7c52eeed4f 100644 --- a/net/sunrpc/auth_gss/gss_krb5_crypto.c +++ b/net/sunrpc/auth_gss/gss_krb5_crypto.c @@ -713,10 +713,21 @@ int krb5_cbc_cts_encrypt(struct crypto_sync_skcipher *cts_tfm, } EXPORT_SYMBOL_IF_KUNIT(krb5_cbc_cts_encrypt);
-static int -krb5_cbc_cts_decrypt(struct crypto_sync_skcipher *cts_tfm, - struct crypto_sync_skcipher *cbc_tfm, - u32 offset, struct xdr_buf *buf) +/** + * 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; @@ -752,6 +763,7 @@ krb5_cbc_cts_decrypt(struct crypto_sync_skcipher *cts_tfm, /* 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);
u32 gss_krb5_aes_encrypt(struct krb5_ctx *kctx, u32 offset, diff --git a/net/sunrpc/auth_gss/gss_krb5_internal.h b/net/sunrpc/auth_gss/gss_krb5_internal.h index c907eda2ad72..b673e2626acb 100644 --- a/net/sunrpc/auth_gss/gss_krb5_internal.h +++ b/net/sunrpc/auth_gss/gss_krb5_internal.h @@ -221,6 +221,9 @@ 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); diff --git a/net/sunrpc/auth_gss/gss_krb5_test.c b/net/sunrpc/auth_gss/gss_krb5_test.c index fe3e4b81221a..c287ce15c419 100644 --- a/net/sunrpc/auth_gss/gss_krb5_test.c +++ b/net/sunrpc/auth_gss/gss_krb5_test.c @@ -1909,10 +1909,132 @@ static struct kunit_suite rfc8009_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); + KUNIT_ASSERT_NOT_NULL(test, gk5e); + + 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_EQ_MSG(test, + memcmp(param->plaintext->data, + buf.head[0].iov_base, buf.len), 0, + "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); + &rfc8009_suite, + &encryption_test_suite);
MODULE_DESCRIPTION("Test RPCSEC GSS Kerberos 5 functions"); MODULE_LICENSE("GPL");
On Sun, 2023-01-15 at 12:20 -0500, Chuck Lever wrote:
The purpose of this series is to improve/harden the security provided by the Linux kernel's RPCSEC GSS Kerberos 5 mechanism. There are lots of clean-ups in this series, but the pertinent feature is the addition of a clean deprecation path for the DES- and SHA1-based encryption types in accordance with Internet BCPs.
This series disables DES-based enctypes by default, provides a mechanism for disabling SHA1-based enctypes, and introduces two modern enctypes that do not use deprecated crypto algorithms.
Not only does that improve security for Kerberos 5 users, but it also prepares SunRPC for eventually switching to a shared common kernel Kerberos 5 implementation, which surely will not implement any deprecated encryption types (in particular, DES-based ones).
Today, MIT supports both of the newly-introduced enctypes, but Heimdal does not appear to. Thus distributions can enable and disable kernel enctype support to match the set of enctypes supported in their user space Kerberos libraries.
Scott has been kicking the tires -- we've found no regressions with the current SHA1-based enctypes, while the new ones are disabled by default until we have an opportunity for interop testing. The KUnit tests for the new enctypes pass and this implementation successfully interoperates with itself using these enctypes. Therefore I believe it to be safe to merge.
When this series gets merged, the Linux NFS community should select and announce a date-certain for removal of SunRPC's DES-based enctype code.
Changes since v1:
- Addressed Simo's NAK on "SUNRPC: Improve Kerberos confounder generation"
- Added Cc: linux-kselftest@ for review of the KUnit-related patches
Chuck Lever (41): SUNRPC: Add header ifdefs to linux/sunrpc/gss_krb5.h SUNRPC: Remove .blocksize field from struct gss_krb5_enctype SUNRPC: Remove .conflen field from struct gss_krb5_enctype SUNRPC: Improve Kerberos confounder generation SUNRPC: Obscure Kerberos session key SUNRPC: Refactor set-up for aux_cipher SUNRPC: Obscure Kerberos encryption keys SUNRPC: Obscure Kerberos signing keys SUNRPC: Obscure Kerberos integrity keys SUNRPC: Refactor the GSS-API Per Message calls in the Kerberos mechanism SUNRPC: Remove another switch on ctx->enctype SUNRPC: Add /proc/net/rpc/gss_krb5_enctypes file NFSD: Replace /proc/fs/nfsd/supported_krb5_enctypes with a symlink SUNRPC: Replace KRB5_SUPPORTED_ENCTYPES macro SUNRPC: Enable rpcsec_gss_krb5.ko to be built without CRYPTO_DES SUNRPC: Remove ->encrypt and ->decrypt methods from struct gss_krb5_enctype SUNRPC: Rename .encrypt_v2 and .decrypt_v2 methods SUNRPC: Hoist KDF into struct gss_krb5_enctype SUNRPC: Clean up cipher set up for v1 encryption types SUNRPC: Parametrize the key length passed to context_v2_alloc_cipher() SUNRPC: Add new subkey length fields SUNRPC: Refactor CBC with CTS into helpers SUNRPC: Add gk5e definitions for RFC 8009 encryption types SUNRPC: Add KDF-HMAC-SHA2 SUNRPC: Add RFC 8009 encryption and decryption functions SUNRPC: Advertise support for RFC 8009 encryption types SUNRPC: Support the Camellia enctypes SUNRPC: Add KDF_FEEDBACK_CMAC SUNRPC: Advertise support for the Camellia encryption types SUNRPC: Move remaining internal definitions to gss_krb5_internal.h SUNRPC: Add KUnit tests for rpcsec_krb5.ko SUNRPC: Export get_gss_krb5_enctype() SUNRPC: Add KUnit tests RFC 3961 Key Derivation SUNRPC: Add Kunit tests for RFC 3962-defined encryption/decryption SUNRPC: Add KDF KUnit tests for the RFC 6803 encryption types SUNRPC: Add checksum KUnit tests for the RFC 6803 encryption types SUNRPC: Add encryption KUnit tests for the RFC 6803 encryption types SUNRPC: Add KDF-HMAC-SHA2 Kunit tests SUNRPC: Add RFC 8009 checksum KUnit tests SUNRPC: Add RFC 8009 encryption KUnit tests SUNRPC: Add encryption self-tests
fs/nfsd/nfsctl.c | 74 +- include/linux/sunrpc/gss_krb5.h | 196 +-- include/linux/sunrpc/gss_krb5_enctypes.h | 41 - net/sunrpc/.kunitconfig | 30 + net/sunrpc/Kconfig | 96 +- net/sunrpc/auth_gss/Makefile | 2 + net/sunrpc/auth_gss/auth_gss.c | 17 + net/sunrpc/auth_gss/gss_krb5_crypto.c | 656 +++++-- net/sunrpc/auth_gss/gss_krb5_internal.h | 232 +++ net/sunrpc/auth_gss/gss_krb5_keys.c | 416 ++++- net/sunrpc/auth_gss/gss_krb5_mech.c | 730 +++++--- net/sunrpc/auth_gss/gss_krb5_seal.c | 122 +- net/sunrpc/auth_gss/gss_krb5_seqnum.c | 2 + net/sunrpc/auth_gss/gss_krb5_test.c | 2040 ++++++++++++++++++++++ net/sunrpc/auth_gss/gss_krb5_unseal.c | 63 +- net/sunrpc/auth_gss/gss_krb5_wrap.c | 124 +- net/sunrpc/auth_gss/svcauth_gss.c | 65 + 17 files changed, 4001 insertions(+), 905 deletions(-) delete mode 100644 include/linux/sunrpc/gss_krb5_enctypes.h create mode 100644 net/sunrpc/.kunitconfig create mode 100644 net/sunrpc/auth_gss/gss_krb5_internal.h create mode 100644 net/sunrpc/auth_gss/gss_krb5_test.c
-- Chuck Lever
I reviewed the whole patchset (except the Camellia related commits): Reviewed-by: Simo Sorce simo@redhat.com
Simo.
On Jan 18, 2023, at 11:02 AM, Simo Sorce simo@redhat.com wrote:
On Sun, 2023-01-15 at 12:20 -0500, Chuck Lever wrote:
The purpose of this series is to improve/harden the security provided by the Linux kernel's RPCSEC GSS Kerberos 5 mechanism. There are lots of clean-ups in this series, but the pertinent feature is the addition of a clean deprecation path for the DES- and SHA1-based encryption types in accordance with Internet BCPs.
This series disables DES-based enctypes by default, provides a mechanism for disabling SHA1-based enctypes, and introduces two modern enctypes that do not use deprecated crypto algorithms.
Not only does that improve security for Kerberos 5 users, but it also prepares SunRPC for eventually switching to a shared common kernel Kerberos 5 implementation, which surely will not implement any deprecated encryption types (in particular, DES-based ones).
Today, MIT supports both of the newly-introduced enctypes, but Heimdal does not appear to. Thus distributions can enable and disable kernel enctype support to match the set of enctypes supported in their user space Kerberos libraries.
Scott has been kicking the tires -- we've found no regressions with the current SHA1-based enctypes, while the new ones are disabled by default until we have an opportunity for interop testing. The KUnit tests for the new enctypes pass and this implementation successfully interoperates with itself using these enctypes. Therefore I believe it to be safe to merge.
When this series gets merged, the Linux NFS community should select and announce a date-certain for removal of SunRPC's DES-based enctype code.
Changes since v1:
- Addressed Simo's NAK on "SUNRPC: Improve Kerberos confounder generation"
- Added Cc: linux-kselftest@ for review of the KUnit-related patches
Chuck Lever (41): SUNRPC: Add header ifdefs to linux/sunrpc/gss_krb5.h SUNRPC: Remove .blocksize field from struct gss_krb5_enctype SUNRPC: Remove .conflen field from struct gss_krb5_enctype SUNRPC: Improve Kerberos confounder generation SUNRPC: Obscure Kerberos session key SUNRPC: Refactor set-up for aux_cipher SUNRPC: Obscure Kerberos encryption keys SUNRPC: Obscure Kerberos signing keys SUNRPC: Obscure Kerberos integrity keys SUNRPC: Refactor the GSS-API Per Message calls in the Kerberos mechanism SUNRPC: Remove another switch on ctx->enctype SUNRPC: Add /proc/net/rpc/gss_krb5_enctypes file NFSD: Replace /proc/fs/nfsd/supported_krb5_enctypes with a symlink SUNRPC: Replace KRB5_SUPPORTED_ENCTYPES macro SUNRPC: Enable rpcsec_gss_krb5.ko to be built without CRYPTO_DES SUNRPC: Remove ->encrypt and ->decrypt methods from struct gss_krb5_enctype SUNRPC: Rename .encrypt_v2 and .decrypt_v2 methods SUNRPC: Hoist KDF into struct gss_krb5_enctype SUNRPC: Clean up cipher set up for v1 encryption types SUNRPC: Parametrize the key length passed to context_v2_alloc_cipher() SUNRPC: Add new subkey length fields SUNRPC: Refactor CBC with CTS into helpers SUNRPC: Add gk5e definitions for RFC 8009 encryption types SUNRPC: Add KDF-HMAC-SHA2 SUNRPC: Add RFC 8009 encryption and decryption functions SUNRPC: Advertise support for RFC 8009 encryption types SUNRPC: Support the Camellia enctypes SUNRPC: Add KDF_FEEDBACK_CMAC SUNRPC: Advertise support for the Camellia encryption types SUNRPC: Move remaining internal definitions to gss_krb5_internal.h SUNRPC: Add KUnit tests for rpcsec_krb5.ko SUNRPC: Export get_gss_krb5_enctype() SUNRPC: Add KUnit tests RFC 3961 Key Derivation SUNRPC: Add Kunit tests for RFC 3962-defined encryption/decryption SUNRPC: Add KDF KUnit tests for the RFC 6803 encryption types SUNRPC: Add checksum KUnit tests for the RFC 6803 encryption types SUNRPC: Add encryption KUnit tests for the RFC 6803 encryption types SUNRPC: Add KDF-HMAC-SHA2 Kunit tests SUNRPC: Add RFC 8009 checksum KUnit tests SUNRPC: Add RFC 8009 encryption KUnit tests SUNRPC: Add encryption self-tests
fs/nfsd/nfsctl.c | 74 +- include/linux/sunrpc/gss_krb5.h | 196 +-- include/linux/sunrpc/gss_krb5_enctypes.h | 41 - net/sunrpc/.kunitconfig | 30 + net/sunrpc/Kconfig | 96 +- net/sunrpc/auth_gss/Makefile | 2 + net/sunrpc/auth_gss/auth_gss.c | 17 + net/sunrpc/auth_gss/gss_krb5_crypto.c | 656 +++++-- net/sunrpc/auth_gss/gss_krb5_internal.h | 232 +++ net/sunrpc/auth_gss/gss_krb5_keys.c | 416 ++++- net/sunrpc/auth_gss/gss_krb5_mech.c | 730 +++++--- net/sunrpc/auth_gss/gss_krb5_seal.c | 122 +- net/sunrpc/auth_gss/gss_krb5_seqnum.c | 2 + net/sunrpc/auth_gss/gss_krb5_test.c | 2040 ++++++++++++++++++++++ net/sunrpc/auth_gss/gss_krb5_unseal.c | 63 +- net/sunrpc/auth_gss/gss_krb5_wrap.c | 124 +- net/sunrpc/auth_gss/svcauth_gss.c | 65 + 17 files changed, 4001 insertions(+), 905 deletions(-) delete mode 100644 include/linux/sunrpc/gss_krb5_enctypes.h create mode 100644 net/sunrpc/.kunitconfig create mode 100644 net/sunrpc/auth_gss/gss_krb5_internal.h create mode 100644 net/sunrpc/auth_gss/gss_krb5_test.c
-- Chuck Lever
I reviewed the whole patchset (except the Camellia related commits): Reviewed-by: Simo Sorce simo@redhat.com
Thank you!
I've applied this series to nfsd-next. Comments and testing are still welcome.
-- Chuck Lever
Hi Chuck,
On Sun, 15 Jan 2023, Chuck Lever wrote:
The purpose of this series is to improve/harden the security provided by the Linux kernel's RPCSEC GSS Kerberos 5 mechanism. There are lots of clean-ups in this series, but the pertinent feature is the addition of a clean deprecation path for the DES- and SHA1-based encryption types in accordance with Internet BCPs.
This series disables DES-based enctypes by default, provides a mechanism for disabling SHA1-based enctypes, and introduces two modern enctypes that do not use deprecated crypto algorithms.
Not only does that improve security for Kerberos 5 users, but it also prepares SunRPC for eventually switching to a shared common kernel Kerberos 5 implementation, which surely will not implement any deprecated encryption types (in particular, DES-based ones).
Today, MIT supports both of the newly-introduced enctypes, but Heimdal does not appear to. Thus distributions can enable and disable kernel enctype support to match the set of enctypes supported in their user space Kerberos libraries.
Scott has been kicking the tires -- we've found no regressions with the current SHA1-based enctypes, while the new ones are disabled by default until we have an opportunity for interop testing. The KUnit tests for the new enctypes pass and this implementation successfully interoperates with itself using these enctypes. Therefore I believe it to be safe to merge.
When this series gets merged, the Linux NFS community should select and announce a date-certain for removal of SunRPC's DES-based enctype code.
As this is now upstream, I gave it a try on m68k (on the ARAnyM emulator), using a config based on atari_defconfig:
KTAP version 1 # Subtest: RFC 3961 tests 1..3 KTAP version 1 # Subtest: RFC 3961 n-fold ok 1 64-fold("012345") ok 2 56-fold("password") ok 3 64-fold("Rough Consensus, and Running Code") ok 4 168-fold("password") ok 5 192-fold("MASSACHVSETTS INSTITVTE OF TECHNOLOGY") ok 6 168-fold("Q") ok 7 168-fold("ba") ok 8 64-fold("kerberos") ok 9 128-fold("kerberos") ok 10 168-fold("kerberos") ok 11 256-fold("kerberos") # RFC 3961 n-fold: pass:11 fail:0 skip:0 total:11 ok 1 RFC 3961 n-fold KTAP version 1 # Subtest: RFC 3961 key derivation # RFC 3961 key derivation: ASSERTION FAILED at net/sunrpc/auth_gss/gss_krb5_test.c:52 Expected gk5e != ((void *)0), but gk5e == 00000000 ((void *)0) == 00000000 not ok 1 des3-hmac-sha1 key derivation case 1 # RFC 3961 key derivation: ASSERTION FAILED at net/sunrpc/auth_gss/gss_krb5_test.c:52 Expected gk5e != ((void *)0), but gk5e == 00000000 ((void *)0) == 00000000 not ok 2 des3-hmac-sha1 key derivation case 2 # RFC 3961 key derivation: ASSERTION FAILED at net/sunrpc/auth_gss/gss_krb5_test.c:52 Expected gk5e != ((void *)0), but gk5e == 00000000 ((void *)0) == 00000000 not ok 3 des3-hmac-sha1 key derivation case 3 # RFC 3961 key derivation: ASSERTION FAILED at net/sunrpc/auth_gss/gss_krb5_test.c:52 Expected gk5e != ((void *)0), but gk5e == 00000000 ((void *)0) == 00000000 not ok 4 des3-hmac-sha1 key derivation case 4 # RFC 3961 key derivation: ASSERTION FAILED at net/sunrpc/auth_gss/gss_krb5_test.c:52 Expected gk5e != ((void *)0), but gk5e == 00000000 ((void *)0) == 00000000 not ok 5 des3-hmac-sha1 key derivation case 5 # RFC 3961 key derivation: ASSERTION FAILED at net/sunrpc/auth_gss/gss_krb5_test.c:52 Expected gk5e != ((void *)0), but gk5e == 00000000 ((void *)0) == 00000000 not ok 6 des3-hmac-sha1 key derivation case 6 # RFC 3961 key derivation: ASSERTION FAILED at net/sunrpc/auth_gss/gss_krb5_test.c:52 Expected gk5e != ((void *)0), but gk5e == 00000000 ((void *)0) == 00000000 not ok 7 des3-hmac-sha1 key derivation case 7 # RFC 3961 key derivation: ASSERTION FAILED at net/sunrpc/auth_gss/gss_krb5_test.c:52 Expected gk5e != ((void *)0), but gk5e == 00000000 ((void *)0) == 00000000 not ok 8 des3-hmac-sha1 key derivation case 8 # RFC 3961 key derivation: ASSERTION FAILED at net/sunrpc/auth_gss/gss_krb5_test.c:52 Expected gk5e != ((void *)0), but gk5e == 00000000 ((void *)0) == 00000000 not ok 9 des3-hmac-sha1 key derivation case 9 # RFC 3961 key derivation: pass:0 fail:9 skip:0 total:9 not ok 2 RFC 3961 key derivation *** CHK *** FORMAT=2 Current process id is 794 BAD KERNEL TRAP: 00000000 Modules linked in: gss_krb5_test rpcsec_gss_krb5 auth_rpcgss oid_registry kunit PC: [<1188975a>] rfc6803_suite+0x2/0xffffc688 [gss_krb5_test] SR: 2200 SP: 93025120 a2: 01b6f700 d0: 00000002 d1: 00000010 d2: 00000014 d3: 01aebcc4 d4: 01aebc44 d5: 00000009 a0: 11889754 a1: 01aebc44 Process insmod (pid: 794, task=c42c6bea) Frame format=2 instr addr=1188975a Stack from 01aebbd8: 11963860 00000000 01aebc44 00000000 00000005 00000001 00000000 00000000 11889e5c 11889e34 11889be8 119644d8 1196356e 00000001 00000009 00000000 00000000 0000000b 01aebcfc 00000001 00000000 00000001 00000002 00000000 00000000 00000000 00000000 00657333 2d686d61 632d7368 6131206b 65792064 65726976 6174696f 6e206361 73652039 00000000 484e4f4c 4f475922 29000000 00000801 000c729c 005b9c58 00000000 00040cc0 00040cc0 00000000 00000000 Call Trace: [<11963860>] kunit_run_tests+0x2f2/0x3d2 [kunit] [<119644d8>] kunit_debugfs_create_suite+0x0/0x54 [kunit] [<1196356e>] kunit_run_tests+0x0/0x3d2 [kunit] [<000c729c>] get_page_from_freelist+0x176/0x48a [<00040cc0>] __finish_swait+0x1a/0x1c [<00040cc0>] __finish_swait+0x1a/0x1c [<00040cc0>] __finish_swait+0x1a/0x1c [<000c7126>] get_page_from_freelist+0x0/0x48a [<00009752>] ssincosnan+0x10/0x26 [<000c6f00>] __putback_isolated_page+0x62/0x7c [<119639e2>] __kunit_test_suites_init+0xa2/0xfa [kunit] [<000405ea>] __wake_up+0x0/0x1c [<00037774>] blocking_notifier_call_chain+0x0/0x46 [<11963a5a>] kunit_module_notify+0x20/0x34 [kunit] [<00037404>] notifier_call_chain+0x34/0x48 [<0004e3b4>] module_put+0x0/0x50 [<000377a0>] blocking_notifier_call_chain+0x2c/0x46 [<0004ebd4>] do_init_module+0xd6/0x1a2 [<0036ec50>] memset+0x0/0x8c [<00005b94>] flush_icache_range+0x0/0x30 [<0005009c>] load_module+0x1304/0x1368 [<0000eb60>] zer_rm2+0x1c/0x24 [<0036ed04>] __generic_copy_from_user+0x0/0x40 [<00010000>] EXPTBL+0x1c8/0x400 [<0036ec50>] memset+0x0/0x8c [<003762ac>] __cond_resched+0x0/0x46 [<000501d4>] sys_init_module+0xd4/0xda [<0000eb60>] zer_rm2+0x1c/0x24 [<0000536e>] buserr_c+0xc6/0x49a [<00002962>] syscall+0x8/0xc [<0000eb60>] zer_rm2+0x1c/0x24 [<0000eb60>] zer_rm2+0x1c/0x24 [<00010000>] EXPTBL+0x1c8/0x400 [<0018c00b>] nfs_direct_write_schedule_iovec+0xe3/0x1d6
Code: 646b 1188 42f6 0000 0000 0000 0000 5246 <4320> 3638 3033 2073 7569 7465 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 Disabling lock debugging due to kernel taint
All of gss_krb5_test, rpcsec_gss_krb5, auth_rpcgss, oid_registry, and kunit are modular.
Thanks!
Gr{oetje,eeting}s,
Geert
-- Geert Uytterhoeven -- There's lots of Linux beyond ia32 -- geert@linux-m68k.org
In personal conversations with technical people, I call myself a hacker. But when I'm talking to journalists I just say "programmer" or something like that. -- Linus Torvalds
On Feb 23, 2023, at 8:05 AM, Geert Uytterhoeven geert@linux-m68k.org wrote:
Hi Chuck,
On Sun, 15 Jan 2023, Chuck Lever wrote:
The purpose of this series is to improve/harden the security provided by the Linux kernel's RPCSEC GSS Kerberos 5 mechanism. There are lots of clean-ups in this series, but the pertinent feature is the addition of a clean deprecation path for the DES- and SHA1-based encryption types in accordance with Internet BCPs.
This series disables DES-based enctypes by default, provides a mechanism for disabling SHA1-based enctypes, and introduces two modern enctypes that do not use deprecated crypto algorithms.
Not only does that improve security for Kerberos 5 users, but it also prepares SunRPC for eventually switching to a shared common kernel Kerberos 5 implementation, which surely will not implement any deprecated encryption types (in particular, DES-based ones).
Today, MIT supports both of the newly-introduced enctypes, but Heimdal does not appear to. Thus distributions can enable and disable kernel enctype support to match the set of enctypes supported in their user space Kerberos libraries.
Scott has been kicking the tires -- we've found no regressions with the current SHA1-based enctypes, while the new ones are disabled by default until we have an opportunity for interop testing. The KUnit tests for the new enctypes pass and this implementation successfully interoperates with itself using these enctypes. Therefore I believe it to be safe to merge.
When this series gets merged, the Linux NFS community should select and announce a date-certain for removal of SunRPC's DES-based enctype code.
As this is now upstream, I gave it a try on m68k (on the ARAnyM emulator), using a config based on atari_defconfig:
KTAP version 1 # Subtest: RFC 3961 tests 1..3 KTAP version 1 # Subtest: RFC 3961 n-fold ok 1 64-fold("012345") ok 2 56-fold("password") ok 3 64-fold("Rough Consensus, and Running Code") ok 4 168-fold("password") ok 5 192-fold("MASSACHVSETTS INSTITVTE OF TECHNOLOGY") ok 6 168-fold("Q") ok 7 168-fold("ba") ok 8 64-fold("kerberos") ok 9 128-fold("kerberos") ok 10 168-fold("kerberos") ok 11 256-fold("kerberos") # RFC 3961 n-fold: pass:11 fail:0 skip:0 total:11 ok 1 RFC 3961 n-fold KTAP version 1 # Subtest: RFC 3961 key derivation # RFC 3961 key derivation: ASSERTION FAILED at net/sunrpc/auth_gss/gss_krb5_test.c:52 Expected gk5e != ((void *)0), but gk5e == 00000000 ((void *)0) == 00000000 not ok 1 des3-hmac-sha1 key derivation case 1
Geert, thanks for testing GSS on m68k.
This assertion failure means that support for the encryption types specified in RFC 3961 is not built into your kernel.
The new Kunit tests don't work unless everything is built in -- there's a net/sunrpc/.kunitconfig that provides the supported build configuration for running them. I typically use a command line similar to this:
./tools/testing/kunit/kunit.py run --raw_output=all --kunitconfig ./net/sunrpc/.kunitconfig
I'm not sure what's crashing at rfc6803_suite+0x2, but I suspect it's a similar issue.
# RFC 3961 key derivation: ASSERTION FAILED at net/sunrpc/auth_gss/gss_krb5_test.c:52 Expected gk5e != ((void *)0), but gk5e == 00000000 ((void *)0) == 00000000 not ok 2 des3-hmac-sha1 key derivation case 2 # RFC 3961 key derivation: ASSERTION FAILED at net/sunrpc/auth_gss/gss_krb5_test.c:52 Expected gk5e != ((void *)0), but gk5e == 00000000 ((void *)0) == 00000000 not ok 3 des3-hmac-sha1 key derivation case 3 # RFC 3961 key derivation: ASSERTION FAILED at net/sunrpc/auth_gss/gss_krb5_test.c:52 Expected gk5e != ((void *)0), but gk5e == 00000000 ((void *)0) == 00000000 not ok 4 des3-hmac-sha1 key derivation case 4 # RFC 3961 key derivation: ASSERTION FAILED at net/sunrpc/auth_gss/gss_krb5_test.c:52 Expected gk5e != ((void *)0), but gk5e == 00000000 ((void *)0) == 00000000 not ok 5 des3-hmac-sha1 key derivation case 5 # RFC 3961 key derivation: ASSERTION FAILED at net/sunrpc/auth_gss/gss_krb5_test.c:52 Expected gk5e != ((void *)0), but gk5e == 00000000 ((void *)0) == 00000000 not ok 6 des3-hmac-sha1 key derivation case 6 # RFC 3961 key derivation: ASSERTION FAILED at net/sunrpc/auth_gss/gss_krb5_test.c:52 Expected gk5e != ((void *)0), but gk5e == 00000000 ((void *)0) == 00000000 not ok 7 des3-hmac-sha1 key derivation case 7 # RFC 3961 key derivation: ASSERTION FAILED at net/sunrpc/auth_gss/gss_krb5_test.c:52 Expected gk5e != ((void *)0), but gk5e == 00000000 ((void *)0) == 00000000 not ok 8 des3-hmac-sha1 key derivation case 8 # RFC 3961 key derivation: ASSERTION FAILED at net/sunrpc/auth_gss/gss_krb5_test.c:52 Expected gk5e != ((void *)0), but gk5e == 00000000 ((void *)0) == 00000000 not ok 9 des3-hmac-sha1 key derivation case 9 # RFC 3961 key derivation: pass:0 fail:9 skip:0 total:9 not ok 2 RFC 3961 key derivation *** CHK *** FORMAT=2 Current process id is 794 BAD KERNEL TRAP: 00000000 Modules linked in: gss_krb5_test rpcsec_gss_krb5 auth_rpcgss oid_registry kunit PC: [<1188975a>] rfc6803_suite+0x2/0xffffc688 [gss_krb5_test] SR: 2200 SP: 93025120 a2: 01b6f700 d0: 00000002 d1: 00000010 d2: 00000014 d3: 01aebcc4 d4: 01aebc44 d5: 00000009 a0: 11889754 a1: 01aebc44 Process insmod (pid: 794, task=c42c6bea) Frame format=2 instr addr=1188975a Stack from 01aebbd8: 11963860 00000000 01aebc44 00000000 00000005 00000001 00000000 00000000 11889e5c 11889e34 11889be8 119644d8 1196356e 00000001 00000009 00000000 00000000 0000000b 01aebcfc 00000001 00000000 00000001 00000002 00000000 00000000 00000000 00000000 00657333 2d686d61 632d7368 6131206b 65792064 65726976 6174696f 6e206361 73652039 00000000 484e4f4c 4f475922 29000000 00000801 000c729c 005b9c58 00000000 00040cc0 00040cc0 00000000 00000000 Call Trace: [<11963860>] kunit_run_tests+0x2f2/0x3d2 [kunit] [<119644d8>] kunit_debugfs_create_suite+0x0/0x54 [kunit] [<1196356e>] kunit_run_tests+0x0/0x3d2 [kunit] [<000c729c>] get_page_from_freelist+0x176/0x48a [<00040cc0>] __finish_swait+0x1a/0x1c [<00040cc0>] __finish_swait+0x1a/0x1c [<00040cc0>] __finish_swait+0x1a/0x1c [<000c7126>] get_page_from_freelist+0x0/0x48a [<00009752>] ssincosnan+0x10/0x26 [<000c6f00>] __putback_isolated_page+0x62/0x7c [<119639e2>] __kunit_test_suites_init+0xa2/0xfa [kunit] [<000405ea>] __wake_up+0x0/0x1c [<00037774>] blocking_notifier_call_chain+0x0/0x46 [<11963a5a>] kunit_module_notify+0x20/0x34 [kunit] [<00037404>] notifier_call_chain+0x34/0x48 [<0004e3b4>] module_put+0x0/0x50 [<000377a0>] blocking_notifier_call_chain+0x2c/0x46 [<0004ebd4>] do_init_module+0xd6/0x1a2 [<0036ec50>] memset+0x0/0x8c [<00005b94>] flush_icache_range+0x0/0x30 [<0005009c>] load_module+0x1304/0x1368 [<0000eb60>] zer_rm2+0x1c/0x24 [<0036ed04>] __generic_copy_from_user+0x0/0x40 [<00010000>] EXPTBL+0x1c8/0x400 [<0036ec50>] memset+0x0/0x8c [<003762ac>] __cond_resched+0x0/0x46 [<000501d4>] sys_init_module+0xd4/0xda [<0000eb60>] zer_rm2+0x1c/0x24 [<0000536e>] buserr_c+0xc6/0x49a [<00002962>] syscall+0x8/0xc [<0000eb60>] zer_rm2+0x1c/0x24 [<0000eb60>] zer_rm2+0x1c/0x24 [<00010000>] EXPTBL+0x1c8/0x400 [<0018c00b>] nfs_direct_write_schedule_iovec+0xe3/0x1d6
Code: 646b 1188 42f6 0000 0000 0000 0000 5246 <4320> 3638 3033 2073 7569 7465 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 Disabling lock debugging due to kernel taint
All of gss_krb5_test, rpcsec_gss_krb5, auth_rpcgss, oid_registry, and kunit are modular.
Thanks!
Gr{oetje,eeting}s,
Geert
-- Geert Uytterhoeven -- There's lots of Linux beyond ia32 -- geert@linux-m68k.org
In personal conversations with technical people, I call myself a hacker. But when I'm talking to journalists I just say "programmer" or something like that. -- Linus Torvalds
-- Chuck Lever
Hi Chuck,
On Thu, Feb 23, 2023 at 3:00 PM Chuck Lever III chuck.lever@oracle.com wrote:
On Feb 23, 2023, at 8:05 AM, Geert Uytterhoeven geert@linux-m68k.org wrote: On Sun, 15 Jan 2023, Chuck Lever wrote:
The purpose of this series is to improve/harden the security provided by the Linux kernel's RPCSEC GSS Kerberos 5 mechanism. There are lots of clean-ups in this series, but the pertinent feature is the addition of a clean deprecation path for the DES- and SHA1-based encryption types in accordance with Internet BCPs.
This series disables DES-based enctypes by default, provides a mechanism for disabling SHA1-based enctypes, and introduces two modern enctypes that do not use deprecated crypto algorithms.
Not only does that improve security for Kerberos 5 users, but it also prepares SunRPC for eventually switching to a shared common kernel Kerberos 5 implementation, which surely will not implement any deprecated encryption types (in particular, DES-based ones).
Today, MIT supports both of the newly-introduced enctypes, but Heimdal does not appear to. Thus distributions can enable and disable kernel enctype support to match the set of enctypes supported in their user space Kerberos libraries.
Scott has been kicking the tires -- we've found no regressions with the current SHA1-based enctypes, while the new ones are disabled by default until we have an opportunity for interop testing. The KUnit tests for the new enctypes pass and this implementation successfully interoperates with itself using these enctypes. Therefore I believe it to be safe to merge.
When this series gets merged, the Linux NFS community should select and announce a date-certain for removal of SunRPC's DES-based enctype code.
As this is now upstream, I gave it a try on m68k (on the ARAnyM emulator), using a config based on atari_defconfig:
KTAP version 1 # Subtest: RFC 3961 tests 1..3 KTAP version 1 # Subtest: RFC 3961 n-fold ok 1 64-fold("012345") ok 2 56-fold("password") ok 3 64-fold("Rough Consensus, and Running Code") ok 4 168-fold("password") ok 5 192-fold("MASSACHVSETTS INSTITVTE OF TECHNOLOGY") ok 6 168-fold("Q") ok 7 168-fold("ba") ok 8 64-fold("kerberos") ok 9 128-fold("kerberos") ok 10 168-fold("kerberos") ok 11 256-fold("kerberos") # RFC 3961 n-fold: pass:11 fail:0 skip:0 total:11 ok 1 RFC 3961 n-fold KTAP version 1 # Subtest: RFC 3961 key derivation # RFC 3961 key derivation: ASSERTION FAILED at net/sunrpc/auth_gss/gss_krb5_test.c:52 Expected gk5e != ((void *)0), but gk5e == 00000000 ((void *)0) == 00000000 not ok 1 des3-hmac-sha1 key derivation case 1
Geert, thanks for testing GSS on m68k.
This assertion failure means that support for the encryption types specified in RFC 3961 is not built into your kernel.
The new Kunit tests don't work unless everything is built in --
there's a net/sunrpc/.kunitconfig that provides the supported build configuration for running them. I typically use a command line similar to this:
./tools/testing/kunit/kunit.py run --raw_output=all --kunitconfig ./net/sunrpc/.kunitconfig
Aren't modular crypto algorithms auto-loaded when needed?
In general, it's a good idea to make the tests test only functionality that is available, either through "depends on" in Kconfig, or "#if IS_ENABLED(...)". Of course that does not preclude providing a .kunitconfig to enable and test everything.
Note that net/sunrpc/.kunitconfig has
CONFIG_RPCSEC_GSS_KRB5_KUNIT_TEST=y
which needs KUNIT_ALL_TESTS=y, else it will still be modular.
First, I tried getting my modular setup working. After enabling: CONFIG_RPCSEC_GSS_KRB5_ENCTYPES_DES=y CONFIG_RPCSEC_GSS_KRB5_ENCTYPES_CAMELLIA=y CONFIG_RPCSEC_GSS_KRB5_ENCTYPES_AES_SHA2=y (the former is marked deprecated!) and loading all needed crypto modules (cfr. the .kunitconfig), I got:
KTAP version 1 # Subtest: RFC 3961 tests 1..3 KTAP version 1 # Subtest: RFC 3961 n-fold ok 1 64-fold("012345") ok 2 56-fold("password") ok 3 64-fold("Rough Consensus, and Running Code") ok 4 168-fold("password") ok 5 192-fold("MASSACHVSETTS INSTITVTE OF TECHNOLOGY") ok 6 168-fold("Q") ok 7 168-fold("ba") ok 8 64-fold("kerberos") ok 9 128-fold("kerberos") ok 10 168-fold("kerberos") ok 11 256-fold("kerberos") # RFC 3961 n-fold: pass:11 fail:0 skip:0 total:11 ok 1 RFC 3961 n-fold KTAP version 1 # Subtest: RFC 3961 key derivation # RFC 3961 key derivation: ASSERTION FAILED at net/sunrpc/auth_gss/gss_krb5_test.c:62 Expected err == 0, but err == -22 (0xffffffffffffffea) not ok 1 des3-hmac-sha1 key derivation case 1 # RFC 3961 key derivation: ASSERTION FAILED at net/sunrpc/auth_gss/gss_krb5_test.c:62 Expected err == 0, but err == -22 (0xffffffffffffffea) not ok 2 des3-hmac-sha1 key derivation case 2 # RFC 3961 key derivation: ASSERTION FAILED at net/sunrpc/auth_gss/gss_krb5_test.c:62 Expected err == 0, but err == -22 (0xffffffffffffffea) not ok 3 des3-hmac-sha1 key derivation case 3 # RFC 3961 key derivation: ASSERTION FAILED at net/sunrpc/auth_gss/gss_krb5_test.c:62 Expected err == 0, but err == -22 (0xffffffffffffffea) not ok 4 des3-hmac-sha1 key derivation case 4 # RFC 3961 key derivation: ASSERTION FAILED at net/sunrpc/auth_gss/gss_krb5_test.c:62 Expected err == 0, but err == -22 (0xffffffffffffffea) not ok 5 des3-hmac-sha1 key derivation case 5 # RFC 3961 key derivation: ASSERTION FAILED at net/sunrpc/auth_gss/gss_krb5_test.c:62 Expected err == 0, but err == -22 (0xffffffffffffffea) not ok 6 des3-hmac-sha1 key derivation case 6 # RFC 3961 key derivation: ASSERTION FAILED at net/sunrpc/auth_gss/gss_krb5_test.c:62 Expected err == 0, but err == -22 (0xffffffffffffffea) not ok 7 des3-hmac-sha1 key derivation case 7 # RFC 3961 key derivation: ASSERTION FAILED at net/sunrpc/auth_gss/gss_krb5_test.c:62 Expected err == 0, but err == -22 (0xffffffffffffffea) not ok 8 des3-hmac-sha1 key derivation case 8 # RFC 3961 key derivation: ASSERTION FAILED at net/sunrpc/auth_gss/gss_krb5_test.c:62 Expected err == 0, but err == -22 (0xffffffffffffffea) not ok 9 des3-hmac-sha1 key derivation case 9 # RFC 3961 key derivation: pass:0 fail:9 skip:0 total:9 not ok 2 RFC 3961 key derivation *** CHK *** FORMAT=2 Current process id is 785 BAD KERNEL TRAP: 00000000 Modules linked in: gss_krb5_test kunit rpcsec_gss_krb5 auth_rpcgss oid_registry camellia_generic sha512_generic sha1_generic md5 cmac hmac ecb cts cbc PC: [<1187775a>] rfc6803_suite+0x2/0xffffc688 [gss_krb5_test] SR: 2200 SP: efc1339e a2: 01b4e610 d0: 00000002 d1: 00000010 d2: 00000014 d3: 01b57cc4 d4: 01b57c44 d5: 00000009 a0: 11877754 a1: 01b57c44 Process insmod (pid: 785, task=52ae00a3) Frame format=2 instr addr=1187775a Stack from 01b57bd8: 11869860 00000000 01b57c44 00000000 00000005 00000001 00000000 00000000 11877e5c 11877e34 11877be8 1186a4d8 1186956e 00000001 00000009 00000000 00000000 0000000b 01b57cfc 00000001 00000000 00000001 00000002 00000000 00000000 00000000 00000000 00657333 2d686d61 632d7368 6131206b 65792064 65726976 6174696f 6e206361 73652039 00000000 484e4f4c 4f475922 29000000 00000801 000c729c 005d6074 00000000 00040cc0 00040cc0 00000000 00000000 Call Trace: [<11869860>] kunit_run_tests+0x2f2/0x3d2 [kunit]
I.e. -EINVAL later, so something is still missing.
Second, with net/sunrpc/.kunitconfig, and just CONFIG_RPCSEC_GSS_KRB5_KUNIT_TEST still modular, the tests succeed, but there is still a crash:
KTAP version 1 # Subtest: RFC 3961 tests 1..3 KTAP version 1 # Subtest: RFC 3961 n-fold ok 1 64-fold("012345") ok 2 56-fold("password") ok 3 64-fold("Rough Consensus, and Running Code") ok 4 168-fold("password") ok 5 192-fold("MASSACHVSETTS INSTITVTE OF TECHNOLOGY") ok 6 168-fold("Q") ok 7 168-fold("ba") ok 8 64-fold("kerberos") ok 9 128-fold("kerberos") ok 10 168-fold("kerberos") ok 11 256-fold("kerberos") # RFC 3961 n-fold: pass:11 fail:0 skip:0 total:11 ok 1 RFC 3961 n-fold KTAP version 1 # Subtest: RFC 3961 key derivation ok 1 des3-hmac-sha1 key derivation case 1 ok 2 des3-hmac-sha1 key derivation case 2 ok 3 des3-hmac-sha1 key derivation case 3 ok 4 des3-hmac-sha1 key derivation case 4 ok 5 des3-hmac-sha1 key derivation case 5 ok 6 des3-hmac-sha1 key derivation case 6 ok 7 des3-hmac-sha1 key derivation case 7 ok 8 des3-hmac-sha1 key derivation case 8 ok 9 des3-hmac-sha1 key derivation case 9 # RFC 3961 key derivation: pass:9 fail:0 skip:0 total:9 ok 2 RFC 3961 key derivation *** CHK *** FORMAT=2 Current process id is 716 BAD KERNEL TRAP: 00000000 Modules linked in: gss_krb5_test PC: [<1197575a>] rfc6803_suite+0x2/0xffffc688 [gss_krb5_test] SR: 2200 SP: acd229e8 a2: 01ae20a0 d0: 00000002 d1: 00000010 d2: 00000014 d3: 01ae1cc4 d4: 01ae1c44 d5: 00000000 a0: 11975754 a1: 01ae1c44 Process insmod (pid: 716, task=962b0746) Frame format=2 instr addr=1197575a Stack from 01ae1bd8: 001f3158 00000000 01ae1c44 00000000 00000005 00000001 00000000 00000000 11975e5c 11975e34 11975be8 001f415c 001f2e66 00000001 00000000 00000000 00000009 00000014 01ae1cfc 00000002 00000000 00000000 00000002 00000000 00000000 00000000 00000000 00657333 2d686d61 632d7368 6131206b 65792064 65726976 6174696f 6e206361 73652039 00000000 484e4f4c 4f475922 29000000 00000801 000c729c 005db3c4 00000000 00040cc0 00040cc0 00000000 00000000 Call Trace: [<001f3158>] kunit_run_tests+0x2f2/0x3d2
Third, with net/sunrpc/.kunitconfig, and CONFIG_RPCSEC_GSS_KRB5_KUNIT_TEST=y:
KTAP version 1 # Subtest: RFC 3961 tests 1..2 KTAP version 1 # Subtest: RFC 3961 n-fold ok 1 64-fold("012345") ok 2 56-fold("password") ok 3 64-fold("Rough Consensus, and Running Code") ok 4 168-fold("password") ok 5 192-fold("MASSACHVSETTS INSTITVTE OF TECHNOLOGY") ok 6 168-fold("Q") ok 7 168-fold("ba") ok 8 64-fold("kerberos") ok 9 128-fold("kerberos") ok 10 168-fold("kerberos") ok 11 256-fold("kerberos") # RFC 3961 n-fold: pass:11 fail:0 skip:0 total:11 ok 1 RFC 3961 n-fold KTAP version 1 # Subtest: RFC 3961 key derivation ok 1 des3-hmac-sha1 key derivation case 1 ok 2 des3-hmac-sha1 key derivation case 2 ok 3 des3-hmac-sha1 key derivation case 3 ok 4 des3-hmac-sha1 key derivation case 4 ok 5 des3-hmac-sha1 key derivation case 5 ok 6 des3-hmac-sha1 key derivation case 6 ok 7 des3-hmac-sha1 key derivation case 7 ok 8 des3-hmac-sha1 key derivation case 8 ok 9 des3-hmac-sha1 key derivation case 9 # RFC 3961 key derivation: pass:9 fail:0 skip:0 total:9 ok 2 RFC 3961 key derivation # RFC 3961 tests: pass:2 fail:0 skip:0 total:2 # Totals: pass:20 fail:0 skip:0 total:20 ok 31 RFC 3961 tests KTAP version 1 # Subtest: RFC 3962 suite 1..2 KTAP version 1 # Subtest: RFC 3962 encryption ok 1 Encrypt with aes128-cts-hmac-sha1-96 case 1 ok 2 Encrypt with aes128-cts-hmac-sha1-96 case 2 ok 3 Encrypt with aes128-cts-hmac-sha1-96 case 3 ok 4 Encrypt with aes128-cts-hmac-sha1-96 case 4 ok 5 Encrypt with aes128-cts-hmac-sha1-96 case 5 ok 6 Encrypt with aes128-cts-hmac-sha1-96 case 6 # RFC 3962 encryption: pass:6 fail:0 skip:0 total:6 ok 1 RFC 3962 encryption Unable to handle kernel access at virtual address af06da84 Oops: 00000000 Modules linked in: PC: [<20746573>] 0x20746573 SR: 2204 SP: 05ef00e4 a2: 010195d0 d0: 00000002 d1: 00000010 d2: 00000006 d3: 0101bdf8 d4: 0101bd78 d5: 00000000 a0: 20746573 a1: 0101bd78 Process swapper (pid: 1, task=b63809d5) Frame format=7 eff addr=20746573 ssw=0546 faddr=20746573 wb 1 stat/addr/data: 0000 00000000 00000000 wb 2 stat/addr/data: 0000 00000000 00000000 wb 3 stat/addr/data: 0000 20746573 00000000 push data: 00000000 00000000 00000000 00000000 Stack from 0101bd0c: 001f64b0 00000000 0101bd78 0000001f 00000023 01015480 000359ba 0000209c 00000000 005890c0 0053aafc 001f7c88 001f61be 00000001 00000000 00000000 00000006 00000006 0101be30 00000001 00000000 00000000 00000001 00000000 00000000 00000000 00000000 006e6372 79707420 77697468 20616573 3132382d 6374732d 686d6163 2d736861 312d3936 20636173 65203600 4f475922 29000000 00000801 000c886c 006003b4 00000000 00040cc0 00040cc0 00000000 00000000 Call Trace: [<001f64b0>] kunit_run_tests+0x2f2/0x3d2 [<000359ba>] parse_args+0x0/0x202 [<0000209c>] do_one_initcall+0x0/0x184 [<001f7c88>] kunit_debugfs_create_suite+0x0/0x54 [<001f61be>] kunit_run_tests+0x0/0x3d2 [<000c886c>] get_page_from_freelist+0x176/0x48a [<00040cc0>] __finish_swait+0x1a/0x1c [<00040cc0>] __finish_swait+0x1a/0x1c [<00040cc0>] __finish_swait+0x1a/0x1c [<0000209c>] do_one_initcall+0x0/0x184 [<000c86f6>] get_page_from_freelist+0x0/0x48a [<000c8500>] prepare_alloc_pages.isra.0+0x12/0x84 [<001f6632>] __kunit_test_suites_init+0xa2/0xfa [<003a160c>] _printk+0x0/0x18 [<001f7b9e>] kunit_run_all_tests+0xd0/0x1a6 [<0039a0c0>] strcpy+0x0/0x1c [<00564602>] kernel_init_freeable+0x152/0x190 [<000359ba>] parse_args+0x0/0x202 [<003a6e76>] kernel_init+0x0/0xec [<003a6e8a>] kernel_init+0x14/0xec [<003a6e76>] kernel_init+0x0/0xec [<000028d4>] ret_from_kernel_thread+0xc/0x14
I.e. a slightly different crash. As the difference between the two crashes is modular vs. builtin, this looks like an out-of-bound access in the test.
Gr{oetje,eeting}s,
Geert
On Feb 23, 2023, at 10:16 AM, Geert Uytterhoeven geert@linux-m68k.org wrote:
Hi Chuck,
On Thu, Feb 23, 2023 at 3:00 PM Chuck Lever III chuck.lever@oracle.com wrote:
On Feb 23, 2023, at 8:05 AM, Geert Uytterhoeven geert@linux-m68k.org wrote: On Sun, 15 Jan 2023, Chuck Lever wrote:
The purpose of this series is to improve/harden the security provided by the Linux kernel's RPCSEC GSS Kerberos 5 mechanism. There are lots of clean-ups in this series, but the pertinent feature is the addition of a clean deprecation path for the DES- and SHA1-based encryption types in accordance with Internet BCPs.
This series disables DES-based enctypes by default, provides a mechanism for disabling SHA1-based enctypes, and introduces two modern enctypes that do not use deprecated crypto algorithms.
Not only does that improve security for Kerberos 5 users, but it also prepares SunRPC for eventually switching to a shared common kernel Kerberos 5 implementation, which surely will not implement any deprecated encryption types (in particular, DES-based ones).
Today, MIT supports both of the newly-introduced enctypes, but Heimdal does not appear to. Thus distributions can enable and disable kernel enctype support to match the set of enctypes supported in their user space Kerberos libraries.
Scott has been kicking the tires -- we've found no regressions with the current SHA1-based enctypes, while the new ones are disabled by default until we have an opportunity for interop testing. The KUnit tests for the new enctypes pass and this implementation successfully interoperates with itself using these enctypes. Therefore I believe it to be safe to merge.
When this series gets merged, the Linux NFS community should select and announce a date-certain for removal of SunRPC's DES-based enctype code.
As this is now upstream, I gave it a try on m68k (on the ARAnyM emulator), using a config based on atari_defconfig:
KTAP version 1 # Subtest: RFC 3961 tests 1..3 KTAP version 1 # Subtest: RFC 3961 n-fold ok 1 64-fold("012345") ok 2 56-fold("password") ok 3 64-fold("Rough Consensus, and Running Code") ok 4 168-fold("password") ok 5 192-fold("MASSACHVSETTS INSTITVTE OF TECHNOLOGY") ok 6 168-fold("Q") ok 7 168-fold("ba") ok 8 64-fold("kerberos") ok 9 128-fold("kerberos") ok 10 168-fold("kerberos") ok 11 256-fold("kerberos") # RFC 3961 n-fold: pass:11 fail:0 skip:0 total:11 ok 1 RFC 3961 n-fold KTAP version 1 # Subtest: RFC 3961 key derivation # RFC 3961 key derivation: ASSERTION FAILED at net/sunrpc/auth_gss/gss_krb5_test.c:52 Expected gk5e != ((void *)0), but gk5e == 00000000 ((void *)0) == 00000000 not ok 1 des3-hmac-sha1 key derivation case 1
Geert, thanks for testing GSS on m68k.
This assertion failure means that support for the encryption types specified in RFC 3961 is not built into your kernel.
The new Kunit tests don't work unless everything is built in --
there's a net/sunrpc/.kunitconfig that provides the supported build configuration for running them. I typically use a command line similar to this:
./tools/testing/kunit/kunit.py run --raw_output=all --kunitconfig ./net/sunrpc/.kunitconfig
Aren't modular crypto algorithms auto-loaded when needed?
The ciphers and digests are handled via the kernel's crypto manager. They will indeed get auto-loaded by SunRPC's GSS on demand, but of course, the set of algorithms used by GSS has to be enabled by Kconfig options first.
SunRPC GSS has a set of Kerberos encryption types that make use of individual ciphers and digests. Those have never been modularized, and they are each enabled by Kconfig options, as explained below.
In general, it's a good idea to make the tests test only functionality that is available, either through "depends on" in Kconfig, or "#if IS_ENABLED(...)".
An earlier version of this patch set did just that. It became quite a mess. That's why I chose the .kunitconfig approach.
Of course that does not preclude providing a .kunitconfig to enable and test everything.
The suite should test every Kerberos encryption type that SunRPC GSS has support for. There's no reason to disable a particular encryption type when running the unit tests... unless I'm missing something?
Note that net/sunrpc/.kunitconfig has
CONFIG_RPCSEC_GSS_KRB5_KUNIT_TEST=y
which needs KUNIT_ALL_TESTS=y, else it will still be modular.
First, I tried getting my modular setup working. After enabling: CONFIG_RPCSEC_GSS_KRB5_ENCTYPES_DES=y
And CONFIG_RPCSEC_GSS_KRB5_ENCTYPES_AES_SHA1=y ??
CONFIG_RPCSEC_GSS_KRB5_ENCTYPES_CAMELLIA=y CONFIG_RPCSEC_GSS_KRB5_ENCTYPES_AES_SHA2=y (the former is marked deprecated!)
Yes, that's one of the main points of my patches. ENCTYPES_DES gates support for several Kerberos encryption types that we want to remove from the kernel eventually.
AES_SHA1 is another set of encryption types that still has legs, but will need to be deprecated because it uses SHA1, which is scheduled for deprecation.
CAMELLIA is apparently not widely supported, so it can be disabled separately.
AES_SHA2 is shiny and new. Some distributions might choose to keep it disabled until it's had more road testing. But these are the encryption types that are to replace both DES and AES_SHA1.
and loading all needed crypto modules (cfr. the .kunitconfig), I got:
KTAP version 1 # Subtest: RFC 3961 tests 1..3 KTAP version 1 # Subtest: RFC 3961 n-fold ok 1 64-fold("012345") ok 2 56-fold("password") ok 3 64-fold("Rough Consensus, and Running Code") ok 4 168-fold("password") ok 5 192-fold("MASSACHVSETTS INSTITVTE OF TECHNOLOGY") ok 6 168-fold("Q") ok 7 168-fold("ba") ok 8 64-fold("kerberos") ok 9 128-fold("kerberos") ok 10 168-fold("kerberos") ok 11 256-fold("kerberos") # RFC 3961 n-fold: pass:11 fail:0 skip:0 total:11 ok 1 RFC 3961 n-fold KTAP version 1 # Subtest: RFC 3961 key derivation # RFC 3961 key derivation: ASSERTION FAILED at net/sunrpc/auth_gss/gss_krb5_test.c:62 Expected err == 0, but err == -22 (0xffffffffffffffea) not ok 1 des3-hmac-sha1 key derivation case 1
This assertion means the RFC 3961 KDF function is not available -- it was not enabled via Kconfig.
# RFC 3961 key derivation: ASSERTION FAILED at net/sunrpc/auth_gss/gss_krb5_test.c:62 Expected err == 0, but err == -22 (0xffffffffffffffea) not ok 2 des3-hmac-sha1 key derivation case 2 # RFC 3961 key derivation: ASSERTION FAILED at net/sunrpc/auth_gss/gss_krb5_test.c:62 Expected err == 0, but err == -22 (0xffffffffffffffea) not ok 3 des3-hmac-sha1 key derivation case 3 # RFC 3961 key derivation: ASSERTION FAILED at net/sunrpc/auth_gss/gss_krb5_test.c:62 Expected err == 0, but err == -22 (0xffffffffffffffea) not ok 4 des3-hmac-sha1 key derivation case 4 # RFC 3961 key derivation: ASSERTION FAILED at net/sunrpc/auth_gss/gss_krb5_test.c:62 Expected err == 0, but err == -22 (0xffffffffffffffea) not ok 5 des3-hmac-sha1 key derivation case 5 # RFC 3961 key derivation: ASSERTION FAILED at net/sunrpc/auth_gss/gss_krb5_test.c:62 Expected err == 0, but err == -22 (0xffffffffffffffea) not ok 6 des3-hmac-sha1 key derivation case 6 # RFC 3961 key derivation: ASSERTION FAILED at net/sunrpc/auth_gss/gss_krb5_test.c:62 Expected err == 0, but err == -22 (0xffffffffffffffea) not ok 7 des3-hmac-sha1 key derivation case 7 # RFC 3961 key derivation: ASSERTION FAILED at net/sunrpc/auth_gss/gss_krb5_test.c:62 Expected err == 0, but err == -22 (0xffffffffffffffea) not ok 8 des3-hmac-sha1 key derivation case 8 # RFC 3961 key derivation: ASSERTION FAILED at net/sunrpc/auth_gss/gss_krb5_test.c:62 Expected err == 0, but err == -22 (0xffffffffffffffea) not ok 9 des3-hmac-sha1 key derivation case 9 # RFC 3961 key derivation: pass:0 fail:9 skip:0 total:9 not ok 2 RFC 3961 key derivation *** CHK *** FORMAT=2 Current process id is 785 BAD KERNEL TRAP: 00000000 Modules linked in: gss_krb5_test kunit rpcsec_gss_krb5 auth_rpcgss oid_registry camellia_generic sha512_generic sha1_generic md5 cmac hmac ecb cts cbc PC: [<1187775a>] rfc6803_suite+0x2/0xffffc688 [gss_krb5_test]
Assuming that "PC:" on m68k is the same as "RIP:" on x86... this does not make sense. rfc6803_suite is not a function.
1416 static struct kunit_suite rfc6803_suite = { 1417 .name = "RFC 6803 suite", 1418 .test_cases = rfc6803_test_cases, 1419 };
SR: 2200 SP: efc1339e a2: 01b4e610 d0: 00000002 d1: 00000010 d2: 00000014 d3: 01b57cc4 d4: 01b57c44 d5: 00000009 a0: 11877754 a1: 01b57c44 Process insmod (pid: 785, task=52ae00a3) Frame format=2 instr addr=1187775a Stack from 01b57bd8: 11869860 00000000 01b57c44 00000000 00000005 00000001 00000000 00000000 11877e5c 11877e34 11877be8 1186a4d8 1186956e 00000001 00000009 00000000 00000000 0000000b 01b57cfc 00000001 00000000 00000001 00000002 00000000 00000000 00000000 00000000 00657333 2d686d61 632d7368 6131206b 65792064 65726976 6174696f 6e206361 73652039 00000000 484e4f4c 4f475922 29000000 00000801 000c729c 005d6074 00000000 00040cc0 00040cc0 00000000 00000000 Call Trace: [<11869860>] kunit_run_tests+0x2f2/0x3d2 [kunit]
I.e. -EINVAL later, so something is still missing.
Second, with net/sunrpc/.kunitconfig, and just CONFIG_RPCSEC_GSS_KRB5_KUNIT_TEST still modular, the tests succeed, but there is still a crash:
KTAP version 1 # Subtest: RFC 3961 tests 1..3 KTAP version 1 # Subtest: RFC 3961 n-fold ok 1 64-fold("012345") ok 2 56-fold("password") ok 3 64-fold("Rough Consensus, and Running Code") ok 4 168-fold("password") ok 5 192-fold("MASSACHVSETTS INSTITVTE OF TECHNOLOGY") ok 6 168-fold("Q") ok 7 168-fold("ba") ok 8 64-fold("kerberos") ok 9 128-fold("kerberos") ok 10 168-fold("kerberos") ok 11 256-fold("kerberos") # RFC 3961 n-fold: pass:11 fail:0 skip:0 total:11 ok 1 RFC 3961 n-fold KTAP version 1 # Subtest: RFC 3961 key derivation ok 1 des3-hmac-sha1 key derivation case 1 ok 2 des3-hmac-sha1 key derivation case 2 ok 3 des3-hmac-sha1 key derivation case 3 ok 4 des3-hmac-sha1 key derivation case 4 ok 5 des3-hmac-sha1 key derivation case 5 ok 6 des3-hmac-sha1 key derivation case 6 ok 7 des3-hmac-sha1 key derivation case 7 ok 8 des3-hmac-sha1 key derivation case 8 ok 9 des3-hmac-sha1 key derivation case 9 # RFC 3961 key derivation: pass:9 fail:0 skip:0 total:9 ok 2 RFC 3961 key derivation *** CHK *** FORMAT=2 Current process id is 716 BAD KERNEL TRAP: 00000000 Modules linked in: gss_krb5_test PC: [<1197575a>] rfc6803_suite+0x2/0xffffc688 [gss_krb5_test] SR: 2200 SP: acd229e8 a2: 01ae20a0 d0: 00000002 d1: 00000010 d2: 00000014 d3: 01ae1cc4 d4: 01ae1c44 d5: 00000000 a0: 11975754 a1: 01ae1c44 Process insmod (pid: 716, task=962b0746) Frame format=2 instr addr=1197575a Stack from 01ae1bd8: 001f3158 00000000 01ae1c44 00000000 00000005 00000001 00000000 00000000 11975e5c 11975e34 11975be8 001f415c 001f2e66 00000001 00000000 00000000 00000009 00000014 01ae1cfc 00000002 00000000 00000000 00000002 00000000 00000000 00000000 00000000 00657333 2d686d61 632d7368 6131206b 65792064 65726976 6174696f 6e206361 73652039 00000000 484e4f4c 4f475922 29000000 00000801 000c729c 005db3c4 00000000 00040cc0 00040cc0 00000000 00000000 Call Trace: [<001f3158>] kunit_run_tests+0x2f2/0x3d2
Third, with net/sunrpc/.kunitconfig, and CONFIG_RPCSEC_GSS_KRB5_KUNIT_TEST=y:
KTAP version 1 # Subtest: RFC 3961 tests 1..2 KTAP version 1 # Subtest: RFC 3961 n-fold ok 1 64-fold("012345") ok 2 56-fold("password") ok 3 64-fold("Rough Consensus, and Running Code") ok 4 168-fold("password") ok 5 192-fold("MASSACHVSETTS INSTITVTE OF TECHNOLOGY") ok 6 168-fold("Q") ok 7 168-fold("ba") ok 8 64-fold("kerberos") ok 9 128-fold("kerberos") ok 10 168-fold("kerberos") ok 11 256-fold("kerberos") # RFC 3961 n-fold: pass:11 fail:0 skip:0 total:11 ok 1 RFC 3961 n-fold KTAP version 1 # Subtest: RFC 3961 key derivation ok 1 des3-hmac-sha1 key derivation case 1 ok 2 des3-hmac-sha1 key derivation case 2 ok 3 des3-hmac-sha1 key derivation case 3 ok 4 des3-hmac-sha1 key derivation case 4 ok 5 des3-hmac-sha1 key derivation case 5 ok 6 des3-hmac-sha1 key derivation case 6 ok 7 des3-hmac-sha1 key derivation case 7 ok 8 des3-hmac-sha1 key derivation case 8 ok 9 des3-hmac-sha1 key derivation case 9 # RFC 3961 key derivation: pass:9 fail:0 skip:0 total:9 ok 2 RFC 3961 key derivation # RFC 3961 tests: pass:2 fail:0 skip:0 total:2 # Totals: pass:20 fail:0 skip:0 total:20 ok 31 RFC 3961 tests KTAP version 1 # Subtest: RFC 3962 suite 1..2 KTAP version 1 # Subtest: RFC 3962 encryption ok 1 Encrypt with aes128-cts-hmac-sha1-96 case 1 ok 2 Encrypt with aes128-cts-hmac-sha1-96 case 2 ok 3 Encrypt with aes128-cts-hmac-sha1-96 case 3 ok 4 Encrypt with aes128-cts-hmac-sha1-96 case 4 ok 5 Encrypt with aes128-cts-hmac-sha1-96 case 5 ok 6 Encrypt with aes128-cts-hmac-sha1-96 case 6 # RFC 3962 encryption: pass:6 fail:0 skip:0 total:6 ok 1 RFC 3962 encryption Unable to handle kernel access at virtual address af06da84 Oops: 00000000 Modules linked in: PC: [<20746573>] 0x20746573 SR: 2204 SP: 05ef00e4 a2: 010195d0 d0: 00000002 d1: 00000010 d2: 00000006 d3: 0101bdf8 d4: 0101bd78 d5: 00000000 a0: 20746573 a1: 0101bd78 Process swapper (pid: 1, task=b63809d5) Frame format=7 eff addr=20746573 ssw=0546 faddr=20746573 wb 1 stat/addr/data: 0000 00000000 00000000 wb 2 stat/addr/data: 0000 00000000 00000000 wb 3 stat/addr/data: 0000 20746573 00000000 push data: 00000000 00000000 00000000 00000000 Stack from 0101bd0c: 001f64b0 00000000 0101bd78 0000001f 00000023 01015480 000359ba 0000209c 00000000 005890c0 0053aafc 001f7c88 001f61be 00000001 00000000 00000000 00000006 00000006 0101be30 00000001 00000000 00000000 00000001 00000000 00000000 00000000 00000000 006e6372 79707420 77697468 20616573 3132382d 6374732d 686d6163 2d736861 312d3936 20636173 65203600 4f475922 29000000 00000801 000c886c 006003b4 00000000 00040cc0 00040cc0 00000000 00000000 Call Trace: [<001f64b0>] kunit_run_tests+0x2f2/0x3d2 [<000359ba>] parse_args+0x0/0x202 [<0000209c>] do_one_initcall+0x0/0x184 [<001f7c88>] kunit_debugfs_create_suite+0x0/0x54 [<001f61be>] kunit_run_tests+0x0/0x3d2 [<000c886c>] get_page_from_freelist+0x176/0x48a [<00040cc0>] __finish_swait+0x1a/0x1c [<00040cc0>] __finish_swait+0x1a/0x1c [<00040cc0>] __finish_swait+0x1a/0x1c [<0000209c>] do_one_initcall+0x0/0x184 [<000c86f6>] get_page_from_freelist+0x0/0x48a [<000c8500>] prepare_alloc_pages.isra.0+0x12/0x84 [<001f6632>] __kunit_test_suites_init+0xa2/0xfa [<003a160c>] _printk+0x0/0x18 [<001f7b9e>] kunit_run_all_tests+0xd0/0x1a6 [<0039a0c0>] strcpy+0x0/0x1c [<00564602>] kernel_init_freeable+0x152/0x190 [<000359ba>] parse_args+0x0/0x202 [<003a6e76>] kernel_init+0x0/0xec [<003a6e8a>] kernel_init+0x14/0xec [<003a6e76>] kernel_init+0x0/0xec [<000028d4>] ret_from_kernel_thread+0xc/0x14
I.e. a slightly different crash. As the difference between the two crashes is modular vs. builtin, this looks like an out-of-bound access in the test.
Why not run the test suite just as I suggested?
Since I cannot reproduce this crash and do not have an m68k platform available to me, I will need you to continue to pursue the issue. I'll help as much as I can.
I would very much like to see successful test results on non-x86 platforms.
-- Chuck Lever
Hi Chuck,
On Thu, Feb 23, 2023 at 5:19 PM Chuck Lever III chuck.lever@oracle.com wrote:
On Feb 23, 2023, at 10:16 AM, Geert Uytterhoeven geert@linux-m68k.org wrote: On Thu, Feb 23, 2023 at 3:00 PM Chuck Lever III chuck.lever@oracle.com wrote:
On Feb 23, 2023, at 8:05 AM, Geert Uytterhoeven geert@linux-m68k.org wrote: On Sun, 15 Jan 2023, Chuck Lever wrote:
The purpose of this series is to improve/harden the security provided by the Linux kernel's RPCSEC GSS Kerberos 5 mechanism. There are lots of clean-ups in this series, but the pertinent feature is the addition of a clean deprecation path for the DES- and SHA1-based encryption types in accordance with Internet BCPs.
This series disables DES-based enctypes by default, provides a mechanism for disabling SHA1-based enctypes, and introduces two modern enctypes that do not use deprecated crypto algorithms.
Not only does that improve security for Kerberos 5 users, but it also prepares SunRPC for eventually switching to a shared common kernel Kerberos 5 implementation, which surely will not implement any deprecated encryption types (in particular, DES-based ones).
Today, MIT supports both of the newly-introduced enctypes, but Heimdal does not appear to. Thus distributions can enable and disable kernel enctype support to match the set of enctypes supported in their user space Kerberos libraries.
Scott has been kicking the tires -- we've found no regressions with the current SHA1-based enctypes, while the new ones are disabled by default until we have an opportunity for interop testing. The KUnit tests for the new enctypes pass and this implementation successfully interoperates with itself using these enctypes. Therefore I believe it to be safe to merge.
When this series gets merged, the Linux NFS community should select and announce a date-certain for removal of SunRPC's DES-based enctype code.
As this is now upstream, I gave it a try on m68k (on the ARAnyM emulator), using a config based on atari_defconfig:
KTAP version 1 # Subtest: RFC 3961 tests 1..3 KTAP version 1 # Subtest: RFC 3961 n-fold ok 1 64-fold("012345") ok 2 56-fold("password") ok 3 64-fold("Rough Consensus, and Running Code") ok 4 168-fold("password") ok 5 192-fold("MASSACHVSETTS INSTITVTE OF TECHNOLOGY") ok 6 168-fold("Q") ok 7 168-fold("ba") ok 8 64-fold("kerberos") ok 9 128-fold("kerberos") ok 10 168-fold("kerberos") ok 11 256-fold("kerberos") # RFC 3961 n-fold: pass:11 fail:0 skip:0 total:11 ok 1 RFC 3961 n-fold KTAP version 1 # Subtest: RFC 3961 key derivation # RFC 3961 key derivation: ASSERTION FAILED at net/sunrpc/auth_gss/gss_krb5_test.c:52 Expected gk5e != ((void *)0), but gk5e == 00000000 ((void *)0) == 00000000 not ok 1 des3-hmac-sha1 key derivation case 1
Geert, thanks for testing GSS on m68k.
This assertion failure means that support for the encryption types specified in RFC 3961 is not built into your kernel.
The new Kunit tests don't work unless everything is built in --
there's a net/sunrpc/.kunitconfig that provides the supported build configuration for running them. I typically use a command line similar to this:
./tools/testing/kunit/kunit.py run --raw_output=all --kunitconfig ./net/sunrpc/.kunitconfig
Aren't modular crypto algorithms auto-loaded when needed?
The ciphers and digests are handled via the kernel's crypto manager. They will indeed get auto-loaded by SunRPC's GSS on demand, but of course, the set of algorithms used by GSS has to be enabled by Kconfig options first.
SunRPC GSS has a set of Kerberos encryption types that make use of individual ciphers and digests. Those have never been modularized, and they are each enabled by Kconfig options, as explained below.
In general, it's a good idea to make the tests test only functionality that is available, either through "depends on" in Kconfig, or "#if IS_ENABLED(...)".
An earlier version of this patch set did just that. It became quite a mess. That's why I chose the .kunitconfig approach.
Of course that does not preclude providing a .kunitconfig to enable and test everything.
The suite should test every Kerberos encryption type that SunRPC GSS has support for. There's no reason to disable a particular encryption type when running the unit tests... unless I'm missing something?
That depends: do you want to test everything, or do you want to test (only) the functionality you enabled for your product? I tend to enable all modular tests, so I can use insmod to run any relevant test when needed. If a test suddenly needs something that is not enabled, you can not run the test without enabling extra functionality (which you may not want to enable).
Note that net/sunrpc/.kunitconfig has
CONFIG_RPCSEC_GSS_KRB5_KUNIT_TEST=y
which needs KUNIT_ALL_TESTS=y, else it will still be modular.
First, I tried getting my modular setup working. After enabling: CONFIG_RPCSEC_GSS_KRB5_ENCTYPES_DES=y
And CONFIG_RPCSEC_GSS_KRB5_ENCTYPES_AES_SHA1=y ??
Sure, I had that enabled, thanks to "default y".
Third, with net/sunrpc/.kunitconfig, and CONFIG_RPCSEC_GSS_KRB5_KUNIT_TEST=y:
[...]
Unable to handle kernel access at virtual address af06da84
I.e. a slightly different crash. As the difference between the two crashes is modular vs. builtin, this looks like an out-of-bound access in the test.
Why not run the test suite just as I suggested?
I don't think I can use tools/testing/kunit/kunit.py to run the tests when cross-compiling my kernel?
My third case (adding options from net/sunrpc/.kunitconfig, and setting CONFIG_RPCSEC_GSS_KRB5_KUNIT_TEST=y) should be equivalent to that, right?
Since I cannot reproduce this crash and do not have an m68k platform available to me, I will need you to continue to pursue the issue. I'll help as much as I can.
I would very much like to see successful test results on non-x86 platforms.
Thanks, I'll give it a try on some other platforms, later...
Gr{oetje,eeting}s,
Geert
On Feb 23, 2023, at 11:52 AM, Geert Uytterhoeven geert@linux-m68k.org wrote:
Hi Chuck,
On Thu, Feb 23, 2023 at 5:19 PM Chuck Lever III chuck.lever@oracle.com wrote:
On Feb 23, 2023, at 10:16 AM, Geert Uytterhoeven geert@linux-m68k.org wrote: On Thu, Feb 23, 2023 at 3:00 PM Chuck Lever III chuck.lever@oracle.com wrote:
On Feb 23, 2023, at 8:05 AM, Geert Uytterhoeven geert@linux-m68k.org wrote: On Sun, 15 Jan 2023, Chuck Lever wrote:
The purpose of this series is to improve/harden the security provided by the Linux kernel's RPCSEC GSS Kerberos 5 mechanism. There are lots of clean-ups in this series, but the pertinent feature is the addition of a clean deprecation path for the DES- and SHA1-based encryption types in accordance with Internet BCPs.
This series disables DES-based enctypes by default, provides a mechanism for disabling SHA1-based enctypes, and introduces two modern enctypes that do not use deprecated crypto algorithms.
Not only does that improve security for Kerberos 5 users, but it also prepares SunRPC for eventually switching to a shared common kernel Kerberos 5 implementation, which surely will not implement any deprecated encryption types (in particular, DES-based ones).
Today, MIT supports both of the newly-introduced enctypes, but Heimdal does not appear to. Thus distributions can enable and disable kernel enctype support to match the set of enctypes supported in their user space Kerberos libraries.
Scott has been kicking the tires -- we've found no regressions with the current SHA1-based enctypes, while the new ones are disabled by default until we have an opportunity for interop testing. The KUnit tests for the new enctypes pass and this implementation successfully interoperates with itself using these enctypes. Therefore I believe it to be safe to merge.
When this series gets merged, the Linux NFS community should select and announce a date-certain for removal of SunRPC's DES-based enctype code.
As this is now upstream, I gave it a try on m68k (on the ARAnyM emulator), using a config based on atari_defconfig:
KTAP version 1 # Subtest: RFC 3961 tests 1..3 KTAP version 1 # Subtest: RFC 3961 n-fold ok 1 64-fold("012345") ok 2 56-fold("password") ok 3 64-fold("Rough Consensus, and Running Code") ok 4 168-fold("password") ok 5 192-fold("MASSACHVSETTS INSTITVTE OF TECHNOLOGY") ok 6 168-fold("Q") ok 7 168-fold("ba") ok 8 64-fold("kerberos") ok 9 128-fold("kerberos") ok 10 168-fold("kerberos") ok 11 256-fold("kerberos") # RFC 3961 n-fold: pass:11 fail:0 skip:0 total:11 ok 1 RFC 3961 n-fold KTAP version 1 # Subtest: RFC 3961 key derivation # RFC 3961 key derivation: ASSERTION FAILED at net/sunrpc/auth_gss/gss_krb5_test.c:52 Expected gk5e != ((void *)0), but gk5e == 00000000 ((void *)0) == 00000000 not ok 1 des3-hmac-sha1 key derivation case 1
Geert, thanks for testing GSS on m68k.
This assertion failure means that support for the encryption types specified in RFC 3961 is not built into your kernel.
The new Kunit tests don't work unless everything is built in --
there's a net/sunrpc/.kunitconfig that provides the supported build configuration for running them. I typically use a command line similar to this:
./tools/testing/kunit/kunit.py run --raw_output=all --kunitconfig ./net/sunrpc/.kunitconfig
Aren't modular crypto algorithms auto-loaded when needed?
The ciphers and digests are handled via the kernel's crypto manager. They will indeed get auto-loaded by SunRPC's GSS on demand, but of course, the set of algorithms used by GSS has to be enabled by Kconfig options first.
SunRPC GSS has a set of Kerberos encryption types that make use of individual ciphers and digests. Those have never been modularized, and they are each enabled by Kconfig options, as explained below.
In general, it's a good idea to make the tests test only functionality that is available, either through "depends on" in Kconfig, or "#if IS_ENABLED(...)".
An earlier version of this patch set did just that. It became quite a mess. That's why I chose the .kunitconfig approach.
Of course that does not preclude providing a .kunitconfig to enable and test everything.
The suite should test every Kerberos encryption type that SunRPC GSS has support for. There's no reason to disable a particular encryption type when running the unit tests... unless I'm missing something?
That depends: do you want to test everything, or do you want to test (only) the functionality you enabled for your product?
Each Kunit test is supposed to test one thing in particular. These tests each test a feature of the GSS Kerberos encryption type implementation.
So... they are really not for the purpose of configuration or integration testing. I didn't have distributors in mind for running these tests. They are instead targeted to kernel developers and platform maintainers.
I tend to enable all modular tests, so I can use insmod to run any relevant test when needed. If a test suddenly needs something that is not enabled, you can not run the test without enabling extra functionality (which you may not want to enable).
I wouldn't expect these tests to be run as part of a product CI suite. They are most valuable when making changes to the SunRPC GSS code, or crypto code that GSS depends on.
"Did I just break this code?"
Note that net/sunrpc/.kunitconfig has
CONFIG_RPCSEC_GSS_KRB5_KUNIT_TEST=y
which needs KUNIT_ALL_TESTS=y, else it will still be modular.
First, I tried getting my modular setup working. After enabling: CONFIG_RPCSEC_GSS_KRB5_ENCTYPES_DES=y
And CONFIG_RPCSEC_GSS_KRB5_ENCTYPES_AES_SHA1=y ??
Sure, I had that enabled, thanks to "default y".
Third, with net/sunrpc/.kunitconfig, and CONFIG_RPCSEC_GSS_KRB5_KUNIT_TEST=y:
[...]
Unable to handle kernel access at virtual address af06da84
I.e. a slightly different crash. As the difference between the two crashes is modular vs. builtin, this looks like an out-of-bound access in the test.
Why not run the test suite just as I suggested?
I don't think I can use tools/testing/kunit/kunit.py to run the tests when cross-compiling my kernel?
You should be able to... that tool runs under UML and compiles what it needs to run the tests.
My third case (adding options from net/sunrpc/.kunitconfig, and setting CONFIG_RPCSEC_GSS_KRB5_KUNIT_TEST=y) should be equivalent to that, right?
Since I cannot reproduce this crash and do not have an m68k platform available to me, I will need you to continue to pursue the issue. I'll help as much as I can.
I would very much like to see successful test results on non-x86 platforms.
Thanks, I'll give it a try on some other platforms, later...
-- Chuck Lever
Hi Chuck,
On Thu, Feb 23, 2023 at 5:52 PM Geert Uytterhoeven geert@linux-m68k.org wrote:
On Thu, Feb 23, 2023 at 5:19 PM Chuck Lever III chuck.lever@oracle.com wrote:
On Feb 23, 2023, at 10:16 AM, Geert Uytterhoeven geert@linux-m68k.org wrote:
Unable to handle kernel access at virtual address af06da84
I.e. a slightly different crash. As the difference between the two crashes is modular vs. builtin, this looks like an out-of-bound access in the test.
Just ran it on physical arm32 and arm64 (Renesas APE6EVM and Salvator-XS), and the test crashes there, too.
Why not run the test suite just as I suggested?
kunit_kernel.ConfigError: m68k is not a valid arch, options are ['alpha', 'arm', 'arm64', 'i386', 'powerpc', 'riscv', 's390', 'sparc', 'x86_64']
Will look into adding m68k support ;-)
But the issue can easily be reproduced using ".../tools/testing/kunit/kunit.py run --arch=arm --cross_compile=arm-linux-gnueabihf- --raw_output=all --kunitconfig ./net/sunrpc/.kunitconfig" on current upstream[1]:
KTAP version 1 1..5 KTAP version 1 # Subtest: RFC 3961 tests 1..2 KTAP version 1 # Subtest: RFC 3961 n-fold ok 1 64-fold("012345") ok 2 56-fold("password") ok 3 64-fold("Rough Consensus, and Running Code") ok 4 168-fold("password") ok 5 192-fold("MASSACHVSETTS INSTITVTE OF TECHNOLOGY") ok 6 168-fold("Q") ok 7 168-fold("ba") ok 8 64-fold("kerberos") ok 9 128-fold("kerberos") ok 10 168-fold("kerberos") ok 11 256-fold("kerberos") # RFC 3961 n-fold: pass:11 fail:0 skip:0 total:11 ok 1 RFC 3961 n-fold KTAP version 1 # Subtest: RFC 3961 key derivation ok 1 des3-hmac-sha1 key derivation case 1 ok 2 des3-hmac-sha1 key derivation case 2 ok 3 des3-hmac-sha1 key derivation case 3 ok 4 des3-hmac-sha1 key derivation case 4 ok 5 des3-hmac-sha1 key derivation case 5 ok 6 des3-hmac-sha1 key derivation case 6 ok 7 des3-hmac-sha1 key derivation case 7 ok 8 des3-hmac-sha1 key derivation case 8 ok 9 des3-hmac-sha1 key derivation case 9 # RFC 3961 key derivation: pass:9 fail:0 skip:0 total:9 ok 2 RFC 3961 key derivation # RFC 3961 tests: pass:2 fail:0 skip:0 total:2 # Totals: pass:20 fail:0 skip:0 total:20 ok 1 RFC 3961 tests KTAP version 1 # Subtest: RFC 3962 suite 1..2 KTAP version 1 # Subtest: RFC 3962 encryption ok 1 Encrypt with aes128-cts-hmac-sha1-96 case 1 ok 2 Encrypt with aes128-cts-hmac-sha1-96 case 2 ok 3 Encrypt with aes128-cts-hmac-sha1-96 case 3 ok 4 Encrypt with aes128-cts-hmac-sha1-96 case 4 ok 5 Encrypt with aes128-cts-hmac-sha1-96 case 5 ok 6 Encrypt with aes128-cts-hmac-sha1-96 case 6 # RFC 3962 encryption: pass:6 fail:0 skip:0 total:6 ok 1 RFC 3962 encryption 8<--- cut here --- Unable to handle kernel paging request at virtual address 73657420 when execute [73657420] *pgd=00000000 Internal error: Oops: 80000005 [#1] ARM CPU: 0 PID: 1 Comm: swapper Tainted: G N 6.2.0-12486-g85f341272fa9 #1 Hardware name: Generic DT based system PC is at 0x73657420 LR is at kunit_run_tests+0x3cc/0x5e8 pc : [<73657420>] lr : [<c02d0e54>] psr: 20000053 sp : f0809cc8 ip : f0809e54 fp : 00000006 r10: c069dc30 r9 : c069dd84 r8 : f0809e54 r7 : 00000000 r6 : 00000006 r5 : c08a8504 r4 : c08a82d0 r3 : 73657420 r2 : 00000002 r1 : f0809e54 r0 : 00000000 Flags: nzCv IRQs on FIQs off Mode SVC_32 ISA ARM Segment none Control: 10c53c7d Table: 40004059 DAC: 00000051 Register r0 information: NULL pointer Register r1 information: 2-page vmalloc region starting at 0xf0808000 allocated at kernel_clone+0x94/0x2fc Register r2 information: non-paged memory Register r3 information: non-paged memory Register r4 information: non-slab/vmalloc memory Register r5 information: non-slab/vmalloc memory Register r6 information: non-paged memory Register r7 information: NULL pointer Register r8 information: 2-page vmalloc region starting at 0xf0808000 allocated at kernel_clone+0x94/0x2fc Register r9 information: non-slab/vmalloc memory Register r10 information: non-slab/vmalloc memory Register r11 information: non-paged memory Register r12 information: 2-page vmalloc region starting at 0xf0808000 allocated at kernel_clone+0x94/0x2fc Process swapper (pid: 1, stack limit = 0x(ptrval)) Stack: (0xf0809cc8 to 0xf080a000) 9cc0: c06b6154 f0809d54 00000006 c01443d8 00000000 00000000 9ce0: 00000000 00000000 c088a8c0 c069dd1c c069dd38 c0698d6c 00000000 00000001 9d00: 00000000 00000000 00000001 00000000 00000000 00000000 00000000 00000000 9d20: 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 9d40: 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 9d60: 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 9d80: 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 9da0: 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 9dc0: 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 9de0: 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 9e00: 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 9e20: 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 9e40: 00000000 00000000 00000000 00000000 00000000 72636e00 20747079 68746977 9e60: 73656120 2d383231 2d737463 63616d68 6168732d 36392d31 73616320 00362065 9e80: 2259474f 00000029 800000d3 3ffff049 0000000c 00313601 0000004a 00000000 9ea0: c0894480 ff7583a2 00000004 ffffffff 00000000 c069e520 00000000 c072185c 9ec0: c072183c c0141eac f0809f1c c031fd5c 0251f4a2 ff7583a2 c0727f10 c08d932c 9ee0: c0727f14 00000002 00000005 c0804205 00000000 c072183c c0700510 c02d1160 9f00: c0cf534e c050f460 f0809f1c 00000005 c0727f10 c0cf5340 00000000 00000001 9f20: c072185c c02d2e94 c0c01100 c0727f24 c0727f10 c08d9318 c072185c c0806cd0 9f40: c0728750 c0cf5340 c06b9808 c06b73e0 c072185c c072183c c0700510 c07015f4 9f60: 00000007 00000007 00000000 c0700510 00000002 0000005d c0c5c000 c0804200 9f80: c0515dd8 00000000 00000000 00000000 00000000 00000000 00000000 c0515df0 9fa0: 00000000 c0515dd8 00000000 c0100148 00000000 00000000 00000000 00000000 9fc0: 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 9fe0: 00000000 00000000 00000000 00000000 00000013 00000000 00000000 00000000 kunit_run_tests from __kunit_test_suites_init+0xc0/0x1a8 __kunit_test_suites_init from kunit_run_all_tests+0x24c/0x41c kunit_run_all_tests from kernel_init_freeable+0x20c/0x258 kernel_init_freeable from kernel_init+0x18/0x144 kernel_init from ret_from_fork+0x14/0x2c Exception stack(0xf0809fb0 to 0xf0809ff8) 9fa0: 00000000 00000000 00000000 00000000 9fc0: 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 9fe0: 00000000 00000000 00000000 00000000 00000013 00000000 Code: bad PC value ---[ end trace 0000000000000000 ]--- Kernel panic - not syncing: Attempted to kill init! exitcode=0x0000000b
[1] 85f341272fa9 = f3a2439f20d91893 ("Merge tag 'rproc-v6.3' of git://git.kernel.org/pub/scm/linux/kernel/git/remoteproc/linux") + a cherry-pick of a fix for a regression on my arm64 platforms)
Gr{oetje,eeting}s,
Geert
On Feb 27, 2023, at 4:51 AM, Geert Uytterhoeven geert@linux-m68k.org wrote:
Hi Chuck,
On Thu, Feb 23, 2023 at 5:52 PM Geert Uytterhoeven geert@linux-m68k.org wrote:
On Thu, Feb 23, 2023 at 5:19 PM Chuck Lever III chuck.lever@oracle.com wrote:
On Feb 23, 2023, at 10:16 AM, Geert Uytterhoeven geert@linux-m68k.org wrote:
Unable to handle kernel access at virtual address af06da84
I.e. a slightly different crash. As the difference between the two crashes is modular vs. builtin, this looks like an out-of-bound access in the test.
Just ran it on physical arm32 and arm64 (Renesas APE6EVM and Salvator-XS), and the test crashes there, too.
Why not run the test suite just as I suggested?
kunit_kernel.ConfigError: m68k is not a valid arch, options are ['alpha', 'arm', 'arm64', 'i386', 'powerpc', 'riscv', 's390', 'sparc', 'x86_64']
Will look into adding m68k support ;-)
But the issue can easily be reproduced using ".../tools/testing/kunit/kunit.py run --arch=arm --cross_compile=arm-linux-gnueabihf- --raw_output=all --kunitconfig ./net/sunrpc/.kunitconfig" on current upstream[1]:
KTAP version 1 1..5 KTAP version 1 # Subtest: RFC 3961 tests 1..2 KTAP version 1 # Subtest: RFC 3961 n-fold ok 1 64-fold("012345") ok 2 56-fold("password") ok 3 64-fold("Rough Consensus, and Running Code") ok 4 168-fold("password") ok 5 192-fold("MASSACHVSETTS INSTITVTE OF TECHNOLOGY") ok 6 168-fold("Q") ok 7 168-fold("ba") ok 8 64-fold("kerberos") ok 9 128-fold("kerberos") ok 10 168-fold("kerberos") ok 11 256-fold("kerberos") # RFC 3961 n-fold: pass:11 fail:0 skip:0 total:11 ok 1 RFC 3961 n-fold KTAP version 1 # Subtest: RFC 3961 key derivation ok 1 des3-hmac-sha1 key derivation case 1 ok 2 des3-hmac-sha1 key derivation case 2 ok 3 des3-hmac-sha1 key derivation case 3 ok 4 des3-hmac-sha1 key derivation case 4 ok 5 des3-hmac-sha1 key derivation case 5 ok 6 des3-hmac-sha1 key derivation case 6 ok 7 des3-hmac-sha1 key derivation case 7 ok 8 des3-hmac-sha1 key derivation case 8 ok 9 des3-hmac-sha1 key derivation case 9 # RFC 3961 key derivation: pass:9 fail:0 skip:0 total:9 ok 2 RFC 3961 key derivation # RFC 3961 tests: pass:2 fail:0 skip:0 total:2 # Totals: pass:20 fail:0 skip:0 total:20 ok 1 RFC 3961 tests KTAP version 1 # Subtest: RFC 3962 suite 1..2 KTAP version 1 # Subtest: RFC 3962 encryption ok 1 Encrypt with aes128-cts-hmac-sha1-96 case 1 ok 2 Encrypt with aes128-cts-hmac-sha1-96 case 2 ok 3 Encrypt with aes128-cts-hmac-sha1-96 case 3 ok 4 Encrypt with aes128-cts-hmac-sha1-96 case 4 ok 5 Encrypt with aes128-cts-hmac-sha1-96 case 5 ok 6 Encrypt with aes128-cts-hmac-sha1-96 case 6 # RFC 3962 encryption: pass:6 fail:0 skip:0 total:6 ok 1 RFC 3962 encryption 8<--- cut here --- Unable to handle kernel paging request at virtual address 73657420 when execute [73657420] *pgd=00000000 Internal error: Oops: 80000005 [#1] ARM CPU: 0 PID: 1 Comm: swapper Tainted: G N 6.2.0-12486-g85f341272fa9 #1 Hardware name: Generic DT based system PC is at 0x73657420 LR is at kunit_run_tests+0x3cc/0x5e8 pc : [<73657420>] lr : [<c02d0e54>] psr: 20000053 sp : f0809cc8 ip : f0809e54 fp : 00000006 r10: c069dc30 r9 : c069dd84 r8 : f0809e54 r7 : 00000000 r6 : 00000006 r5 : c08a8504 r4 : c08a82d0 r3 : 73657420 r2 : 00000002 r1 : f0809e54 r0 : 00000000 Flags: nzCv IRQs on FIQs off Mode SVC_32 ISA ARM Segment none Control: 10c53c7d Table: 40004059 DAC: 00000051 Register r0 information: NULL pointer Register r1 information: 2-page vmalloc region starting at 0xf0808000 allocated at kernel_clone+0x94/0x2fc Register r2 information: non-paged memory Register r3 information: non-paged memory Register r4 information: non-slab/vmalloc memory Register r5 information: non-slab/vmalloc memory Register r6 information: non-paged memory Register r7 information: NULL pointer Register r8 information: 2-page vmalloc region starting at 0xf0808000 allocated at kernel_clone+0x94/0x2fc Register r9 information: non-slab/vmalloc memory Register r10 information: non-slab/vmalloc memory Register r11 information: non-paged memory Register r12 information: 2-page vmalloc region starting at 0xf0808000 allocated at kernel_clone+0x94/0x2fc Process swapper (pid: 1, stack limit = 0x(ptrval)) Stack: (0xf0809cc8 to 0xf080a000) 9cc0: c06b6154 f0809d54 00000006 c01443d8 00000000 00000000 9ce0: 00000000 00000000 c088a8c0 c069dd1c c069dd38 c0698d6c 00000000 00000001 9d00: 00000000 00000000 00000001 00000000 00000000 00000000 00000000 00000000 9d20: 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 9d40: 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 9d60: 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 9d80: 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 9da0: 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 9dc0: 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 9de0: 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 9e00: 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 9e20: 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 9e40: 00000000 00000000 00000000 00000000 00000000 72636e00 20747079 68746977 9e60: 73656120 2d383231 2d737463 63616d68 6168732d 36392d31 73616320 00362065 9e80: 2259474f 00000029 800000d3 3ffff049 0000000c 00313601 0000004a 00000000 9ea0: c0894480 ff7583a2 00000004 ffffffff 00000000 c069e520 00000000 c072185c 9ec0: c072183c c0141eac f0809f1c c031fd5c 0251f4a2 ff7583a2 c0727f10 c08d932c 9ee0: c0727f14 00000002 00000005 c0804205 00000000 c072183c c0700510 c02d1160 9f00: c0cf534e c050f460 f0809f1c 00000005 c0727f10 c0cf5340 00000000 00000001 9f20: c072185c c02d2e94 c0c01100 c0727f24 c0727f10 c08d9318 c072185c c0806cd0 9f40: c0728750 c0cf5340 c06b9808 c06b73e0 c072185c c072183c c0700510 c07015f4 9f60: 00000007 00000007 00000000 c0700510 00000002 0000005d c0c5c000 c0804200 9f80: c0515dd8 00000000 00000000 00000000 00000000 00000000 00000000 c0515df0 9fa0: 00000000 c0515dd8 00000000 c0100148 00000000 00000000 00000000 00000000 9fc0: 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 9fe0: 00000000 00000000 00000000 00000000 00000013 00000000 00000000 00000000 kunit_run_tests from __kunit_test_suites_init+0xc0/0x1a8 __kunit_test_suites_init from kunit_run_all_tests+0x24c/0x41c kunit_run_all_tests from kernel_init_freeable+0x20c/0x258 kernel_init_freeable from kernel_init+0x18/0x144 kernel_init from ret_from_fork+0x14/0x2c Exception stack(0xf0809fb0 to 0xf0809ff8) 9fa0: 00000000 00000000 00000000 00000000 9fc0: 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 9fe0: 00000000 00000000 00000000 00000000 00000013 00000000 Code: bad PC value ---[ end trace 0000000000000000 ]--- Kernel panic - not syncing: Attempted to kill init! exitcode=0x0000000b
[1] 85f341272fa9 = f3a2439f20d91893 ("Merge tag 'rproc-v6.3' of git://git.kernel.org/pub/scm/linux/kernel/git/remoteproc/linux") + a cherry-pick of a fix for a regression on my arm64 platforms)
I'm still not able to reproduce:
[cel@bazille odd-releases]$ tools/testing/kunit/kunit.py run --arch=arm --cross_compile=arm-linux-gnueabihf- --raw_output=all --kunitconfig ./net/sunrpc/.kunitconfig [10:04:14] Configuring KUnit Kernel ... Generating .config ... Populating config with: $ make ARCH=arm O=.kunit olddefconfig [10:04:18] Building KUnit Kernel ... Populating config with: $ make ARCH=arm O=.kunit olddefconfig Building with: $ make ARCH=arm O=.kunit --jobs=4 ERROR:root:gcc: error: unrecognized argument in option ‘-mabi=aapcs-linux’ gcc: note: valid arguments to ‘-mabi=’ are: ms sysv gcc: error: unrecognized argument in option ‘-mabi=aapcs-linux’ gcc: note: valid arguments to ‘-mabi=’ are: ms sysv gcc: error: unrecognized command-line option ‘-mlittle-endian’ gcc: error: unrecognized command-line option ‘-mlittle-endian’ gcc: error: unrecognized command-line option ‘-mtp=cp15’ gcc: error: unrecognized command-line option ‘-mtp=cp15’ gcc: error: unrecognized command-line option ‘-mfpu=vfp’ make[2]: *** [../scripts/Makefile.build:252: scripts/mod/empty.o] Error 1 make[2]: *** Waiting for unfinished jobs.... gcc: error: unrecognized command-line option ‘-mfpu=vfp’ make[2]: *** [../scripts/Makefile.build:114: scripts/mod/devicetable-offsets.s] Error 1 make[1]: *** [/home/cel/src/linux/odd-releases/Makefile:1297: prepare0] Error 2 make: *** [Makefile:242: __sub-make] Error 2
-bash: --cross_compile=arm-linux-gnueabihf-: command not found -bash: ./net/sunrpc/.kunitconfig: Permission denied [cel@bazille odd-releases]$ gcc --version gcc (GCC) 12.2.1 20221121 (Red Hat 12.2.1-4) Copyright (C) 2022 Free Software Foundation, Inc. This is free software; see the source for copying conditions. There is NO warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
[cel@bazille odd-releases]$
What am I missing?
-- Chuck Lever
Hi Chuck,
On Mon, Feb 27, 2023 at 4:06 PM Chuck Lever III chuck.lever@oracle.com wrote:
On Feb 27, 2023, at 4:51 AM, Geert Uytterhoeven geert@linux-m68k.org wrote: On Thu, Feb 23, 2023 at 5:52 PM Geert Uytterhoeven geert@linux-m68k.org wrote:
On Thu, Feb 23, 2023 at 5:19 PM Chuck Lever III chuck.lever@oracle.com wrote:
On Feb 23, 2023, at 10:16 AM, Geert Uytterhoeven geert@linux-m68k.org wrote:
Unable to handle kernel access at virtual address af06da84
I.e. a slightly different crash. As the difference between the two crashes is modular vs. builtin, this looks like an out-of-bound access in the test.
Just ran it on physical arm32 and arm64 (Renesas APE6EVM and Salvator-XS), and the test crashes there, too.
Why not run the test suite just as I suggested?
kunit_kernel.ConfigError: m68k is not a valid arch, options are ['alpha', 'arm', 'arm64', 'i386', 'powerpc', 'riscv', 's390', 'sparc', 'x86_64']
Will look into adding m68k support ;-)
But the issue can easily be reproduced using ".../tools/testing/kunit/kunit.py run --arch=arm --cross_compile=arm-linux-gnueabihf- --raw_output=all --kunitconfig ./net/sunrpc/.kunitconfig" on current upstream[1]:
I'm still not able to reproduce:
[cel@bazille odd-releases]$ tools/testing/kunit/kunit.py run --arch=arm --cross_compile=arm-linux-gnueabihf- --raw_output=all --kunitconfig ./net/sunrpc/.kunitconfig [10:04:14] Configuring KUnit Kernel ... Generating .config ... Populating config with: $ make ARCH=arm O=.kunit olddefconfig [10:04:18] Building KUnit Kernel ... Populating config with: $ make ARCH=arm O=.kunit olddefconfig Building with: $ make ARCH=arm O=.kunit --jobs=4 ERROR:root:gcc: error: unrecognized argument in option ‘-mabi=aapcs-linux’ gcc: note: valid arguments to ‘-mabi=’ are: ms sysv gcc: error: unrecognized argument in option ‘-mabi=aapcs-linux’ gcc: note: valid arguments to ‘-mabi=’ are: ms sysv gcc: error: unrecognized command-line option ‘-mlittle-endian’ gcc: error: unrecognized command-line option ‘-mlittle-endian’ gcc: error: unrecognized command-line option ‘-mtp=cp15’ gcc: error: unrecognized command-line option ‘-mtp=cp15’ gcc: error: unrecognized command-line option ‘-mfpu=vfp’ make[2]: *** [../scripts/Makefile.build:252: scripts/mod/empty.o] Error 1 make[2]: *** Waiting for unfinished jobs.... gcc: error: unrecognized command-line option ‘-mfpu=vfp’ make[2]: *** [../scripts/Makefile.build:114: scripts/mod/devicetable-offsets.s] Error 1 make[1]: *** [/home/cel/src/linux/odd-releases/Makefile:1297: prepare0] Error 2 make: *** [Makefile:242: __sub-make] Error 2
-bash: --cross_compile=arm-linux-gnueabihf-: command not found -bash: ./net/sunrpc/.kunitconfig: Permission denied [cel@bazille odd-releases]$ gcc --version gcc (GCC) 12.2.1 20221121 (Red Hat 12.2.1-4) Copyright (C) 2022 Free Software Foundation, Inc. This is free software; see the source for copying conditions. There is NO warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
[cel@bazille odd-releases]$
What am I missing?
Please run that as a single command, not split across 3 lines.
Gr{oetje,eeting}s,
Geert
On Feb 23 2023, Chuck Lever III wrote:
Assuming that "PC:" on m68k is the same as "RIP:" on x86... this does not make sense. rfc6803_suite is not a function.
That can mean that something has overwritten the return PC.
Hi Andreas,
On 24/02/23 06:57, Andreas Schwab wrote:
On Feb 23 2023, Chuck Lever III wrote:
Assuming that "PC:" on m68k is the same as "RIP:" on x86... this does not make sense. rfc6803_suite is not a function.
That can mean that something has overwritten the return PC.
Wouldn't you expect a format error in that case?
Cheers,
Michael
On Feb 24 2023, Michael Schmitz wrote:
Hi Andreas,
On 24/02/23 06:57, Andreas Schwab wrote:
On Feb 23 2023, Chuck Lever III wrote:
Assuming that "PC:" on m68k is the same as "RIP:" on x86... this does not make sense. rfc6803_suite is not a function.
That can mean that something has overwritten the return PC.
Wouldn't you expect a format error in that case?
What format error do you mean? There was a chk exception, presumably because the first word of rfc6803_suite happens to match the encoding of the chk insn.
Hi Andreas,
On 24/02/23 10:46, Andreas Schwab wrote:
On Feb 24 2023, Michael Schmitz wrote:
Hi Andreas,
On 24/02/23 06:57, Andreas Schwab wrote:
On Feb 23 2023, Chuck Lever III wrote:
Assuming that "PC:" on m68k is the same as "RIP:" on x86... this does not make sense. rfc6803_suite is not a function.
That can mean that something has overwritten the return PC.
Wouldn't you expect a format error in that case?
What format error do you mean? There was a chk exception, presumably because the first word of rfc6803_suite happens to match the encoding of the chk insn.
I got confused by 'return PC' and thought the exception had happened on a return instruction (but even that would be unlikely - only rte can generate a format error ...).
Your explanation is more likely to be correct. Would that Geert had copied the code snipped from the log.
Cheers,
Michael
Hi,
On 23.2.2023 18.18, Chuck Lever III wrote:
Since I cannot reproduce this crash and do not have an m68k platform available to me, I will need you to continue to pursue the issue. I'll help as much as I can.
There are multiple m68k emulators that can run m68k Linux. At least Qemu, WinUAE, Aranym and Hatari.
Of those, Qemu, Aranym & Hatari are available directly from Debian: * https://packages.debian.org/bookworm/qemu-system-misc * https://packages.debian.org/bookworm/aranym * https://packages.debian.org/bookworm/hatari
Crypto in general is very (too) slow on ancient HW which does not have any crypto instructions or acceleration, so I would avoid emulators that aim for cycle accuracy with old HW (WinUAE & Hatari).
Qemu can be used to test also other platforms than m68k, and its usage may be easier to automate for your CI than Aranym, so you could try that (not necessarily starting with m68k).
- Eero
linux-kselftest-mirror@lists.linaro.org