gss_krb5: add support for triple-des encryption
authorKevin Coffman <kwc@citi.umich.edu>
Wed, 17 Mar 2010 17:02:55 +0000 (13:02 -0400)
committerTrond Myklebust <Trond.Myklebust@netapp.com>
Fri, 14 May 2010 19:09:17 +0000 (15:09 -0400)
Add the final pieces to support the triple-des encryption type.

Signed-off-by: Kevin Coffman <kwc@citi.umich.edu>
Signed-off-by: Steve Dickson <steved@redhat.com>
Signed-off-by: Trond Myklebust <Trond.Myklebust@netapp.com>
include/linux/sunrpc/gss_krb5.h
net/sunrpc/auth_gss/gss_krb5_crypto.c
net/sunrpc/auth_gss/gss_krb5_keys.c
net/sunrpc/auth_gss/gss_krb5_mech.c
net/sunrpc/auth_gss/gss_krb5_seal.c
net/sunrpc/auth_gss/gss_krb5_unseal.c
net/sunrpc/auth_gss/gss_krb5_wrap.c

index 04d5279..db0522b 100644 (file)
@@ -261,3 +261,8 @@ krb5_derive_key(const struct gss_krb5_enctype *gk5e,
                const struct xdr_netobj *inkey,
                struct xdr_netobj *outkey,
                const struct xdr_netobj *in_constant);
+
+u32
+gss_krb5_des3_make_key(const struct gss_krb5_enctype *gk5e,
+                      struct xdr_netobj *randombits,
+                      struct xdr_netobj *key);
index cae04d7..bb76873 100644 (file)
@@ -184,6 +184,9 @@ make_checksum(struct krb5_ctx *kctx, char *header, int hdrlen,
                       checksumdata + checksumlen - kctx->gk5e->cksumlength,
                       kctx->gk5e->cksumlength);
                break;
+       case CKSUMTYPE_HMAC_SHA1_DES3:
+               memcpy(cksumout->data, checksumdata, kctx->gk5e->cksumlength);
+               break;
        default:
                BUG();
                break;
index 253b414..d546687 100644 (file)
@@ -250,3 +250,56 @@ err_free_cipher:
 err_return:
        return ret;
 }
+
+#define smask(step) ((1<<step)-1)
+#define pstep(x, step) (((x)&smask(step))^(((x)>>step)&smask(step)))
+#define parity_char(x) pstep(pstep(pstep((x), 4), 2), 1)
+
+static void mit_des_fixup_key_parity(u8 key[8])
+{
+       int i;
+       for (i = 0; i < 8; i++) {
+               key[i] &= 0xfe;
+               key[i] |= 1^parity_char(key[i]);
+       }
+}
+
+/*
+ * 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)
+{
+       int i;
+       u32 ret = EINVAL;
+
+       if (key->len != 24) {
+               dprintk("%s: key->len is %d\n", __func__, key->len);
+               goto err_out;
+       }
+       if (randombits->len != 21) {
+               dprintk("%s: randombits->len is %d\n",
+                       __func__, randombits->len);
+               goto err_out;
+       }
+
+       /* take the seven bytes, move them around into the top 7 bits of the
+          8 key bytes, then compute the parity bits.  Do this three times. */
+
+       for (i = 0; i < 3; i++) {
+               memcpy(key->data + i*8, randombits->data + i*7, 7);
+               key->data[i*8+7] = (((key->data[i*8]&1)<<1) |
+                                   ((key->data[i*8+1]&1)<<2) |
+                                   ((key->data[i*8+2]&1)<<3) |
+                                   ((key->data[i*8+3]&1)<<4) |
+                                   ((key->data[i*8+4]&1)<<5) |
+                                   ((key->data[i*8+5]&1)<<6) |
+                                   ((key->data[i*8+6]&1)<<7));
+
+               mit_des_fixup_key_parity(key->data + i*8);
+       }
+       ret = 0;
+err_out:
+       return ret;
+}
index 03f1dcd..7cebdf8 100644 (file)
@@ -71,6 +71,26 @@ static const struct gss_krb5_enctype supported_gss_krb5_enctypes[] = {
          .cksumlength = 8,
          .keyed_cksum = 0,
        },
+       /*
+        * 3DES
+        */
+       {
+         .etype = ENCTYPE_DES3_CBC_RAW,
+         .ctype = CKSUMTYPE_HMAC_SHA1_DES3,
+         .name = "des3-hmac-sha1",
+         .encrypt_name = "cbc(des3_ede)",
+         .cksum_name = "hmac(sha1)",
+         .encrypt = krb5_encrypt,
+         .decrypt = krb5_decrypt,
+         .mk_key = gss_krb5_des3_make_key,
+         .signalg = SGN_ALG_HMAC_SHA1_DES3_KD,
+         .sealalg = SEAL_ALG_DES3KD,
+         .keybytes = 21,
+         .keylength = 24,
+         .blocksize = 8,
+         .cksumlength = 20,
+         .keyed_cksum = 1,
+       },
 };
 
 static const int num_supported_enctypes =
@@ -440,6 +460,9 @@ gss_import_v2_context(const void *p, const void *end, struct krb5_ctx *ctx)
        p = simple_get_bytes(p, end, &ctx->enctype, sizeof(ctx->enctype));
        if (IS_ERR(p))
                goto out_err;
+       /* 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);
        if (ctx->gk5e == NULL) {
                dprintk("gss_kerberos_mech: unsupported krb5 enctype %u\n",
index cd51271..7ede900 100644 (file)
@@ -142,6 +142,7 @@ gss_get_mic_kerberos(struct gss_ctx *gss_ctx, struct xdr_buf *text,
        default:
                BUG();
        case ENCTYPE_DES_CBC_RAW:
+       case ENCTYPE_DES3_CBC_RAW:
                return gss_get_mic_v1(ctx, text, token);
        }
 }
index 7515bff..3e15bdb 100644 (file)
@@ -152,6 +152,7 @@ gss_verify_mic_kerberos(struct gss_ctx *gss_ctx,
        default:
                BUG();
        case ENCTYPE_DES_CBC_RAW:
+       case ENCTYPE_DES3_CBC_RAW:
                return gss_verify_mic_v1(ctx, message_buffer, read_token);
        }
 }
index 2eb3046..1c8ebd3 100644 (file)
@@ -350,6 +350,7 @@ gss_wrap_kerberos(struct gss_ctx *gctx, int offset,
        default:
                BUG();
        case ENCTYPE_DES_CBC_RAW:
+       case ENCTYPE_DES3_CBC_RAW:
                return gss_wrap_kerberos_v1(kctx, offset, buf, pages);
        }
 }
@@ -363,6 +364,7 @@ gss_unwrap_kerberos(struct gss_ctx *gctx, int offset, struct xdr_buf *buf)
        default:
                BUG();
        case ENCTYPE_DES_CBC_RAW:
+       case ENCTYPE_DES3_CBC_RAW:
                return gss_unwrap_kerberos_v1(kctx, offset, buf);
        }
 }