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 04d5279f17dfeca5bcb15c520900e9c0b6be1675..db0522b4c4c9cb929cfb1549d41e44c753040bed 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 cae04d7a45a5089865acd5fae22a4b136475d2eb..bb76873aa01982723114e6ed9f4b3a9427a999ad 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 253b4149584a2e7ed9723882acf366773849ce31..d54668790f0cc33e1a6521be0400ce1de6bcf9a3 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 03f1dcddbd29d352c3041fbbfd6e7f76e1fcb968..7cebdf843266882e545efbaece139a9b0e15ff11 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 cd512719092b8addad5e39e334dee4a4a131c17b..7ede900049a701195008aae5700c4d0715c54c79 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 7515bffddf1572a1aae29f49b832c1f0e76a26ac..3e15bdb5a9ebeb37a102dd8640231327355d2169 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 2eb3046a84ea2ed6e0b8b7e45a553a405a253810..1c8ebd3dbd3c42b443c78eedec91c8548885afd2 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);
        }
 }