Message ID | 20200702101947.682-4-ardb@kernel.org (mailing list archive) |
---|---|
State | RFC |
Delegated to: | Herbert Xu |
Headers | show |
Series | crypto: get rid of ecb(arc4) | expand |
Acked-by: J. Bruce Fields <bfields@redhat.com> On Thu, Jul 02, 2020 at 12:19:43PM +0200, Ard Biesheuvel wrote: > The RC4-HMAC-MD5 KerberosV algorithm is based on RFC 4757 [0], which > was specifically issued for interoperability with Windows 2000, but was > never intended to receive the same level of support. The RFC says > > The IETF Kerberos community supports publishing this specification as > an informational document in order to describe this widely > implemented technology. However, while these encryption types > provide the operations necessary to implement the base Kerberos > specification [RFC4120], they do not provide all the required > operations in the Kerberos cryptography framework [RFC3961]. As a > result, it is not generally possible to implement potential > extensions to Kerberos using these encryption types. The Kerberos > encryption type negotiation mechanism [RFC4537] provides one approach > for using such extensions even when a Kerberos infrastructure uses > long-term RC4 keys. Because this specification does not implement > operations required by RFC 3961 and because of security concerns with > the use of RC4 and MD4 discussed in Section 8, this specification is > not appropriate for publication on the standards track. > > The RC4-HMAC encryption types are used to ease upgrade of existing > Windows NT environments, provide strong cryptography (128-bit key > lengths), and provide exportable (meet United States government > export restriction requirements) encryption. This document describes > the implementation of those encryption types. > > Furthermore, this RFC was re-classified as 'historic' by RFC 8429 [1] in > 2018, stating that 'none of the encryption types it specifies should be > used' > > Note that other outdated algorithms are left in place (some of which are > guarded by CONFIG_SUNRPC_DISABLE_INSECURE_ENCTYPES), so this should only > adversely affect interoperability with Windows NT/2000 systems that have > not received any updates since 2008 (but are connected to a network > nonetheless) > > [0] https://tools.ietf.org/html/rfc4757 > [1] https://tools.ietf.org/html/rfc8429 > > Signed-off-by: Ard Biesheuvel <ardb@kernel.org> > --- > include/linux/sunrpc/gss_krb5.h | 11 - > include/linux/sunrpc/gss_krb5_enctypes.h | 9 +- > net/sunrpc/Kconfig | 1 - > net/sunrpc/auth_gss/gss_krb5_crypto.c | 276 -------------------- > net/sunrpc/auth_gss/gss_krb5_mech.c | 95 ------- > net/sunrpc/auth_gss/gss_krb5_seal.c | 1 - > net/sunrpc/auth_gss/gss_krb5_seqnum.c | 87 ------ > net/sunrpc/auth_gss/gss_krb5_unseal.c | 1 - > net/sunrpc/auth_gss/gss_krb5_wrap.c | 65 +---- > 9 files changed, 16 insertions(+), 530 deletions(-) > > diff --git a/include/linux/sunrpc/gss_krb5.h b/include/linux/sunrpc/gss_krb5.h > index e8f8ffe7448b..91f43d86879d 100644 > --- a/include/linux/sunrpc/gss_krb5.h > +++ b/include/linux/sunrpc/gss_krb5.h > @@ -141,14 +141,12 @@ enum sgn_alg { > SGN_ALG_MD2_5 = 0x0001, > SGN_ALG_DES_MAC = 0x0002, > SGN_ALG_3 = 0x0003, /* not published */ > - SGN_ALG_HMAC_MD5 = 0x0011, /* microsoft w2k; no support */ > SGN_ALG_HMAC_SHA1_DES3_KD = 0x0004 > }; > enum seal_alg { > SEAL_ALG_NONE = 0xffff, > SEAL_ALG_DES = 0x0000, > SEAL_ALG_1 = 0x0001, /* not published */ > - SEAL_ALG_MICROSOFT_RC4 = 0x0010,/* microsoft w2k; no support */ > SEAL_ALG_DES3KD = 0x0002 > }; > > @@ -316,14 +314,5 @@ gss_krb5_aes_decrypt(struct krb5_ctx *kctx, u32 offset, u32 len, > struct xdr_buf *buf, u32 *plainoffset, > u32 *plainlen); > > -int > -krb5_rc4_setup_seq_key(struct krb5_ctx *kctx, > - struct crypto_sync_skcipher *cipher, > - unsigned char *cksum); > - > -int > -krb5_rc4_setup_enc_key(struct krb5_ctx *kctx, > - struct crypto_sync_skcipher *cipher, > - s32 seqnum); > void > gss_krb5_make_confounder(char *p, u32 conflen); > diff --git a/include/linux/sunrpc/gss_krb5_enctypes.h b/include/linux/sunrpc/gss_krb5_enctypes.h > index 981c89cef19d..87eea679d750 100644 > --- a/include/linux/sunrpc/gss_krb5_enctypes.h > +++ b/include/linux/sunrpc/gss_krb5_enctypes.h > @@ -13,15 +13,13 @@ > #ifdef CONFIG_SUNRPC_DISABLE_INSECURE_ENCTYPES > > /* > - * NB: This list includes encryption types that were deprecated > - * by RFC 8429 (DES3_CBC_SHA1 and ARCFOUR_HMAC). > + * 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 > - * ENCTYPE_ARCFOUR_HMAC > */ > -#define KRB5_SUPPORTED_ENCTYPES "18,17,16,23" > +#define KRB5_SUPPORTED_ENCTYPES "18,17,16" > > #else /* CONFIG_SUNRPC_DISABLE_INSECURE_ENCTYPES */ > > @@ -32,12 +30,11 @@ > * ENCTYPE_AES256_CTS_HMAC_SHA1_96 > * ENCTYPE_AES128_CTS_HMAC_SHA1_96 > * ENCTYPE_DES3_CBC_SHA1 > - * ENCTYPE_ARCFOUR_HMAC > * ENCTYPE_DES_CBC_MD5 > * ENCTYPE_DES_CBC_CRC > * ENCTYPE_DES_CBC_MD4 > */ > -#define KRB5_SUPPORTED_ENCTYPES "18,17,16,23,3,1,2" > +#define KRB5_SUPPORTED_ENCTYPES "18,17,16,3,1,2" > > #endif /* CONFIG_SUNRPC_DISABLE_INSECURE_ENCTYPES */ > > diff --git a/net/sunrpc/Kconfig b/net/sunrpc/Kconfig > index 3bcf985507be..bbbb5af0af13 100644 > --- a/net/sunrpc/Kconfig > +++ b/net/sunrpc/Kconfig > @@ -21,7 +21,6 @@ config RPCSEC_GSS_KRB5 > depends on SUNRPC && CRYPTO > depends on CRYPTO_MD5 && CRYPTO_DES && CRYPTO_CBC && CRYPTO_CTS > depends on CRYPTO_ECB && CRYPTO_HMAC && CRYPTO_SHA1 && CRYPTO_AES > - depends on CRYPTO_ARC4 > default y > select SUNRPC_GSS > help > diff --git a/net/sunrpc/auth_gss/gss_krb5_crypto.c b/net/sunrpc/auth_gss/gss_krb5_crypto.c > index e7180da1fc6a..634b6c6e0dcb 100644 > --- a/net/sunrpc/auth_gss/gss_krb5_crypto.c > +++ b/net/sunrpc/auth_gss/gss_krb5_crypto.c > @@ -138,135 +138,6 @@ checksummer(struct scatterlist *sg, void *data) > return crypto_ahash_update(req); > } > > -static int > -arcfour_hmac_md5_usage_to_salt(unsigned int usage, u8 salt[4]) > -{ > - unsigned int ms_usage; > - > - switch (usage) { > - case KG_USAGE_SIGN: > - ms_usage = 15; > - break; > - case KG_USAGE_SEAL: > - ms_usage = 13; > - break; > - default: > - return -EINVAL; > - } > - salt[0] = (ms_usage >> 0) & 0xff; > - salt[1] = (ms_usage >> 8) & 0xff; > - salt[2] = (ms_usage >> 16) & 0xff; > - salt[3] = (ms_usage >> 24) & 0xff; > - > - return 0; > -} > - > -static u32 > -make_checksum_hmac_md5(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 scatterlist sg[1]; > - int err = -1; > - u8 *checksumdata; > - u8 *rc4salt; > - struct crypto_ahash *md5; > - struct crypto_ahash *hmac_md5; > - struct ahash_request *req; > - > - if (cksumkey == NULL) > - return GSS_S_FAILURE; > - > - if (cksumout->len < kctx->gk5e->cksumlength) { > - dprintk("%s: checksum buffer length, %u, too small for %s\n", > - __func__, cksumout->len, kctx->gk5e->name); > - return GSS_S_FAILURE; > - } > - > - rc4salt = kmalloc_array(4, sizeof(*rc4salt), GFP_NOFS); > - if (!rc4salt) > - return GSS_S_FAILURE; > - > - if (arcfour_hmac_md5_usage_to_salt(usage, rc4salt)) { > - dprintk("%s: invalid usage value %u\n", __func__, usage); > - goto out_free_rc4salt; > - } > - > - checksumdata = kmalloc(GSS_KRB5_MAX_CKSUM_LEN, GFP_NOFS); > - if (!checksumdata) > - goto out_free_rc4salt; > - > - md5 = crypto_alloc_ahash("md5", 0, CRYPTO_ALG_ASYNC); > - if (IS_ERR(md5)) > - goto out_free_cksum; > - > - hmac_md5 = crypto_alloc_ahash(kctx->gk5e->cksum_name, 0, > - CRYPTO_ALG_ASYNC); > - if (IS_ERR(hmac_md5)) > - goto out_free_md5; > - > - req = ahash_request_alloc(md5, GFP_NOFS); > - if (!req) > - goto out_free_hmac_md5; > - > - ahash_request_set_callback(req, CRYPTO_TFM_REQ_MAY_SLEEP, NULL, NULL); > - > - err = crypto_ahash_init(req); > - if (err) > - goto out; > - sg_init_one(sg, rc4salt, 4); > - ahash_request_set_crypt(req, sg, NULL, 4); > - err = crypto_ahash_update(req); > - if (err) > - goto out; > - > - sg_init_one(sg, header, hdrlen); > - ahash_request_set_crypt(req, sg, NULL, hdrlen); > - err = crypto_ahash_update(req); > - if (err) > - goto out; > - err = xdr_process_buf(body, body_offset, body->len - body_offset, > - checksummer, req); > - if (err) > - goto out; > - ahash_request_set_crypt(req, NULL, checksumdata, 0); > - err = crypto_ahash_final(req); > - if (err) > - goto out; > - > - ahash_request_free(req); > - req = ahash_request_alloc(hmac_md5, GFP_NOFS); > - if (!req) > - goto out_free_hmac_md5; > - > - ahash_request_set_callback(req, CRYPTO_TFM_REQ_MAY_SLEEP, NULL, NULL); > - > - err = crypto_ahash_setkey(hmac_md5, cksumkey, kctx->gk5e->keylength); > - if (err) > - goto out; > - > - sg_init_one(sg, checksumdata, crypto_ahash_digestsize(md5)); > - ahash_request_set_crypt(req, sg, checksumdata, > - crypto_ahash_digestsize(md5)); > - err = crypto_ahash_digest(req); > - if (err) > - goto out; > - > - memcpy(cksumout->data, checksumdata, kctx->gk5e->cksumlength); > - cksumout->len = kctx->gk5e->cksumlength; > -out: > - ahash_request_free(req); > -out_free_hmac_md5: > - crypto_free_ahash(hmac_md5); > -out_free_md5: > - crypto_free_ahash(md5); > -out_free_cksum: > - kfree(checksumdata); > -out_free_rc4salt: > - kfree(rc4salt); > - return err ? GSS_S_FAILURE : 0; > -} > - > /* > * checksum the plaintext data and hdrlen bytes of the token header > * The checksum is performed over the first 8 bytes of the > @@ -284,11 +155,6 @@ make_checksum(struct krb5_ctx *kctx, char *header, int hdrlen, > u8 *checksumdata; > unsigned int checksumlen; > > - if (kctx->gk5e->ctype == CKSUMTYPE_HMAC_MD5_ARCFOUR) > - return make_checksum_hmac_md5(kctx, header, hdrlen, > - body, body_offset, > - cksumkey, usage, cksumout); > - > if (cksumout->len < kctx->gk5e->cksumlength) { > dprintk("%s: checksum buffer length, %u, too small for %s\n", > __func__, cksumout->len, kctx->gk5e->name); > @@ -942,145 +808,3 @@ gss_krb5_aes_decrypt(struct krb5_ctx *kctx, u32 offset, u32 len, > ret = GSS_S_FAILURE; > return ret; > } > - > -/* > - * Compute Kseq given the initial session key and the checksum. > - * Set the key of the given cipher. > - */ > -int > -krb5_rc4_setup_seq_key(struct krb5_ctx *kctx, > - struct crypto_sync_skcipher *cipher, > - unsigned char *cksum) > -{ > - struct crypto_shash *hmac; > - struct shash_desc *desc; > - u8 Kseq[GSS_KRB5_MAX_KEYLEN]; > - u32 zeroconstant = 0; > - int err; > - > - dprintk("%s: entered\n", __func__); > - > - hmac = crypto_alloc_shash(kctx->gk5e->cksum_name, 0, 0); > - if (IS_ERR(hmac)) { > - dprintk("%s: error %ld, allocating hash '%s'\n", > - __func__, PTR_ERR(hmac), kctx->gk5e->cksum_name); > - return PTR_ERR(hmac); > - } > - > - desc = kmalloc(sizeof(*desc) + crypto_shash_descsize(hmac), > - GFP_NOFS); > - if (!desc) { > - dprintk("%s: failed to allocate shash descriptor for '%s'\n", > - __func__, kctx->gk5e->cksum_name); > - crypto_free_shash(hmac); > - return -ENOMEM; > - } > - > - desc->tfm = hmac; > - > - /* Compute intermediate Kseq from session key */ > - err = crypto_shash_setkey(hmac, kctx->Ksess, kctx->gk5e->keylength); > - if (err) > - goto out_err; > - > - err = crypto_shash_digest(desc, (u8 *)&zeroconstant, 4, Kseq); > - if (err) > - goto out_err; > - > - /* Compute final Kseq from the checksum and intermediate Kseq */ > - err = crypto_shash_setkey(hmac, Kseq, kctx->gk5e->keylength); > - if (err) > - goto out_err; > - > - err = crypto_shash_digest(desc, cksum, 8, Kseq); > - if (err) > - goto out_err; > - > - err = crypto_sync_skcipher_setkey(cipher, Kseq, kctx->gk5e->keylength); > - if (err) > - goto out_err; > - > - err = 0; > - > -out_err: > - kzfree(desc); > - crypto_free_shash(hmac); > - dprintk("%s: returning %d\n", __func__, err); > - return err; > -} > - > -/* > - * Compute Kcrypt given the initial session key and the plaintext seqnum. > - * Set the key of cipher kctx->enc. > - */ > -int > -krb5_rc4_setup_enc_key(struct krb5_ctx *kctx, > - struct crypto_sync_skcipher *cipher, > - s32 seqnum) > -{ > - struct crypto_shash *hmac; > - struct shash_desc *desc; > - u8 Kcrypt[GSS_KRB5_MAX_KEYLEN]; > - u8 zeroconstant[4] = {0}; > - u8 seqnumarray[4]; > - int err, i; > - > - dprintk("%s: entered, seqnum %u\n", __func__, seqnum); > - > - hmac = crypto_alloc_shash(kctx->gk5e->cksum_name, 0, 0); > - if (IS_ERR(hmac)) { > - dprintk("%s: error %ld, allocating hash '%s'\n", > - __func__, PTR_ERR(hmac), kctx->gk5e->cksum_name); > - return PTR_ERR(hmac); > - } > - > - desc = kmalloc(sizeof(*desc) + crypto_shash_descsize(hmac), > - GFP_NOFS); > - if (!desc) { > - dprintk("%s: failed to allocate shash descriptor for '%s'\n", > - __func__, kctx->gk5e->cksum_name); > - crypto_free_shash(hmac); > - return -ENOMEM; > - } > - > - desc->tfm = hmac; > - > - /* Compute intermediate Kcrypt from session key */ > - for (i = 0; i < kctx->gk5e->keylength; i++) > - Kcrypt[i] = kctx->Ksess[i] ^ 0xf0; > - > - err = crypto_shash_setkey(hmac, Kcrypt, kctx->gk5e->keylength); > - if (err) > - goto out_err; > - > - err = crypto_shash_digest(desc, zeroconstant, 4, Kcrypt); > - if (err) > - goto out_err; > - > - /* Compute final Kcrypt from the seqnum and intermediate Kcrypt */ > - err = crypto_shash_setkey(hmac, Kcrypt, kctx->gk5e->keylength); > - if (err) > - goto out_err; > - > - seqnumarray[0] = (unsigned char) ((seqnum >> 24) & 0xff); > - seqnumarray[1] = (unsigned char) ((seqnum >> 16) & 0xff); > - seqnumarray[2] = (unsigned char) ((seqnum >> 8) & 0xff); > - seqnumarray[3] = (unsigned char) ((seqnum >> 0) & 0xff); > - > - err = crypto_shash_digest(desc, seqnumarray, 4, Kcrypt); > - if (err) > - goto out_err; > - > - err = crypto_sync_skcipher_setkey(cipher, Kcrypt, > - kctx->gk5e->keylength); > - if (err) > - goto out_err; > - > - err = 0; > - > -out_err: > - kzfree(desc); > - crypto_free_shash(hmac); > - dprintk("%s: returning %d\n", __func__, err); > - return err; > -} > diff --git a/net/sunrpc/auth_gss/gss_krb5_mech.c b/net/sunrpc/auth_gss/gss_krb5_mech.c > index 75b3c2e9e8f8..ae9acf3a7389 100644 > --- a/net/sunrpc/auth_gss/gss_krb5_mech.c > +++ b/net/sunrpc/auth_gss/gss_krb5_mech.c > @@ -51,27 +51,6 @@ static const struct gss_krb5_enctype supported_gss_krb5_enctypes[] = { > .keyed_cksum = 0, > }, > #endif /* CONFIG_SUNRPC_DISABLE_INSECURE_ENCTYPES */ > - /* > - * RC4-HMAC > - */ > - { > - .etype = ENCTYPE_ARCFOUR_HMAC, > - .ctype = CKSUMTYPE_HMAC_MD5_ARCFOUR, > - .name = "rc4-hmac", > - .encrypt_name = "ecb(arc4)", > - .cksum_name = "hmac(md5)", > - .encrypt = krb5_encrypt, > - .decrypt = krb5_decrypt, > - .mk_key = NULL, > - .signalg = SGN_ALG_HMAC_MD5, > - .sealalg = SEAL_ALG_MICROSOFT_RC4, > - .keybytes = 16, > - .keylength = 16, > - .blocksize = 1, > - .conflen = 8, > - .cksumlength = 8, > - .keyed_cksum = 1, > - }, > /* > * 3DES > */ > @@ -401,78 +380,6 @@ context_derive_keys_des3(struct krb5_ctx *ctx, gfp_t gfp_mask) > return -EINVAL; > } > > -/* > - * Note that RC4 depends on deriving keys using the sequence > - * number or the checksum of a token. Therefore, the final keys > - * cannot be calculated until the token is being constructed! > - */ > -static int > -context_derive_keys_rc4(struct krb5_ctx *ctx) > -{ > - struct crypto_shash *hmac; > - char sigkeyconstant[] = "signaturekey"; > - int slen = strlen(sigkeyconstant) + 1; /* include null terminator */ > - struct shash_desc *desc; > - int err; > - > - dprintk("RPC: %s: entered\n", __func__); > - /* > - * derive cksum (aka Ksign) key > - */ > - hmac = crypto_alloc_shash(ctx->gk5e->cksum_name, 0, 0); > - if (IS_ERR(hmac)) { > - dprintk("%s: error %ld allocating hash '%s'\n", > - __func__, PTR_ERR(hmac), ctx->gk5e->cksum_name); > - err = PTR_ERR(hmac); > - goto out_err; > - } > - > - err = crypto_shash_setkey(hmac, ctx->Ksess, ctx->gk5e->keylength); > - if (err) > - goto out_err_free_hmac; > - > - > - desc = kmalloc(sizeof(*desc) + crypto_shash_descsize(hmac), GFP_NOFS); > - if (!desc) { > - dprintk("%s: failed to allocate hash descriptor for '%s'\n", > - __func__, ctx->gk5e->cksum_name); > - err = -ENOMEM; > - goto out_err_free_hmac; > - } > - > - desc->tfm = hmac; > - > - err = crypto_shash_digest(desc, sigkeyconstant, slen, ctx->cksum); > - kzfree(desc); > - if (err) > - goto out_err_free_hmac; > - /* > - * allocate hash, and skciphers for data and seqnum encryption > - */ > - ctx->enc = crypto_alloc_sync_skcipher(ctx->gk5e->encrypt_name, 0, 0); > - if (IS_ERR(ctx->enc)) { > - err = PTR_ERR(ctx->enc); > - goto out_err_free_hmac; > - } > - > - ctx->seq = crypto_alloc_sync_skcipher(ctx->gk5e->encrypt_name, 0, 0); > - if (IS_ERR(ctx->seq)) { > - crypto_free_sync_skcipher(ctx->enc); > - err = PTR_ERR(ctx->seq); > - goto out_err_free_hmac; > - } > - > - dprintk("RPC: %s: returning success\n", __func__); > - > - err = 0; > - > -out_err_free_hmac: > - crypto_free_shash(hmac); > -out_err: > - dprintk("RPC: %s: returning %d\n", __func__, err); > - return err; > -} > - > static int > context_derive_keys_new(struct krb5_ctx *ctx, gfp_t gfp_mask) > { > @@ -649,8 +556,6 @@ gss_import_v2_context(const void *p, const void *end, struct krb5_ctx *ctx, > switch (ctx->enctype) { > case ENCTYPE_DES3_CBC_RAW: > return context_derive_keys_des3(ctx, gfp_mask); > - case ENCTYPE_ARCFOUR_HMAC: > - return context_derive_keys_rc4(ctx); > case ENCTYPE_AES128_CTS_HMAC_SHA1_96: > case ENCTYPE_AES256_CTS_HMAC_SHA1_96: > return context_derive_keys_new(ctx, gfp_mask); > diff --git a/net/sunrpc/auth_gss/gss_krb5_seal.c b/net/sunrpc/auth_gss/gss_krb5_seal.c > index f1d280accf43..33061417ec97 100644 > --- a/net/sunrpc/auth_gss/gss_krb5_seal.c > +++ b/net/sunrpc/auth_gss/gss_krb5_seal.c > @@ -214,7 +214,6 @@ gss_get_mic_kerberos(struct gss_ctx *gss_ctx, struct xdr_buf *text, > BUG(); > case ENCTYPE_DES_CBC_RAW: > case ENCTYPE_DES3_CBC_RAW: > - case ENCTYPE_ARCFOUR_HMAC: > return gss_get_mic_v1(ctx, text, token); > case ENCTYPE_AES128_CTS_HMAC_SHA1_96: > case ENCTYPE_AES256_CTS_HMAC_SHA1_96: > diff --git a/net/sunrpc/auth_gss/gss_krb5_seqnum.c b/net/sunrpc/auth_gss/gss_krb5_seqnum.c > index 507105127095..fb117817ff5d 100644 > --- a/net/sunrpc/auth_gss/gss_krb5_seqnum.c > +++ b/net/sunrpc/auth_gss/gss_krb5_seqnum.c > @@ -39,42 +39,6 @@ > # define RPCDBG_FACILITY RPCDBG_AUTH > #endif > > -static s32 > -krb5_make_rc4_seq_num(struct krb5_ctx *kctx, int direction, s32 seqnum, > - unsigned char *cksum, unsigned char *buf) > -{ > - struct crypto_sync_skcipher *cipher; > - unsigned char *plain; > - s32 code; > - > - dprintk("RPC: %s:\n", __func__); > - cipher = crypto_alloc_sync_skcipher(kctx->gk5e->encrypt_name, 0, 0); > - if (IS_ERR(cipher)) > - return PTR_ERR(cipher); > - > - plain = kmalloc(8, GFP_NOFS); > - if (!plain) > - return -ENOMEM; > - > - plain[0] = (unsigned char) ((seqnum >> 24) & 0xff); > - plain[1] = (unsigned char) ((seqnum >> 16) & 0xff); > - plain[2] = (unsigned char) ((seqnum >> 8) & 0xff); > - plain[3] = (unsigned char) ((seqnum >> 0) & 0xff); > - plain[4] = direction; > - plain[5] = direction; > - plain[6] = direction; > - plain[7] = direction; > - > - code = krb5_rc4_setup_seq_key(kctx, cipher, cksum); > - if (code) > - goto out; > - > - code = krb5_encrypt(cipher, cksum, plain, buf, 8); > -out: > - kfree(plain); > - crypto_free_sync_skcipher(cipher); > - return code; > -} > s32 > krb5_make_seq_num(struct krb5_ctx *kctx, > struct crypto_sync_skcipher *key, > @@ -85,10 +49,6 @@ krb5_make_seq_num(struct krb5_ctx *kctx, > unsigned char *plain; > s32 code; > > - if (kctx->enctype == ENCTYPE_ARCFOUR_HMAC) > - return krb5_make_rc4_seq_num(kctx, direction, seqnum, > - cksum, buf); > - > plain = kmalloc(8, GFP_NOFS); > if (!plain) > return -ENOMEM; > @@ -108,50 +68,6 @@ krb5_make_seq_num(struct krb5_ctx *kctx, > return code; > } > > -static s32 > -krb5_get_rc4_seq_num(struct krb5_ctx *kctx, unsigned char *cksum, > - unsigned char *buf, int *direction, s32 *seqnum) > -{ > - struct crypto_sync_skcipher *cipher; > - unsigned char *plain; > - s32 code; > - > - dprintk("RPC: %s:\n", __func__); > - cipher = crypto_alloc_sync_skcipher(kctx->gk5e->encrypt_name, 0, 0); > - if (IS_ERR(cipher)) > - return PTR_ERR(cipher); > - > - code = krb5_rc4_setup_seq_key(kctx, cipher, cksum); > - if (code) > - goto out; > - > - plain = kmalloc(8, GFP_NOFS); > - if (!plain) { > - code = -ENOMEM; > - goto out; > - } > - > - code = krb5_decrypt(cipher, cksum, buf, plain, 8); > - if (code) > - goto out_plain; > - > - if ((plain[4] != plain[5]) || (plain[4] != plain[6]) > - || (plain[4] != plain[7])) { > - code = (s32)KG_BAD_SEQ; > - goto out_plain; > - } > - > - *direction = plain[4]; > - > - *seqnum = ((plain[0] << 24) | (plain[1] << 16) | > - (plain[2] << 8) | (plain[3])); > -out_plain: > - kfree(plain); > -out: > - crypto_free_sync_skcipher(cipher); > - return code; > -} > - > s32 > krb5_get_seq_num(struct krb5_ctx *kctx, > unsigned char *cksum, > @@ -164,9 +80,6 @@ krb5_get_seq_num(struct krb5_ctx *kctx, > > dprintk("RPC: krb5_get_seq_num:\n"); > > - if (kctx->enctype == ENCTYPE_ARCFOUR_HMAC) > - return krb5_get_rc4_seq_num(kctx, cksum, buf, > - direction, seqnum); > plain = kmalloc(8, GFP_NOFS); > if (!plain) > return -ENOMEM; > diff --git a/net/sunrpc/auth_gss/gss_krb5_unseal.c b/net/sunrpc/auth_gss/gss_krb5_unseal.c > index aaab91cf24c8..ba04e3ec970a 100644 > --- a/net/sunrpc/auth_gss/gss_krb5_unseal.c > +++ b/net/sunrpc/auth_gss/gss_krb5_unseal.c > @@ -218,7 +218,6 @@ gss_verify_mic_kerberos(struct gss_ctx *gss_ctx, > BUG(); > case ENCTYPE_DES_CBC_RAW: > case ENCTYPE_DES3_CBC_RAW: > - case ENCTYPE_ARCFOUR_HMAC: > return gss_verify_mic_v1(ctx, message_buffer, read_token); > case ENCTYPE_AES128_CTS_HMAC_SHA1_96: > case ENCTYPE_AES256_CTS_HMAC_SHA1_96: > diff --git a/net/sunrpc/auth_gss/gss_krb5_wrap.c b/net/sunrpc/auth_gss/gss_krb5_wrap.c > index cf0fd170ac18..a412a734ee17 100644 > --- a/net/sunrpc/auth_gss/gss_krb5_wrap.c > +++ b/net/sunrpc/auth_gss/gss_krb5_wrap.c > @@ -236,26 +236,9 @@ gss_wrap_kerberos_v1(struct krb5_ctx *kctx, int offset, > seq_send, ptr + GSS_KRB5_TOK_HDR_LEN, ptr + 8))) > return GSS_S_FAILURE; > > - if (kctx->enctype == ENCTYPE_ARCFOUR_HMAC) { > - struct crypto_sync_skcipher *cipher; > - int err; > - cipher = crypto_alloc_sync_skcipher(kctx->gk5e->encrypt_name, > - 0, 0); > - if (IS_ERR(cipher)) > - return GSS_S_FAILURE; > - > - krb5_rc4_setup_enc_key(kctx, cipher, seq_send); > - > - err = gss_encrypt_xdr_buf(cipher, buf, > - offset + headlen - conflen, pages); > - crypto_free_sync_skcipher(cipher); > - if (err) > - return GSS_S_FAILURE; > - } else { > - if (gss_encrypt_xdr_buf(kctx->enc, buf, > - offset + headlen - conflen, pages)) > - return GSS_S_FAILURE; > - } > + if (gss_encrypt_xdr_buf(kctx->enc, buf, > + offset + headlen - conflen, pages)) > + return GSS_S_FAILURE; > > return (kctx->endtime < now) ? GSS_S_CONTEXT_EXPIRED : GSS_S_COMPLETE; > } > @@ -316,37 +299,9 @@ gss_unwrap_kerberos_v1(struct krb5_ctx *kctx, int offset, int len, > crypt_offset = ptr + (GSS_KRB5_TOK_HDR_LEN + kctx->gk5e->cksumlength) - > (unsigned char *)buf->head[0].iov_base; > > - /* > - * Need plaintext seqnum to derive encryption key for arcfour-hmac > - */ > - if (krb5_get_seq_num(kctx, ptr + GSS_KRB5_TOK_HDR_LEN, > - ptr + 8, &direction, &seqnum)) > - return GSS_S_BAD_SIG; > - > - if ((kctx->initiate && direction != 0xff) || > - (!kctx->initiate && direction != 0)) > - return GSS_S_BAD_SIG; > - > buf->len = len; > - if (kctx->enctype == ENCTYPE_ARCFOUR_HMAC) { > - struct crypto_sync_skcipher *cipher; > - int err; > - > - cipher = crypto_alloc_sync_skcipher(kctx->gk5e->encrypt_name, > - 0, 0); > - if (IS_ERR(cipher)) > - return GSS_S_FAILURE; > - > - krb5_rc4_setup_enc_key(kctx, cipher, seqnum); > - > - err = gss_decrypt_xdr_buf(cipher, buf, crypt_offset); > - crypto_free_sync_skcipher(cipher); > - if (err) > - return GSS_S_DEFECTIVE_TOKEN; > - } else { > - if (gss_decrypt_xdr_buf(kctx->enc, buf, crypt_offset)) > - return GSS_S_DEFECTIVE_TOKEN; > - } > + if (gss_decrypt_xdr_buf(kctx->enc, buf, crypt_offset)) > + return GSS_S_DEFECTIVE_TOKEN; > > if (kctx->gk5e->keyed_cksum) > cksumkey = kctx->cksum; > @@ -370,6 +325,14 @@ gss_unwrap_kerberos_v1(struct krb5_ctx *kctx, int offset, int len, > > /* do sequencing checks */ > > + if (krb5_get_seq_num(kctx, ptr + GSS_KRB5_TOK_HDR_LEN, > + ptr + 8, &direction, &seqnum)) > + return GSS_S_BAD_SIG; > + > + if ((kctx->initiate && direction != 0xff) || > + (!kctx->initiate && direction != 0)) > + return GSS_S_BAD_SIG; > + > /* Copy the data back to the right position. XXX: Would probably be > * better to copy and encrypt at the same time. */ > > @@ -605,7 +568,6 @@ gss_wrap_kerberos(struct gss_ctx *gctx, int offset, > BUG(); > case ENCTYPE_DES_CBC_RAW: > case ENCTYPE_DES3_CBC_RAW: > - case ENCTYPE_ARCFOUR_HMAC: > return gss_wrap_kerberos_v1(kctx, offset, buf, pages); > case ENCTYPE_AES128_CTS_HMAC_SHA1_96: > case ENCTYPE_AES256_CTS_HMAC_SHA1_96: > @@ -624,7 +586,6 @@ gss_unwrap_kerberos(struct gss_ctx *gctx, int offset, > BUG(); > case ENCTYPE_DES_CBC_RAW: > case ENCTYPE_DES3_CBC_RAW: > - case ENCTYPE_ARCFOUR_HMAC: > return gss_unwrap_kerberos_v1(kctx, offset, len, buf, > &gctx->slack, &gctx->align); > case ENCTYPE_AES128_CTS_HMAC_SHA1_96: > -- > 2.17.1
diff --git a/include/linux/sunrpc/gss_krb5.h b/include/linux/sunrpc/gss_krb5.h index e8f8ffe7448b..91f43d86879d 100644 --- a/include/linux/sunrpc/gss_krb5.h +++ b/include/linux/sunrpc/gss_krb5.h @@ -141,14 +141,12 @@ enum sgn_alg { SGN_ALG_MD2_5 = 0x0001, SGN_ALG_DES_MAC = 0x0002, SGN_ALG_3 = 0x0003, /* not published */ - SGN_ALG_HMAC_MD5 = 0x0011, /* microsoft w2k; no support */ SGN_ALG_HMAC_SHA1_DES3_KD = 0x0004 }; enum seal_alg { SEAL_ALG_NONE = 0xffff, SEAL_ALG_DES = 0x0000, SEAL_ALG_1 = 0x0001, /* not published */ - SEAL_ALG_MICROSOFT_RC4 = 0x0010,/* microsoft w2k; no support */ SEAL_ALG_DES3KD = 0x0002 }; @@ -316,14 +314,5 @@ gss_krb5_aes_decrypt(struct krb5_ctx *kctx, u32 offset, u32 len, struct xdr_buf *buf, u32 *plainoffset, u32 *plainlen); -int -krb5_rc4_setup_seq_key(struct krb5_ctx *kctx, - struct crypto_sync_skcipher *cipher, - unsigned char *cksum); - -int -krb5_rc4_setup_enc_key(struct krb5_ctx *kctx, - struct crypto_sync_skcipher *cipher, - s32 seqnum); void gss_krb5_make_confounder(char *p, u32 conflen); diff --git a/include/linux/sunrpc/gss_krb5_enctypes.h b/include/linux/sunrpc/gss_krb5_enctypes.h index 981c89cef19d..87eea679d750 100644 --- a/include/linux/sunrpc/gss_krb5_enctypes.h +++ b/include/linux/sunrpc/gss_krb5_enctypes.h @@ -13,15 +13,13 @@ #ifdef CONFIG_SUNRPC_DISABLE_INSECURE_ENCTYPES /* - * NB: This list includes encryption types that were deprecated - * by RFC 8429 (DES3_CBC_SHA1 and ARCFOUR_HMAC). + * 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 - * ENCTYPE_ARCFOUR_HMAC */ -#define KRB5_SUPPORTED_ENCTYPES "18,17,16,23" +#define KRB5_SUPPORTED_ENCTYPES "18,17,16" #else /* CONFIG_SUNRPC_DISABLE_INSECURE_ENCTYPES */ @@ -32,12 +30,11 @@ * ENCTYPE_AES256_CTS_HMAC_SHA1_96 * ENCTYPE_AES128_CTS_HMAC_SHA1_96 * ENCTYPE_DES3_CBC_SHA1 - * ENCTYPE_ARCFOUR_HMAC * ENCTYPE_DES_CBC_MD5 * ENCTYPE_DES_CBC_CRC * ENCTYPE_DES_CBC_MD4 */ -#define KRB5_SUPPORTED_ENCTYPES "18,17,16,23,3,1,2" +#define KRB5_SUPPORTED_ENCTYPES "18,17,16,3,1,2" #endif /* CONFIG_SUNRPC_DISABLE_INSECURE_ENCTYPES */ diff --git a/net/sunrpc/Kconfig b/net/sunrpc/Kconfig index 3bcf985507be..bbbb5af0af13 100644 --- a/net/sunrpc/Kconfig +++ b/net/sunrpc/Kconfig @@ -21,7 +21,6 @@ config RPCSEC_GSS_KRB5 depends on SUNRPC && CRYPTO depends on CRYPTO_MD5 && CRYPTO_DES && CRYPTO_CBC && CRYPTO_CTS depends on CRYPTO_ECB && CRYPTO_HMAC && CRYPTO_SHA1 && CRYPTO_AES - depends on CRYPTO_ARC4 default y select SUNRPC_GSS help diff --git a/net/sunrpc/auth_gss/gss_krb5_crypto.c b/net/sunrpc/auth_gss/gss_krb5_crypto.c index e7180da1fc6a..634b6c6e0dcb 100644 --- a/net/sunrpc/auth_gss/gss_krb5_crypto.c +++ b/net/sunrpc/auth_gss/gss_krb5_crypto.c @@ -138,135 +138,6 @@ checksummer(struct scatterlist *sg, void *data) return crypto_ahash_update(req); } -static int -arcfour_hmac_md5_usage_to_salt(unsigned int usage, u8 salt[4]) -{ - unsigned int ms_usage; - - switch (usage) { - case KG_USAGE_SIGN: - ms_usage = 15; - break; - case KG_USAGE_SEAL: - ms_usage = 13; - break; - default: - return -EINVAL; - } - salt[0] = (ms_usage >> 0) & 0xff; - salt[1] = (ms_usage >> 8) & 0xff; - salt[2] = (ms_usage >> 16) & 0xff; - salt[3] = (ms_usage >> 24) & 0xff; - - return 0; -} - -static u32 -make_checksum_hmac_md5(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 scatterlist sg[1]; - int err = -1; - u8 *checksumdata; - u8 *rc4salt; - struct crypto_ahash *md5; - struct crypto_ahash *hmac_md5; - struct ahash_request *req; - - if (cksumkey == NULL) - return GSS_S_FAILURE; - - if (cksumout->len < kctx->gk5e->cksumlength) { - dprintk("%s: checksum buffer length, %u, too small for %s\n", - __func__, cksumout->len, kctx->gk5e->name); - return GSS_S_FAILURE; - } - - rc4salt = kmalloc_array(4, sizeof(*rc4salt), GFP_NOFS); - if (!rc4salt) - return GSS_S_FAILURE; - - if (arcfour_hmac_md5_usage_to_salt(usage, rc4salt)) { - dprintk("%s: invalid usage value %u\n", __func__, usage); - goto out_free_rc4salt; - } - - checksumdata = kmalloc(GSS_KRB5_MAX_CKSUM_LEN, GFP_NOFS); - if (!checksumdata) - goto out_free_rc4salt; - - md5 = crypto_alloc_ahash("md5", 0, CRYPTO_ALG_ASYNC); - if (IS_ERR(md5)) - goto out_free_cksum; - - hmac_md5 = crypto_alloc_ahash(kctx->gk5e->cksum_name, 0, - CRYPTO_ALG_ASYNC); - if (IS_ERR(hmac_md5)) - goto out_free_md5; - - req = ahash_request_alloc(md5, GFP_NOFS); - if (!req) - goto out_free_hmac_md5; - - ahash_request_set_callback(req, CRYPTO_TFM_REQ_MAY_SLEEP, NULL, NULL); - - err = crypto_ahash_init(req); - if (err) - goto out; - sg_init_one(sg, rc4salt, 4); - ahash_request_set_crypt(req, sg, NULL, 4); - err = crypto_ahash_update(req); - if (err) - goto out; - - sg_init_one(sg, header, hdrlen); - ahash_request_set_crypt(req, sg, NULL, hdrlen); - err = crypto_ahash_update(req); - if (err) - goto out; - err = xdr_process_buf(body, body_offset, body->len - body_offset, - checksummer, req); - if (err) - goto out; - ahash_request_set_crypt(req, NULL, checksumdata, 0); - err = crypto_ahash_final(req); - if (err) - goto out; - - ahash_request_free(req); - req = ahash_request_alloc(hmac_md5, GFP_NOFS); - if (!req) - goto out_free_hmac_md5; - - ahash_request_set_callback(req, CRYPTO_TFM_REQ_MAY_SLEEP, NULL, NULL); - - err = crypto_ahash_setkey(hmac_md5, cksumkey, kctx->gk5e->keylength); - if (err) - goto out; - - sg_init_one(sg, checksumdata, crypto_ahash_digestsize(md5)); - ahash_request_set_crypt(req, sg, checksumdata, - crypto_ahash_digestsize(md5)); - err = crypto_ahash_digest(req); - if (err) - goto out; - - memcpy(cksumout->data, checksumdata, kctx->gk5e->cksumlength); - cksumout->len = kctx->gk5e->cksumlength; -out: - ahash_request_free(req); -out_free_hmac_md5: - crypto_free_ahash(hmac_md5); -out_free_md5: - crypto_free_ahash(md5); -out_free_cksum: - kfree(checksumdata); -out_free_rc4salt: - kfree(rc4salt); - return err ? GSS_S_FAILURE : 0; -} - /* * checksum the plaintext data and hdrlen bytes of the token header * The checksum is performed over the first 8 bytes of the @@ -284,11 +155,6 @@ make_checksum(struct krb5_ctx *kctx, char *header, int hdrlen, u8 *checksumdata; unsigned int checksumlen; - if (kctx->gk5e->ctype == CKSUMTYPE_HMAC_MD5_ARCFOUR) - return make_checksum_hmac_md5(kctx, header, hdrlen, - body, body_offset, - cksumkey, usage, cksumout); - if (cksumout->len < kctx->gk5e->cksumlength) { dprintk("%s: checksum buffer length, %u, too small for %s\n", __func__, cksumout->len, kctx->gk5e->name); @@ -942,145 +808,3 @@ gss_krb5_aes_decrypt(struct krb5_ctx *kctx, u32 offset, u32 len, ret = GSS_S_FAILURE; return ret; } - -/* - * Compute Kseq given the initial session key and the checksum. - * Set the key of the given cipher. - */ -int -krb5_rc4_setup_seq_key(struct krb5_ctx *kctx, - struct crypto_sync_skcipher *cipher, - unsigned char *cksum) -{ - struct crypto_shash *hmac; - struct shash_desc *desc; - u8 Kseq[GSS_KRB5_MAX_KEYLEN]; - u32 zeroconstant = 0; - int err; - - dprintk("%s: entered\n", __func__); - - hmac = crypto_alloc_shash(kctx->gk5e->cksum_name, 0, 0); - if (IS_ERR(hmac)) { - dprintk("%s: error %ld, allocating hash '%s'\n", - __func__, PTR_ERR(hmac), kctx->gk5e->cksum_name); - return PTR_ERR(hmac); - } - - desc = kmalloc(sizeof(*desc) + crypto_shash_descsize(hmac), - GFP_NOFS); - if (!desc) { - dprintk("%s: failed to allocate shash descriptor for '%s'\n", - __func__, kctx->gk5e->cksum_name); - crypto_free_shash(hmac); - return -ENOMEM; - } - - desc->tfm = hmac; - - /* Compute intermediate Kseq from session key */ - err = crypto_shash_setkey(hmac, kctx->Ksess, kctx->gk5e->keylength); - if (err) - goto out_err; - - err = crypto_shash_digest(desc, (u8 *)&zeroconstant, 4, Kseq); - if (err) - goto out_err; - - /* Compute final Kseq from the checksum and intermediate Kseq */ - err = crypto_shash_setkey(hmac, Kseq, kctx->gk5e->keylength); - if (err) - goto out_err; - - err = crypto_shash_digest(desc, cksum, 8, Kseq); - if (err) - goto out_err; - - err = crypto_sync_skcipher_setkey(cipher, Kseq, kctx->gk5e->keylength); - if (err) - goto out_err; - - err = 0; - -out_err: - kzfree(desc); - crypto_free_shash(hmac); - dprintk("%s: returning %d\n", __func__, err); - return err; -} - -/* - * Compute Kcrypt given the initial session key and the plaintext seqnum. - * Set the key of cipher kctx->enc. - */ -int -krb5_rc4_setup_enc_key(struct krb5_ctx *kctx, - struct crypto_sync_skcipher *cipher, - s32 seqnum) -{ - struct crypto_shash *hmac; - struct shash_desc *desc; - u8 Kcrypt[GSS_KRB5_MAX_KEYLEN]; - u8 zeroconstant[4] = {0}; - u8 seqnumarray[4]; - int err, i; - - dprintk("%s: entered, seqnum %u\n", __func__, seqnum); - - hmac = crypto_alloc_shash(kctx->gk5e->cksum_name, 0, 0); - if (IS_ERR(hmac)) { - dprintk("%s: error %ld, allocating hash '%s'\n", - __func__, PTR_ERR(hmac), kctx->gk5e->cksum_name); - return PTR_ERR(hmac); - } - - desc = kmalloc(sizeof(*desc) + crypto_shash_descsize(hmac), - GFP_NOFS); - if (!desc) { - dprintk("%s: failed to allocate shash descriptor for '%s'\n", - __func__, kctx->gk5e->cksum_name); - crypto_free_shash(hmac); - return -ENOMEM; - } - - desc->tfm = hmac; - - /* Compute intermediate Kcrypt from session key */ - for (i = 0; i < kctx->gk5e->keylength; i++) - Kcrypt[i] = kctx->Ksess[i] ^ 0xf0; - - err = crypto_shash_setkey(hmac, Kcrypt, kctx->gk5e->keylength); - if (err) - goto out_err; - - err = crypto_shash_digest(desc, zeroconstant, 4, Kcrypt); - if (err) - goto out_err; - - /* Compute final Kcrypt from the seqnum and intermediate Kcrypt */ - err = crypto_shash_setkey(hmac, Kcrypt, kctx->gk5e->keylength); - if (err) - goto out_err; - - seqnumarray[0] = (unsigned char) ((seqnum >> 24) & 0xff); - seqnumarray[1] = (unsigned char) ((seqnum >> 16) & 0xff); - seqnumarray[2] = (unsigned char) ((seqnum >> 8) & 0xff); - seqnumarray[3] = (unsigned char) ((seqnum >> 0) & 0xff); - - err = crypto_shash_digest(desc, seqnumarray, 4, Kcrypt); - if (err) - goto out_err; - - err = crypto_sync_skcipher_setkey(cipher, Kcrypt, - kctx->gk5e->keylength); - if (err) - goto out_err; - - err = 0; - -out_err: - kzfree(desc); - crypto_free_shash(hmac); - dprintk("%s: returning %d\n", __func__, err); - return err; -} diff --git a/net/sunrpc/auth_gss/gss_krb5_mech.c b/net/sunrpc/auth_gss/gss_krb5_mech.c index 75b3c2e9e8f8..ae9acf3a7389 100644 --- a/net/sunrpc/auth_gss/gss_krb5_mech.c +++ b/net/sunrpc/auth_gss/gss_krb5_mech.c @@ -51,27 +51,6 @@ static const struct gss_krb5_enctype supported_gss_krb5_enctypes[] = { .keyed_cksum = 0, }, #endif /* CONFIG_SUNRPC_DISABLE_INSECURE_ENCTYPES */ - /* - * RC4-HMAC - */ - { - .etype = ENCTYPE_ARCFOUR_HMAC, - .ctype = CKSUMTYPE_HMAC_MD5_ARCFOUR, - .name = "rc4-hmac", - .encrypt_name = "ecb(arc4)", - .cksum_name = "hmac(md5)", - .encrypt = krb5_encrypt, - .decrypt = krb5_decrypt, - .mk_key = NULL, - .signalg = SGN_ALG_HMAC_MD5, - .sealalg = SEAL_ALG_MICROSOFT_RC4, - .keybytes = 16, - .keylength = 16, - .blocksize = 1, - .conflen = 8, - .cksumlength = 8, - .keyed_cksum = 1, - }, /* * 3DES */ @@ -401,78 +380,6 @@ context_derive_keys_des3(struct krb5_ctx *ctx, gfp_t gfp_mask) return -EINVAL; } -/* - * Note that RC4 depends on deriving keys using the sequence - * number or the checksum of a token. Therefore, the final keys - * cannot be calculated until the token is being constructed! - */ -static int -context_derive_keys_rc4(struct krb5_ctx *ctx) -{ - struct crypto_shash *hmac; - char sigkeyconstant[] = "signaturekey"; - int slen = strlen(sigkeyconstant) + 1; /* include null terminator */ - struct shash_desc *desc; - int err; - - dprintk("RPC: %s: entered\n", __func__); - /* - * derive cksum (aka Ksign) key - */ - hmac = crypto_alloc_shash(ctx->gk5e->cksum_name, 0, 0); - if (IS_ERR(hmac)) { - dprintk("%s: error %ld allocating hash '%s'\n", - __func__, PTR_ERR(hmac), ctx->gk5e->cksum_name); - err = PTR_ERR(hmac); - goto out_err; - } - - err = crypto_shash_setkey(hmac, ctx->Ksess, ctx->gk5e->keylength); - if (err) - goto out_err_free_hmac; - - - desc = kmalloc(sizeof(*desc) + crypto_shash_descsize(hmac), GFP_NOFS); - if (!desc) { - dprintk("%s: failed to allocate hash descriptor for '%s'\n", - __func__, ctx->gk5e->cksum_name); - err = -ENOMEM; - goto out_err_free_hmac; - } - - desc->tfm = hmac; - - err = crypto_shash_digest(desc, sigkeyconstant, slen, ctx->cksum); - kzfree(desc); - if (err) - goto out_err_free_hmac; - /* - * allocate hash, and skciphers for data and seqnum encryption - */ - ctx->enc = crypto_alloc_sync_skcipher(ctx->gk5e->encrypt_name, 0, 0); - if (IS_ERR(ctx->enc)) { - err = PTR_ERR(ctx->enc); - goto out_err_free_hmac; - } - - ctx->seq = crypto_alloc_sync_skcipher(ctx->gk5e->encrypt_name, 0, 0); - if (IS_ERR(ctx->seq)) { - crypto_free_sync_skcipher(ctx->enc); - err = PTR_ERR(ctx->seq); - goto out_err_free_hmac; - } - - dprintk("RPC: %s: returning success\n", __func__); - - err = 0; - -out_err_free_hmac: - crypto_free_shash(hmac); -out_err: - dprintk("RPC: %s: returning %d\n", __func__, err); - return err; -} - static int context_derive_keys_new(struct krb5_ctx *ctx, gfp_t gfp_mask) { @@ -649,8 +556,6 @@ gss_import_v2_context(const void *p, const void *end, struct krb5_ctx *ctx, switch (ctx->enctype) { case ENCTYPE_DES3_CBC_RAW: return context_derive_keys_des3(ctx, gfp_mask); - case ENCTYPE_ARCFOUR_HMAC: - return context_derive_keys_rc4(ctx); case ENCTYPE_AES128_CTS_HMAC_SHA1_96: case ENCTYPE_AES256_CTS_HMAC_SHA1_96: return context_derive_keys_new(ctx, gfp_mask); diff --git a/net/sunrpc/auth_gss/gss_krb5_seal.c b/net/sunrpc/auth_gss/gss_krb5_seal.c index f1d280accf43..33061417ec97 100644 --- a/net/sunrpc/auth_gss/gss_krb5_seal.c +++ b/net/sunrpc/auth_gss/gss_krb5_seal.c @@ -214,7 +214,6 @@ gss_get_mic_kerberos(struct gss_ctx *gss_ctx, struct xdr_buf *text, BUG(); case ENCTYPE_DES_CBC_RAW: case ENCTYPE_DES3_CBC_RAW: - case ENCTYPE_ARCFOUR_HMAC: return gss_get_mic_v1(ctx, text, token); case ENCTYPE_AES128_CTS_HMAC_SHA1_96: case ENCTYPE_AES256_CTS_HMAC_SHA1_96: diff --git a/net/sunrpc/auth_gss/gss_krb5_seqnum.c b/net/sunrpc/auth_gss/gss_krb5_seqnum.c index 507105127095..fb117817ff5d 100644 --- a/net/sunrpc/auth_gss/gss_krb5_seqnum.c +++ b/net/sunrpc/auth_gss/gss_krb5_seqnum.c @@ -39,42 +39,6 @@ # define RPCDBG_FACILITY RPCDBG_AUTH #endif -static s32 -krb5_make_rc4_seq_num(struct krb5_ctx *kctx, int direction, s32 seqnum, - unsigned char *cksum, unsigned char *buf) -{ - struct crypto_sync_skcipher *cipher; - unsigned char *plain; - s32 code; - - dprintk("RPC: %s:\n", __func__); - cipher = crypto_alloc_sync_skcipher(kctx->gk5e->encrypt_name, 0, 0); - if (IS_ERR(cipher)) - return PTR_ERR(cipher); - - plain = kmalloc(8, GFP_NOFS); - if (!plain) - return -ENOMEM; - - plain[0] = (unsigned char) ((seqnum >> 24) & 0xff); - plain[1] = (unsigned char) ((seqnum >> 16) & 0xff); - plain[2] = (unsigned char) ((seqnum >> 8) & 0xff); - plain[3] = (unsigned char) ((seqnum >> 0) & 0xff); - plain[4] = direction; - plain[5] = direction; - plain[6] = direction; - plain[7] = direction; - - code = krb5_rc4_setup_seq_key(kctx, cipher, cksum); - if (code) - goto out; - - code = krb5_encrypt(cipher, cksum, plain, buf, 8); -out: - kfree(plain); - crypto_free_sync_skcipher(cipher); - return code; -} s32 krb5_make_seq_num(struct krb5_ctx *kctx, struct crypto_sync_skcipher *key, @@ -85,10 +49,6 @@ krb5_make_seq_num(struct krb5_ctx *kctx, unsigned char *plain; s32 code; - if (kctx->enctype == ENCTYPE_ARCFOUR_HMAC) - return krb5_make_rc4_seq_num(kctx, direction, seqnum, - cksum, buf); - plain = kmalloc(8, GFP_NOFS); if (!plain) return -ENOMEM; @@ -108,50 +68,6 @@ krb5_make_seq_num(struct krb5_ctx *kctx, return code; } -static s32 -krb5_get_rc4_seq_num(struct krb5_ctx *kctx, unsigned char *cksum, - unsigned char *buf, int *direction, s32 *seqnum) -{ - struct crypto_sync_skcipher *cipher; - unsigned char *plain; - s32 code; - - dprintk("RPC: %s:\n", __func__); - cipher = crypto_alloc_sync_skcipher(kctx->gk5e->encrypt_name, 0, 0); - if (IS_ERR(cipher)) - return PTR_ERR(cipher); - - code = krb5_rc4_setup_seq_key(kctx, cipher, cksum); - if (code) - goto out; - - plain = kmalloc(8, GFP_NOFS); - if (!plain) { - code = -ENOMEM; - goto out; - } - - code = krb5_decrypt(cipher, cksum, buf, plain, 8); - if (code) - goto out_plain; - - if ((plain[4] != plain[5]) || (plain[4] != plain[6]) - || (plain[4] != plain[7])) { - code = (s32)KG_BAD_SEQ; - goto out_plain; - } - - *direction = plain[4]; - - *seqnum = ((plain[0] << 24) | (plain[1] << 16) | - (plain[2] << 8) | (plain[3])); -out_plain: - kfree(plain); -out: - crypto_free_sync_skcipher(cipher); - return code; -} - s32 krb5_get_seq_num(struct krb5_ctx *kctx, unsigned char *cksum, @@ -164,9 +80,6 @@ krb5_get_seq_num(struct krb5_ctx *kctx, dprintk("RPC: krb5_get_seq_num:\n"); - if (kctx->enctype == ENCTYPE_ARCFOUR_HMAC) - return krb5_get_rc4_seq_num(kctx, cksum, buf, - direction, seqnum); plain = kmalloc(8, GFP_NOFS); if (!plain) return -ENOMEM; diff --git a/net/sunrpc/auth_gss/gss_krb5_unseal.c b/net/sunrpc/auth_gss/gss_krb5_unseal.c index aaab91cf24c8..ba04e3ec970a 100644 --- a/net/sunrpc/auth_gss/gss_krb5_unseal.c +++ b/net/sunrpc/auth_gss/gss_krb5_unseal.c @@ -218,7 +218,6 @@ gss_verify_mic_kerberos(struct gss_ctx *gss_ctx, BUG(); case ENCTYPE_DES_CBC_RAW: case ENCTYPE_DES3_CBC_RAW: - case ENCTYPE_ARCFOUR_HMAC: return gss_verify_mic_v1(ctx, message_buffer, read_token); case ENCTYPE_AES128_CTS_HMAC_SHA1_96: case ENCTYPE_AES256_CTS_HMAC_SHA1_96: diff --git a/net/sunrpc/auth_gss/gss_krb5_wrap.c b/net/sunrpc/auth_gss/gss_krb5_wrap.c index cf0fd170ac18..a412a734ee17 100644 --- a/net/sunrpc/auth_gss/gss_krb5_wrap.c +++ b/net/sunrpc/auth_gss/gss_krb5_wrap.c @@ -236,26 +236,9 @@ gss_wrap_kerberos_v1(struct krb5_ctx *kctx, int offset, seq_send, ptr + GSS_KRB5_TOK_HDR_LEN, ptr + 8))) return GSS_S_FAILURE; - if (kctx->enctype == ENCTYPE_ARCFOUR_HMAC) { - struct crypto_sync_skcipher *cipher; - int err; - cipher = crypto_alloc_sync_skcipher(kctx->gk5e->encrypt_name, - 0, 0); - if (IS_ERR(cipher)) - return GSS_S_FAILURE; - - krb5_rc4_setup_enc_key(kctx, cipher, seq_send); - - err = gss_encrypt_xdr_buf(cipher, buf, - offset + headlen - conflen, pages); - crypto_free_sync_skcipher(cipher); - if (err) - return GSS_S_FAILURE; - } else { - if (gss_encrypt_xdr_buf(kctx->enc, buf, - offset + headlen - conflen, pages)) - return GSS_S_FAILURE; - } + if (gss_encrypt_xdr_buf(kctx->enc, buf, + offset + headlen - conflen, pages)) + return GSS_S_FAILURE; return (kctx->endtime < now) ? GSS_S_CONTEXT_EXPIRED : GSS_S_COMPLETE; } @@ -316,37 +299,9 @@ gss_unwrap_kerberos_v1(struct krb5_ctx *kctx, int offset, int len, crypt_offset = ptr + (GSS_KRB5_TOK_HDR_LEN + kctx->gk5e->cksumlength) - (unsigned char *)buf->head[0].iov_base; - /* - * Need plaintext seqnum to derive encryption key for arcfour-hmac - */ - if (krb5_get_seq_num(kctx, ptr + GSS_KRB5_TOK_HDR_LEN, - ptr + 8, &direction, &seqnum)) - return GSS_S_BAD_SIG; - - if ((kctx->initiate && direction != 0xff) || - (!kctx->initiate && direction != 0)) - return GSS_S_BAD_SIG; - buf->len = len; - if (kctx->enctype == ENCTYPE_ARCFOUR_HMAC) { - struct crypto_sync_skcipher *cipher; - int err; - - cipher = crypto_alloc_sync_skcipher(kctx->gk5e->encrypt_name, - 0, 0); - if (IS_ERR(cipher)) - return GSS_S_FAILURE; - - krb5_rc4_setup_enc_key(kctx, cipher, seqnum); - - err = gss_decrypt_xdr_buf(cipher, buf, crypt_offset); - crypto_free_sync_skcipher(cipher); - if (err) - return GSS_S_DEFECTIVE_TOKEN; - } else { - if (gss_decrypt_xdr_buf(kctx->enc, buf, crypt_offset)) - return GSS_S_DEFECTIVE_TOKEN; - } + if (gss_decrypt_xdr_buf(kctx->enc, buf, crypt_offset)) + return GSS_S_DEFECTIVE_TOKEN; if (kctx->gk5e->keyed_cksum) cksumkey = kctx->cksum; @@ -370,6 +325,14 @@ gss_unwrap_kerberos_v1(struct krb5_ctx *kctx, int offset, int len, /* do sequencing checks */ + if (krb5_get_seq_num(kctx, ptr + GSS_KRB5_TOK_HDR_LEN, + ptr + 8, &direction, &seqnum)) + return GSS_S_BAD_SIG; + + if ((kctx->initiate && direction != 0xff) || + (!kctx->initiate && direction != 0)) + return GSS_S_BAD_SIG; + /* Copy the data back to the right position. XXX: Would probably be * better to copy and encrypt at the same time. */ @@ -605,7 +568,6 @@ gss_wrap_kerberos(struct gss_ctx *gctx, int offset, BUG(); case ENCTYPE_DES_CBC_RAW: case ENCTYPE_DES3_CBC_RAW: - case ENCTYPE_ARCFOUR_HMAC: return gss_wrap_kerberos_v1(kctx, offset, buf, pages); case ENCTYPE_AES128_CTS_HMAC_SHA1_96: case ENCTYPE_AES256_CTS_HMAC_SHA1_96: @@ -624,7 +586,6 @@ gss_unwrap_kerberos(struct gss_ctx *gctx, int offset, BUG(); case ENCTYPE_DES_CBC_RAW: case ENCTYPE_DES3_CBC_RAW: - case ENCTYPE_ARCFOUR_HMAC: return gss_unwrap_kerberos_v1(kctx, offset, len, buf, &gctx->slack, &gctx->align); case ENCTYPE_AES128_CTS_HMAC_SHA1_96:
The RC4-HMAC-MD5 KerberosV algorithm is based on RFC 4757 [0], which was specifically issued for interoperability with Windows 2000, but was never intended to receive the same level of support. The RFC says The IETF Kerberos community supports publishing this specification as an informational document in order to describe this widely implemented technology. However, while these encryption types provide the operations necessary to implement the base Kerberos specification [RFC4120], they do not provide all the required operations in the Kerberos cryptography framework [RFC3961]. As a result, it is not generally possible to implement potential extensions to Kerberos using these encryption types. The Kerberos encryption type negotiation mechanism [RFC4537] provides one approach for using such extensions even when a Kerberos infrastructure uses long-term RC4 keys. Because this specification does not implement operations required by RFC 3961 and because of security concerns with the use of RC4 and MD4 discussed in Section 8, this specification is not appropriate for publication on the standards track. The RC4-HMAC encryption types are used to ease upgrade of existing Windows NT environments, provide strong cryptography (128-bit key lengths), and provide exportable (meet United States government export restriction requirements) encryption. This document describes the implementation of those encryption types. Furthermore, this RFC was re-classified as 'historic' by RFC 8429 [1] in 2018, stating that 'none of the encryption types it specifies should be used' Note that other outdated algorithms are left in place (some of which are guarded by CONFIG_SUNRPC_DISABLE_INSECURE_ENCTYPES), so this should only adversely affect interoperability with Windows NT/2000 systems that have not received any updates since 2008 (but are connected to a network nonetheless) [0] https://tools.ietf.org/html/rfc4757 [1] https://tools.ietf.org/html/rfc8429 Signed-off-by: Ard Biesheuvel <ardb@kernel.org> --- include/linux/sunrpc/gss_krb5.h | 11 - include/linux/sunrpc/gss_krb5_enctypes.h | 9 +- net/sunrpc/Kconfig | 1 - net/sunrpc/auth_gss/gss_krb5_crypto.c | 276 -------------------- net/sunrpc/auth_gss/gss_krb5_mech.c | 95 ------- net/sunrpc/auth_gss/gss_krb5_seal.c | 1 - net/sunrpc/auth_gss/gss_krb5_seqnum.c | 87 ------ net/sunrpc/auth_gss/gss_krb5_unseal.c | 1 - net/sunrpc/auth_gss/gss_krb5_wrap.c | 65 +---- 9 files changed, 16 insertions(+), 530 deletions(-)