SUNRPC: Obscure Kerberos encryption keys
authorChuck Lever <chuck.lever@oracle.com>
Sun, 15 Jan 2023 17:21:01 +0000 (12:21 -0500)
committerChuck Lever <chuck.lever@oracle.com>
Mon, 20 Feb 2023 14:20:35 +0000 (09:20 -0500)
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>
Reviewed-by: Simo Sorce <simo@redhat.com>
Signed-off-by: Chuck Lever <chuck.lever@oracle.com>
include/linux/sunrpc/gss_krb5.h
net/sunrpc/auth_gss/gss_krb5_mech.c

index 34d54714c6a33f18d861be351d4c7e28cf210143..46eaa2ee9c21814886068f3ccd61961ecd53d4fb 100644 (file)
@@ -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];
 };
index afa6a692ccddac5e4107dd4ee30d505ab491ed0a..8bc24c0684cb97c5bbf48b8e92cff381851c230b 100644 (file)
@@ -350,42 +350,49 @@ out_err:
 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