Linux NFS development
 help / color / mirror / Atom feed
* [PATCH 00/19] RFC add kernel support for newer encrytpion types
@ 2008-02-21 18:43 Kevin Coffman
       [not found] ` <20080221184208.19195.94518.stgit-zTNJhAanYLVZN1qrTdtDg5Vzexx5G7lz@public.gmane.org>
  0 siblings, 1 reply; 31+ messages in thread
From: Kevin Coffman @ 2008-02-21 18:43 UTC (permalink / raw)
  To: linux-nfs

Consider this an RFC.

These patches add kernel support for triple-DES and AES encryption to the
Kerberos gss code.

These are currently built on 2.6.25-rc1, but I think they should apply
to the latest code as well.

The first patch adds a crypto cts wrapper to do the cts mode req'd by
AES.  This has been submitted to Herbert Xu.

A couple of things remain:

 - Allocate the blkcipher(s) for "cbc(aes)" during context initialization
   rather than on-demand.  I'll include this in the next version.

 - Add support for rc4-hmac.

 - Implement the code necessary to handle possibly rotated data in the
   version two tokens.  I don't expect we'll see rotated data in normal
   operation, but this should be done for completeness.

There are nfs-utils patches required for the new context format from
user-land to kernel.  I need to finish changes for non-lucid contexts
and test those further.


K.C.

^ permalink raw reply	[flat|nested] 31+ messages in thread

* [PATCH 01/19] crypto: Add CTS mode required for Kerberos AES support
       [not found] ` <20080221184208.19195.94518.stgit-zTNJhAanYLVZN1qrTdtDg5Vzexx5G7lz@public.gmane.org>
@ 2008-02-21 18:43   ` Kevin Coffman
  2008-02-21 18:43   ` [PATCH 02/19] rpc: gss: Add oid values to the gss_api mechanism structures Kevin Coffman
                     ` (17 subsequent siblings)
  18 siblings, 0 replies; 31+ messages in thread
From: Kevin Coffman @ 2008-02-21 18:43 UTC (permalink / raw)
  To: linux-nfs

Implement CTS wrapper for CBC mode required for support of AES
encryption support for Kerberos (rfc3962).

Signed-off-by: Kevin Coffman <kwc@citi.umich.edu>
---

 crypto/Kconfig  |   11 ++
 crypto/Makefile |    1 
 crypto/cts.c    |  347 +++++++++++++++++++++++++++++++++++++++++++++++++++++++
 crypto/tcrypt.c |   16 ++-
 crypto/tcrypt.h |  209 +++++++++++++++++++++++++++++++++
 5 files changed, 582 insertions(+), 2 deletions(-)

diff --git a/crypto/Kconfig b/crypto/Kconfig
index c3166a1..375d269 100644
--- a/crypto/Kconfig
+++ b/crypto/Kconfig
@@ -212,6 +212,17 @@ config CRYPTO_CTR
 	  CTR: Counter mode
 	  This block cipher algorithm is required for IPSec.
 
+config CRYPTO_CTS
+	tristate "CTS support"
+	select CRYPTO_BLKCIPHER
+	help
+	  CTS: Cipher Text Stealing
+	  This is the Cipher Text Stealing mode as described by
+	  Section 8 of rfc2040 and referenced by rfc3962.
+	  (rfc3962 includes errata information in its Appendix A)
+	  This mode is required for Kerberos gss mechanism support
+	  for AES encryption.
+
 config CRYPTO_GCM
 	tristate "GCM/GMAC support"
 	select CRYPTO_CTR
diff --git a/crypto/Makefile b/crypto/Makefile
index 48c7583..1b95dec 100644
--- a/crypto/Makefile
+++ b/crypto/Makefile
@@ -35,6 +35,7 @@ obj-$(CONFIG_CRYPTO_GF128MUL) += gf128mul.o
 obj-$(CONFIG_CRYPTO_ECB) += ecb.o
 obj-$(CONFIG_CRYPTO_CBC) += cbc.o
 obj-$(CONFIG_CRYPTO_PCBC) += pcbc.o
+obj-$(CONFIG_CRYPTO_CTS) += cts.o
 obj-$(CONFIG_CRYPTO_LRW) += lrw.o
 obj-$(CONFIG_CRYPTO_XTS) += xts.o
 obj-$(CONFIG_CRYPTO_CTR) += ctr.o
diff --git a/crypto/cts.c b/crypto/cts.c
new file mode 100644
index 0000000..6fe968a
--- /dev/null
+++ b/crypto/cts.c
@@ -0,0 +1,347 @@
+/*
+ * CTS: Cipher Text Stealing mode
+ *
+ * COPYRIGHT (c) 2008
+ * The Regents of the University of Michigan
+ * ALL RIGHTS RESERVED
+ *
+ * Permission is granted to use, copy, create derivative works
+ * and redistribute this software and such derivative works
+ * for any purpose, so long as the name of The University of
+ * Michigan is not used in any advertising or publicity
+ * pertaining to the use of distribution of this software
+ * without specific, written prior authorization.  If the
+ * above copyright notice or any other identification of the
+ * University of Michigan is included in any copy of any
+ * portion of this software, then the disclaimer below must
+ * also be included.
+ *
+ * THIS SOFTWARE IS PROVIDED AS IS, WITHOUT REPRESENTATION
+ * FROM THE UNIVERSITY OF MICHIGAN AS TO ITS FITNESS FOR ANY
+ * PURPOSE, AND WITHOUT WARRANTY BY THE UNIVERSITY OF
+ * MICHIGAN OF ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING
+ * WITHOUT LIMITATION THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE
+ * REGENTS OF THE UNIVERSITY OF MICHIGAN SHALL NOT BE LIABLE
+ * FOR ANY DAMAGES, INCLUDING SPECIAL, INDIRECT, INCIDENTAL, OR
+ * CONSEQUENTIAL DAMAGES, WITH RESPECT TO ANY CLAIM ARISING
+ * OUT OF OR IN CONNECTION WITH THE USE OF THE SOFTWARE, EVEN
+ * IF IT HAS BEEN OR IS HEREAFTER ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGES.
+ */
+
+/* Derived from various:
+ *	Copyright (c) 2006 Herbert Xu <herbert-lOAM2aK0SrRLBo1qDEOMRrpzq4S04n8Q@public.gmane.org>
+ */
+
+/*
+ * This is the Cipher Text Stealing mode as described by
+ * Section 8 of rfc2040 and referenced by rfc3962.
+ * rfc3962 includes errata information in its Appendix A.
+ */
+
+#include <crypto/algapi.h>
+#include <linux/err.h>
+#include <linux/init.h>
+#include <linux/kernel.h>
+#include <linux/log2.h>
+#include <linux/module.h>
+#include <linux/scatterlist.h>
+#include <crypto/scatterwalk.h>
+#include <linux/slab.h>
+
+struct crypto_cts_ctx {
+	struct crypto_blkcipher *child;
+};
+
+static int crypto_cts_setkey(struct crypto_tfm *parent, const u8 *key,
+			     unsigned int keylen)
+{
+	struct crypto_cts_ctx *ctx = crypto_tfm_ctx(parent);
+	struct crypto_blkcipher *child = ctx->child;
+	int err;
+
+	crypto_blkcipher_clear_flags(child, CRYPTO_TFM_REQ_MASK);
+	crypto_blkcipher_set_flags(child, crypto_tfm_get_flags(parent) &
+				       CRYPTO_TFM_REQ_MASK);
+	err = crypto_blkcipher_setkey(child, key, keylen);
+	crypto_tfm_set_flags(parent, crypto_blkcipher_get_flags(child) &
+				     CRYPTO_TFM_RES_MASK);
+	return err;
+}
+
+static int cts_cbc_encrypt(struct crypto_cts_ctx *ctx,
+			   struct blkcipher_desc *desc,
+			   struct scatterlist *dst,
+			   struct scatterlist *src,
+			   unsigned int offset,
+			   unsigned int nbytes)
+{
+	int bsize = crypto_blkcipher_blocksize(desc->tfm);
+	u8 tmp[bsize], tmp2[bsize];
+	struct blkcipher_desc lcldesc;
+	struct scatterlist sgsrc[1], sgdst[1];
+	int lastn = nbytes - bsize;
+	u8 iv[bsize];
+	u8 s[bsize * 2], d[bsize * 2];
+	int err;
+
+	if (lastn < 0)
+		return -EINVAL;
+
+	memset(s, 0, sizeof(s));
+	scatterwalk_map_and_copy(s, src, offset, nbytes, 0);
+
+	memcpy(iv, desc->info, bsize);
+
+	lcldesc.tfm = ctx->child;
+	lcldesc.info = iv;
+	lcldesc.flags = desc->flags;
+
+	sg_set_buf(&sgsrc[0], s, bsize);
+	sg_set_buf(&sgdst[0], tmp, bsize);
+	err = crypto_blkcipher_encrypt_iv(&lcldesc, sgdst, sgsrc, bsize);
+
+	memcpy(d + bsize, tmp, lastn);
+
+	lcldesc.info = tmp;
+
+	sg_set_buf(&sgsrc[0], s + bsize, bsize);
+	sg_set_buf(&sgdst[0], tmp2, bsize);
+	err = crypto_blkcipher_encrypt_iv(&lcldesc, sgdst, sgsrc, bsize);
+
+	memcpy(d, tmp2, bsize);
+
+	scatterwalk_map_and_copy(d, dst, offset, nbytes, 1);
+
+	memcpy(desc->info, tmp2, bsize);
+
+	return err;
+}
+
+static int crypto_cts_encrypt(struct blkcipher_desc *desc,
+			      struct scatterlist *dst, struct scatterlist *src,
+			      unsigned int nbytes)
+{
+	struct crypto_cts_ctx *ctx = crypto_blkcipher_ctx(desc->tfm);
+	int bsize = crypto_blkcipher_blocksize(desc->tfm);
+	int tot_blocks = (nbytes + bsize - 1) / bsize;
+	int cbc_blocks = tot_blocks > 2 ? tot_blocks - 2 : 0;
+	struct blkcipher_desc lcldesc;
+	int err;
+
+	lcldesc.tfm = ctx->child;
+	lcldesc.info = desc->info;
+	lcldesc.flags = desc->flags;
+
+	if (tot_blocks == 1) {
+		err = crypto_blkcipher_encrypt_iv(&lcldesc, dst, src, bsize);
+	} else if (nbytes <= bsize * 2) {
+		err = cts_cbc_encrypt(ctx, desc, dst, src, 0, nbytes);
+	} else {
+		/* do normal function for tot_blocks - 2 */
+		err = crypto_blkcipher_encrypt_iv(&lcldesc, dst, src,
+							cbc_blocks * bsize);
+		if (err == 0) {
+			/* do cts for final two blocks */
+			err = cts_cbc_encrypt(ctx, desc, dst, src,
+						cbc_blocks * bsize,
+						nbytes - (cbc_blocks * bsize));
+		}
+	}
+
+	return err;
+}
+
+static int cts_cbc_decrypt(struct crypto_cts_ctx *ctx,
+			   struct blkcipher_desc *desc,
+			   struct scatterlist *dst,
+			   struct scatterlist *src,
+			   unsigned int offset,
+			   unsigned int nbytes)
+{
+	int bsize = crypto_blkcipher_blocksize(desc->tfm);
+	u8 tmp[bsize];
+	struct blkcipher_desc lcldesc;
+	struct scatterlist sgsrc[1], sgdst[1];
+	int lastn = nbytes - bsize;
+	u8 iv[bsize];
+	u8 s[bsize * 2], d[bsize * 2];
+	int err;
+
+	if (lastn < 0)
+		return -EINVAL;
+
+	scatterwalk_map_and_copy(s, src, offset, nbytes, 0);
+
+	lcldesc.tfm = ctx->child;
+	lcldesc.info = iv;
+	lcldesc.flags = desc->flags;
+
+	/* 1. Decrypt Cn-1 (s) to create Dn (tmp)*/
+	memset(iv, 0, sizeof(iv));
+	sg_set_buf(&sgsrc[0], s, bsize);
+	sg_set_buf(&sgdst[0], tmp, bsize);
+	err = crypto_blkcipher_decrypt_iv(&lcldesc, sgdst, sgsrc, bsize);
+	if (err)
+		return err;
+	/* 2. Pad Cn with zeros at the end to create C of length BB */
+	memset(iv, 0, sizeof(iv));
+	memcpy(iv, s + bsize, lastn);
+	/* 3. Exclusive-or Dn (tmp) with C (iv) to create Xn (tmp) */
+	crypto_xor(tmp, iv, bsize);
+	/* 4. Select the first Ln bytes of Xn (tmp) to create Pn */
+	memcpy(d + bsize, tmp, lastn);
+
+	/* 5. Append the tail (BB - Ln) bytes of Xn (tmp) to Cn to create En */
+	memcpy(s + bsize + lastn, tmp + lastn, bsize - lastn);
+	/* 6. Decrypt En to create Pn-1 */
+	memset(iv, 0, sizeof(iv));
+	sg_set_buf(&sgsrc[0], s + bsize, bsize);
+	sg_set_buf(&sgdst[0], d, bsize);
+	err = crypto_blkcipher_decrypt_iv(&lcldesc, sgdst, sgsrc, bsize);
+
+	/* XXX xor with previous block ?? */
+	crypto_xor(d, desc->info, bsize);
+
+	scatterwalk_map_and_copy(d, dst, offset, nbytes, 1);
+
+	memcpy(desc->info, s, bsize);
+	return err;
+}
+
+static int crypto_cts_decrypt(struct blkcipher_desc *desc,
+			      struct scatterlist *dst, struct scatterlist *src,
+			      unsigned int nbytes)
+{
+	struct crypto_cts_ctx *ctx = crypto_blkcipher_ctx(desc->tfm);
+	int bsize = crypto_blkcipher_blocksize(desc->tfm);
+	int tot_blocks = (nbytes + bsize - 1) / bsize;
+	int cbc_blocks = tot_blocks > 2 ? tot_blocks - 2 : 0;
+	struct blkcipher_desc lcldesc;
+	int err;
+
+	lcldesc.tfm = ctx->child;
+	lcldesc.info = desc->info;
+	lcldesc.flags = desc->flags;
+
+	if (tot_blocks == 1) {
+		err = crypto_blkcipher_decrypt_iv(&lcldesc, dst, src, bsize);
+	} else if (nbytes <= bsize * 2) {
+		err = cts_cbc_decrypt(ctx, desc, dst, src, 0, nbytes);
+	} else {
+		/* do normal function for tot_blocks - 2 */
+		err = crypto_blkcipher_decrypt_iv(&lcldesc, dst, src,
+							cbc_blocks * bsize);
+		if (err == 0) {
+			/* do cts for final two blocks */
+			err = cts_cbc_decrypt(ctx, desc, dst, src,
+						cbc_blocks * bsize,
+						nbytes - (cbc_blocks * bsize));
+		}
+	}
+	return err;
+}
+
+static int crypto_cts_init_tfm(struct crypto_tfm *tfm)
+{
+	struct crypto_instance *inst = (void *)tfm->__crt_alg;
+	struct crypto_spawn *spawn = crypto_instance_ctx(inst);
+	struct crypto_cts_ctx *ctx = crypto_tfm_ctx(tfm);
+	struct crypto_blkcipher *cipher;
+
+	cipher = crypto_spawn_blkcipher(spawn);
+	if (IS_ERR(cipher))
+		return PTR_ERR(cipher);
+
+	ctx->child = cipher;
+	return 0;
+}
+
+static void crypto_cts_exit_tfm(struct crypto_tfm *tfm)
+{
+	struct crypto_cts_ctx *ctx = crypto_tfm_ctx(tfm);
+	crypto_free_blkcipher(ctx->child);
+}
+
+static struct crypto_instance *crypto_cts_alloc(struct rtattr **tb)
+{
+	struct crypto_instance *inst;
+	struct crypto_alg *alg;
+	int err;
+
+	err = crypto_check_attr_type(tb, CRYPTO_ALG_TYPE_BLKCIPHER);
+	if (err)
+		return ERR_PTR(err);
+
+	alg = crypto_attr_alg(tb[1], CRYPTO_ALG_TYPE_BLKCIPHER,
+				  CRYPTO_ALG_TYPE_MASK);
+	err = PTR_ERR(alg);
+	if (IS_ERR(alg))
+		return ERR_PTR(err);
+
+	inst = ERR_PTR(-EINVAL);
+	if (!is_power_of_2(alg->cra_blocksize))
+		goto out_put_alg;
+
+	inst = crypto_alloc_instance("cts", alg);
+	if (IS_ERR(inst))
+		goto out_put_alg;
+
+	inst->alg.cra_flags = CRYPTO_ALG_TYPE_BLKCIPHER;
+	inst->alg.cra_priority = alg->cra_priority;
+	inst->alg.cra_blocksize = alg->cra_blocksize;
+	inst->alg.cra_alignmask = alg->cra_alignmask;
+	inst->alg.cra_type = &crypto_blkcipher_type;
+
+	/* We access the data as u32s when xoring. */
+	inst->alg.cra_alignmask |= __alignof__(u32) - 1;
+
+	inst->alg.cra_blkcipher.ivsize = alg->cra_blocksize;
+	inst->alg.cra_blkcipher.min_keysize = alg->cra_blkcipher.min_keysize;
+	inst->alg.cra_blkcipher.max_keysize = alg->cra_blkcipher.max_keysize;
+
+	inst->alg.cra_blkcipher.geniv = "seqiv";
+
+	inst->alg.cra_ctxsize = sizeof(struct crypto_cts_ctx);
+
+	inst->alg.cra_init = crypto_cts_init_tfm;
+	inst->alg.cra_exit = crypto_cts_exit_tfm;
+
+	inst->alg.cra_blkcipher.setkey = crypto_cts_setkey;
+	inst->alg.cra_blkcipher.encrypt = crypto_cts_encrypt;
+	inst->alg.cra_blkcipher.decrypt = crypto_cts_decrypt;
+
+out_put_alg:
+	crypto_mod_put(alg);
+	return inst;
+}
+
+static void crypto_cts_free(struct crypto_instance *inst)
+{
+	crypto_drop_spawn(crypto_instance_ctx(inst));
+	kfree(inst);
+}
+
+static struct crypto_template crypto_cts_tmpl = {
+	.name = "cts",
+	.alloc = crypto_cts_alloc,
+	.free = crypto_cts_free,
+	.module = THIS_MODULE,
+};
+
+static int __init crypto_cts_module_init(void)
+{
+	return crypto_register_template(&crypto_cts_tmpl);
+}
+
+static void __exit crypto_cts_module_exit(void)
+{
+	crypto_unregister_template(&crypto_cts_tmpl);
+}
+
+module_init(crypto_cts_module_init);
+module_exit(crypto_cts_module_exit);
+
+MODULE_LICENSE("GPL");
+MODULE_DESCRIPTION("CTS-CBC) CipherText Stealing for CBC");
diff --git a/crypto/tcrypt.c b/crypto/tcrypt.c
index 1ab8c01..103d9e0 100644
--- a/crypto/tcrypt.c
+++ b/crypto/tcrypt.c
@@ -82,9 +82,8 @@ static char *check[] = {
 	"des", "md5", "des3_ede", "rot13", "sha1", "sha224", "sha256",
 	"blowfish", "twofish", "serpent", "sha384", "sha512", "md4", "aes",
 	"cast6", "arc4", "michael_mic", "deflate", "crc32c", "tea", "xtea",
-	"arc4", "michael_mic", "deflate", "crc32c", "tea", "xtea",
 	"khazad", "wp512", "wp384", "wp256", "tnepres", "xeta",  "fcrypt",
-	"camellia", "seed", "salsa20", "lzo", NULL
+	"camellia", "seed", "salsa20", "lzo", "cts", NULL
 };
 
 static void hexdump(unsigned char *buf, unsigned int len)
@@ -1301,6 +1300,12 @@ static void do_test(void)
 		test_cipher("ecb(seed)", DECRYPT, seed_dec_tv_template,
 			    SEED_DEC_TEST_VECTORS);
 
+		//CTS
+		test_cipher("cts(cbc(aes))", ENCRYPT, cts_mode_enc_tv_template,
+			    CTS_MODE_ENC_TEST_VECTORS);
+		test_cipher("cts(cbc(aes))", DECRYPT, cts_mode_dec_tv_template,
+			    CTS_MODE_DEC_TEST_VECTORS);
+
 		test_hash("sha384", sha384_tv_template, SHA384_TEST_VECTORS);
 		test_hash("sha512", sha512_tv_template, SHA512_TEST_VECTORS);
 		test_hash("wp512", wp512_tv_template, WP512_TEST_VECTORS);
@@ -1584,6 +1589,13 @@ static void do_test(void)
 			  AES_CCM_DEC_TEST_VECTORS);
 		break;
 
+	case 38:
+		test_cipher("cts(cbc(aes))", ENCRYPT, cts_mode_enc_tv_template,
+			    CTS_MODE_ENC_TEST_VECTORS);
+		test_cipher("cts(cbc(aes))", DECRYPT, cts_mode_dec_tv_template,
+			    CTS_MODE_DEC_TEST_VECTORS);
+		break;
+
 	case 100:
 		test_hash("hmac(md5)", hmac_md5_tv_template,
 			  HMAC_MD5_TEST_VECTORS);
diff --git a/crypto/tcrypt.h b/crypto/tcrypt.h
index f785e56..548716b 100644
--- a/crypto/tcrypt.h
+++ b/crypto/tcrypt.h
@@ -7631,6 +7631,215 @@ static struct cipher_testvec salsa20_stream_enc_tv_template[] = {
 };
 
 /*
+ * CTS (Cipher Text Stealing) mode tests
+ */
+#define CTS_MODE_ENC_TEST_VECTORS 6
+#define CTS_MODE_DEC_TEST_VECTORS 6
+static struct cipher_testvec cts_mode_enc_tv_template[] = {
+	{ /* from rfc3962 */
+		.klen	= 16,
+		.key    = { 0x63, 0x68, 0x69, 0x63, 0x6b, 0x65, 0x6e, 0x20,
+			    0x74, 0x65, 0x72, 0x69, 0x79, 0x61, 0x6b, 0x69 },
+		.ilen	= 17,
+		.input  = { 0x49, 0x20, 0x77, 0x6f, 0x75, 0x6c, 0x64, 0x20,
+			    0x6c, 0x69, 0x6b, 0x65, 0x20, 0x74, 0x68, 0x65,
+			    0x20 },
+		.rlen	= 17,
+		.result	= { 0xc6, 0x35, 0x35, 0x68, 0xf2, 0xbf, 0x8c, 0xb4,
+			    0xd8, 0xa5, 0x80, 0x36, 0x2d, 0xa7, 0xff, 0x7f,
+			    0x97 },
+	}, {
+		.klen	= 16,
+		.key    = { 0x63, 0x68, 0x69, 0x63, 0x6b, 0x65, 0x6e, 0x20,
+			    0x74, 0x65, 0x72, 0x69, 0x79, 0x61, 0x6b, 0x69 },
+		.ilen   = 31,
+		.input  = { 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 },
+		.rlen   = 31,
+		.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 },
+	}, {
+		.klen	= 16,
+		.key    = { 0x63, 0x68, 0x69, 0x63, 0x6b, 0x65, 0x6e, 0x20,
+			    0x74, 0x65, 0x72, 0x69, 0x79, 0x61, 0x6b, 0x69 },
+		.ilen   = 32,
+		.input  = { 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 },
+		.rlen   = 32,
+		.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 },
+	}, {
+		.klen	= 16,
+		.key    = { 0x63, 0x68, 0x69, 0x63, 0x6b, 0x65, 0x6e, 0x20,
+			    0x74, 0x65, 0x72, 0x69, 0x79, 0x61, 0x6b, 0x69 },
+		.ilen   = 47,
+		.input  = { 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 },
+		.rlen   = 47,
+		.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 },
+	}, {
+		.klen	= 16,
+		.key    = { 0x63, 0x68, 0x69, 0x63, 0x6b, 0x65, 0x6e, 0x20,
+			    0x74, 0x65, 0x72, 0x69, 0x79, 0x61, 0x6b, 0x69 },
+		.ilen   = 48,
+		.input  = { 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 },
+		.rlen   = 48,
+		.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 },
+	}, {
+		.klen	= 16,
+		.key    = { 0x63, 0x68, 0x69, 0x63, 0x6b, 0x65, 0x6e, 0x20,
+			    0x74, 0x65, 0x72, 0x69, 0x79, 0x61, 0x6b, 0x69 },
+		.ilen   = 64,
+		.input  = { 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 },
+		.rlen   = 64,
+		.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 },
+	}
+};
+
+static struct cipher_testvec cts_mode_dec_tv_template[] = {
+	{ /* from rfc3962 */
+		.klen	= 16,
+		.key    = { 0x63, 0x68, 0x69, 0x63, 0x6b, 0x65, 0x6e, 0x20,
+			    0x74, 0x65, 0x72, 0x69, 0x79, 0x61, 0x6b, 0x69 },
+		.rlen	= 17,
+		.result = { 0x49, 0x20, 0x77, 0x6f, 0x75, 0x6c, 0x64, 0x20,
+			    0x6c, 0x69, 0x6b, 0x65, 0x20, 0x74, 0x68, 0x65,
+			    0x20 },
+		.ilen	= 17,
+		.input	= { 0xc6, 0x35, 0x35, 0x68, 0xf2, 0xbf, 0x8c, 0xb4,
+			    0xd8, 0xa5, 0x80, 0x36, 0x2d, 0xa7, 0xff, 0x7f,
+			    0x97 },
+	}, {
+		.klen	= 16,
+		.key    = { 0x63, 0x68, 0x69, 0x63, 0x6b, 0x65, 0x6e, 0x20,
+			    0x74, 0x65, 0x72, 0x69, 0x79, 0x61, 0x6b, 0x69 },
+		.rlen   = 31,
+		.result = { 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 },
+		.ilen   = 31,
+		.input  = { 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 },
+	}, {
+		.klen	= 16,
+		.key    = { 0x63, 0x68, 0x69, 0x63, 0x6b, 0x65, 0x6e, 0x20,
+			    0x74, 0x65, 0x72, 0x69, 0x79, 0x61, 0x6b, 0x69 },
+		.rlen   = 32,
+		.result = { 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 },
+		.ilen   = 32,
+		.input  = { 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 },
+	}, {
+		.klen	= 16,
+		.key    = { 0x63, 0x68, 0x69, 0x63, 0x6b, 0x65, 0x6e, 0x20,
+			    0x74, 0x65, 0x72, 0x69, 0x79, 0x61, 0x6b, 0x69 },
+		.rlen   = 47,
+		.result = { 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 },
+		.ilen   = 47,
+		.input  = { 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 },
+	}, {
+		.klen	= 16,
+		.key    = { 0x63, 0x68, 0x69, 0x63, 0x6b, 0x65, 0x6e, 0x20,
+			    0x74, 0x65, 0x72, 0x69, 0x79, 0x61, 0x6b, 0x69 },
+		.rlen   = 48,
+		.result = { 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 },
+		.ilen   = 48,
+		.input  = { 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 },
+	}, {
+		.klen	= 16,
+		.key    = { 0x63, 0x68, 0x69, 0x63, 0x6b, 0x65, 0x6e, 0x20,
+			    0x74, 0x65, 0x72, 0x69, 0x79, 0x61, 0x6b, 0x69 },
+		.rlen   = 64,
+		.result = { 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 },
+		.ilen   = 64,
+		.input  = { 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 },
+	}
+};
+
+/*
  * Compression stuff.
  */
 #define COMP_BUF_SIZE           512


^ permalink raw reply related	[flat|nested] 31+ messages in thread

* [PATCH 02/19] rpc: gss: Add oid values to the gss_api mechanism structures
       [not found] ` <20080221184208.19195.94518.stgit-zTNJhAanYLVZN1qrTdtDg5Vzexx5G7lz@public.gmane.org>
  2008-02-21 18:43   ` [PATCH 01/19] crypto: Add CTS mode required for Kerberos AES support Kevin Coffman
@ 2008-02-21 18:43   ` Kevin Coffman
  2008-02-21 18:44   ` [PATCH 03/19] sunrpc: make token header values less confusing Kevin Coffman
                     ` (16 subsequent siblings)
  18 siblings, 0 replies; 31+ messages in thread
From: Kevin Coffman @ 2008-02-21 18:43 UTC (permalink / raw)
  To: linux-nfs

From: Usha Ketineni <uketinen@us.ibm.com>

On NFSV4 server side, these are required as part of the security
triple(oid,qop,service) information being sent in the response of the
SECINFO operation.

Signed-off-by: Usha Ketineni <uketinen@us.ibm.com>
Signed-off-by: J. Bruce Fields <bfields@citi.umich.edu>
---

 fs/nfsd/nfs4xdr.c                    |    6 +++---
 include/linux/sunrpc/gss_api.h       |    2 +-
 include/linux/sunrpc/gss_krb5.h      |    2 ++
 net/sunrpc/auth_gss/gss_krb5_mech.c  |    4 +++-
 net/sunrpc/auth_gss/gss_spkm3_mech.c |    4 +++-
 5 files changed, 12 insertions(+), 6 deletions(-)

diff --git a/fs/nfsd/nfs4xdr.c b/fs/nfsd/nfs4xdr.c
index b0592e7..d6b43eb 100644
--- a/fs/nfsd/nfs4xdr.c
+++ b/fs/nfsd/nfs4xdr.c
@@ -2519,9 +2519,9 @@ nfsd4_encode_secinfo(struct nfsd4_compoundres *resp, __be32 nfserr,
 			RESERVE_SPACE(4);
 			WRITE32(RPC_AUTH_GSS);
 			ADJUST_ARGS();
-			RESERVE_SPACE(4 + gm->gm_oid.len);
-			WRITE32(gm->gm_oid.len);
-			WRITEMEM(gm->gm_oid.data, gm->gm_oid.len);
+			RESERVE_SPACE(4 + gm->gm_oid->len);
+			WRITE32(gm->gm_oid->len);
+			WRITEMEM(gm->gm_oid->data, gm->gm_oid->len);
 			ADJUST_ARGS();
 			RESERVE_SPACE(4);
 			WRITE32(0); /* qop */
diff --git a/include/linux/sunrpc/gss_api.h b/include/linux/sunrpc/gss_api.h
index 459c5fc..ed0b80c 100644
--- a/include/linux/sunrpc/gss_api.h
+++ b/include/linux/sunrpc/gss_api.h
@@ -76,7 +76,7 @@ struct pf_desc {
 struct gss_api_mech {
 	struct list_head	gm_list;
 	struct module		*gm_owner;
-	struct xdr_netobj	gm_oid;
+	struct xdr_netobj	*gm_oid;
 	char			*gm_name;
 	const struct gss_api_ops *gm_ops;
 	/* pseudoflavors supported by this mechanism: */
diff --git a/include/linux/sunrpc/gss_krb5.h b/include/linux/sunrpc/gss_krb5.h
index 5a4b1e0..8c38aba 100644
--- a/include/linux/sunrpc/gss_krb5.h
+++ b/include/linux/sunrpc/gss_krb5.h
@@ -70,6 +70,8 @@ enum seal_alg {
 	SEAL_ALG_DES3KD = 0x0002
 };
 
+extern struct xdr_netobj krb5_oid;
+
 #define KRB5_CKSUM_LENGTH 8
 
 #define CKSUMTYPE_CRC32			0x0001
diff --git a/net/sunrpc/auth_gss/gss_krb5_mech.c b/net/sunrpc/auth_gss/gss_krb5_mech.c
index 60c3dba..3c070d0 100644
--- a/net/sunrpc/auth_gss/gss_krb5_mech.c
+++ b/net/sunrpc/auth_gss/gss_krb5_mech.c
@@ -232,10 +232,12 @@ static struct pf_desc gss_kerberos_pfs[] = {
 	},
 };
 
+struct xdr_netobj krb5_oid = {9, "\x2a\x86\x48\x86\xf7\x12\x01\x02\x02"};
+
 static struct gss_api_mech gss_kerberos_mech = {
 	.gm_name	= "krb5",
 	.gm_owner	= THIS_MODULE,
-	.gm_oid		= {9, (void *)"\x2a\x86\x48\x86\xf7\x12\x01\x02\x02"},
+	.gm_oid		= &krb5_oid,
 	.gm_ops		= &gss_kerberos_ops,
 	.gm_pf_num	= ARRAY_SIZE(gss_kerberos_pfs),
 	.gm_pfs		= gss_kerberos_pfs,
diff --git a/net/sunrpc/auth_gss/gss_spkm3_mech.c b/net/sunrpc/auth_gss/gss_spkm3_mech.c
index 5deb4b6..210b23b 100644
--- a/net/sunrpc/auth_gss/gss_spkm3_mech.c
+++ b/net/sunrpc/auth_gss/gss_spkm3_mech.c
@@ -214,10 +214,12 @@ static struct pf_desc gss_spkm3_pfs[] = {
 	{RPC_AUTH_GSS_SPKMI, RPC_GSS_SVC_INTEGRITY, "spkm3i"},
 };
 
+struct xdr_netobj spkm3_oid = {7, "\053\006\001\005\005\001\003"};
+
 static struct gss_api_mech gss_spkm3_mech = {
 	.gm_name	= "spkm3",
 	.gm_owner	= THIS_MODULE,
-	.gm_oid		= {7, "\053\006\001\005\005\001\003"},
+	.gm_oid		= &spkm3_oid,
 	.gm_ops		= &gss_spkm3_ops,
 	.gm_pf_num	= ARRAY_SIZE(gss_spkm3_pfs),
 	.gm_pfs		= gss_spkm3_pfs,


^ permalink raw reply related	[flat|nested] 31+ messages in thread

* [PATCH 03/19] sunrpc: make token header values less confusing
       [not found] ` <20080221184208.19195.94518.stgit-zTNJhAanYLVZN1qrTdtDg5Vzexx5G7lz@public.gmane.org>
  2008-02-21 18:43   ` [PATCH 01/19] crypto: Add CTS mode required for Kerberos AES support Kevin Coffman
  2008-02-21 18:43   ` [PATCH 02/19] rpc: gss: Add oid values to the gss_api mechanism structures Kevin Coffman
@ 2008-02-21 18:44   ` Kevin Coffman
       [not found]     ` <20080221184402.19195.57873.stgit-zTNJhAanYLVZN1qrTdtDg5Vzexx5G7lz@public.gmane.org>
  2008-02-21 18:44   ` [PATCH 04/19] Add new pipefs file indicating which Kerberos enctypes the kernel supports Kevin Coffman
                     ` (15 subsequent siblings)
  18 siblings, 1 reply; 31+ messages in thread
From: Kevin Coffman @ 2008-02-21 18:44 UTC (permalink / raw)
  To: linux-nfs

g_make_token_header() and g_token_size() add two too many, and
therefore their callers pass in "(logical_value - 2)" rather
than "logical_value" as hard-coded values which causes confusion.

This dates back to the original g_make_token_header which took an
optional token type (token_id) value and added it to the token.
This was removed, but the routine always adds room for the token_id
rather than not.

Signed-off-by: Kevin Coffman <kwc@citi.umich.edu>
---

 net/sunrpc/auth_gss/gss_generic_token.c |    4 ++--
 net/sunrpc/auth_gss/gss_krb5_seal.c     |    4 ++--
 net/sunrpc/auth_gss/gss_krb5_wrap.c     |    4 ++--
 net/sunrpc/auth_gss/gss_spkm3_seal.c    |    2 +-
 4 files changed, 7 insertions(+), 7 deletions(-)

diff --git a/net/sunrpc/auth_gss/gss_generic_token.c b/net/sunrpc/auth_gss/gss_generic_token.c
index ea8c92e..d83b881 100644
--- a/net/sunrpc/auth_gss/gss_generic_token.c
+++ b/net/sunrpc/auth_gss/gss_generic_token.c
@@ -148,7 +148,7 @@ int
 g_token_size(struct xdr_netobj *mech, unsigned int body_size)
 {
 	/* set body_size to sequence contents size */
-	body_size += 4 + (int) mech->len;         /* NEED overflow check */
+	body_size += 2 + (int) mech->len;         /* NEED overflow check */
 	return(1 + der_length_size(body_size) + body_size);
 }
 
@@ -161,7 +161,7 @@ void
 g_make_token_header(struct xdr_netobj *mech, int body_size, unsigned char **buf)
 {
 	*(*buf)++ = 0x60;
-	der_write_length(buf, 4 + mech->len + body_size);
+	der_write_length(buf, 2 + mech->len + body_size);
 	*(*buf)++ = 0x06;
 	*(*buf)++ = (unsigned char) mech->len;
 	TWRITE_STR(*buf, mech->data, ((int) mech->len));
diff --git a/net/sunrpc/auth_gss/gss_krb5_seal.c b/net/sunrpc/auth_gss/gss_krb5_seal.c
index dedcbd6..b2fa785 100644
--- a/net/sunrpc/auth_gss/gss_krb5_seal.c
+++ b/net/sunrpc/auth_gss/gss_krb5_seal.c
@@ -87,10 +87,10 @@ gss_get_mic_kerberos(struct gss_ctx *gss_ctx, struct xdr_buf *text,
 
 	now = get_seconds();
 
-	token->len = g_token_size(&ctx->mech_used, 22);
+	token->len = g_token_size(&ctx->mech_used, 24);
 
 	ptr = token->data;
-	g_make_token_header(&ctx->mech_used, 22, &ptr);
+	g_make_token_header(&ctx->mech_used, 24, &ptr);
 
 	*ptr++ = (unsigned char) ((KG_TOK_MIC_MSG>>8)&0xff);
 	*ptr++ = (unsigned char) (KG_TOK_MIC_MSG&0xff);
diff --git a/net/sunrpc/auth_gss/gss_krb5_wrap.c b/net/sunrpc/auth_gss/gss_krb5_wrap.c
index 3bdc527..a2c92f1 100644
--- a/net/sunrpc/auth_gss/gss_krb5_wrap.c
+++ b/net/sunrpc/auth_gss/gss_krb5_wrap.c
@@ -137,7 +137,7 @@ gss_wrap_kerberos(struct gss_ctx *ctx, int offset,
 	BUG_ON((buf->len - offset) % blocksize);
 	plainlen = blocksize + buf->len - offset;
 
-	headlen = g_token_size(&kctx->mech_used, 22 + plainlen) -
+	headlen = g_token_size(&kctx->mech_used, 24 + plainlen) -
 						(buf->len - offset);
 
 	ptr = buf->head[0].iov_base + offset;
@@ -149,7 +149,7 @@ gss_wrap_kerberos(struct gss_ctx *ctx, int offset,
 	buf->len += headlen;
 	BUG_ON((buf->len - offset - headlen) % blocksize);
 
-	g_make_token_header(&kctx->mech_used, 22 + plainlen, &ptr);
+	g_make_token_header(&kctx->mech_used, 24 + plainlen, &ptr);
 
 
 	*ptr++ = (unsigned char) ((KG_TOK_WRAP_MSG>>8)&0xff);
diff --git a/net/sunrpc/auth_gss/gss_spkm3_seal.c b/net/sunrpc/auth_gss/gss_spkm3_seal.c
index abf17ce..88505d5 100644
--- a/net/sunrpc/auth_gss/gss_spkm3_seal.c
+++ b/net/sunrpc/auth_gss/gss_spkm3_seal.c
@@ -104,7 +104,7 @@ spkm3_make_token(struct spkm3_ctx *ctx,
 			goto out_err;
 
 		asn1_bitstring_len(&md5cksum, &md5elen, &md5zbit);
-		tokenlen = 10 + ctxelen + 1 + md5elen + 1;
+		tokenlen = 12 + ctxelen + 1 + md5elen + 1;
 
 		/* Create token header using generic routines */
 		token->len = g_token_size(&ctx->mech_used, tokenlen);


^ permalink raw reply related	[flat|nested] 31+ messages in thread

* [PATCH 04/19] Add new pipefs file indicating which Kerberos enctypes the kernel supports
       [not found] ` <20080221184208.19195.94518.stgit-zTNJhAanYLVZN1qrTdtDg5Vzexx5G7lz@public.gmane.org>
                     ` (2 preceding siblings ...)
  2008-02-21 18:44   ` [PATCH 03/19] sunrpc: make token header values less confusing Kevin Coffman
@ 2008-02-21 18:44   ` Kevin Coffman
       [not found]     ` <20080221184407.19195.62074.stgit-zTNJhAanYLVZN1qrTdtDg5Vzexx5G7lz@public.gmane.org>
  2008-02-21 18:44   ` [PATCH 05/19] Correct grammer/typos in dprintks Kevin Coffman
                     ` (14 subsequent siblings)
  18 siblings, 1 reply; 31+ messages in thread
From: Kevin Coffman @ 2008-02-21 18:44 UTC (permalink / raw)
  To: linux-nfs

New file, krb5_info, indicates which Kerberos encryption types are
supported by the kernel rpcsecgss code.  This is used by gssd to
determine which encryption types it should attempt to negotiate
when creating a context with a server.

The server principal's database and keytab encryption types are
what limits what it should negotiate.  Therefore, its keytab
should be created with only the enctypes listed by this file.

From: J. Bruce Fields <bfields@citi.umich.edu>
Signed-off-by: Kevin Coffman <kwc@citi.umich.edu>
---

 net/sunrpc/rpc_pipe.c |   31 +++++++++++++++++++++++++++++++
 1 files changed, 31 insertions(+), 0 deletions(-)

diff --git a/net/sunrpc/rpc_pipe.c b/net/sunrpc/rpc_pipe.c
index 7e19716..5781862 100644
--- a/net/sunrpc/rpc_pipe.c
+++ b/net/sunrpc/rpc_pipe.c
@@ -385,6 +385,31 @@ static const struct file_operations rpc_info_operations = {
 	.release	= rpc_info_release,
 };
 
+/*
+ * This really belongs in the gss_krb5 code,
+ * but the info file logically belongs here
+ */
+static int
+rpc_show_krb5_info(struct seq_file *m, void *v)
+{
+	seq_printf(m, "enctypes: 3,1,2\n");
+	return 0;
+}
+
+static int
+rpc_krb5_info_open(struct inode *inode, struct file *file)
+{
+	return single_open(file, rpc_show_krb5_info, NULL);
+}
+
+static struct file_operations krb5_info_operations = {
+	.owner		= THIS_MODULE,
+	.open		= rpc_krb5_info_open,
+	.read		= seq_read,
+	.llseek		= seq_lseek,
+	.release	= single_release,
+};
+
 
 /*
  * We have a single directory with 1 node in it.
@@ -396,6 +421,7 @@ enum {
 	RPCAUTH_nfs,
 	RPCAUTH_portmap,
 	RPCAUTH_statd,
+	RPCAUTH_krb5_info,
 	RPCAUTH_RootEOF
 };
 
@@ -429,6 +455,11 @@ static struct rpc_filelist files[] = {
 		.name = "statd",
 		.mode = S_IFDIR | S_IRUGO | S_IXUGO,
 	},
+	[RPCAUTH_krb5_info] = {
+		.name = "krb5_info",
+		.i_fop = &krb5_info_operations,
+		.mode = S_IFREG | S_IRUSR,
+	},
 };
 
 enum {


^ permalink raw reply related	[flat|nested] 31+ messages in thread

* [PATCH 05/19] Correct grammer/typos in dprintks
       [not found] ` <20080221184208.19195.94518.stgit-zTNJhAanYLVZN1qrTdtDg5Vzexx5G7lz@public.gmane.org>
                     ` (3 preceding siblings ...)
  2008-02-21 18:44   ` [PATCH 04/19] Add new pipefs file indicating which Kerberos enctypes the kernel supports Kevin Coffman
@ 2008-02-21 18:44   ` Kevin Coffman
       [not found]     ` <20080221184412.19195.93743.stgit-zTNJhAanYLVZN1qrTdtDg5Vzexx5G7lz@public.gmane.org>
  2008-02-21 18:44   ` [PATCH 06/19] Use get_random_bytes() to create confounder Kevin Coffman
                     ` (13 subsequent siblings)
  18 siblings, 1 reply; 31+ messages in thread
From: Kevin Coffman @ 2008-02-21 18:44 UTC (permalink / raw)
  To: linux-nfs

cleanup:  Fix grammer/typos to use "too" instead of "to"

Signed-off-by: Kevin Coffman <kwc@citi.umich.edu>
---

 net/sunrpc/auth_gss/gss_krb5_crypto.c |    6 +++---
 1 files changed, 3 insertions(+), 3 deletions(-)

diff --git a/net/sunrpc/auth_gss/gss_krb5_crypto.c b/net/sunrpc/auth_gss/gss_krb5_crypto.c
index 0dd7923..1d52308 100644
--- a/net/sunrpc/auth_gss/gss_krb5_crypto.c
+++ b/net/sunrpc/auth_gss/gss_krb5_crypto.c
@@ -66,8 +66,8 @@ krb5_encrypt(
 		goto out;
 
 	if (crypto_blkcipher_ivsize(tfm) > 16) {
-		dprintk("RPC:       gss_k5encrypt: tfm iv size to large %d\n",
-			 crypto_blkcipher_ivsize(tfm));
+		dprintk("RPC:       gss_k5encrypt: tfm iv size too large %d\n",
+			crypto_blkcipher_ivsize(tfm));
 		goto out;
 	}
 
@@ -102,7 +102,7 @@ krb5_decrypt(
 		goto out;
 
 	if (crypto_blkcipher_ivsize(tfm) > 16) {
-		dprintk("RPC:       gss_k5decrypt: tfm iv size to large %d\n",
+		dprintk("RPC:       gss_k5decrypt: tfm iv size too large %d\n",
 			crypto_blkcipher_ivsize(tfm));
 		goto out;
 	}


^ permalink raw reply related	[flat|nested] 31+ messages in thread

* [PATCH 06/19] Use get_random_bytes() to create confounder
       [not found] ` <20080221184208.19195.94518.stgit-zTNJhAanYLVZN1qrTdtDg5Vzexx5G7lz@public.gmane.org>
                     ` (4 preceding siblings ...)
  2008-02-21 18:44   ` [PATCH 05/19] Correct grammer/typos in dprintks Kevin Coffman
@ 2008-02-21 18:44   ` Kevin Coffman
       [not found]     ` <20080221184417.19195.55123.stgit-zTNJhAanYLVZN1qrTdtDg5Vzexx5G7lz@public.gmane.org>
  2008-02-21 18:44   ` [PATCH 07/19] Don't expect blocksize to always be 8 when calculating padding Kevin Coffman
                     ` (12 subsequent siblings)
  18 siblings, 1 reply; 31+ messages in thread
From: Kevin Coffman @ 2008-02-21 18:44 UTC (permalink / raw)
  To: linux-nfs

Instead of using an incementing value for the confounder, use
get_random_bytes() which gives us the desired unpredictable value.

Signed-off-by: Kevin Coffman <kwc@citi.umich.edu>
---

 net/sunrpc/auth_gss/gss_krb5_wrap.c |   15 +--------------
 1 files changed, 1 insertions(+), 14 deletions(-)

diff --git a/net/sunrpc/auth_gss/gss_krb5_wrap.c b/net/sunrpc/auth_gss/gss_krb5_wrap.c
index a2c92f1..7a0002f 100644
--- a/net/sunrpc/auth_gss/gss_krb5_wrap.c
+++ b/net/sunrpc/auth_gss/gss_krb5_wrap.c
@@ -90,20 +90,7 @@ out:
 static inline void
 make_confounder(char *p, int blocksize)
 {
-	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. */
-
-	BUG_ON(blocksize != 8);
-	*q = i++;
+	get_random_bytes(p, blocksize);
 }
 
 /* Assumptions: the head and tail of inbuf are ours to play with.


^ permalink raw reply related	[flat|nested] 31+ messages in thread

* [PATCH 07/19] Don't expect blocksize to always be 8 when calculating padding
       [not found] ` <20080221184208.19195.94518.stgit-zTNJhAanYLVZN1qrTdtDg5Vzexx5G7lz@public.gmane.org>
                     ` (5 preceding siblings ...)
  2008-02-21 18:44   ` [PATCH 06/19] Use get_random_bytes() to create confounder Kevin Coffman
@ 2008-02-21 18:44   ` Kevin Coffman
  2008-02-21 18:44   ` [PATCH 08/19] Remove define for KRB5_CKSUM_LENGTH, which will become enctype-dependent Kevin Coffman
                     ` (11 subsequent siblings)
  18 siblings, 0 replies; 31+ messages in thread
From: Kevin Coffman @ 2008-02-21 18:44 UTC (permalink / raw)
  To: linux-nfs

Allow blocksizes other than 8 when calculating padding

Signed-off-by: Kevin Coffman <kwc@citi.umich.edu>
---

 net/sunrpc/auth_gss/gss_krb5_wrap.c |    5 +----
 1 files changed, 1 insertions(+), 4 deletions(-)

diff --git a/net/sunrpc/auth_gss/gss_krb5_wrap.c b/net/sunrpc/auth_gss/gss_krb5_wrap.c
index 7a0002f..384f470 100644
--- a/net/sunrpc/auth_gss/gss_krb5_wrap.c
+++ b/net/sunrpc/auth_gss/gss_krb5_wrap.c
@@ -13,10 +13,7 @@
 static inline int
 gss_krb5_padding(int blocksize, int length)
 {
-	/* Most of the code is block-size independent but currently we
-	 * use only 8: */
-	BUG_ON(blocksize != 8);
-	return 8 - (length & 7);
+	return blocksize - (length & (blocksize - 1));
 }
 
 static inline void


^ permalink raw reply related	[flat|nested] 31+ messages in thread

* [PATCH 08/19] Remove define for KRB5_CKSUM_LENGTH, which will become enctype-dependent
       [not found] ` <20080221184208.19195.94518.stgit-zTNJhAanYLVZN1qrTdtDg5Vzexx5G7lz@public.gmane.org>
                     ` (6 preceding siblings ...)
  2008-02-21 18:44   ` [PATCH 07/19] Don't expect blocksize to always be 8 when calculating padding Kevin Coffman
@ 2008-02-21 18:44   ` Kevin Coffman
       [not found]     ` <20080221184427.19195.16243.stgit-zTNJhAanYLVZN1qrTdtDg5Vzexx5G7lz@public.gmane.org>
  2008-02-21 18:44   ` [PATCH 09/19] gss_krb5: split up functions in preparation of adding new enctypes Kevin Coffman
                     ` (10 subsequent siblings)
  18 siblings, 1 reply; 31+ messages in thread
From: Kevin Coffman @ 2008-02-21 18:44 UTC (permalink / raw)
  To: linux-nfs

cleanup: When adding new encryption types, the checksum length
can be different for each enctype.  Face the fact that the
current code only supports DES which has a checksum length of 8.

Signed-off-by: Kevin Coffman <kwc@citi.umich.edu>
---

 include/linux/sunrpc/gss_krb5.h     |    2 --
 net/sunrpc/auth_gss/gss_krb5_seal.c |    3 +--
 net/sunrpc/auth_gss/gss_krb5_wrap.c |    4 +---
 3 files changed, 2 insertions(+), 7 deletions(-)

diff --git a/include/linux/sunrpc/gss_krb5.h b/include/linux/sunrpc/gss_krb5.h
index 8c38aba..47d2110 100644
--- a/include/linux/sunrpc/gss_krb5.h
+++ b/include/linux/sunrpc/gss_krb5.h
@@ -72,8 +72,6 @@ enum seal_alg {
 
 extern struct xdr_netobj krb5_oid;
 
-#define KRB5_CKSUM_LENGTH 8
-
 #define CKSUMTYPE_CRC32			0x0001
 #define CKSUMTYPE_RSA_MD4		0x0002
 #define CKSUMTYPE_RSA_MD4_DES		0x0003
diff --git a/net/sunrpc/auth_gss/gss_krb5_seal.c b/net/sunrpc/auth_gss/gss_krb5_seal.c
index b2fa785..e7b2a52 100644
--- a/net/sunrpc/auth_gss/gss_krb5_seal.c
+++ b/net/sunrpc/auth_gss/gss_krb5_seal.c
@@ -109,8 +109,7 @@ gss_get_mic_kerberos(struct gss_ctx *gss_ctx, struct xdr_buf *text,
 			  md5cksum.data, md5cksum.len))
 		return GSS_S_FAILURE;
 
-	memcpy(krb5_hdr + 16, md5cksum.data + md5cksum.len - KRB5_CKSUM_LENGTH,
-	       KRB5_CKSUM_LENGTH);
+	memcpy(krb5_hdr + 16, md5cksum.data + md5cksum.len - 8, 8);
 
 	spin_lock(&krb5_seq_lock);
 	seq_send = ctx->seq_send++;
diff --git a/net/sunrpc/auth_gss/gss_krb5_wrap.c b/net/sunrpc/auth_gss/gss_krb5_wrap.c
index 384f470..9763bf1 100644
--- a/net/sunrpc/auth_gss/gss_krb5_wrap.c
+++ b/net/sunrpc/auth_gss/gss_krb5_wrap.c
@@ -160,9 +160,7 @@ gss_wrap_kerberos(struct gss_ctx *ctx, int offset,
 	if (krb5_encrypt(kctx->seq, NULL, md5cksum.data,
 			  md5cksum.data, md5cksum.len))
 		return GSS_S_FAILURE;
-	memcpy(krb5_hdr + 16,
-	       md5cksum.data + md5cksum.len - KRB5_CKSUM_LENGTH,
-	       KRB5_CKSUM_LENGTH);
+	memcpy(krb5_hdr + 16, md5cksum.data + md5cksum.len - 8, 8);
 
 	spin_lock(&krb5_seq_lock);
 	seq_send = kctx->seq_send++;


^ permalink raw reply related	[flat|nested] 31+ messages in thread

* [PATCH 09/19] gss_krb5: split up functions in preparation of adding new enctypes
       [not found] ` <20080221184208.19195.94518.stgit-zTNJhAanYLVZN1qrTdtDg5Vzexx5G7lz@public.gmane.org>
                     ` (7 preceding siblings ...)
  2008-02-21 18:44   ` [PATCH 08/19] Remove define for KRB5_CKSUM_LENGTH, which will become enctype-dependent Kevin Coffman
@ 2008-02-21 18:44   ` Kevin Coffman
  2008-02-21 18:44   ` [PATCH 10/19] gss_krb5: prepare for new context format Kevin Coffman
                     ` (9 subsequent siblings)
  18 siblings, 0 replies; 31+ messages in thread
From: Kevin Coffman @ 2008-02-21 18:44 UTC (permalink / raw)
  To: linux-nfs

Add encryption type to the krb5 context structure and use it to switch
to the correct functions depending on the encryption type.

Signed-off-by: Kevin Coffman <kwc@citi.umich.edu>
---

 include/linux/sunrpc/gss_krb5.h       |    1 +
 net/sunrpc/auth_gss/gss_krb5_mech.c   |    1 +
 net/sunrpc/auth_gss/gss_krb5_seal.c   |   21 ++++++++++++++--
 net/sunrpc/auth_gss/gss_krb5_unseal.c |   22 ++++++++++++++---
 net/sunrpc/auth_gss/gss_krb5_wrap.c   |   44 +++++++++++++++++++++++++++++----
 5 files changed, 77 insertions(+), 12 deletions(-)

diff --git a/include/linux/sunrpc/gss_krb5.h b/include/linux/sunrpc/gss_krb5.h
index 47d2110..dfe382a 100644
--- a/include/linux/sunrpc/gss_krb5.h
+++ b/include/linux/sunrpc/gss_krb5.h
@@ -42,6 +42,7 @@
 
 struct krb5_ctx {
 	int			initiate; /* 1 = initiating, 0 = accepting */
+	u32			enctype;
 	struct crypto_blkcipher	*enc;
 	struct crypto_blkcipher	*seq;
 	s32			endtime;
diff --git a/net/sunrpc/auth_gss/gss_krb5_mech.c b/net/sunrpc/auth_gss/gss_krb5_mech.c
index 3c070d0..477cf07 100644
--- a/net/sunrpc/auth_gss/gss_krb5_mech.c
+++ b/net/sunrpc/auth_gss/gss_krb5_mech.c
@@ -137,6 +137,7 @@ gss_import_sec_context_kerberos(const void *p,
 	p = simple_get_bytes(p, end, &ctx->initiate, sizeof(ctx->initiate));
 	if (IS_ERR(p))
 		goto out_err_free_ctx;
+	ctx->enctype = ENCTYPE_DES_CBC_RAW;
 	/* The downcall format was designed before we completely understood
 	 * the uses of the context fields; so it includes some stuff we
 	 * just give some minimal sanity-checking, and some we ignore
diff --git a/net/sunrpc/auth_gss/gss_krb5_seal.c b/net/sunrpc/auth_gss/gss_krb5_seal.c
index e7b2a52..3b9cc47 100644
--- a/net/sunrpc/auth_gss/gss_krb5_seal.c
+++ b/net/sunrpc/auth_gss/gss_krb5_seal.c
@@ -71,11 +71,10 @@
 
 DEFINE_SPINLOCK(krb5_seq_lock);
 
-u32
-gss_get_mic_kerberos(struct gss_ctx *gss_ctx, struct xdr_buf *text,
+static u32
+gss_get_mic_v1(struct krb5_ctx *ctx, struct xdr_buf *text,
 		struct xdr_netobj *token)
 {
-	struct krb5_ctx		*ctx = gss_ctx->internal_ctx_id;
 	char			cksumdata[16];
 	struct xdr_netobj	md5cksum = {.len = 0, .data = cksumdata};
 	unsigned char		*ptr, *krb5_hdr, *msg_start;
@@ -121,3 +120,19 @@ gss_get_mic_kerberos(struct gss_ctx *gss_ctx, struct xdr_buf *text,
 
 	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) {
+	case ENCTYPE_DES_CBC_RAW:
+		return gss_get_mic_v1(ctx, text, token);
+	default:
+		BUG();
+	}
+	return 0;
+}
+
diff --git a/net/sunrpc/auth_gss/gss_krb5_unseal.c b/net/sunrpc/auth_gss/gss_krb5_unseal.c
index e30a993..211eca4 100644
--- a/net/sunrpc/auth_gss/gss_krb5_unseal.c
+++ b/net/sunrpc/auth_gss/gss_krb5_unseal.c
@@ -71,11 +71,10 @@
 /* read_token is a mic token, and message_buffer is the data that the mic was
  * supposedly taken over. */
 
-u32
-gss_verify_mic_kerberos(struct gss_ctx *gss_ctx,
+static u32
+gss_verify_mic_v1(struct krb5_ctx *ctx,
 		struct xdr_buf *message_buffer, struct xdr_netobj *read_token)
 {
-	struct krb5_ctx		*ctx = gss_ctx->internal_ctx_id;
 	int			signalg;
 	int			sealalg;
 	char			cksumdata[16];
@@ -136,3 +135,20 @@ gss_verify_mic_kerberos(struct gss_ctx *gss_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) {
+	case ENCTYPE_DES_CBC_RAW:
+		return gss_verify_mic_v1(ctx, message_buffer, read_token);
+	default:
+		BUG();
+	}
+	return 0;
+}
+
diff --git a/net/sunrpc/auth_gss/gss_krb5_wrap.c b/net/sunrpc/auth_gss/gss_krb5_wrap.c
index 9763bf1..9f13411 100644
--- a/net/sunrpc/auth_gss/gss_krb5_wrap.c
+++ b/net/sunrpc/auth_gss/gss_krb5_wrap.c
@@ -98,11 +98,10 @@ make_confounder(char *p, int blocksize)
 
 /* XXX factor out common code with seal/unseal. */
 
-u32
-gss_wrap_kerberos(struct gss_ctx *ctx, int offset,
+static u32
+gss_wrap_kerberos_v1(struct krb5_ctx *kctx, int offset,
 		struct xdr_buf *buf, struct page **pages)
 {
-	struct krb5_ctx		*kctx = ctx->internal_ctx_id;
 	char			cksumdata[16];
 	struct xdr_netobj	md5cksum = {.len = 0, .data = cksumdata};
 	int			blocksize = 0, plainlen;
@@ -179,10 +178,9 @@ gss_wrap_kerberos(struct gss_ctx *ctx, int offset,
 	return (kctx->endtime < now) ? GSS_S_CONTEXT_EXPIRED : GSS_S_COMPLETE;
 }
 
-u32
-gss_unwrap_kerberos(struct gss_ctx *ctx, int offset, struct xdr_buf *buf)
+static u32
+gss_unwrap_kerberos_v1(struct krb5_ctx *kctx, int offset, struct xdr_buf *buf)
 {
-	struct krb5_ctx		*kctx = ctx->internal_ctx_id;
 	int			signalg;
 	int			sealalg;
 	char			cksumdata[16];
@@ -270,3 +268,37 @@ gss_unwrap_kerberos(struct gss_ctx *ctx, int offset, struct xdr_buf *buf)
 
 	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) {
+	case ENCTYPE_DES_CBC_RAW:
+		return gss_wrap_kerberos_v1(kctx, offset, buf, pages);
+		break;
+	default:
+		BUG();
+		break;
+	}
+	return 0;
+}
+
+u32
+gss_unwrap_kerberos(struct gss_ctx *gctx, int offset, struct xdr_buf *buf)
+{
+	struct krb5_ctx	*kctx = gctx->internal_ctx_id;
+
+	switch (kctx->enctype) {
+	case ENCTYPE_DES_CBC_RAW:
+		return gss_unwrap_kerberos_v1(kctx, offset, buf);
+		break;
+	default:
+		BUG();
+		break;
+	}
+	return 0;
+}
+


^ permalink raw reply related	[flat|nested] 31+ messages in thread

* [PATCH 10/19] gss_krb5: prepare for new context format
       [not found] ` <20080221184208.19195.94518.stgit-zTNJhAanYLVZN1qrTdtDg5Vzexx5G7lz@public.gmane.org>
                     ` (8 preceding siblings ...)
  2008-02-21 18:44   ` [PATCH 09/19] gss_krb5: split up functions in preparation of adding new enctypes Kevin Coffman
@ 2008-02-21 18:44   ` Kevin Coffman
  2008-02-21 18:44   ` [PATCH 11/19] gss_krb5: introduce encryption type framework Kevin Coffman
                     ` (8 subsequent siblings)
  18 siblings, 0 replies; 31+ messages in thread
From: Kevin Coffman @ 2008-02-21 18:44 UTC (permalink / raw)
  To: linux-nfs

Prepare for new context format by splitting out the old "v1"
context processing function.

From: J. Bruce Fields <bfields@citi.umich.edu>
Signed-off-by: Kevin Coffman <kwc@citi.umich.edu>
---

 net/sunrpc/auth_gss/gss_krb5_mech.c |   62 +++++++++++++++++++++++------------
 1 files changed, 40 insertions(+), 22 deletions(-)

diff --git a/net/sunrpc/auth_gss/gss_krb5_mech.c b/net/sunrpc/auth_gss/gss_krb5_mech.c
index 477cf07..f0f0749 100644
--- a/net/sunrpc/auth_gss/gss_krb5_mech.c
+++ b/net/sunrpc/auth_gss/gss_krb5_mech.c
@@ -123,51 +123,47 @@ out_err:
 }
 
 static int
-gss_import_sec_context_kerberos(const void *p,
-				size_t len,
-				struct gss_ctx *ctx_id)
+gss_import_v1_context(const void *p, const void *end, struct krb5_ctx *ctx)
 {
-	const void *end = (const void *)((const char *)p + len);
-	struct	krb5_ctx *ctx;
 	int tmp;
 
-	if (!(ctx = kzalloc(sizeof(*ctx), GFP_KERNEL)))
-		goto out_err;
-
 	p = simple_get_bytes(p, end, &ctx->initiate, sizeof(ctx->initiate));
 	if (IS_ERR(p))
-		goto out_err_free_ctx;
+		goto out_err;
+
+	/* Old format supports only DES!  Any other enctype uses new format */
 	ctx->enctype = ENCTYPE_DES_CBC_RAW;
+
 	/* The downcall format was designed before we completely understood
 	 * the uses of the context fields; so it includes some stuff we
 	 * just give some minimal sanity-checking, and some we ignore
 	 * completely (like the next twenty bytes): */
 	if (unlikely(p + 20 > end || p + 20 < p))
-		goto out_err_free_ctx;
+		goto out_err;
 	p += 20;
 	p = simple_get_bytes(p, end, &tmp, sizeof(tmp));
 	if (IS_ERR(p))
-		goto out_err_free_ctx;
+		goto out_err;
 	if (tmp != SGN_ALG_DES_MAC_MD5) {
 		p = ERR_PTR(-ENOSYS);
-		goto out_err_free_ctx;
+		goto out_err;
 	}
 	p = simple_get_bytes(p, end, &tmp, sizeof(tmp));
 	if (IS_ERR(p))
-		goto out_err_free_ctx;
+		goto out_err;
 	if (tmp != SEAL_ALG_DES) {
 		p = ERR_PTR(-ENOSYS);
-		goto out_err_free_ctx;
+		goto out_err;
 	}
 	p = simple_get_bytes(p, end, &ctx->endtime, sizeof(ctx->endtime));
 	if (IS_ERR(p))
-		goto out_err_free_ctx;
+		goto out_err;
 	p = simple_get_bytes(p, end, &ctx->seq_send, sizeof(ctx->seq_send));
 	if (IS_ERR(p))
-		goto out_err_free_ctx;
+		goto out_err;
 	p = simple_get_netobj(p, end, &ctx->mech_used);
 	if (IS_ERR(p))
-		goto out_err_free_ctx;
+		goto out_err;
 	p = get_key(p, end, &ctx->enc);
 	if (IS_ERR(p))
 		goto out_err_free_mech;
@@ -179,9 +175,6 @@ gss_import_sec_context_kerberos(const void *p,
 		goto out_err_free_key2;
 	}
 
-	ctx_id->internal_ctx_id = ctx;
-
-	dprintk("RPC:       Successfully imported new context.\n");
 	return 0;
 
 out_err_free_key2:
@@ -190,12 +183,37 @@ out_err_free_key1:
 	crypto_free_blkcipher(ctx->enc);
 out_err_free_mech:
 	kfree(ctx->mech_used.data);
-out_err_free_ctx:
-	kfree(ctx);
 out_err:
 	return PTR_ERR(p);
 }
 
+static int
+gss_import_sec_context_kerberos(const void *p, size_t len,
+				struct gss_ctx *ctx_id)
+{
+	const void *end = (const void *)((const char *)p + len);
+	struct  krb5_ctx *ctx;
+	int ret;
+
+	ctx = kmalloc(sizeof(*ctx), GFP_KERNEL);
+	if (ctx == NULL)
+		return -ENOMEM;
+	memset(ctx, 0, sizeof(*ctx));
+
+	if (len == 85)
+		ret = gss_import_v1_context(p, end, ctx);
+	else
+		ret = -EINVAL;
+
+	if (ret == 0)
+		ctx_id->internal_ctx_id = ctx;
+	else
+		kfree(ctx);
+
+	dprintk("RPC:       %s: returning %d\n", __func__, ret);
+	return ret;
+}
+
 static void
 gss_delete_sec_context_kerberos(void *internal_ctx) {
 	struct krb5_ctx *kctx = internal_ctx;


^ permalink raw reply related	[flat|nested] 31+ messages in thread

* [PATCH 11/19] gss_krb5: introduce encryption type framework
       [not found] ` <20080221184208.19195.94518.stgit-zTNJhAanYLVZN1qrTdtDg5Vzexx5G7lz@public.gmane.org>
                     ` (9 preceding siblings ...)
  2008-02-21 18:44   ` [PATCH 10/19] gss_krb5: prepare for new context format Kevin Coffman
@ 2008-02-21 18:44   ` Kevin Coffman
  2008-02-21 18:44   ` [PATCH 12/19] gss_krb5: add ability to have a keyed checksum (hmac) Kevin Coffman
                     ` (7 subsequent siblings)
  18 siblings, 0 replies; 31+ messages in thread
From: Kevin Coffman @ 2008-02-21 18:44 UTC (permalink / raw)
  To: linux-nfs

Add enctype framework and change functions to use the generic
values from it rather than the values hard-coded for des.

Signed-off-by: Kevin Coffman <kwc@citi.umich.edu>
---

 include/linux/sunrpc/gss_krb5.h       |   29 +++++++++++
 net/sunrpc/auth_gss/gss_krb5_crypto.c |   16 +++---
 net/sunrpc/auth_gss/gss_krb5_mech.c   |   88 +++++++++++++++++++++++++++------
 net/sunrpc/auth_gss/gss_krb5_seal.c   |   48 +++++++++++-------
 net/sunrpc/auth_gss/gss_krb5_unseal.c |   12 +++--
 net/sunrpc/auth_gss/gss_krb5_wrap.c   |   49 +++++++++++-------
 6 files changed, 175 insertions(+), 67 deletions(-)

diff --git a/include/linux/sunrpc/gss_krb5.h b/include/linux/sunrpc/gss_krb5.h
index dfe382a..d10d8ce 100644
--- a/include/linux/sunrpc/gss_krb5.h
+++ b/include/linux/sunrpc/gss_krb5.h
@@ -36,13 +36,42 @@
  *
  */
 
+#include <linux/crypto.h>
 #include <linux/sunrpc/auth_gss.h>
 #include <linux/sunrpc/gss_err.h>
 #include <linux/sunrpc/gss_asn1.h>
 
+/* Maximum checksum function output for the supported crypto algorithms */
+#define GSS_KRB5_MAX_CKSUM_LEN  20
+
+/* Maximum blocksize for the supported crypto algorithms */
+#define GSS_KRB5_MAX_BLOCKSIZE  16
+
+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		*cksum_name;	/* crypto checksum name */
+	const u16		signalg;	/* signing algorithm */
+	const u16		sealalg;	/* sealing algorithm */
+	const u32		blocksize;	/* encryption blocksize */
+	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 */
+	u32 (*encrypt) (struct crypto_blkcipher *tfm,
+			void *iv, void *in, void *out,
+			int length);		/* encryption function */
+	u32 (*decrypt) (struct crypto_blkcipher *tfm,
+			void *iv, void *in, void *out,
+			int length);		/* decryption function */
+};
+
 struct krb5_ctx {
 	int			initiate; /* 1 = initiating, 0 = accepting */
 	u32			enctype;
+	struct gss_krb5_enctype *gk5e;		/* enctype-specific info */
 	struct crypto_blkcipher	*enc;
 	struct crypto_blkcipher	*seq;
 	s32			endtime;
diff --git a/net/sunrpc/auth_gss/gss_krb5_crypto.c b/net/sunrpc/auth_gss/gss_krb5_crypto.c
index 1d52308..39643a7 100644
--- a/net/sunrpc/auth_gss/gss_krb5_crypto.c
+++ b/net/sunrpc/auth_gss/gss_krb5_crypto.c
@@ -59,13 +59,13 @@ krb5_encrypt(
 {
 	u32 ret = -EINVAL;
 	struct scatterlist sg[1];
-	u8 local_iv[16] = {0};
+	u8 local_iv[GSS_KRB5_MAX_BLOCKSIZE] = {0};
 	struct blkcipher_desc desc = { .tfm = tfm, .info = local_iv };
 
 	if (length % crypto_blkcipher_blocksize(tfm) != 0)
 		goto out;
 
-	if (crypto_blkcipher_ivsize(tfm) > 16) {
+	if (crypto_blkcipher_ivsize(tfm) > GSS_KRB5_MAX_BLOCKSIZE) {
 		dprintk("RPC:       gss_k5encrypt: tfm iv size too large %d\n",
 			crypto_blkcipher_ivsize(tfm));
 		goto out;
@@ -95,13 +95,13 @@ krb5_decrypt(
 {
 	u32 ret = -EINVAL;
 	struct scatterlist sg[1];
-	u8 local_iv[16] = {0};
+	u8 local_iv[GSS_KRB5_MAX_BLOCKSIZE] = {0};
 	struct blkcipher_desc desc = { .tfm = tfm, .info = local_iv };
 
 	if (length % crypto_blkcipher_blocksize(tfm) != 0)
 		goto out;
 
-	if (crypto_blkcipher_ivsize(tfm) > 16) {
+	if (crypto_blkcipher_ivsize(tfm) > GSS_KRB5_MAX_BLOCKSIZE) {
 		dprintk("RPC:       gss_k5decrypt: tfm iv size too large %d\n",
 			crypto_blkcipher_ivsize(tfm));
 		goto out;
@@ -164,7 +164,7 @@ out:
 EXPORT_SYMBOL(make_checksum);
 
 struct encryptor_desc {
-	u8 iv[8]; /* XXX hard-coded blocksize */
+	u8 iv[GSS_KRB5_MAX_BLOCKSIZE];
 	struct blkcipher_desc desc;
 	int pos;
 	struct xdr_buf *outbuf;
@@ -205,7 +205,7 @@ encryptor(struct scatterlist *sg, void *data)
 	desc->fraglen += sg->length;
 	desc->pos += sg->length;
 
-	fraglen = thislen & 7; /* XXX hardcoded blocksize */
+	fraglen = thislen & (crypto_blkcipher_blocksize(desc->desc.tfm) - 1);
 	thislen -= fraglen;
 
 	if (thislen == 0)
@@ -265,7 +265,7 @@ gss_encrypt_xdr_buf(struct crypto_blkcipher *tfm, struct xdr_buf *buf,
 EXPORT_SYMBOL(gss_encrypt_xdr_buf);
 
 struct decryptor_desc {
-	u8 iv[8]; /* XXX hard-coded blocksize */
+	u8 iv[GSS_KRB5_MAX_BLOCKSIZE];
 	struct blkcipher_desc desc;
 	struct scatterlist frags[4];
 	int fragno;
@@ -287,7 +287,7 @@ decryptor(struct scatterlist *sg, void *data)
 	desc->fragno++;
 	desc->fraglen += sg->length;
 
-	fraglen = thislen & 7; /* XXX hardcoded blocksize */
+	fraglen = thislen & (crypto_blkcipher_blocksize(desc->desc.tfm) - 1);
 	thislen -= fraglen;
 
 	if (thislen == 0)
diff --git a/net/sunrpc/auth_gss/gss_krb5_mech.c b/net/sunrpc/auth_gss/gss_krb5_mech.c
index f0f0749..fe88266 100644
--- a/net/sunrpc/auth_gss/gss_krb5_mech.c
+++ b/net/sunrpc/auth_gss/gss_krb5_mech.c
@@ -48,6 +48,50 @@
 # define RPCDBG_FACILITY	RPCDBG_AUTH
 #endif
 
+static struct gss_krb5_enctype supported_gss_krb5_enctypes[] = {
+	/*
+	 * DES (All DES enctypes are mapped to the same gss functionality)
+	 */
+	{
+	  .etype = ENCTYPE_DES_CBC_RAW,
+	  .ctype = CKSUMTYPE_RSA_MD5,
+	  .name = "des-cbc-crc",
+	  .encrypt_name = "cbc(des)",
+	  .cksum_name = "md5",
+	  .encrypt = krb5_encrypt,
+	  .decrypt = krb5_decrypt,
+	  .signalg = SGN_ALG_DES_MAC_MD5,
+	  .sealalg = SEAL_ALG_DES,
+	  .keybytes = 7,
+	  .keylength = 8,
+	  .blocksize = 8,
+	  .cksumlength = 8,
+	},
+};
+
+static int num_supported_enctypes =
+	sizeof(supported_gss_krb5_enctypes) / sizeof(struct gss_krb5_enctype);
+
+static int
+supported_gss_krb5_enctype(int etype)
+{
+	int i;
+	for (i = 0; i < num_supported_enctypes; i++)
+		if (supported_gss_krb5_enctypes[i].etype == etype)
+			return 1;
+	return 0;
+}
+
+static struct gss_krb5_enctype *
+get_gss_krb5_enctype(int etype)
+{
+	int i;
+	for (i = 0; i < num_supported_enctypes; i++)
+		if (supported_gss_krb5_enctypes[i].etype == etype)
+			return &supported_gss_krb5_enctypes[i];
+	return NULL;
+}
+
 static const void *
 simple_get_bytes(const void *p, const void *end, void *res, int len)
 {
@@ -78,35 +122,45 @@ simple_get_netobj(const void *p, const void *end, struct xdr_netobj *res)
 }
 
 static inline const void *
-get_key(const void *p, const void *end, struct crypto_blkcipher **res)
+get_key(const void *p, const void *end,
+	struct krb5_ctx *ctx, struct crypto_blkcipher **res)
 {
 	struct xdr_netobj	key;
 	int			alg;
-	char			*alg_name;
 
 	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:
+	case ENCTYPE_DES_CBC_MD5:
+		/* Map all these key types to ENCTYPE_DES_CBC_RAW */
+		alg = ENCTYPE_DES_CBC_RAW;
+		break;
+	}
+
+	if (!supported_gss_krb5_enctype(alg)) {
+		printk("gss_kerberos_mech: unsupported encryption "
+			"key algorithm %d\n", alg);
+		goto out_err;
+	}
 	p = simple_get_netobj(p, end, &key);
 	if (IS_ERR(p))
 		goto out_err;
 
-	switch (alg) {
-		case ENCTYPE_DES_CBC_RAW:
-			alg_name = "cbc(des)";
-			break;
-		default:
-			printk("gss_kerberos_mech: unsupported algorithm %d\n", alg);
-			goto out_err_free_key;
-	}
-	*res = crypto_alloc_blkcipher(alg_name, 0, CRYPTO_ALG_ASYNC);
+	*res = crypto_alloc_blkcipher(ctx->gk5e->encrypt_name, 0,
+							CRYPTO_ALG_ASYNC);
 	if (IS_ERR(*res)) {
-		printk("gss_kerberos_mech: unable to initialize crypto algorithm %s\n", alg_name);
+		printk("gss_kerberos_mech: unable to initialize crypto "
+			"algorithm %s\n", ctx->gk5e->encrypt_name);
 		*res = NULL;
 		goto out_err_free_key;
 	}
 	if (crypto_blkcipher_setkey(*res, key.data, key.len)) {
-		printk("gss_kerberos_mech: error setting key for crypto algorithm %s\n", alg_name);
+		printk("gss_kerberos_mech: error setting key for crypto "
+			"algorithm %s\n", ctx->gk5e->encrypt_name);
 		goto out_err_free_tfm;
 	}
 
@@ -134,6 +188,10 @@ 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);
+	if (ctx->gk5e == NULL)
+		goto out_err;
+
 	/* The downcall format was designed before we completely understood
 	 * the uses of the context fields; so it includes some stuff we
 	 * just give some minimal sanity-checking, and some we ignore
@@ -164,10 +222,10 @@ gss_import_v1_context(const void *p, const void *end, struct krb5_ctx *ctx)
 	p = simple_get_netobj(p, end, &ctx->mech_used);
 	if (IS_ERR(p))
 		goto out_err;
-	p = get_key(p, end, &ctx->enc);
+	p = get_key(p, end, ctx, &ctx->enc);
 	if (IS_ERR(p))
 		goto out_err_free_mech;
-	p = get_key(p, end, &ctx->seq);
+	p = get_key(p, end, ctx, &ctx->seq);
 	if (IS_ERR(p))
 		goto out_err_free_key1;
 	if (p != end) {
diff --git a/net/sunrpc/auth_gss/gss_krb5_seal.c b/net/sunrpc/auth_gss/gss_krb5_seal.c
index 3b9cc47..64cabf2 100644
--- a/net/sunrpc/auth_gss/gss_krb5_seal.c
+++ b/net/sunrpc/auth_gss/gss_krb5_seal.c
@@ -71,37 +71,47 @@
 
 DEFINE_SPINLOCK(krb5_seq_lock);
 
+static char *
+setup_token(struct krb5_ctx *ctx, struct xdr_netobj *token)
+{
+	__be16 *ptr, *krb5_hdr;
+	int body_size = 16 + ctx->gk5e->cksumlength;
+
+	token->len = g_token_size(&ctx->mech_used, body_size);
+
+	ptr = (__be16 *)token->data;
+	g_make_token_header(&ctx->mech_used, body_size, (unsigned char **)&ptr);
+
+	/* ptr now at start of header described in rfc 1964, section 1.2.1: */
+	krb5_hdr = ptr;
+	*ptr++ = KG_TOK_MIC_MSG;
+	*ptr++ = cpu_to_le16(ctx->gk5e->signalg);
+	*ptr++ = SEAL_ALG_NONE;
+	*ptr++ = 0xffff;
+
+	return (char *)krb5_hdr;
+}
+
 static u32
 gss_get_mic_v1(struct krb5_ctx *ctx, struct xdr_buf *text,
 		struct xdr_netobj *token)
 {
-	char			cksumdata[16];
-	struct xdr_netobj	md5cksum = {.len = 0, .data = cksumdata};
-	unsigned char		*ptr, *krb5_hdr, *msg_start;
+	char			cksumdata[GSS_KRB5_MAX_CKSUM_LEN];
+	struct xdr_netobj	md5cksum = {.len = sizeof(cksumdata),
+					    .data = cksumdata};
+	void			*krb5_hdr;
 	s32			now;
 	u32			seq_send;
 
-	dprintk("RPC:       gss_krb5_seal\n");
+	dprintk("RPC:       %s\n", __func__);
 	BUG_ON(ctx == NULL);
 
 	now = get_seconds();
 
-	token->len = g_token_size(&ctx->mech_used, 24);
-
-	ptr = token->data;
-	g_make_token_header(&ctx->mech_used, 24, &ptr);
-
-	*ptr++ = (unsigned char) ((KG_TOK_MIC_MSG>>8)&0xff);
-	*ptr++ = (unsigned char) (KG_TOK_MIC_MSG&0xff);
-
-	/* ptr now at byte 2 of header described in rfc 1964, section 1.2.1: */
-	krb5_hdr = ptr - 2;
-	msg_start = krb5_hdr + 24;
-
-	*(__be16 *)(krb5_hdr + 2) = htons(SGN_ALG_DES_MAC_MD5);
-	memset(krb5_hdr + 4, 0xff, 4);
+	krb5_hdr = setup_token(ctx, token);
 
-	if (make_checksum("md5", krb5_hdr, 8, text, 0, &md5cksum))
+	if (make_checksum((char *)ctx->gk5e->cksum_name, krb5_hdr, 8,
+						text, 0, &md5cksum))
 		return GSS_S_FAILURE;
 
 	if (krb5_encrypt(ctx->seq, NULL, md5cksum.data,
diff --git a/net/sunrpc/auth_gss/gss_krb5_unseal.c b/net/sunrpc/auth_gss/gss_krb5_unseal.c
index 211eca4..43bd213 100644
--- a/net/sunrpc/auth_gss/gss_krb5_unseal.c
+++ b/net/sunrpc/auth_gss/gss_krb5_unseal.c
@@ -77,8 +77,9 @@ gss_verify_mic_v1(struct krb5_ctx *ctx,
 {
 	int			signalg;
 	int			sealalg;
-	char			cksumdata[16];
-	struct xdr_netobj	md5cksum = {.len = 0, .data = cksumdata};
+	char			cksumdata[GSS_KRB5_MAX_CKSUM_LEN];
+	struct xdr_netobj	md5cksum = {.len = sizeof(cksumdata),
+					    .data = cksumdata};
 	s32			now;
 	int			direction;
 	s32			seqnum;
@@ -98,7 +99,7 @@ gss_verify_mic_v1(struct krb5_ctx *ctx,
 	/* XXX sanity-check bodysize?? */
 
 	signalg = ptr[0] + (ptr[1] << 8);
-	if (signalg != SGN_ALG_DES_MAC_MD5)
+	if (signalg != ctx->gk5e->signalg)
 		return GSS_S_DEFECTIVE_TOKEN;
 
 	sealalg = ptr[2] + (ptr[3] << 8);
@@ -108,13 +109,14 @@ gss_verify_mic_v1(struct krb5_ctx *ctx,
 	if ((ptr[4] != 0xff) || (ptr[5] != 0xff))
 		return GSS_S_DEFECTIVE_TOKEN;
 
-	if (make_checksum("md5", ptr - 2, 8, message_buffer, 0, &md5cksum))
+	if (make_checksum((char *)ctx->gk5e->cksum_name, ptr - 2, 8,
+					message_buffer, 0, &md5cksum))
 		return GSS_S_FAILURE;
 
 	if (krb5_encrypt(ctx->seq, NULL, md5cksum.data, md5cksum.data, 16))
 		return GSS_S_FAILURE;
 
-	if (memcmp(md5cksum.data + 8, ptr + 14, 8))
+	if (memcmp(md5cksum.data + 8, ptr + 14, ctx->gk5e->cksumlength))
 		return GSS_S_BAD_SIG;
 
 	/* it got through unscathed.  Make sure the context is unexpired */
diff --git a/net/sunrpc/auth_gss/gss_krb5_wrap.c b/net/sunrpc/auth_gss/gss_krb5_wrap.c
index 9f13411..e369696 100644
--- a/net/sunrpc/auth_gss/gss_krb5_wrap.c
+++ b/net/sunrpc/auth_gss/gss_krb5_wrap.c
@@ -102,8 +102,9 @@ static u32
 gss_wrap_kerberos_v1(struct krb5_ctx *kctx, int offset,
 		struct xdr_buf *buf, struct page **pages)
 {
-	char			cksumdata[16];
-	struct xdr_netobj	md5cksum = {.len = 0, .data = cksumdata};
+	char			cksumdata[GSS_KRB5_MAX_CKSUM_LEN];
+	struct xdr_netobj	md5cksum = {.len = sizeof(cksumdata),
+					    .data = cksumdata};
 	int			blocksize = 0, plainlen;
 	unsigned char		*ptr, *krb5_hdr, *msg_start;
 	s32			now;
@@ -111,7 +112,7 @@ gss_wrap_kerberos_v1(struct krb5_ctx *kctx, int offset,
 	struct page		**tmp_pages;
 	u32			seq_send;
 
-	dprintk("RPC:       gss_wrap_kerberos\n");
+	dprintk("RPC:       %s\n", __func__);
 
 	now = get_seconds();
 
@@ -120,8 +121,8 @@ gss_wrap_kerberos_v1(struct krb5_ctx *kctx, int offset,
 	BUG_ON((buf->len - offset) % blocksize);
 	plainlen = blocksize + buf->len - offset;
 
-	headlen = g_token_size(&kctx->mech_used, 24 + plainlen) -
-						(buf->len - offset);
+	headlen = g_token_size(&kctx->mech_used,
+		16 + kctx->gk5e->cksumlength + plainlen) - (buf->len - offset);
 
 	ptr = buf->head[0].iov_base + offset;
 	/* shift data to make room for header. */
@@ -132,7 +133,8 @@ gss_wrap_kerberos_v1(struct krb5_ctx *kctx, int offset,
 	buf->len += headlen;
 	BUG_ON((buf->len - offset - headlen) % blocksize);
 
-	g_make_token_header(&kctx->mech_used, 24 + plainlen, &ptr);
+	g_make_token_header(&kctx->mech_used,
+				16 + kctx->gk5e->cksumlength + plainlen, &ptr);
 
 
 	*ptr++ = (unsigned char) ((KG_TOK_WRAP_MSG>>8)&0xff);
@@ -140,18 +142,18 @@ gss_wrap_kerberos_v1(struct krb5_ctx *kctx, int offset,
 
 	/* ptr now at byte 2 of header described in rfc 1964, section 1.2.1: */
 	krb5_hdr = ptr - 2;
-	msg_start = krb5_hdr + 24;
+	msg_start = krb5_hdr + 16 + kctx->gk5e->cksumlength;
 
-	*(__be16 *)(krb5_hdr + 2) = htons(SGN_ALG_DES_MAC_MD5);
+	*(__be16 *)(krb5_hdr + 2) = cpu_to_le16(kctx->gk5e->signalg);
 	memset(krb5_hdr + 4, 0xff, 4);
-	*(__be16 *)(krb5_hdr + 4) = htons(SEAL_ALG_DES);
+	*(__be16 *)(krb5_hdr + 4) = cpu_to_le16(kctx->gk5e->sealalg);
 
 	make_confounder(msg_start, blocksize);
 
 	/* XXXJBF: UGH!: */
 	tmp_pages = buf->pages;
 	buf->pages = pages;
-	if (make_checksum("md5", krb5_hdr, 8, buf,
+	if (make_checksum((char *)kctx->gk5e->cksum_name, krb5_hdr, 8, buf,
 				offset + headlen - blocksize, &md5cksum))
 		return GSS_S_FAILURE;
 	buf->pages = tmp_pages;
@@ -183,8 +185,9 @@ gss_unwrap_kerberos_v1(struct krb5_ctx *kctx, int offset, struct xdr_buf *buf)
 {
 	int			signalg;
 	int			sealalg;
-	char			cksumdata[16];
-	struct xdr_netobj	md5cksum = {.len = 0, .data = cksumdata};
+	char			cksumdata[GSS_KRB5_MAX_CKSUM_LEN];
+	struct xdr_netobj	md5cksum = {.len = sizeof(cksumdata),
+					    .data = cksumdata};
 	s32			now;
 	int			direction;
 	s32			seqnum;
@@ -193,6 +196,7 @@ gss_unwrap_kerberos_v1(struct krb5_ctx *kctx, int offset, struct xdr_buf *buf)
 	void			*data_start, *orig_start;
 	int			data_len;
 	int			blocksize;
+	int			crypt_offset;
 
 	dprintk("RPC:       gss_unwrap_kerberos\n");
 
@@ -210,29 +214,34 @@ gss_unwrap_kerberos_v1(struct krb5_ctx *kctx, int offset, struct xdr_buf *buf)
 	/* get the sign and seal algorithms */
 
 	signalg = ptr[0] + (ptr[1] << 8);
-	if (signalg != SGN_ALG_DES_MAC_MD5)
+	if (signalg != kctx->gk5e->signalg)
 		return GSS_S_DEFECTIVE_TOKEN;
 
 	sealalg = ptr[2] + (ptr[3] << 8);
-	if (sealalg != SEAL_ALG_DES)
+	if (sealalg != kctx->gk5e->sealalg)
 		return GSS_S_DEFECTIVE_TOKEN;
 
 	if ((ptr[4] != 0xff) || (ptr[5] != 0xff))
 		return GSS_S_DEFECTIVE_TOKEN;
 
-	if (gss_decrypt_xdr_buf(kctx->enc, buf,
-			ptr + 22 - (unsigned char *)buf->head[0].iov_base))
+	/*
+	 * Data starts after token header and checksum.  ptr points
+	 * two past the beginning of the token header (which is 16 bytes)
+	 */
+	crypt_offset = ptr + (16 - 2 + kctx->gk5e->cksumlength) -
+					(unsigned char *)buf->head[0].iov_base;
+	if (gss_decrypt_xdr_buf(kctx->enc, buf, crypt_offset))
 		return GSS_S_DEFECTIVE_TOKEN;
 
-	if (make_checksum("md5", ptr - 2, 8, buf,
-		 ptr + 22 - (unsigned char *)buf->head[0].iov_base, &md5cksum))
+	if (make_checksum((char *)kctx->gk5e->cksum_name, ptr - 2, 8, buf,
+						crypt_offset, &md5cksum))
 		return GSS_S_FAILURE;
 
 	if (krb5_encrypt(kctx->seq, NULL, md5cksum.data,
 			   md5cksum.data, md5cksum.len))
 		return GSS_S_FAILURE;
 
-	if (memcmp(md5cksum.data + 8, ptr + 14, 8))
+	if (memcmp(md5cksum.data + 8, ptr + 14, 8))/* this is still DES-aware */
 		return GSS_S_BAD_SIG;
 
 	/* it got through unscathed.  Make sure the context is unexpired */
@@ -256,7 +265,7 @@ gss_unwrap_kerberos_v1(struct krb5_ctx *kctx, int offset, struct xdr_buf *buf)
 	 * better to copy and encrypt at the same time. */
 
 	blocksize = crypto_blkcipher_blocksize(kctx->enc);
-	data_start = ptr + 22 + blocksize;
+	data_start = ptr + (16 - 2 + kctx->gk5e->cksumlength) + blocksize;
 	orig_start = buf->head[0].iov_base + offset;
 	data_len = (buf->head[0].iov_base + buf->head[0].iov_len) - data_start;
 	memmove(orig_start, data_start, data_len);


^ permalink raw reply related	[flat|nested] 31+ messages in thread

* [PATCH 12/19] gss_krb5: add ability to have a keyed checksum (hmac)
       [not found] ` <20080221184208.19195.94518.stgit-zTNJhAanYLVZN1qrTdtDg5Vzexx5G7lz@public.gmane.org>
                     ` (10 preceding siblings ...)
  2008-02-21 18:44   ` [PATCH 11/19] gss_krb5: introduce encryption type framework Kevin Coffman
@ 2008-02-21 18:44   ` Kevin Coffman
  2008-02-21 18:44   ` [PATCH 13/19] gss_krb5: import functionality to derive keys into the kernel Kevin Coffman
                     ` (6 subsequent siblings)
  18 siblings, 0 replies; 31+ messages in thread
From: Kevin Coffman @ 2008-02-21 18:44 UTC (permalink / raw)
  To: linux-nfs

Encryption types besides DES may use a keyed checksum (hmac).
Modify the make_checksum() function to allow for a key
and take care of enctype-specific processing such as truncating
the resulting hash.

Signed-off-by: Kevin Coffman <kwc@citi.umich.edu>
---

 include/linux/sunrpc/gss_krb5.h       |   11 +++++--
 net/sunrpc/auth_gss/gss_krb5_crypto.c |   54 ++++++++++++++++++++++++++++-----
 net/sunrpc/auth_gss/gss_krb5_mech.c   |    1 +
 net/sunrpc/auth_gss/gss_krb5_seal.c   |   13 ++++----
 net/sunrpc/auth_gss/gss_krb5_unseal.c |   13 +++++---
 net/sunrpc/auth_gss/gss_krb5_wrap.c   |   29 ++++++++++--------
 6 files changed, 87 insertions(+), 34 deletions(-)

diff --git a/include/linux/sunrpc/gss_krb5.h b/include/linux/sunrpc/gss_krb5.h
index d10d8ce..c33a657 100644
--- a/include/linux/sunrpc/gss_krb5.h
+++ b/include/linux/sunrpc/gss_krb5.h
@@ -41,6 +41,9 @@
 #include <linux/sunrpc/gss_err.h>
 #include <linux/sunrpc/gss_asn1.h>
 
+/* 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
 
@@ -74,6 +77,7 @@ struct krb5_ctx {
 	struct gss_krb5_enctype *gk5e;		/* enctype-specific info */
 	struct crypto_blkcipher	*enc;
 	struct crypto_blkcipher	*seq;
+	u8			cksum[GSS_KRB5_MAX_KEYLEN];
 	s32			endtime;
 	u32			seq_send;
 	struct xdr_netobj	mech_used;
@@ -142,9 +146,10 @@ extern struct xdr_netobj krb5_oid;
 #define ENCTYPE_DES3_CBC_SHA1   0x0010
 #define ENCTYPE_UNKNOWN         0x01ff
 
-s32
-make_checksum(char *, char *header, int hdrlen, struct xdr_buf *body,
-		   int body_offset, struct xdr_netobj *cksum);
+u32
+make_checksum(struct krb5_ctx *kctx, char *header, int hdrlen,
+		struct xdr_buf *body, int body_offset, u8 *cksumkey,
+		struct xdr_netobj *cksumout);
 
 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 39643a7..8b12f34 100644
--- a/net/sunrpc/auth_gss/gss_krb5_crypto.c
+++ b/net/sunrpc/auth_gss/gss_krb5_crypto.c
@@ -128,21 +128,42 @@ checksummer(struct scatterlist *sg, void *data)
 	return crypto_hash_update(desc, sg, sg->length);
 }
 
-/* checksum the plaintext data and hdrlen bytes of the token header */
-s32
-make_checksum(char *cksumname, char *header, int hdrlen, struct xdr_buf *body,
-		   int body_offset, struct xdr_netobj *cksum)
+/*
+ * checksum the plaintext data and hdrlen bytes of the token header
+ * The checksum is performed over the first 8 bytes of the
+ * gss token header and then over the data body
+ */
+u32
+make_checksum(struct krb5_ctx *kctx, char *header, int hdrlen,
+	      struct xdr_buf *body, int body_offset, u8 *cksumkey,
+	      struct xdr_netobj *cksumout)
 {
-	struct hash_desc                desc; /* XXX add to ctx? */
+	struct hash_desc                desc;
 	struct scatterlist              sg[1];
 	int err;
+	u8 checksumdata[GSS_KRB5_MAX_CKSUM_LEN];
+	unsigned int checksumlen;
+
+	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;
+	}
 
-	desc.tfm = crypto_alloc_hash(cksumname, 0, CRYPTO_ALG_ASYNC);
+	desc.tfm = crypto_alloc_hash(kctx->gk5e->cksum_name, 0, CRYPTO_ALG_ASYNC);
 	if (IS_ERR(desc.tfm))
 		return GSS_S_FAILURE;
-	cksum->len = crypto_hash_digestsize(desc.tfm);
 	desc.flags = CRYPTO_TFM_REQ_MAY_SLEEP;
 
+	checksumlen = crypto_hash_digestsize(desc.tfm);
+
+	if (cksumkey != NULL) {
+		err = crypto_hash_setkey(desc.tfm, cksumkey,
+					 kctx->gk5e->keylength);
+		if (err)
+			goto out;
+	}
+
 	err = crypto_hash_init(&desc);
 	if (err)
 		goto out;
@@ -154,8 +175,25 @@ make_checksum(char *cksumname, char *header, int hdrlen, struct xdr_buf *body,
 			      checksummer, &desc);
 	if (err)
 		goto out;
-	err = crypto_hash_final(&desc, cksum->data);
+	err = crypto_hash_final(&desc, checksumdata);
+	if (err)
+		goto out;
 
+	switch (kctx->gk5e->ctype) {
+	case CKSUMTYPE_RSA_MD5:
+		err = kctx->gk5e->encrypt(kctx->seq, NULL, checksumdata,
+					  checksumdata, checksumlen);
+		if (err)
+			goto out;
+		memcpy(cksumout->data,
+		       checksumdata + checksumlen - kctx->gk5e->cksumlength,
+		       kctx->gk5e->cksumlength);
+		break;
+	default:
+		BUG();
+		break;
+	}
+	cksumout->len = kctx->gk5e->cksumlength;
 out:
 	crypto_free_hash(desc.tfm);
 	return err ? GSS_S_FAILURE : 0;
diff --git a/net/sunrpc/auth_gss/gss_krb5_mech.c b/net/sunrpc/auth_gss/gss_krb5_mech.c
index fe88266..28335cc 100644
--- a/net/sunrpc/auth_gss/gss_krb5_mech.c
+++ b/net/sunrpc/auth_gss/gss_krb5_mech.c
@@ -66,6 +66,7 @@ static struct gss_krb5_enctype supported_gss_krb5_enctypes[] = {
 	  .keylength = 8,
 	  .blocksize = 8,
 	  .cksumlength = 8,
+	  .keyed_cksum = 0,
 	},
 };
 
diff --git a/net/sunrpc/auth_gss/gss_krb5_seal.c b/net/sunrpc/auth_gss/gss_krb5_seal.c
index 64cabf2..f5badc7 100644
--- a/net/sunrpc/auth_gss/gss_krb5_seal.c
+++ b/net/sunrpc/auth_gss/gss_krb5_seal.c
@@ -102,6 +102,7 @@ gss_get_mic_v1(struct krb5_ctx *ctx, struct xdr_buf *text,
 	void			*krb5_hdr;
 	s32			now;
 	u32			seq_send;
+	u8			*cksumkey;
 
 	dprintk("RPC:       %s\n", __func__);
 	BUG_ON(ctx == NULL);
@@ -110,15 +111,15 @@ gss_get_mic_v1(struct krb5_ctx *ctx, struct xdr_buf *text,
 
 	krb5_hdr = setup_token(ctx, token);
 
-	if (make_checksum((char *)ctx->gk5e->cksum_name, krb5_hdr, 8,
-						text, 0, &md5cksum))
-		return GSS_S_FAILURE;
+	if (ctx->gk5e->keyed_cksum)
+		cksumkey = ctx->cksum;
+	else
+		cksumkey = NULL;
 
-	if (krb5_encrypt(ctx->seq, NULL, md5cksum.data,
-			  md5cksum.data, md5cksum.len))
+	if (make_checksum(ctx, krb5_hdr, 8, text, 0, cksumkey, &md5cksum))
 		return GSS_S_FAILURE;
 
-	memcpy(krb5_hdr + 16, md5cksum.data + md5cksum.len - 8, 8);
+	memcpy(krb5_hdr + 16, md5cksum.data, md5cksum.len);
 
 	spin_lock(&krb5_seq_lock);
 	seq_send = ctx->seq_send++;
diff --git a/net/sunrpc/auth_gss/gss_krb5_unseal.c b/net/sunrpc/auth_gss/gss_krb5_unseal.c
index 43bd213..5494ba4 100644
--- a/net/sunrpc/auth_gss/gss_krb5_unseal.c
+++ b/net/sunrpc/auth_gss/gss_krb5_unseal.c
@@ -85,6 +85,7 @@ gss_verify_mic_v1(struct krb5_ctx *ctx,
 	s32			seqnum;
 	unsigned char		*ptr = (unsigned char *)read_token->data;
 	int			bodysize;
+	u8			*cksumkey;
 
 	dprintk("RPC:       krb5_read_token\n");
 
@@ -109,14 +110,16 @@ gss_verify_mic_v1(struct krb5_ctx *ctx,
 	if ((ptr[4] != 0xff) || (ptr[5] != 0xff))
 		return GSS_S_DEFECTIVE_TOKEN;
 
-	if (make_checksum((char *)ctx->gk5e->cksum_name, ptr - 2, 8,
-					message_buffer, 0, &md5cksum))
-		return GSS_S_FAILURE;
+	if (ctx->gk5e->keyed_cksum)
+		cksumkey = ctx->cksum;
+	else
+		cksumkey = NULL;
 
-	if (krb5_encrypt(ctx->seq, NULL, md5cksum.data, md5cksum.data, 16))
+	if (make_checksum(ctx, ptr - 2, 8, message_buffer, 0,
+			  cksumkey, &md5cksum))
 		return GSS_S_FAILURE;
 
-	if (memcmp(md5cksum.data + 8, ptr + 14, ctx->gk5e->cksumlength))
+	if (memcmp(md5cksum.data, ptr + 14, ctx->gk5e->cksumlength))
 		return GSS_S_BAD_SIG;
 
 	/* it got through unscathed.  Make sure the context is unexpired */
diff --git a/net/sunrpc/auth_gss/gss_krb5_wrap.c b/net/sunrpc/auth_gss/gss_krb5_wrap.c
index e369696..dd6caf3 100644
--- a/net/sunrpc/auth_gss/gss_krb5_wrap.c
+++ b/net/sunrpc/auth_gss/gss_krb5_wrap.c
@@ -111,6 +111,7 @@ gss_wrap_kerberos_v1(struct krb5_ctx *kctx, int offset,
 	int			headlen;
 	struct page		**tmp_pages;
 	u32			seq_send;
+	u8			*cksumkey;
 
 	dprintk("RPC:       %s\n", __func__);
 
@@ -150,18 +151,20 @@ gss_wrap_kerberos_v1(struct krb5_ctx *kctx, int offset,
 
 	make_confounder(msg_start, blocksize);
 
+	if (kctx->gk5e->keyed_cksum)
+		cksumkey = kctx->cksum;
+	else
+		cksumkey = NULL;
+
 	/* XXXJBF: UGH!: */
 	tmp_pages = buf->pages;
 	buf->pages = pages;
-	if (make_checksum((char *)kctx->gk5e->cksum_name, krb5_hdr, 8, buf,
-				offset + headlen - blocksize, &md5cksum))
+	if (make_checksum(kctx, krb5_hdr, 8, buf, offset + headlen - blocksize,
+					cksumkey, &md5cksum))
 		return GSS_S_FAILURE;
 	buf->pages = tmp_pages;
 
-	if (krb5_encrypt(kctx->seq, NULL, md5cksum.data,
-			  md5cksum.data, md5cksum.len))
-		return GSS_S_FAILURE;
-	memcpy(krb5_hdr + 16, md5cksum.data + md5cksum.len - 8, 8);
+	memcpy(krb5_hdr + 16, md5cksum.data, md5cksum.len);
 
 	spin_lock(&krb5_seq_lock);
 	seq_send = kctx->seq_send++;
@@ -197,6 +200,7 @@ gss_unwrap_kerberos_v1(struct krb5_ctx *kctx, int offset, struct xdr_buf *buf)
 	int			data_len;
 	int			blocksize;
 	int			crypt_offset;
+	u8			*cksumkey;
 
 	dprintk("RPC:       gss_unwrap_kerberos\n");
 
@@ -233,15 +237,16 @@ gss_unwrap_kerberos_v1(struct krb5_ctx *kctx, int offset, struct xdr_buf *buf)
 	if (gss_decrypt_xdr_buf(kctx->enc, buf, crypt_offset))
 		return GSS_S_DEFECTIVE_TOKEN;
 
-	if (make_checksum((char *)kctx->gk5e->cksum_name, ptr - 2, 8, buf,
-						crypt_offset, &md5cksum))
-		return GSS_S_FAILURE;
+	if (kctx->gk5e->keyed_cksum)
+		cksumkey = kctx->cksum;
+	else
+		cksumkey = NULL;
 
-	if (krb5_encrypt(kctx->seq, NULL, md5cksum.data,
-			   md5cksum.data, md5cksum.len))
+	if (make_checksum(kctx, ptr - 2, 8, buf, crypt_offset,
+						cksumkey, &md5cksum))
 		return GSS_S_FAILURE;
 
-	if (memcmp(md5cksum.data + 8, ptr + 14, 8))/* this is still DES-aware */
+	if (memcmp(md5cksum.data, ptr + 14, kctx->gk5e->cksumlength))
 		return GSS_S_BAD_SIG;
 
 	/* it got through unscathed.  Make sure the context is unexpired */


^ permalink raw reply related	[flat|nested] 31+ messages in thread

* [PATCH 13/19] gss_krb5: import functionality to derive keys into the kernel
       [not found] ` <20080221184208.19195.94518.stgit-zTNJhAanYLVZN1qrTdtDg5Vzexx5G7lz@public.gmane.org>
                     ` (11 preceding siblings ...)
  2008-02-21 18:44   ` [PATCH 12/19] gss_krb5: add ability to have a keyed checksum (hmac) Kevin Coffman
@ 2008-02-21 18:44   ` Kevin Coffman
  2008-02-21 18:44   ` [PATCH 14/19] gss_krb5: use a global static OID value for krb5 Kevin Coffman
                     ` (5 subsequent siblings)
  18 siblings, 0 replies; 31+ messages in thread
From: Kevin Coffman @ 2008-02-21 18:44 UTC (permalink / raw)
  To: linux-nfs

Import the code to derive Kerberos keys from a base key into the
kernel.  This will allow us to change the format of the context
information sent down from gssd to include only a single key.

Signed-off-by: Kevin Coffman <kwc@citi.umich.edu>
---

 include/linux/sunrpc/gss_krb5.h     |   30 ++++
 net/sunrpc/auth_gss/Makefile        |    4 -
 net/sunrpc/auth_gss/gss_krb5_keys.c |  255 +++++++++++++++++++++++++++++++++++
 net/sunrpc/auth_gss/gss_krb5_mech.c |    1 
 4 files changed, 288 insertions(+), 2 deletions(-)

diff --git a/include/linux/sunrpc/gss_krb5.h b/include/linux/sunrpc/gss_krb5.h
index c33a657..d326911 100644
--- a/include/linux/sunrpc/gss_krb5.h
+++ b/include/linux/sunrpc/gss_krb5.h
@@ -41,6 +41,9 @@
 #include <linux/sunrpc/gss_err.h>
 #include <linux/sunrpc/gss_asn1.h>
 
+/* Length of constant used in key derivation */
+#define GSS_KRB5_K5CLENGTH 5
+
 /* Maximum key length (in bytes) for the supported crypto algorithms*/
 #define GSS_KRB5_MAX_KEYLEN 32
 
@@ -69,6 +72,9 @@ struct gss_krb5_enctype {
 	u32 (*decrypt) (struct crypto_blkcipher *tfm,
 			void *iv, void *in, void *out,
 			int length);		/* decryption function */
+	u32 (*mk_key) (struct gss_krb5_enctype *gk5e,
+		       struct xdr_netobj *in,
+		       struct xdr_netobj *out);	/* complete key generation */
 };
 
 struct krb5_ctx {
@@ -146,6 +152,25 @@ extern struct xdr_netobj krb5_oid;
 #define ENCTYPE_DES3_CBC_SHA1   0x0010
 #define ENCTYPE_UNKNOWN         0x01ff
 
+/*
+ * Constants used for key derivation
+ */
+/* for 3DES */
+#define KG_USAGE_SEAL 22
+#define KG_USAGE_SIGN 23
+#define KG_USAGE_SEQ  24
+
+/* from rfc3961 */
+#define KEY_USAGE_SEED_CHECKSUM         0x99
+#define KEY_USAGE_SEED_ENCRYPTION       0xAA
+#define KEY_USAGE_SEED_INTEGRITY        0x55
+
+/* from rfc4121 */
+#define KG_USAGE_ACCEPTOR_SEAL  22
+#define KG_USAGE_ACCEPTOR_SIGN  23
+#define KG_USAGE_INITIATOR_SEAL 24
+#define KG_USAGE_INITIATOR_SIGN 25
+
 u32
 make_checksum(struct krb5_ctx *kctx, char *header, int hdrlen,
 		struct xdr_buf *body, int body_offset, u8 *cksumkey,
@@ -191,3 +216,8 @@ s32
 krb5_get_seq_num(struct crypto_blkcipher *key,
 	       unsigned char *cksum,
 	       unsigned char *buf, int *direction, s32 * seqnum);
+
+u32 krb5_derive_key(struct gss_krb5_enctype *gk5e,
+		    const struct xdr_netobj *inkey,
+		    struct xdr_netobj *outkey,
+		    const struct xdr_netobj *in_constant);
diff --git a/net/sunrpc/auth_gss/Makefile b/net/sunrpc/auth_gss/Makefile
index f3431a7..e8981e9 100644
--- a/net/sunrpc/auth_gss/Makefile
+++ b/net/sunrpc/auth_gss/Makefile
@@ -5,12 +5,12 @@
 obj-$(CONFIG_SUNRPC_GSS) += auth_rpcgss.o
 
 auth_rpcgss-objs := auth_gss.o gss_generic_token.o \
-	gss_mech_switch.o svcauth_gss.o gss_krb5_crypto.o
+	gss_mech_switch.o svcauth_gss.o gss_debug.o
 
 obj-$(CONFIG_RPCSEC_GSS_KRB5) += rpcsec_gss_krb5.o
 
 rpcsec_gss_krb5-objs := gss_krb5_mech.o gss_krb5_seal.o gss_krb5_unseal.o \
-	gss_krb5_seqnum.o gss_krb5_wrap.o
+	gss_krb5_seqnum.o gss_krb5_wrap.o gss_krb5_crypto.o gss_krb5_keys.o
 
 obj-$(CONFIG_RPCSEC_GSS_SPKM3) += rpcsec_gss_spkm3.o
 
diff --git a/net/sunrpc/auth_gss/gss_krb5_keys.c b/net/sunrpc/auth_gss/gss_krb5_keys.c
new file mode 100644
index 0000000..97ec67d
--- /dev/null
+++ b/net/sunrpc/auth_gss/gss_krb5_keys.c
@@ -0,0 +1,255 @@
+/*
+ *  linux/net/sunrpc/gss_krb5_keys.c
+ *
+ * COPYRIGHT (c) 2008
+ * The Regents of the University of Michigan
+ * ALL RIGHTS RESERVED
+ *
+ * Permission is granted to use, copy, create derivative works
+ * and redistribute this software and such derivative works
+ * for any purpose, so long as the name of The University of
+ * Michigan is not used in any advertising or publicity
+ * pertaining to the use of distribution of this software
+ * without specific, written prior authorization.  If the
+ * above copyright notice or any other identification of the
+ * University of Michigan is included in any copy of any
+ * portion of this software, then the disclaimer below must
+ * also be included.
+ *
+ * THIS SOFTWARE IS PROVIDED AS IS, WITHOUT REPRESENTATION
+ * FROM THE UNIVERSITY OF MICHIGAN AS TO ITS FITNESS FOR ANY
+ * PURPOSE, AND WITHOUT WARRANTY BY THE UNIVERSITY OF
+ * MICHIGAN OF ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING
+ * WITHOUT LIMITATION THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE
+ * REGENTS OF THE UNIVERSITY OF MICHIGAN SHALL NOT BE LIABLE
+ * FOR ANY DAMAGES, INCLUDING SPECIAL, INDIRECT, INCIDENTAL, OR
+ * CONSEQUENTIAL DAMAGES, WITH RESPECT TO ANY CLAIM ARISING
+ * OUT OF OR IN CONNECTION WITH THE USE OF THE SOFTWARE, EVEN
+ * IF IT HAS BEEN OR IS HEREAFTER ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGES.
+ */
+
+/*
+ * Copyright (C) 1998 by the FundsXpress, INC.
+ *
+ * All rights reserved.
+ *
+ * Export of this software from the United States of America may require
+ * a specific license from the United States Government.  It is the
+ * responsibility of any person or organization contemplating export to
+ * obtain such a license before exporting.
+ *
+ * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and
+ * distribute this software and its documentation for any purpose and
+ * without fee is hereby granted, provided that the above copyright
+ * notice appear in all copies and that both that copyright notice and
+ * this permission notice appear in supporting documentation, and that
+ * the name of FundsXpress. not be used in advertising or publicity pertaining
+ * to distribution of the software without specific, written prior
+ * permission.  FundsXpress makes no representations about the suitability of
+ * this software for any purpose.  It is provided "as is" without express
+ * or implied warranty.
+ *
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
+ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+ */
+
+#include <linux/err.h>
+#include <linux/types.h>
+#include <linux/crypto.h>
+#include <linux/sunrpc/gss_krb5.h>
+#include <linux/sunrpc/xdr.h>
+
+#ifdef RPC_DEBUG
+# define RPCDBG_FACILITY        RPCDBG_AUTH
+#endif
+
+/*
+ * 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)
+{
+	int a, b, c, lcm;
+	int byte, i, msbit;
+
+	/* the code below is more readable if I make these bytes
+	   instead of bits */
+
+	inbits >>= 3;
+	outbits >>= 3;
+
+	/* first compute lcm(n,k) */
+
+	a = outbits;
+	b = inbits;
+
+	while (b != 0) {
+		c = b;
+		b = a%b;
+		a = c;
+	}
+
+	lcm = outbits*inbits/a;
+
+	/* now do the real work */
+
+	memset(out, 0, outbits);
+	byte = 0;
+
+	/* this will end up cycling through k lcm(k,n)/k times, which
+	   is correct */
+	for (i = lcm-1; i >= 0; i--) {
+		/* compute the msbit in k which gets added into this byte */
+		msbit = (
+			/* first, start with the msbit in the first,
+			 * unrotated byte */
+			 ((inbits << 3) - 1)
+			 /* then, for each byte, shift to the right
+			  * for each repetition */
+			 + (((inbits << 3) + 13) * (i/inbits))
+			 /* last, pick out the correct byte within
+			  * that shifted repetition */
+			 + ((inbits - (i % inbits)) << 3)
+			 ) % (inbits << 3);
+
+		/* pull out the byte value itself */
+		byte += (((in[((inbits - 1) - (msbit >> 3)) % inbits] << 8)|
+				  (in[((inbits) - (msbit >> 3)) % inbits]))
+				 >> ((msbit & 7) + 1)) & 0xff;
+
+		/* do the addition */
+		byte += out[i % outbits];
+		out[i % outbits] = byte & 0xff;
+
+		/* keep around the carry bit, if any */
+		byte >>= 8;
+
+	}
+
+	/* if there's a carry bit left over, add it back in */
+	if (byte) {
+		for (i = outbits - 1; i >= 0; i--) {
+			/* do the addition */
+			byte += out[i];
+			out[i] = byte & 0xff;
+
+			/* keep around the carry bit, if any */
+			byte >>= 8;
+		}
+	}
+}
+
+/*
+ * This is the DK (derive_key) function as described in rfc3961, sec 5.1
+ * Taken from MIT Kerberos and modified.
+ */
+
+u32 krb5_derive_key(struct gss_krb5_enctype *gk5e,
+		    const struct xdr_netobj *inkey,
+		    struct xdr_netobj *outkey,
+		    const struct xdr_netobj *in_constant)
+{
+	size_t blocksize, keybytes, keylength, n;
+	unsigned char *inblockdata, *outblockdata, *rawkey;
+	struct xdr_netobj inblock, outblock;
+	struct crypto_blkcipher *cipher;
+	u32 ret = EINVAL;
+
+	blocksize = gk5e->blocksize;
+	keybytes = gk5e->keybytes;
+	keylength = gk5e->keylength;
+
+	if ((inkey->len != keylength) || (outkey->len != keylength))
+		goto err_return;
+
+	cipher = crypto_alloc_blkcipher(gk5e->encrypt_name, 0,
+					CRYPTO_ALG_ASYNC);
+	if (IS_ERR(cipher))
+		goto err_return;
+	if (crypto_blkcipher_setkey(cipher, inkey->data, inkey->len))
+		goto err_return;
+
+	/* allocate and set up buffers */
+
+	ret = ENOMEM;
+	inblockdata = kmalloc(blocksize, GFP_KERNEL);
+	if (inblockdata == NULL)
+		goto err_free_cipher;
+
+	outblockdata = kmalloc(blocksize, GFP_KERNEL);
+	if (outblockdata == NULL)
+		goto err_free_in;
+
+	rawkey = kmalloc(keybytes, GFP_KERNEL);
+	if (rawkey == NULL)
+		goto err_free_out;
+
+	inblock.data = (char *) inblockdata;
+	inblock.len = blocksize;
+
+	outblock.data = (char *) outblockdata;
+	outblock.len = blocksize;
+
+	/* initialize the input block */
+
+	if (in_constant->len == inblock.len) {
+		memcpy(inblock.data, in_constant->data, inblock.len);
+	} else {
+		krb5_nfold(in_constant->len * 8, in_constant->data,
+			   inblock.len * 8, inblock.data);
+	}
+
+	/* loop encrypting the blocks until enough key bytes are generated */
+
+	n = 0;
+	while (n < keybytes) {
+		(*(gk5e->encrypt))(cipher, NULL, inblock.data,
+				   outblock.data, inblock.len);
+
+		if ((keybytes - n) <= outblock.len) {
+			memcpy(rawkey + n, outblock.data, (keybytes - n));
+			break;
+		}
+
+		memcpy(rawkey + n, outblock.data, outblock.len);
+		memcpy(inblock.data, outblock.data, outblock.len);
+		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:
+	memset(rawkey, 0, keybytes);
+	kfree(rawkey);
+err_free_out:
+	memset(outblockdata, 0, blocksize);
+	kfree(outblockdata);
+err_free_in:
+	memset(inblockdata, 0, blocksize);
+	kfree(inblockdata);
+err_free_cipher:
+	crypto_free_blkcipher(cipher);
+err_return:
+	return ret;
+}
+EXPORT_SYMBOL(krb5_derive_key);
diff --git a/net/sunrpc/auth_gss/gss_krb5_mech.c b/net/sunrpc/auth_gss/gss_krb5_mech.c
index 28335cc..83973c8 100644
--- a/net/sunrpc/auth_gss/gss_krb5_mech.c
+++ b/net/sunrpc/auth_gss/gss_krb5_mech.c
@@ -60,6 +60,7 @@ static struct gss_krb5_enctype supported_gss_krb5_enctypes[] = {
 	  .cksum_name = "md5",
 	  .encrypt = krb5_encrypt,
 	  .decrypt = krb5_decrypt,
+	  .mk_key = NULL,
 	  .signalg = SGN_ALG_DES_MAC_MD5,
 	  .sealalg = SEAL_ALG_DES,
 	  .keybytes = 7,


^ permalink raw reply related	[flat|nested] 31+ messages in thread

* [PATCH 14/19] gss_krb5: use a global static OID value for krb5
       [not found] ` <20080221184208.19195.94518.stgit-zTNJhAanYLVZN1qrTdtDg5Vzexx5G7lz@public.gmane.org>
                     ` (12 preceding siblings ...)
  2008-02-21 18:44   ` [PATCH 13/19] gss_krb5: import functionality to derive keys into the kernel Kevin Coffman
@ 2008-02-21 18:44   ` Kevin Coffman
  2008-02-21 18:45   ` [PATCH 15/19] gss_krb5: handle new context format from gssd Kevin Coffman
                     ` (4 subsequent siblings)
  18 siblings, 0 replies; 31+ messages in thread
From: Kevin Coffman @ 2008-02-21 18:44 UTC (permalink / raw)
  To: linux-nfs

Rather than depend on the mechanism oid passed down with the context
information, use a static version.  The new context format introduced
later will not include the oid.

Signed-off-by: Kevin Coffman <kwc@citi.umich.edu>
---

 net/sunrpc/auth_gss/gss_krb5_seal.c   |    4 ++--
 net/sunrpc/auth_gss/gss_krb5_unseal.c |    2 +-
 net/sunrpc/auth_gss/gss_krb5_wrap.c   |    6 +++---
 3 files changed, 6 insertions(+), 6 deletions(-)

diff --git a/net/sunrpc/auth_gss/gss_krb5_seal.c b/net/sunrpc/auth_gss/gss_krb5_seal.c
index f5badc7..285188d 100644
--- a/net/sunrpc/auth_gss/gss_krb5_seal.c
+++ b/net/sunrpc/auth_gss/gss_krb5_seal.c
@@ -77,10 +77,10 @@ setup_token(struct krb5_ctx *ctx, struct xdr_netobj *token)
 	__be16 *ptr, *krb5_hdr;
 	int body_size = 16 + ctx->gk5e->cksumlength;
 
-	token->len = g_token_size(&ctx->mech_used, body_size);
+	token->len = g_token_size(&krb5_oid, body_size);
 
 	ptr = (__be16 *)token->data;
-	g_make_token_header(&ctx->mech_used, body_size, (unsigned char **)&ptr);
+	g_make_token_header(&krb5_oid, body_size, (unsigned char **)&ptr);
 
 	/* ptr now at start of header described in rfc 1964, section 1.2.1: */
 	krb5_hdr = ptr;
diff --git a/net/sunrpc/auth_gss/gss_krb5_unseal.c b/net/sunrpc/auth_gss/gss_krb5_unseal.c
index 5494ba4..c9adcfc 100644
--- a/net/sunrpc/auth_gss/gss_krb5_unseal.c
+++ b/net/sunrpc/auth_gss/gss_krb5_unseal.c
@@ -89,7 +89,7 @@ gss_verify_mic_v1(struct krb5_ctx *ctx,
 
 	dprintk("RPC:       krb5_read_token\n");
 
-	if (g_verify_token_header(&ctx->mech_used, &bodysize, &ptr,
+	if (g_verify_token_header(&krb5_oid, &bodysize, &ptr,
 					read_token->len))
 		return GSS_S_DEFECTIVE_TOKEN;
 
diff --git a/net/sunrpc/auth_gss/gss_krb5_wrap.c b/net/sunrpc/auth_gss/gss_krb5_wrap.c
index dd6caf3..a68677c 100644
--- a/net/sunrpc/auth_gss/gss_krb5_wrap.c
+++ b/net/sunrpc/auth_gss/gss_krb5_wrap.c
@@ -122,7 +122,7 @@ gss_wrap_kerberos_v1(struct krb5_ctx *kctx, int offset,
 	BUG_ON((buf->len - offset) % blocksize);
 	plainlen = blocksize + buf->len - offset;
 
-	headlen = g_token_size(&kctx->mech_used,
+	headlen = g_token_size(&krb5_oid,
 		16 + kctx->gk5e->cksumlength + plainlen) - (buf->len - offset);
 
 	ptr = buf->head[0].iov_base + offset;
@@ -134,7 +134,7 @@ gss_wrap_kerberos_v1(struct krb5_ctx *kctx, int offset,
 	buf->len += headlen;
 	BUG_ON((buf->len - offset - headlen) % blocksize);
 
-	g_make_token_header(&kctx->mech_used,
+	g_make_token_header(&krb5_oid,
 				16 + kctx->gk5e->cksumlength + plainlen, &ptr);
 
 
@@ -205,7 +205,7 @@ gss_unwrap_kerberos_v1(struct krb5_ctx *kctx, int offset, struct xdr_buf *buf)
 	dprintk("RPC:       gss_unwrap_kerberos\n");
 
 	ptr = (u8 *)buf->head[0].iov_base + offset;
-	if (g_verify_token_header(&kctx->mech_used, &bodysize, &ptr,
+	if (g_verify_token_header(&krb5_oid, &bodysize, &ptr,
 					buf->len - offset))
 		return GSS_S_DEFECTIVE_TOKEN;
 


^ permalink raw reply related	[flat|nested] 31+ messages in thread

* [PATCH 15/19] gss_krb5: handle new context format from gssd
       [not found] ` <20080221184208.19195.94518.stgit-zTNJhAanYLVZN1qrTdtDg5Vzexx5G7lz@public.gmane.org>
                     ` (13 preceding siblings ...)
  2008-02-21 18:44   ` [PATCH 14/19] gss_krb5: use a global static OID value for krb5 Kevin Coffman
@ 2008-02-21 18:45   ` Kevin Coffman
  2008-02-21 18:45   ` [PATCH 16/19] gss_krb5: add support for triple-des encryption Kevin Coffman
                     ` (3 subsequent siblings)
  18 siblings, 0 replies; 31+ messages in thread
From: Kevin Coffman @ 2008-02-21 18:45 UTC (permalink / raw)
  To: linux-nfs

For encryption types other than DES, gssd sends down context information
in a new format.  This new format includes the information needed to
support the new Kerberos GSS-API tokens defined in rfc4121.

Signed-off-by: Kevin Coffman <kwc@citi.umich.edu>
---

 include/linux/sunrpc/gss_krb5.h     |   19 +++
 net/sunrpc/auth_gss/gss_krb5_mech.c |  236 +++++++++++++++++++++++++++++++++++
 2 files changed, 254 insertions(+), 1 deletions(-)

diff --git a/include/linux/sunrpc/gss_krb5.h b/include/linux/sunrpc/gss_krb5.h
index d326911..e828e98 100644
--- a/include/linux/sunrpc/gss_krb5.h
+++ b/include/linux/sunrpc/gss_krb5.h
@@ -77,16 +77,31 @@ struct gss_krb5_enctype {
 		       struct xdr_netobj *out);	/* complete key generation */
 };
 
+/* 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;
 	struct gss_krb5_enctype *gk5e;		/* enctype-specific info */
 	struct crypto_blkcipher	*enc;
 	struct crypto_blkcipher	*seq;
+	struct crypto_blkcipher *acceptor_enc;
+	struct crypto_blkcipher *initiator_enc;
 	u8			cksum[GSS_KRB5_MAX_KEYLEN];
 	s32			endtime;
 	u32			seq_send;
+	u64			seq_send64;
 	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];
 };
 
 extern spinlock_t krb5_seq_lock;
@@ -150,6 +165,10 @@ extern struct xdr_netobj krb5_oid;
 #define ENCTYPE_DES3_CBC_RAW    0x0006	/* DES-3 cbc mode raw */
 #define ENCTYPE_DES_HMAC_SHA1   0x0008
 #define ENCTYPE_DES3_CBC_SHA1   0x0010
+#define ENCTYPE_AES128_CTS_HMAC_SHA1_96 0x0011
+#define ENCTYPE_AES256_CTS_HMAC_SHA1_96 0x0012
+#define ENCTYPE_ARCFOUR_HMAC            0x0017
+#define ENCTYPE_ARCFOUR_HMAC_EXP        0x0018
 #define ENCTYPE_UNKNOWN         0x01ff
 
 /*
diff --git a/net/sunrpc/auth_gss/gss_krb5_mech.c b/net/sunrpc/auth_gss/gss_krb5_mech.c
index 83973c8..fc30538 100644
--- a/net/sunrpc/auth_gss/gss_krb5_mech.c
+++ b/net/sunrpc/auth_gss/gss_krb5_mech.c
@@ -247,6 +247,238 @@ out_err:
 	return PTR_ERR(p);
 }
 
+struct crypto_blkcipher *
+context_v2_alloc_cipher(struct krb5_ctx *ctx, u8 *key)
+{
+	struct crypto_blkcipher *cp;
+
+	cp = crypto_alloc_blkcipher(ctx->gk5e->encrypt_name,
+					0, CRYPTO_ALG_ASYNC);
+	if (IS_ERR(cp)) {
+		printk("gss_kerberos_mech: unable to initialize "
+			"crypto algorithm %s\n", ctx->gk5e->encrypt_name);
+		return NULL;
+	}
+	if (crypto_blkcipher_setkey(cp, key, ctx->gk5e->keylength)) {
+		printk("gss_kerberos_mech: error setting key for "
+			"crypto algorithm %s\n", ctx->gk5e->encrypt_name);
+		crypto_free_blkcipher(cp);
+		return NULL;
+	}
+	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;
+}
+
+static int
+context_derive_keys_des3(struct krb5_ctx *ctx, u8 *rawkey, u32 keylen)
+{
+	struct xdr_netobj c, keyin, keyout;
+	u8 cdata[GSS_KRB5_K5CLENGTH];
+#if 0
+	u8 derivedkey[GSS_KRB5_MAX_KEYLEN];
+#endif
+	u32 err;
+
+	c.len = GSS_KRB5_K5CLENGTH;
+	c.data = cdata;
+
+	keyin.data = rawkey;
+	keyin.len = keylen;
+	keyout.len = keylen;
+
+	/* seq uses the raw key */
+	ctx->seq = context_v2_alloc_cipher(ctx, rawkey);
+	if (ctx->seq == NULL)
+		goto out_err;
+
+#if 0
+	/* derive enc */
+	set_cdata(cdata, KG_USAGE_SEQ, KEY_USAGE_SEED_ENCRYPTION);
+	keyout.data = derivedkey;
+	err = krb5_derive_key(ctx->gk5e, &keyin, &keyout, &c);
+	if (err) {
+		dprintk("%s: Error %d deriving enc key\n",
+			__func__, err);
+		goto out_free_seq;
+	}
+	ctx->enc = context_v2_alloc_cipher(ctx, derivedkey);
+#else
+	ctx->enc = context_v2_alloc_cipher(ctx, rawkey);
+#endif
+	if (ctx->enc == NULL)
+		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);
+	if (err) {
+		dprintk("%s: Error %d deriving cksum key\n",
+			__func__, err);
+		goto out_free_enc;
+	}
+
+	return 0;
+
+out_free_enc:
+	crypto_free_blkcipher(ctx->enc);
+out_free_seq:
+	crypto_free_blkcipher(ctx->seq);
+out_err:
+	return -EINVAL;
+}
+
+static int
+context_derive_keys_new(struct krb5_ctx *ctx, u8 *rawkey, u32 keylen)
+{
+	struct xdr_netobj c, keyin, keyout;
+	u8 cdata[GSS_KRB5_K5CLENGTH];
+	u32 err;
+
+	c.len = GSS_KRB5_K5CLENGTH;
+	c.data = cdata;
+
+	keyin.data = rawkey;
+	keyin.len = keylen;
+	keyout.len = keylen;
+
+	/* 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);
+	if (err) {
+		dprintk("%s: Error %d deriving initiator_seal key\n",
+			__func__, err);
+		goto out_err;
+	}
+	ctx->initiator_enc = context_v2_alloc_cipher(ctx, ctx->initiator_seal);
+	if (ctx->initiator_enc == NULL)
+		goto out_err;
+
+	/* 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);
+	if (err) {
+		dprintk("%s: Error %d deriving acceptor_seal key\n",
+			__func__, err);
+		goto out_free_initiator_enc;
+	}
+	ctx->acceptor_enc = context_v2_alloc_cipher(ctx, ctx->acceptor_seal);
+	if (ctx->acceptor_enc == NULL)
+		goto out_free_initiator_enc;
+
+	/* 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);
+	if (err) {
+		dprintk("%s: Error %d deriving initiator_sign key\n",
+			__func__, err);
+		goto out_free_acceptor_enc;
+	}
+
+	/* 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);
+	if (err) {
+		dprintk("%s: Error %d deriving acceptor_sign key\n",
+			__func__, err);
+		goto out_free_acceptor_enc;
+	}
+
+	/* 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);
+	if (err) {
+		dprintk("%s: Error %d deriving initiator_integ key\n",
+			__func__, err);
+		goto out_free_acceptor_enc;
+	}
+
+	/* 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);
+	if (err) {
+		dprintk("%s: Error %d deriving acceptor_integ key\n",
+			__func__, err);
+		goto out_free_acceptor_enc;
+	}
+
+	return 0;
+
+out_free_acceptor_enc:
+	crypto_free_blkcipher(ctx->acceptor_enc);
+out_free_initiator_enc:
+	crypto_free_blkcipher(ctx->initiator_enc);
+out_err:
+	return -EINVAL;
+}
+
+static int
+gss_import_v2_context(const void *p, const void *end, struct krb5_ctx *ctx)
+{
+	u8 rawkey[GSS_KRB5_MAX_KEYLEN];
+	int keylen;
+
+	p = simple_get_bytes(p, end, &ctx->flags, sizeof(ctx->flags));
+	if (IS_ERR(p))
+		goto out_err;
+	ctx->initiate = ctx->flags & KRB5_CTX_FLAG_INITIATOR;
+
+	p = simple_get_bytes(p, end, &ctx->endtime, sizeof(ctx->endtime));
+	if (IS_ERR(p))
+		goto out_err;
+	p = simple_get_bytes(p, end, &ctx->seq_send64, sizeof(ctx->seq_send64));
+	if (IS_ERR(p))
+		goto out_err;
+	p = simple_get_bytes(p, end, &ctx->enctype, sizeof(ctx->enctype));
+	if (IS_ERR(p))
+		goto out_err;
+	ctx->gk5e = get_gss_krb5_enctype(ctx->enctype);
+	if (ctx->gk5e == NULL) {
+		printk("gss_kerberos_mech: unsupported krb5 enctype %u\n",
+			ctx->enctype);
+		p = ERR_PTR(-EINVAL);
+		goto out_err;
+	}
+	keylen = ctx->gk5e->keylength;
+
+	p = simple_get_bytes(p, end, rawkey, keylen);
+	if (IS_ERR(p))
+		goto out_err;
+
+	if (p != end) {
+		p = ERR_PTR(-EINVAL);
+		goto out_err;
+	}
+
+	switch (ctx->enctype) {
+	case ENCTYPE_DES3_CBC_RAW:
+		return context_derive_keys_des3(ctx, rawkey, keylen);
+	case ENCTYPE_AES128_CTS_HMAC_SHA1_96:
+	case ENCTYPE_AES256_CTS_HMAC_SHA1_96:
+		return context_derive_keys_new(ctx, rawkey, keylen);
+	default:
+		return -EINVAL;
+	}
+
+out_err:
+	return PTR_ERR(p);
+}
+
 static int
 gss_import_sec_context_kerberos(const void *p, size_t len,
 				struct gss_ctx *ctx_id)
@@ -263,7 +495,7 @@ gss_import_sec_context_kerberos(const void *p, size_t len,
 	if (len == 85)
 		ret = gss_import_v1_context(p, end, ctx);
 	else
-		ret = -EINVAL;
+		ret = gss_import_v2_context(p, end, ctx);
 
 	if (ret == 0)
 		ctx_id->internal_ctx_id = ctx;
@@ -280,6 +512,8 @@ gss_delete_sec_context_kerberos(void *internal_ctx) {
 
 	crypto_free_blkcipher(kctx->seq);
 	crypto_free_blkcipher(kctx->enc);
+	crypto_free_blkcipher(kctx->acceptor_enc);
+	crypto_free_blkcipher(kctx->initiator_enc);
 	kfree(kctx->mech_used.data);
 	kfree(kctx);
 }


^ permalink raw reply related	[flat|nested] 31+ messages in thread

* [PATCH 16/19] gss_krb5: add support for triple-des encryption
       [not found] ` <20080221184208.19195.94518.stgit-zTNJhAanYLVZN1qrTdtDg5Vzexx5G7lz@public.gmane.org>
                     ` (14 preceding siblings ...)
  2008-02-21 18:45   ` [PATCH 15/19] gss_krb5: handle new context format from gssd Kevin Coffman
@ 2008-02-21 18:45   ` Kevin Coffman
  2008-02-21 18:45   ` [PATCH 17/19] xdr: add a new utility function to shift the head data of an xdr buffer Kevin Coffman
                     ` (2 subsequent siblings)
  18 siblings, 0 replies; 31+ messages in thread
From: Kevin Coffman @ 2008-02-21 18:45 UTC (permalink / raw)
  To: linux-nfs

Add the final pieces to support the triple-des encryption type.

Signed-off-by: Kevin Coffman <kwc@citi.umich.edu>
---

 include/linux/sunrpc/gss_krb5.h       |    4 ++
 net/sunrpc/auth_gss/gss_krb5_crypto.c |    3 ++
 net/sunrpc/auth_gss/gss_krb5_keys.c   |   53 +++++++++++++++++++++++++++++++++
 net/sunrpc/auth_gss/gss_krb5_mech.c   |   23 ++++++++++++++
 net/sunrpc/auth_gss/gss_krb5_seal.c   |    1 +
 net/sunrpc/auth_gss/gss_krb5_unseal.c |    1 +
 net/sunrpc/auth_gss/gss_krb5_wrap.c   |    2 +
 net/sunrpc/rpc_pipe.c                 |    2 +
 8 files changed, 88 insertions(+), 1 deletions(-)

diff --git a/include/linux/sunrpc/gss_krb5.h b/include/linux/sunrpc/gss_krb5.h
index e828e98..bf58284 100644
--- a/include/linux/sunrpc/gss_krb5.h
+++ b/include/linux/sunrpc/gss_krb5.h
@@ -240,3 +240,7 @@ u32 krb5_derive_key(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(struct gss_krb5_enctype *gk5e,
+			   struct xdr_netobj *randombits,
+			   struct xdr_netobj *key);
diff --git a/net/sunrpc/auth_gss/gss_krb5_crypto.c b/net/sunrpc/auth_gss/gss_krb5_crypto.c
index 8b12f34..4f963c2 100644
--- a/net/sunrpc/auth_gss/gss_krb5_crypto.c
+++ b/net/sunrpc/auth_gss/gss_krb5_crypto.c
@@ -189,6 +189,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;
diff --git a/net/sunrpc/auth_gss/gss_krb5_keys.c b/net/sunrpc/auth_gss/gss_krb5_keys.c
index 97ec67d..a722fba 100644
--- a/net/sunrpc/auth_gss/gss_krb5_keys.c
+++ b/net/sunrpc/auth_gss/gss_krb5_keys.c
@@ -253,3 +253,56 @@ err_return:
 	return ret;
 }
 EXPORT_SYMBOL(krb5_derive_key);
+
+#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(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);
+}
diff --git a/net/sunrpc/auth_gss/gss_krb5_mech.c b/net/sunrpc/auth_gss/gss_krb5_mech.c
index fc30538..2edf28e 100644
--- a/net/sunrpc/auth_gss/gss_krb5_mech.c
+++ b/net/sunrpc/auth_gss/gss_krb5_mech.c
@@ -69,6 +69,26 @@ static 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 int num_supported_enctypes =
@@ -447,6 +467,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) {
 		printk("gss_kerberos_mech: unsupported krb5 enctype %u\n",
diff --git a/net/sunrpc/auth_gss/gss_krb5_seal.c b/net/sunrpc/auth_gss/gss_krb5_seal.c
index 285188d..b1d9436 100644
--- a/net/sunrpc/auth_gss/gss_krb5_seal.c
+++ b/net/sunrpc/auth_gss/gss_krb5_seal.c
@@ -140,6 +140,7 @@ gss_get_mic_kerberos(struct gss_ctx *gss_ctx, struct xdr_buf *text,
 
 	switch (ctx->enctype) {
 	case ENCTYPE_DES_CBC_RAW:
+	case ENCTYPE_DES3_CBC_RAW:
 		return gss_get_mic_v1(ctx, text, token);
 	default:
 		BUG();
diff --git a/net/sunrpc/auth_gss/gss_krb5_unseal.c b/net/sunrpc/auth_gss/gss_krb5_unseal.c
index c9adcfc..7ba63ae 100644
--- a/net/sunrpc/auth_gss/gss_krb5_unseal.c
+++ b/net/sunrpc/auth_gss/gss_krb5_unseal.c
@@ -150,6 +150,7 @@ gss_verify_mic_kerberos(struct gss_ctx *gss_ctx,
 
 	switch (ctx->enctype) {
 	case ENCTYPE_DES_CBC_RAW:
+	case ENCTYPE_DES3_CBC_RAW:
 		return gss_verify_mic_v1(ctx, message_buffer, read_token);
 	default:
 		BUG();
diff --git a/net/sunrpc/auth_gss/gss_krb5_wrap.c b/net/sunrpc/auth_gss/gss_krb5_wrap.c
index a68677c..d59e9b2 100644
--- a/net/sunrpc/auth_gss/gss_krb5_wrap.c
+++ b/net/sunrpc/auth_gss/gss_krb5_wrap.c
@@ -291,6 +291,7 @@ gss_wrap_kerberos(struct gss_ctx *gctx, int offset,
 
 	switch (kctx->enctype) {
 	case ENCTYPE_DES_CBC_RAW:
+	case ENCTYPE_DES3_CBC_RAW:
 		return gss_wrap_kerberos_v1(kctx, offset, buf, pages);
 		break;
 	default:
@@ -307,6 +308,7 @@ gss_unwrap_kerberos(struct gss_ctx *gctx, int offset, struct xdr_buf *buf)
 
 	switch (kctx->enctype) {
 	case ENCTYPE_DES_CBC_RAW:
+	case ENCTYPE_DES3_CBC_RAW:
 		return gss_unwrap_kerberos_v1(kctx, offset, buf);
 		break;
 	default:
diff --git a/net/sunrpc/rpc_pipe.c b/net/sunrpc/rpc_pipe.c
index 5781862..d84632a 100644
--- a/net/sunrpc/rpc_pipe.c
+++ b/net/sunrpc/rpc_pipe.c
@@ -392,7 +392,7 @@ static const struct file_operations rpc_info_operations = {
 static int
 rpc_show_krb5_info(struct seq_file *m, void *v)
 {
-	seq_printf(m, "enctypes: 3,1,2\n");
+	seq_printf(m, "enctypes: 16,3,1,2\n");
 	return 0;
 }
 


^ permalink raw reply related	[flat|nested] 31+ messages in thread

* [PATCH 17/19] xdr: add a new utility function to shift the head data of an xdr buffer
       [not found] ` <20080221184208.19195.94518.stgit-zTNJhAanYLVZN1qrTdtDg5Vzexx5G7lz@public.gmane.org>
                     ` (15 preceding siblings ...)
  2008-02-21 18:45   ` [PATCH 16/19] gss_krb5: add support for triple-des encryption Kevin Coffman
@ 2008-02-21 18:45   ` Kevin Coffman
  2008-02-21 18:45   ` [PATCH 18/19] gss_krb5: add support for new token formats in rfc4121 Kevin Coffman
  2008-02-21 18:45   ` [PATCH 19/19] gss_krb5: add remaining pieces to enable AES encryption support Kevin Coffman
  18 siblings, 0 replies; 31+ messages in thread
From: Kevin Coffman @ 2008-02-21 18:45 UTC (permalink / raw)
  To: linux-nfs

Add a new xdr helper function that shifts the data in an xdr
buffer's head to make room for new data.

Also add an export for the helper function  write_bytes_to_xdr_buf().

Signed-off-by: Kevin Coffman <kwc@citi.umich.edu>
---

 include/linux/sunrpc/xdr.h |    2 ++
 net/sunrpc/xdr.c           |   29 +++++++++++++++++++++++++++++
 2 files changed, 31 insertions(+), 0 deletions(-)

diff --git a/include/linux/sunrpc/xdr.h b/include/linux/sunrpc/xdr.h
index e4057d7..518d47c 100644
--- a/include/linux/sunrpc/xdr.h
+++ b/include/linux/sunrpc/xdr.h
@@ -164,6 +164,8 @@ extern int xdr_buf_subsegment(struct xdr_buf *, struct xdr_buf *, unsigned int,
 extern int xdr_buf_read_netobj(struct xdr_buf *, struct xdr_netobj *, unsigned int);
 extern int read_bytes_from_xdr_buf(struct xdr_buf *, unsigned int, void *, unsigned int);
 extern int write_bytes_to_xdr_buf(struct xdr_buf *, unsigned int, void *, unsigned int);
+extern int xdr_shift_head_data(struct xdr_buf *, int, unsigned int);
+
 
 /*
  * Helper structure for copying from an sk_buff.
diff --git a/net/sunrpc/xdr.c b/net/sunrpc/xdr.c
index 995c3fd..de2c986 100644
--- a/net/sunrpc/xdr.c
+++ b/net/sunrpc/xdr.c
@@ -428,6 +428,34 @@ xdr_shift_buf(struct xdr_buf *buf, size_t len)
 EXPORT_SYMBOL(xdr_shift_buf);
 
 /**
+ * xdr_xdr_shift_head_data - Make room for new data within buf->head
+ * @buf: pointer to XDR buffer
+ * @offset: offset within the head to start moving data
+ * @shiftlen: number of bytes to shift the data
+ */
+int
+xdr_shift_head_data(struct xdr_buf *buf, int offset, unsigned int shiftlen)
+{
+	u8 *p;
+
+	if (shiftlen == 0)
+		return 0;
+	/* make sure there is room (assuming head has a page) */
+	if (buf->head[0].iov_len + shiftlen + offset > PAGE_CACHE_SIZE)
+		return 1;
+
+	p = buf->head[0].iov_base + offset;
+
+	memmove(p + shiftlen, p, buf->head[0].iov_len - offset);
+
+	buf->head[0].iov_len += shiftlen;
+	buf->len += shiftlen;
+
+	return 0;
+}
+EXPORT_SYMBOL(xdr_shift_head_data);
+
+/**
  * xdr_init_encode - Initialize a struct xdr_stream for sending data.
  * @xdr: pointer to xdr_stream struct
  * @buf: pointer to XDR buffer in which to encode data
@@ -758,6 +786,7 @@ int write_bytes_to_xdr_buf(struct xdr_buf *buf, unsigned int base, void *obj, un
 	__write_bytes_to_xdr_buf(&subbuf, obj, len);
 	return 0;
 }
+EXPORT_SYMBOL(write_bytes_to_xdr_buf);
 
 int
 xdr_decode_word(struct xdr_buf *buf, unsigned int base, u32 *obj)


^ permalink raw reply related	[flat|nested] 31+ messages in thread

* [PATCH 18/19] gss_krb5: add support for new token formats in rfc4121
       [not found] ` <20080221184208.19195.94518.stgit-zTNJhAanYLVZN1qrTdtDg5Vzexx5G7lz@public.gmane.org>
                     ` (16 preceding siblings ...)
  2008-02-21 18:45   ` [PATCH 17/19] xdr: add a new utility function to shift the head data of an xdr buffer Kevin Coffman
@ 2008-02-21 18:45   ` Kevin Coffman
  2008-02-21 18:45   ` [PATCH 19/19] gss_krb5: add remaining pieces to enable AES encryption support Kevin Coffman
  18 siblings, 0 replies; 31+ messages in thread
From: Kevin Coffman @ 2008-02-21 18:45 UTC (permalink / raw)
  To: linux-nfs

This is a step toward support for AES encryption types which are required
to use the new token formats defined in rfc4121.

Signed-off-by: Kevin Coffman <kwc@citi.umich.edu>
---

 include/linux/sunrpc/gss_krb5.h       |   28 ++++
 net/sunrpc/auth_gss/gss_krb5_crypto.c |   71 +++++++++
 net/sunrpc/auth_gss/gss_krb5_seal.c   |   69 +++++++++
 net/sunrpc/auth_gss/gss_krb5_unseal.c |   60 ++++++++
 net/sunrpc/auth_gss/gss_krb5_wrap.c   |  248 +++++++++++++++++++++++++++++++++
 5 files changed, 476 insertions(+), 0 deletions(-)

diff --git a/include/linux/sunrpc/gss_krb5.h b/include/linux/sunrpc/gss_krb5.h
index bf58284..95b375b 100644
--- a/include/linux/sunrpc/gss_krb5.h
+++ b/include/linux/sunrpc/gss_krb5.h
@@ -53,6 +53,8 @@
 /* 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 */
@@ -75,6 +77,12 @@ struct gss_krb5_enctype {
 	u32 (*mk_key) (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, int ec,
+			   struct page **pages); /* v2 encryption function */
+	u32 (*decrypt_v2) (struct krb5_ctx *kctx, u32 offset,
+			   struct xdr_buf *buf, u32 *headskip,
+			   u32 *tailskip);	/* v2 decryption function */
 };
 
 /* krb5_ctx flags definitions */
@@ -109,6 +117,18 @@ extern spinlock_t krb5_seq_lock;
 #define KG_TOK_MIC_MSG    0x0101
 #define KG_TOK_WRAP_MSG   0x0201
 
+#define KG2_TOK_INITIAL     0x0101
+#define KG2_TOK_RESPONSE    0x0202
+#define KG2_TOK_MIC         0x0404
+#define KG2_TOK_WRAP        0x0504
+
+#define KG2_TOKEN_FLAG_SENTBYACCEPTOR   0x01
+#define KG2_TOKEN_FLAG_SEALED           0x02
+#define KG2_TOKEN_FLAG_ACCEPTORSUBKEY   0x04
+
+#define KG2_RESP_FLAG_ERROR             0x0001
+#define KG2_RESP_FLAG_DELEG_OK          0x0002
+
 enum sgn_alg {
 	SGN_ALG_DES_MAC_MD5 = 0x0000,
 	SGN_ALG_MD2_5 = 0x0001,
@@ -135,6 +155,9 @@ extern struct xdr_netobj krb5_oid;
 #define CKSUMTYPE_RSA_MD5_DES		0x0008
 #define CKSUMTYPE_NIST_SHA		0x0009
 #define CKSUMTYPE_HMAC_SHA1_DES3	0x000c
+#define CKSUMTYPE_HMAC_SHA1_96_AES128   0x000f
+#define CKSUMTYPE_HMAC_SHA1_96_AES256   0x0010
+#define CKSUMTYPE_HMAC_MD5_ARCFOUR      -138 /* Microsoft md5 hmac cksumtype */
 
 /* from gssapi_err_krb5.h */
 #define KG_CCACHE_NOMATCH                        (39756032L)
@@ -195,6 +218,11 @@ make_checksum(struct krb5_ctx *kctx, char *header, int hdrlen,
 		struct xdr_buf *body, int body_offset, u8 *cksumkey,
 		struct xdr_netobj *cksumout);
 
+extern u32
+make_checksum_v2(struct krb5_ctx *, char *header, int hdrlen,
+		 struct xdr_buf *body, int body_offset, u8 *key,
+		 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 4f963c2..0c52194 100644
--- a/net/sunrpc/auth_gss/gss_krb5_crypto.c
+++ b/net/sunrpc/auth_gss/gss_krb5_crypto.c
@@ -204,6 +204,77 @@ out:
 
 EXPORT_SYMBOL(make_checksum);
 
+/*
+ * 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
+ */
+u32
+make_checksum_v2(struct krb5_ctx *kctx, char *header, int hdrlen,
+		 struct xdr_buf *body, int body_offset, u8 *cksumkey,
+		 struct xdr_netobj *cksumout)
+{
+	struct hash_desc desc;
+	struct scatterlist sg[1];
+	int err;
+	u8 checksumdata[GSS_KRB5_MAX_CKSUM_LEN];
+	unsigned int checksumlen;
+
+	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;
+	}
+
+	desc.tfm = crypto_alloc_hash(kctx->gk5e->cksum_name, 0,
+							CRYPTO_ALG_ASYNC);
+	if (IS_ERR(desc.tfm))
+		return GSS_S_FAILURE;
+	checksumlen = crypto_hash_digestsize(desc.tfm);
+	desc.flags = CRYPTO_TFM_REQ_MAY_SLEEP;
+
+	err = crypto_hash_setkey(desc.tfm, cksumkey, kctx->gk5e->keylength);
+	if (err)
+		goto out;
+
+	err = crypto_hash_init(&desc);
+	if (err)
+		goto out;
+	err = xdr_process_buf(body, body_offset, body->len - body_offset,
+			      checksummer, &desc);
+	if (err)
+		goto out;
+	sg_init_one(sg, header, hdrlen);
+	err = crypto_hash_update(&desc, sg, hdrlen);
+	if (err)
+		goto out;
+	err = crypto_hash_final(&desc, checksumdata);
+	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:
+	crypto_free_hash(desc.tfm);
+	return err ? GSS_S_FAILURE : 0;
+}
+EXPORT_SYMBOL(make_checksum_v2);
+
 struct encryptor_desc {
 	u8 iv[GSS_KRB5_MAX_BLOCKSIZE];
 	struct blkcipher_desc desc;
diff --git a/net/sunrpc/auth_gss/gss_krb5_seal.c b/net/sunrpc/auth_gss/gss_krb5_seal.c
index b1d9436..e6083a0 100644
--- a/net/sunrpc/auth_gss/gss_krb5_seal.c
+++ b/net/sunrpc/auth_gss/gss_krb5_seal.c
@@ -92,6 +92,33 @@ setup_token(struct krb5_ctx *ctx, struct xdr_netobj *token)
 	return (char *)krb5_hdr;
 }
 
+static void *
+setup_token_v2(struct krb5_ctx *ctx, struct xdr_netobj *token)
+{
+	__be16 *ptr, *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 = (__be16 *)token->data;
+
+	*ptr++ = KG2_TOK_MIC;
+	p = (u8 *)ptr;
+	*p++ = flags;
+	*p++ = 0xff;
+	ptr = (__be16 *)p;
+	*ptr++ = 0xffff;
+	*ptr++ = 0xffff;
+
+	token->len = 16 + ctx->gk5e->cksumlength;
+	return krb5_hdr;
+}
+
 static u32
 gss_get_mic_v1(struct krb5_ctx *ctx, struct xdr_buf *text,
 		struct xdr_netobj *token)
@@ -133,6 +160,45 @@ gss_get_mic_v1(struct krb5_ctx *ctx, struct xdr_buf *text,
 }
 
 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};
+	void *krb5_hdr;
+	s32 now;
+	u64 seq_send;
+	u8 *cksumkey;
+
+	dprintk("RPC:       %s\n", __func__);
+	BUG_ON(ctx == NULL);
+
+	krb5_hdr = setup_token_v2(ctx, token);
+
+	/* Set up the sequence number. Now 64-bits in clear
+	 * text and w/o direction indicator */
+	spin_lock(&krb5_seq_lock);
+	seq_send = ctx->seq_send64++;
+	spin_unlock(&krb5_seq_lock);
+	*((u64 *)(krb5_hdr + 8)) = cpu_to_be64(seq_send);
+
+	if (ctx->initiate)
+		cksumkey = ctx->initiator_sign;
+	else
+		cksumkey = ctx->acceptor_sign;
+
+	if (make_checksum_v2(ctx, krb5_hdr, 16, text, 0, cksumkey, &cksumobj))
+		return GSS_S_FAILURE;
+
+	memcpy(krb5_hdr + 16, cksumobj.data, cksumobj.len);
+
+	now = get_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)
 {
@@ -142,6 +208,9 @@ gss_get_mic_kerberos(struct gss_ctx *gss_ctx, struct xdr_buf *text,
 	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);
 	default:
 		BUG();
 	}
diff --git a/net/sunrpc/auth_gss/gss_krb5_unseal.c b/net/sunrpc/auth_gss/gss_krb5_unseal.c
index 7ba63ae..70d89cd 100644
--- a/net/sunrpc/auth_gss/gss_krb5_unseal.c
+++ b/net/sunrpc/auth_gss/gss_krb5_unseal.c
@@ -141,6 +141,63 @@ 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)
+{
+	char cksumdata[GSS_KRB5_MAX_CKSUM_LEN];
+	struct xdr_netobj cksumobj = {.len = sizeof(cksumdata),
+				      .data = cksumdata};
+	s32 now;
+	u64 seqnum;
+	u8 *ptr = read_token->data;
+	u8 *cksumkey;
+	u8 flags;
+	int i;
+
+	dprintk("RPC:       %s\n", __func__);
+
+	if (be16_to_cpu(*((__be16 *)ptr)) != KG2_TOK_MIC)
+		return GSS_S_DEFECTIVE_TOKEN;
+
+	flags = ptr[2];
+	if ((!ctx->initiate && (flags & KG2_TOKEN_FLAG_SENTBYACCEPTOR)) ||
+	    (ctx->initiate && !(flags & KG2_TOKEN_FLAG_SENTBYACCEPTOR)))
+		return GSS_S_BAD_SIG;
+
+	if (flags & KG2_TOKEN_FLAG_SEALED) {
+		dprintk("%s: token has unexpected sealed flag\n", __func__);
+		return GSS_S_FAILURE;
+	}
+
+	for (i = 3; i < 8; i++)
+		if (ptr[i] != 0xff)
+			return GSS_S_DEFECTIVE_TOKEN;
+
+	if (ctx->initiate)
+		cksumkey = ctx->acceptor_sign;
+	else
+		cksumkey = ctx->initiator_sign;
+
+	if (make_checksum_v2(ctx, ptr, 16, message_buffer, 0,
+			     cksumkey, &cksumobj))
+		return GSS_S_FAILURE;
+
+	if (memcmp(cksumobj.data, ptr + 16, ctx->gk5e->cksumlength))
+		return GSS_S_BAD_SIG;
+
+	/* it got through unscathed.  Make sure the context is unexpired */
+	now = get_seconds();
+	if (now > ctx->endtime)
+		return GSS_S_CONTEXT_EXPIRED;
+
+	/* do sequencing checks */
+
+	seqnum = be64_to_cpu((__be64 *)ptr + 8);
+
+	return GSS_S_COMPLETE;
+}
+
 u32
 gss_verify_mic_kerberos(struct gss_ctx *gss_ctx,
 			struct xdr_buf *message_buffer,
@@ -152,6 +209,9 @@ gss_verify_mic_kerberos(struct gss_ctx *gss_ctx,
 	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);
 	default:
 		BUG();
 	}
diff --git a/net/sunrpc/auth_gss/gss_krb5_wrap.c b/net/sunrpc/auth_gss/gss_krb5_wrap.c
index d59e9b2..701e001 100644
--- a/net/sunrpc/auth_gss/gss_krb5_wrap.c
+++ b/net/sunrpc/auth_gss/gss_krb5_wrap.c
@@ -283,6 +283,246 @@ gss_unwrap_kerberos_v1(struct krb5_ctx *kctx, int offset, struct xdr_buf *buf)
 	return GSS_S_COMPLETE;
 }
 
+#define TEST_ROTATE 0
+#define TEST_EXTRA_COUNT  0
+
+#if TEST_ROTATE
+static u32
+rotate_right(struct krb5_ctx *kctx, u32 offset, struct xdr_buf *buf,
+	     struct page **pages, u16 *rrc)
+{
+	u16 rotate_count = 0;
+	u8 *tbuf;
+
+	/*
+	 * As a quick test, if there is tail data that will fit within
+	 * the head, move it there
+	 */
+
+	/* If there is no tail, don't bother */
+	if (buf->tail[0].iov_base == NULL)
+		goto out;
+
+	/* If head and tail share a page, don't bother */
+	if (buf->tail[0].iov_base - buf->head[0].iov_base < PAGE_CACHE_SIZE)
+		goto out;
+
+	tbuf = kmalloc(buf->tail[0].iov_len, GFP_KERNEL);
+	if (tbuf == NULL)
+		goto out;
+
+	memcpy(tbuf, buf->tail[0].iov_base, buf->tail[0].iov_len);
+
+	/* XXX This assumes there is room in the head */
+	rotate_count = buf->tail[0].iov_len;
+
+	if (xdr_shift_head_data(buf, offset + 16, rotate_count))
+		goto out;
+	memcpy(buf->head[0].iov_base + offset + 16, tbuf,
+		buf->tail[0].iov_len);
+	/* this is adjusted upwards in xdr_shift_head_data(),
+	 * but we aren't adjusting the total length */
+	buf->len -= rotate_count;
+
+	buf->tail[0].iov_len -= rotate_count;
+	buf->tail[0].iov_base = NULL;   /* Needed? Correct? */
+
+	kfree(tbuf);
+out:
+	*rrc = rotate_count;
+	dprintk("%s: returning with rotate_count of %u\n", __func__, *rrc);
+	return 0;
+}
+#endif
+
+/*
+ * We cannot currently handle tokens with rotated data.  We need a
+ * generalized routine to rotate the data in place.  It is anticipated
+ * that we won't encounter rotated data in the general case.
+ */
+static u32
+rotate_left(struct krb5_ctx *kctx, u32 offset, struct xdr_buf *buf, u16 rrc)
+{
+	unsigned int realrrc = rrc % (buf->len - offset - 16);
+
+	if (realrrc == 0)
+		return 0;
+
+	dprintk("%s: cannot process token with rotated data: "
+		"rrc %u, realrrc %u\n", __func__, rrc, realrrc);
+	return 1;
+}
+
+static u32
+gss_wrap_kerberos_v2(struct krb5_ctx *kctx, u32 offset,
+		     struct xdr_buf *buf, struct page **pages)
+{
+	int		blocksize;
+	u8		*ptr, *plainhdr;
+	s32		now;
+	u8		flags = 0x00;
+	__be16		*be16ptr, ec = 0;
+	__be64		*be64ptr;
+	u32		err;
+#if TEST_ROTATE
+	u16		rrc;
+#endif
+#if TEST_EXTRA_COUNT
+	unsigned int	plainlen;
+#endif
+
+	dprintk("RPC:       %s\n", __func__);
+
+	if (kctx->gk5e->encrypt_v2 == NULL)
+		return GSS_S_FAILURE;
+
+#if TEST_EXTRA_COUNT
+	plainlen = buf->head[0].iov_len - offset
+				+ buf->page_len + buf->tail[0].iov_len;
+#endif
+	/* make room for gss token header (always 16 bytes) */
+	if (xdr_shift_head_data(buf, offset, 16))
+		return GSS_S_FAILURE;
+
+	/* construct gss token header */
+	ptr = plainhdr = buf->head[0].iov_base + offset;
+	*ptr++ = (unsigned char) ((KG2_TOK_WRAP>>8) & 0xff);
+	*ptr++ = (unsigned char) (KG2_TOK_WRAP & 0xff);
+
+	if ((kctx->flags & KRB5_CTX_FLAG_INITIATOR) == 0)
+		flags |= KG2_TOKEN_FLAG_SENTBYACCEPTOR;
+	if ((kctx->flags & KRB5_CTX_FLAG_ACCEPTOR_SUBKEY) != 0)
+		flags |= KG2_TOKEN_FLAG_ACCEPTORSUBKEY;
+	/* We always do confidentiality in wrap tokens */
+	flags |= KG2_TOKEN_FLAG_SEALED;
+
+	*ptr++ = flags;
+	*ptr++ = 0xff;
+	be16ptr = (__be16 *)ptr;
+
+	blocksize = crypto_blkcipher_blocksize(kctx->acceptor_enc);
+#if TEST_EXTRA_COUNT
+	ec = plainlen % blocksize ? blocksize - plainlen % blocksize : 0;
+#endif
+	*be16ptr++ = cpu_to_be16(ec);
+	/* "inner" token header always uses 0 for RRC */
+	*be16ptr++ = cpu_to_be16(0);
+
+	be64ptr = (__be64 *)be16ptr;
+	spin_lock(&krb5_seq_lock);
+	*be64ptr = cpu_to_be64(kctx->seq_send64++);
+	spin_unlock(&krb5_seq_lock);
+
+	err = (*kctx->gk5e->encrypt_v2)(kctx, offset, buf, ec, pages);
+	if (err)
+		return err;
+
+#if TEST_ROTATE
+	err = rotate_right(kctx, offset, buf, pages, &rrc);
+	if (err)
+		return err;
+	*((__be16 *)(plainhdr + 6)) = cpu_to_be16(rrc);
+#endif
+	now = get_seconds();
+	return (kctx->endtime < now) ? GSS_S_CONTEXT_EXPIRED : GSS_S_COMPLETE;
+}
+
+static u32
+gss_unwrap_kerberos_v2(struct krb5_ctx *kctx, int offset, struct xdr_buf *buf)
+{
+	s32		now;
+	u64		seqnum;
+	u8		*ptr;
+	u8		flags = 0x00;
+	u16		ec, rrc;
+	int		err;
+	u32		headskip, tailskip;
+	u8		decrypted_hdr[16];
+	unsigned int	movelen;
+
+
+	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)
+		return GSS_S_DEFECTIVE_TOKEN;
+
+	flags = ptr[2];
+	if ((!kctx->initiate && (flags & KG2_TOKEN_FLAG_SENTBYACCEPTOR)) ||
+	    (kctx->initiate && !(flags & KG2_TOKEN_FLAG_SENTBYACCEPTOR)))
+		return GSS_S_BAD_SIG;
+
+	if ((flags & KG2_TOKEN_FLAG_SEALED) == 0) {
+		dprintk("%s: token missing expected sealed flag\n", __func__);
+		return GSS_S_DEFECTIVE_TOKEN;
+	}
+
+	if (ptr[3] != 0xff)
+		return GSS_S_DEFECTIVE_TOKEN;
+
+	ec = be16_to_cpup((__be16 *)(ptr + 4));
+	rrc = be16_to_cpup((__be16 *)(ptr + 6));
+
+	seqnum = be64_to_cpup((__be64 *)(ptr + 8));
+
+	if (rrc != 0) {
+		err = rotate_left(kctx, offset, buf, rrc);
+		if (err)
+			return GSS_S_FAILURE;
+	}
+
+	err = (*kctx->gk5e->decrypt_v2)(kctx, offset, buf,
+					&headskip, &tailskip);
+	if (err)
+		return GSS_S_FAILURE;
+
+	/*
+	 * Retrieve the decrypted gss token header and verify
+	 * it against the original
+	 */
+	err = read_bytes_from_xdr_buf(buf, buf->len - 16 - tailskip,
+							decrypted_hdr, 16);
+	if (err) {
+		dprintk("%s: error %u getting decrypted_hdr\n", __func__, err);
+		return GSS_S_FAILURE;
+	}
+	if (memcmp(ptr, decrypted_hdr, 6)
+				|| memcmp(ptr + 8, decrypted_hdr + 8, 8)) {
+		dprintk("%s: token hdr, plaintext hdr mismatch!\n", __func__);
+		return GSS_S_FAILURE;
+	}
+
+	/*
+	 * XXX do sequencing checks XXX
+	 * (v1 tokens currently don't do ANY sequencing checks!!!)
+	 */
+
+	/* it got through unscathed.  Make sure the context is unexpired */
+	now = get_seconds();
+	if (now > kctx->endtime)
+		return GSS_S_CONTEXT_EXPIRED;
+
+	/*
+	 * Move the head data back to the right position in xdr_buf.
+	 * We ignore any "ec" data since it might be in the head or
+	 * the tail, and we really don't need to deal with it.
+	 * Note that buf->head[0].iov_len may indicate the available
+	 * head buffer space rather than that actually occupied.
+	 */
+	movelen = min_t(unsigned int, buf->head[0].iov_len, buf->len);
+	movelen -= offset + 16 + headskip;
+	BUG_ON(offset + 16 + headskip + movelen > buf->head[0].iov_len);
+	memmove(ptr, ptr + 16 + headskip, movelen);
+	buf->head[0].iov_len -= 16 + headskip;
+	buf->len -= 16 + headskip;
+
+	return GSS_S_COMPLETE;
+}
+
 u32
 gss_wrap_kerberos(struct gss_ctx *gctx, int offset,
 		  struct xdr_buf *buf, struct page **pages)
@@ -294,6 +534,10 @@ gss_wrap_kerberos(struct gss_ctx *gctx, int offset,
 	case ENCTYPE_DES3_CBC_RAW:
 		return gss_wrap_kerberos_v1(kctx, offset, buf, pages);
 		break;
+	case ENCTYPE_AES128_CTS_HMAC_SHA1_96:
+	case ENCTYPE_AES256_CTS_HMAC_SHA1_96:
+		return gss_wrap_kerberos_v2(kctx, offset, buf, pages);
+		break;
 	default:
 		BUG();
 		break;
@@ -311,6 +555,10 @@ gss_unwrap_kerberos(struct gss_ctx *gctx, int offset, struct xdr_buf *buf)
 	case ENCTYPE_DES3_CBC_RAW:
 		return gss_unwrap_kerberos_v1(kctx, offset, buf);
 		break;
+	case ENCTYPE_AES128_CTS_HMAC_SHA1_96:
+	case ENCTYPE_AES256_CTS_HMAC_SHA1_96:
+		return gss_unwrap_kerberos_v2(kctx, offset, buf);
+		break;
 	default:
 		BUG();
 		break;


^ permalink raw reply related	[flat|nested] 31+ messages in thread

* [PATCH 19/19] gss_krb5: add remaining pieces to enable AES encryption support
       [not found] ` <20080221184208.19195.94518.stgit-zTNJhAanYLVZN1qrTdtDg5Vzexx5G7lz@public.gmane.org>
                     ` (17 preceding siblings ...)
  2008-02-21 18:45   ` [PATCH 18/19] gss_krb5: add support for new token formats in rfc4121 Kevin Coffman
@ 2008-02-21 18:45   ` Kevin Coffman
  18 siblings, 0 replies; 31+ messages in thread
From: Kevin Coffman @ 2008-02-21 18:45 UTC (permalink / raw)
  To: linux-nfs

Add the remaining pieces to enable support for Kerberos AES
encryption types.

Signed-off-by: Kevin Coffman <kwc@citi.umich.edu>
---

 include/linux/sunrpc/gss_krb5.h       |   12 +
 net/sunrpc/auth_gss/gss_krb5_crypto.c |  307 +++++++++++++++++++++++++++++++++
 net/sunrpc/auth_gss/gss_krb5_keys.c   |   30 +++
 net/sunrpc/auth_gss/gss_krb5_mech.c   |   44 +++++
 net/sunrpc/rpc_pipe.c                 |    2 
 5 files changed, 394 insertions(+), 1 deletions(-)

diff --git a/include/linux/sunrpc/gss_krb5.h b/include/linux/sunrpc/gss_krb5.h
index 95b375b..2d60018 100644
--- a/include/linux/sunrpc/gss_krb5.h
+++ b/include/linux/sunrpc/gss_krb5.h
@@ -272,3 +272,15 @@ u32 krb5_derive_key(struct gss_krb5_enctype *gk5e,
 u32 gss_krb5_des3_make_key(struct gss_krb5_enctype *gk5e,
 			   struct xdr_netobj *randombits,
 			   struct xdr_netobj *key);
+
+u32 gss_krb5_aes_make_key(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, int ec,
+			 struct page **pages);
+
+u32 gss_krb5_aes_decrypt(struct krb5_ctx *kctx, u32 offset,
+			 struct xdr_buf *buf, u32 *plainoffset,
+			 u32 *plainlen);
diff --git a/net/sunrpc/auth_gss/gss_krb5_crypto.c b/net/sunrpc/auth_gss/gss_krb5_crypto.c
index 0c52194..92c2eff 100644
--- a/net/sunrpc/auth_gss/gss_krb5_crypto.c
+++ b/net/sunrpc/auth_gss/gss_krb5_crypto.c
@@ -42,6 +42,7 @@
 #include <linux/crypto.h>
 #include <linux/highmem.h>
 #include <linux/pagemap.h>
+#include <linux/random.h>
 #include <linux/sunrpc/gss_krb5.h>
 #include <linux/sunrpc/xdr.h>
 
@@ -448,3 +449,309 @@ gss_decrypt_xdr_buf(struct crypto_blkcipher *tfm, struct xdr_buf *buf,
 }
 
 EXPORT_SYMBOL(gss_decrypt_xdr_buf);
+
+static s32
+gss_cksum_xdr_buf(struct krb5_ctx *kctx, struct xdr_buf *body, int body_offset,
+		  const u8 *key, unsigned int keylen, struct xdr_netobj *out)
+{
+	struct hash_desc desc;
+	int err;
+
+	desc.tfm = crypto_alloc_hash(kctx->gk5e->cksum_name, 0,
+					CRYPTO_ALG_ASYNC);
+	if (IS_ERR(desc.tfm))
+		return GSS_S_FAILURE;
+	if (out->data == NULL)
+		return GSS_S_FAILURE;
+	if (out->len < crypto_hash_digestsize(desc.tfm))
+		return GSS_S_FAILURE;
+	out->len = crypto_hash_digestsize(desc.tfm);
+	desc.flags = CRYPTO_TFM_REQ_MAY_SLEEP;
+
+	if (key != NULL && keylen != 0) {
+		err = crypto_hash_setkey(desc.tfm, key, keylen);
+		if (err)
+			goto out;
+	}
+
+	err = crypto_hash_init(&desc);
+	if (err)
+		goto out;
+	err = xdr_process_buf(body, body_offset, body->len - body_offset,
+			      checksummer, &desc);
+	if (err)
+		goto out;
+	err = crypto_hash_final(&desc, out->data);
+
+out:
+	crypto_free_hash(desc.tfm);
+	return err ? GSS_S_FAILURE : 0;
+}
+
+static u32
+gss_krb5_cts_crypt(struct crypto_blkcipher *cipher, struct xdr_buf *buf,
+		   u32 offset, u8 *iv, struct page **pages, int encrypt)
+{
+	u32 ret;
+	struct scatterlist sg[1];
+	struct blkcipher_desc desc = { .tfm = cipher, .info = iv };
+	u8 data[crypto_blkcipher_blocksize(cipher) * 2];
+	struct page **save_pages;
+	u32 len = buf->len - offset;
+
+	BUG_ON(len > crypto_blkcipher_blocksize(cipher) * 2);
+
+	/*
+	 * For encryption, we want to read from the cleartext
+	 * page cache pages, and write the encrypted data to
+	 * the supplied xdr_buf pages.
+	 */
+	save_pages = buf->pages;
+	if (encrypt)
+		buf->pages = pages;
+
+	ret = read_bytes_from_xdr_buf(buf, offset, data, len);
+	buf->pages = save_pages;
+	if (ret)
+		goto out;
+
+	sg_init_one(sg, data, len);
+
+	if (encrypt)
+		ret = crypto_blkcipher_encrypt_iv(&desc, sg, sg, len);
+	else
+		ret = crypto_blkcipher_decrypt_iv(&desc, sg, sg, len);
+
+	if (ret)
+		goto out;
+
+	ret = write_bytes_to_xdr_buf(buf, offset, data, len);
+
+out:
+	return ret;
+}
+
+u32
+gss_krb5_aes_encrypt(struct krb5_ctx *kctx, u32 offset,
+		     struct xdr_buf *buf, int ec, struct page **pages)
+{
+	u32 err;
+	struct xdr_netobj hmac;
+	u8 *cksumkey, *enckey;
+	u8 *ecptr;
+	struct crypto_blkcipher *cipher, *cbc = NULL;
+	int blocksize;
+	struct page **save_pages;
+	int nblocks, nbytes;
+	struct encryptor_desc desc;
+	u32 cbcbytes;
+
+	if (kctx->initiate) {
+		cipher = kctx->initiator_enc;
+		enckey = kctx->initiator_seal;
+		cksumkey = kctx->initiator_integ;
+	} else {
+		cipher = kctx->acceptor_enc;
+		enckey = kctx->acceptor_seal;
+		cksumkey = kctx->acceptor_integ;
+	}
+	blocksize = crypto_blkcipher_blocksize(cipher);
+
+	/* hide the gss token header and insert the confounder */
+	offset += 16;
+	if (xdr_shift_head_data(buf, offset, blocksize))
+		return GSS_S_FAILURE;
+	get_random_bytes(buf->head[0].iov_base + offset, blocksize);
+	offset -= 16;
+
+	if (buf->tail[0].iov_base != NULL) {
+		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;
+	}
+
+	memset(ecptr, 'X', ec);
+	buf->tail[0].iov_len += ec;
+	buf->len += ec;
+
+	/* copy plaintext gss token header after filler (if any) */
+	memcpy(ecptr + ec, buf->head[0].iov_base + offset, 16);
+	buf->tail[0].iov_len += 16;
+	buf->len += 16;
+
+	/* Do the HMAC */
+	hmac.len = GSS_KRB5_MAX_CKSUM_LEN;
+	hmac.data = buf->tail[0].iov_base + buf->tail[0].iov_len;
+
+	/*
+	 * When we are called, pages points to the real page cache
+	 * data -- which we can't go and encrypt!  buf->pages points
+	 * to scratch pages which we are going to send off to the
+	 * client/server.  Swap in the plaintext pages to calculate
+	 * the hmac.
+	 */
+	save_pages = buf->pages;
+	buf->pages = pages;
+
+	err = gss_cksum_xdr_buf(kctx, buf, offset + 16, cksumkey,
+				kctx->gk5e->keylength, &hmac);
+	buf->pages = save_pages;
+	if (err)
+		return GSS_S_FAILURE;
+
+	nbytes = buf->len - offset - 16;
+	nblocks = (nbytes + blocksize - 1) / blocksize;
+	cbcbytes = 0;
+	if (nblocks > 2)
+		cbcbytes = (nblocks - 2) * blocksize;
+
+	memset(desc.iv, 0, sizeof(desc.iv));
+
+	if (cbcbytes) {
+		/* XXX This does a kzalloc, may need to pre-allocate this! */
+		cbc = crypto_alloc_blkcipher("cbc(aes)", 0, CRYPTO_ALG_ASYNC);
+		if (cbc == NULL)
+			return GSS_S_FAILURE;
+		err = crypto_blkcipher_setkey(cbc, enckey,
+					      kctx->gk5e->keylength);
+		if (err)
+			goto out_err;
+
+		desc.pos = offset + 16;
+		desc.fragno = 0;
+		desc.fraglen = 0;
+		desc.pages = pages;
+		desc.outbuf = buf;
+		desc.desc.info = desc.iv;
+		desc.desc.flags = 0;
+		desc.desc.tfm = cbc;
+
+		sg_init_table(desc.infrags, 4);
+		sg_init_table(desc.outfrags, 4);
+
+		err = xdr_process_buf(buf, offset + 16, cbcbytes,
+							encryptor, &desc);
+		if (err)
+			goto out_err;
+	}
+
+	/* Make sure IV carries forward from any CBC results. */
+	err = gss_krb5_cts_crypt(cipher, buf, offset + 16 + cbcbytes,
+				 desc.iv, pages, 1);
+	if (err) {
+		err = GSS_S_FAILURE;
+		goto out_err;
+	}
+
+	/* Now update buf to account for HMAC */
+	buf->tail[0].iov_len += kctx->gk5e->cksumlength;
+	buf->len += kctx->gk5e->cksumlength;
+
+out_err:
+	if (cbc != NULL)
+		crypto_free_blkcipher(cbc);
+	if (err)
+		err = GSS_S_FAILURE;
+	return err;
+}
+
+u32
+gss_krb5_aes_decrypt(struct krb5_ctx *kctx, u32 offset, struct xdr_buf *buf,
+		     u32 *headskip, u32 *tailskip)
+{
+	struct xdr_buf subbuf;
+	u32 ret = 0;
+	u8 *cksum_key, *enckey;
+	struct crypto_blkcipher *cipher, *cbc = NULL;
+	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;
+
+	if (kctx->initiate) {
+		cipher = kctx->acceptor_enc;
+		enckey = kctx->acceptor_seal;
+		cksum_key = kctx->acceptor_integ;
+	} else {
+		cipher = kctx->initiator_enc;
+		enckey = kctx->initiator_seal;
+		cksum_key = kctx->initiator_integ;
+	}
+	blocksize = crypto_blkcipher_blocksize(cipher);
+
+
+	/* create a segment skipping the header and leaving out the checksum */
+	xdr_buf_subsegment(buf, &subbuf, offset + 16,
+			(buf->len - offset - 16 - 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) {
+		/* XXX This does a kzalloc, may need to pre-allocate this! */
+		cbc = crypto_alloc_blkcipher("cbc(aes)", 0, CRYPTO_ALG_ASYNC);
+		if (cbc == NULL) {
+			ret = GSS_S_FAILURE;
+			goto out_err;
+		}
+		ret = crypto_blkcipher_setkey(cbc, enckey,
+					      kctx->gk5e->keylength);
+		if (ret)
+			goto out_err;
+
+		desc.fragno = 0;
+		desc.fraglen = 0;
+		desc.desc.info = desc.iv;
+		desc.desc.flags = 0;
+		desc.desc.tfm = cbc;
+
+		sg_init_table(desc.frags, 4);
+
+		ret = xdr_process_buf(&subbuf, 0, cbcbytes, decryptor, &desc);
+		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);
+	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_cksum_xdr_buf(kctx, &subbuf, 0, cksum_key,
+					kctx->gk5e->keylength, &our_hmac_obj);
+	if (ret)
+		goto out_err;
+
+	/* Get the packet's hmac value */
+	ret = read_bytes_from_xdr_buf(buf, buf->len - kctx->gk5e->cksumlength,
+				      pkt_hmac, kctx->gk5e->cksumlength);
+	if (ret)
+		goto out_err;
+
+	if (memcmp(pkt_hmac, our_hmac, kctx->gk5e->cksumlength) != 0) {
+		ret = GSS_S_BAD_SIG;
+		goto out_err;
+	}
+	*headskip = crypto_blkcipher_blocksize(cipher);
+	*tailskip = kctx->gk5e->cksumlength;
+out_err:
+	if (cbc != NULL)
+		crypto_free_blkcipher(cbc);
+	if (ret && ret != GSS_S_BAD_SIG)
+		ret = GSS_S_FAILURE;
+	return ret;
+}
diff --git a/net/sunrpc/auth_gss/gss_krb5_keys.c b/net/sunrpc/auth_gss/gss_krb5_keys.c
index a722fba..351383c 100644
--- a/net/sunrpc/auth_gss/gss_krb5_keys.c
+++ b/net/sunrpc/auth_gss/gss_krb5_keys.c
@@ -306,3 +306,33 @@ u32 gss_krb5_des3_make_key(struct gss_krb5_enctype *gk5e,
 err_out:
 	return(ret);
 }
+
+/*
+ * This is the aes key derivation postprocess function
+ */
+u32 gss_krb5_aes_make_key(struct gss_krb5_enctype *gk5e,
+			  struct xdr_netobj *randombits,
+			  struct xdr_netobj *key)
+{
+	u32 ret = EINVAL;
+
+	if (key->len != 16 && key->len != 32) {
+		dprintk("%s: key->len is %d\n", __func__, key->len);
+		goto err_out;
+	}
+	if (randombits->len != 16 && randombits->len != 32) {
+		dprintk("%s: randombits->len is %d\n",
+			__func__, randombits->len);
+		goto err_out;
+	}
+	if (randombits->len != key->len) {
+		dprintk("%s: randombits->len is %d, key->len is %d\n",
+			__func__, randombits->len, key->len);
+		goto err_out;
+	}
+	memcpy(key->data, randombits->data, key->len);
+	ret = 0;
+err_out:
+	return (ret);
+}
+
diff --git a/net/sunrpc/auth_gss/gss_krb5_mech.c b/net/sunrpc/auth_gss/gss_krb5_mech.c
index 2edf28e..cfd06ca 100644
--- a/net/sunrpc/auth_gss/gss_krb5_mech.c
+++ b/net/sunrpc/auth_gss/gss_krb5_mech.c
@@ -89,6 +89,50 @@ static struct gss_krb5_enctype supported_gss_krb5_enctypes[] = {
 	  .cksumlength = 20,
 	  .keyed_cksum = 1,
 	},
+	/*
+	 * AES128
+	 */
+	{
+	  .etype = ENCTYPE_AES128_CTS_HMAC_SHA1_96,
+	  .ctype = CKSUMTYPE_HMAC_SHA1_96_AES128,
+	  .name = "aes128-cts",
+	  .encrypt_name = "cts(cbc(aes))",
+	  .cksum_name = "hmac(sha1)",
+	  .encrypt = krb5_encrypt,
+	  .decrypt = krb5_decrypt,
+	  .mk_key = gss_krb5_aes_make_key,
+	  .encrypt_v2 = gss_krb5_aes_encrypt,
+	  .decrypt_v2 = gss_krb5_aes_decrypt,
+	  .signalg = -1,
+	  .sealalg = -1,
+	  .keybytes = 16,
+	  .keylength = 16,
+	  .blocksize = 16,
+	  .cksumlength = 12,
+	  .keyed_cksum = 1,
+	},
+	/*
+	 * AES256
+	 */
+	{
+	  .etype = ENCTYPE_AES256_CTS_HMAC_SHA1_96,
+	  .ctype = CKSUMTYPE_HMAC_SHA1_96_AES256,
+	  .name = "aes256-cts",
+	  .encrypt_name = "cts(cbc(aes))",
+	  .cksum_name = "hmac(sha1)",
+	  .encrypt = krb5_encrypt,
+	  .decrypt = krb5_decrypt,
+	  .mk_key = gss_krb5_aes_make_key,
+	  .encrypt_v2 = gss_krb5_aes_encrypt,
+	  .decrypt_v2 = gss_krb5_aes_decrypt,
+	  .signalg = -1,
+	  .sealalg = -1,
+	  .keybytes = 32,
+	  .keylength = 32,
+	  .blocksize = 16,
+	  .cksumlength = 12,
+	  .keyed_cksum = 1,
+	},
 };
 
 static int num_supported_enctypes =
diff --git a/net/sunrpc/rpc_pipe.c b/net/sunrpc/rpc_pipe.c
index d84632a..e7f0807 100644
--- a/net/sunrpc/rpc_pipe.c
+++ b/net/sunrpc/rpc_pipe.c
@@ -392,7 +392,7 @@ static const struct file_operations rpc_info_operations = {
 static int
 rpc_show_krb5_info(struct seq_file *m, void *v)
 {
-	seq_printf(m, "enctypes: 16,3,1,2\n");
+	seq_printf(m, "enctypes: 18,17,16,3,1,2\n");
 	return 0;
 }
 


^ permalink raw reply related	[flat|nested] 31+ messages in thread

* Re: [PATCH 03/19] sunrpc: make token header values less confusing
       [not found]     ` <20080221184402.19195.57873.stgit-zTNJhAanYLVZN1qrTdtDg5Vzexx5G7lz@public.gmane.org>
@ 2008-03-12 16:31       ` J. Bruce Fields
  2008-03-12 16:44         ` Kevin Coffman
  0 siblings, 1 reply; 31+ messages in thread
From: J. Bruce Fields @ 2008-03-12 16:31 UTC (permalink / raw)
  To: Kevin Coffman; +Cc: linux-nfs, aglo

On Thu, Feb 21, 2008 at 01:44:02PM -0500, Kevin Coffman wrote:
> g_make_token_header() and g_token_size() add two too many, and
> therefore their callers pass in "(logical_value - 2)" rather
> than "logical_value" as hard-coded values which causes confusion.
> 
> This dates back to the original g_make_token_header which took an
> optional token type (token_id) value and added it to the token.
> This was removed, but the routine always adds room for the token_id
> rather than not.

Looks fine, thanks, but:

> 
> Signed-off-by: Kevin Coffman <kwc@citi.umich.edu>
> ---
> 
>  net/sunrpc/auth_gss/gss_generic_token.c |    4 ++--
>  net/sunrpc/auth_gss/gss_krb5_seal.c     |    4 ++--
>  net/sunrpc/auth_gss/gss_krb5_wrap.c     |    4 ++--
>  net/sunrpc/auth_gss/gss_spkm3_seal.c    |    2 +-
>  4 files changed, 7 insertions(+), 7 deletions(-)
> 
> diff --git a/net/sunrpc/auth_gss/gss_generic_token.c b/net/sunrpc/auth_gss/gss_generic_token.c
> index ea8c92e..d83b881 100644
> --- a/net/sunrpc/auth_gss/gss_generic_token.c
> +++ b/net/sunrpc/auth_gss/gss_generic_token.c
> @@ -148,7 +148,7 @@ int
>  g_token_size(struct xdr_netobj *mech, unsigned int body_size)
>  {
>  	/* set body_size to sequence contents size */
> -	body_size += 4 + (int) mech->len;         /* NEED overflow check */
> +	body_size += 2 + (int) mech->len;         /* NEED overflow check */
>  	return(1 + der_length_size(body_size) + body_size);
>  }
>  
> @@ -161,7 +161,7 @@ void
>  g_make_token_header(struct xdr_netobj *mech, int body_size, unsigned char **buf)
>  {
>  	*(*buf)++ = 0x60;
> -	der_write_length(buf, 4 + mech->len + body_size);
> +	der_write_length(buf, 2 + mech->len + body_size);
>  	*(*buf)++ = 0x06;
>  	*(*buf)++ = (unsigned char) mech->len;
>  	TWRITE_STR(*buf, mech->data, ((int) mech->len));
> diff --git a/net/sunrpc/auth_gss/gss_krb5_seal.c b/net/sunrpc/auth_gss/gss_krb5_seal.c
> index dedcbd6..b2fa785 100644
> --- a/net/sunrpc/auth_gss/gss_krb5_seal.c
> +++ b/net/sunrpc/auth_gss/gss_krb5_seal.c
> @@ -87,10 +87,10 @@ gss_get_mic_kerberos(struct gss_ctx *gss_ctx, struct xdr_buf *text,
>  
>  	now = get_seconds();
>  
> -	token->len = g_token_size(&ctx->mech_used, 22);
> +	token->len = g_token_size(&ctx->mech_used, 24);
>  
>  	ptr = token->data;
> -	g_make_token_header(&ctx->mech_used, 22, &ptr);
> +	g_make_token_header(&ctx->mech_used, 24, &ptr);
>  
>  	*ptr++ = (unsigned char) ((KG_TOK_MIC_MSG>>8)&0xff);
>  	*ptr++ = (unsigned char) (KG_TOK_MIC_MSG&0xff);
> diff --git a/net/sunrpc/auth_gss/gss_krb5_wrap.c b/net/sunrpc/auth_gss/gss_krb5_wrap.c
> index 3bdc527..a2c92f1 100644
> --- a/net/sunrpc/auth_gss/gss_krb5_wrap.c
> +++ b/net/sunrpc/auth_gss/gss_krb5_wrap.c
> @@ -137,7 +137,7 @@ gss_wrap_kerberos(struct gss_ctx *ctx, int offset,
>  	BUG_ON((buf->len - offset) % blocksize);
>  	plainlen = blocksize + buf->len - offset;
>  
> -	headlen = g_token_size(&kctx->mech_used, 22 + plainlen) -
> +	headlen = g_token_size(&kctx->mech_used, 24 + plainlen) -
>  						(buf->len - offset);
>  
>  	ptr = buf->head[0].iov_base + offset;
> @@ -149,7 +149,7 @@ gss_wrap_kerberos(struct gss_ctx *ctx, int offset,
>  	buf->len += headlen;
>  	BUG_ON((buf->len - offset - headlen) % blocksize);
>  
> -	g_make_token_header(&kctx->mech_used, 22 + plainlen, &ptr);
> +	g_make_token_header(&kctx->mech_used, 24 + plainlen, &ptr);
>  
>  
>  	*ptr++ = (unsigned char) ((KG_TOK_WRAP_MSG>>8)&0xff);
> diff --git a/net/sunrpc/auth_gss/gss_spkm3_seal.c b/net/sunrpc/auth_gss/gss_spkm3_seal.c
> index abf17ce..88505d5 100644
> --- a/net/sunrpc/auth_gss/gss_spkm3_seal.c
> +++ b/net/sunrpc/auth_gss/gss_spkm3_seal.c
> @@ -104,7 +104,7 @@ spkm3_make_token(struct spkm3_ctx *ctx,
>  			goto out_err;
>  
>  		asn1_bitstring_len(&md5cksum, &md5elen, &md5zbit);
> -		tokenlen = 10 + ctxelen + 1 + md5elen + 1;
> +		tokenlen = 12 + ctxelen + 1 + md5elen + 1;
>  
>  		/* Create token header using generic routines */
>  		token->len = g_token_size(&ctx->mech_used, tokenlen);

Could you double-check this spkm3 case?  It looks like tokenlen is
passed to spkm3_make_mic_token as well as the two functions you've
modified.

--b.

^ permalink raw reply	[flat|nested] 31+ messages in thread

* Re: [PATCH 04/19] Add new pipefs file indicating which Kerberos enctypes the kernel supports
       [not found]     ` <20080221184407.19195.62074.stgit-zTNJhAanYLVZN1qrTdtDg5Vzexx5G7lz@public.gmane.org>
@ 2008-03-12 16:37       ` J. Bruce Fields
  0 siblings, 0 replies; 31+ messages in thread
From: J. Bruce Fields @ 2008-03-12 16:37 UTC (permalink / raw)
  To: Kevin Coffman; +Cc: linux-nfs, Trond Myklebust

On Thu, Feb 21, 2008 at 01:44:07PM -0500, Kevin Coffman wrote:
> New file, krb5_info, indicates which Kerberos encryption types are
> supported by the kernel rpcsecgss code.  This is used by gssd to
> determine which encryption types it should attempt to negotiate
> when creating a context with a server.
> 
> The server principal's database and keytab encryption types are
> what limits what it should negotiate.  Therefore, its keytab
> should be created with only the enctypes listed by this file.

Trond?  Any comments on this approach?  The new "krb5_info" file is
added to the root directory of rpc_pipefs.

I suppose we could instead add it to the new (text-based) upcall.  My
only objection to that would be that it might be inefficient to add to
the upcall information that's constant across all servers and protocols.
But I suppose it's unlikely to be enough data to matter.

--b.

> 
> From: J. Bruce Fields <bfields@citi.umich.edu>
> Signed-off-by: Kevin Coffman <kwc@citi.umich.edu>
> ---
> 
>  net/sunrpc/rpc_pipe.c |   31 +++++++++++++++++++++++++++++++
>  1 files changed, 31 insertions(+), 0 deletions(-)
> 
> diff --git a/net/sunrpc/rpc_pipe.c b/net/sunrpc/rpc_pipe.c
> index 7e19716..5781862 100644
> --- a/net/sunrpc/rpc_pipe.c
> +++ b/net/sunrpc/rpc_pipe.c
> @@ -385,6 +385,31 @@ static const struct file_operations rpc_info_operations = {
>  	.release	= rpc_info_release,
>  };
>  
> +/*
> + * This really belongs in the gss_krb5 code,
> + * but the info file logically belongs here
> + */
> +static int
> +rpc_show_krb5_info(struct seq_file *m, void *v)
> +{
> +	seq_printf(m, "enctypes: 3,1,2\n");
> +	return 0;
> +}
> +
> +static int
> +rpc_krb5_info_open(struct inode *inode, struct file *file)
> +{
> +	return single_open(file, rpc_show_krb5_info, NULL);
> +}
> +
> +static struct file_operations krb5_info_operations = {
> +	.owner		= THIS_MODULE,
> +	.open		= rpc_krb5_info_open,
> +	.read		= seq_read,
> +	.llseek		= seq_lseek,
> +	.release	= single_release,
> +};
> +
>  
>  /*
>   * We have a single directory with 1 node in it.
> @@ -396,6 +421,7 @@ enum {
>  	RPCAUTH_nfs,
>  	RPCAUTH_portmap,
>  	RPCAUTH_statd,
> +	RPCAUTH_krb5_info,
>  	RPCAUTH_RootEOF
>  };
>  
> @@ -429,6 +455,11 @@ static struct rpc_filelist files[] = {
>  		.name = "statd",
>  		.mode = S_IFDIR | S_IRUGO | S_IXUGO,
>  	},
> +	[RPCAUTH_krb5_info] = {
> +		.name = "krb5_info",
> +		.i_fop = &krb5_info_operations,
> +		.mode = S_IFREG | S_IRUSR,
> +	},
>  };
>  
>  enum {
> 
> -
> To unsubscribe from this list: send the line "unsubscribe linux-nfs" in
> the body of a message to majordomo@vger.kernel.org
> More majordomo info at  http://vger.kernel.org/majordomo-info.html

^ permalink raw reply	[flat|nested] 31+ messages in thread

* Re: [PATCH 05/19] Correct grammer/typos in dprintks
       [not found]     ` <20080221184412.19195.93743.stgit-zTNJhAanYLVZN1qrTdtDg5Vzexx5G7lz@public.gmane.org>
@ 2008-03-12 16:38       ` J. Bruce Fields
  0 siblings, 0 replies; 31+ messages in thread
From: J. Bruce Fields @ 2008-03-12 16:38 UTC (permalink / raw)
  To: Kevin Coffman; +Cc: linux-nfs

On Thu, Feb 21, 2008 at 01:44:12PM -0500, Kevin Coffman wrote:
> cleanup:  Fix grammer/typos to use "too" instead of "to"

Thanks; applied.--b.

> 
> Signed-off-by: Kevin Coffman <kwc@citi.umich.edu>
> ---
> 
>  net/sunrpc/auth_gss/gss_krb5_crypto.c |    6 +++---
>  1 files changed, 3 insertions(+), 3 deletions(-)
> 
> diff --git a/net/sunrpc/auth_gss/gss_krb5_crypto.c b/net/sunrpc/auth_gss/gss_krb5_crypto.c
> index 0dd7923..1d52308 100644
> --- a/net/sunrpc/auth_gss/gss_krb5_crypto.c
> +++ b/net/sunrpc/auth_gss/gss_krb5_crypto.c
> @@ -66,8 +66,8 @@ krb5_encrypt(
>  		goto out;
>  
>  	if (crypto_blkcipher_ivsize(tfm) > 16) {
> -		dprintk("RPC:       gss_k5encrypt: tfm iv size to large %d\n",
> -			 crypto_blkcipher_ivsize(tfm));
> +		dprintk("RPC:       gss_k5encrypt: tfm iv size too large %d\n",
> +			crypto_blkcipher_ivsize(tfm));
>  		goto out;
>  	}
>  
> @@ -102,7 +102,7 @@ krb5_decrypt(
>  		goto out;
>  
>  	if (crypto_blkcipher_ivsize(tfm) > 16) {
> -		dprintk("RPC:       gss_k5decrypt: tfm iv size to large %d\n",
> +		dprintk("RPC:       gss_k5decrypt: tfm iv size too large %d\n",
>  			crypto_blkcipher_ivsize(tfm));
>  		goto out;
>  	}
> 
> -
> To unsubscribe from this list: send the line "unsubscribe linux-nfs" in
> the body of a message to majordomo@vger.kernel.org
> More majordomo info at  http://vger.kernel.org/majordomo-info.html

^ permalink raw reply	[flat|nested] 31+ messages in thread

* Re: [PATCH 03/19] sunrpc: make token header values less confusing
  2008-03-12 16:31       ` J. Bruce Fields
@ 2008-03-12 16:44         ` Kevin Coffman
  0 siblings, 0 replies; 31+ messages in thread
From: Kevin Coffman @ 2008-03-12 16:44 UTC (permalink / raw)
  To: J. Bruce Fields; +Cc: linux-nfs, aglo

On Wed, Mar 12, 2008 at 12:31 PM, J. Bruce Fields <bfields@fieldses.org> wrote:
> On Thu, Feb 21, 2008 at 01:44:02PM -0500, Kevin Coffman wrote:
>
>  Could you double-check this spkm3 case?  It looks like tokenlen is
>  passed to spkm3_make_mic_token as well as the two functions you've
>  modified.

Thanks, I will double-check (and actually test with!) spkm3 before
sending the next round.

K.C.

^ permalink raw reply	[flat|nested] 31+ messages in thread

* Re: [PATCH 06/19] Use get_random_bytes() to create confounder
       [not found]     ` <20080221184417.19195.55123.stgit-zTNJhAanYLVZN1qrTdtDg5Vzexx5G7lz@public.gmane.org>
@ 2008-03-12 16:46       ` J. Bruce Fields
  2008-03-12 17:50         ` Matt Mackall
  0 siblings, 1 reply; 31+ messages in thread
From: J. Bruce Fields @ 2008-03-12 16:46 UTC (permalink / raw)
  To: Kevin Coffman; +Cc: linux-nfs, Matt Mackall

On Thu, Feb 21, 2008 at 01:44:17PM -0500, Kevin Coffman wrote:
> Instead of using an incementing value for the confounder, use
> get_random_bytes() which gives us the desired unpredictable value.

OK, admittedly I was probably nuts to substitute a predictable number
for a random number in any cryptographic protocol, even if I was pretty
sure it didn't matter in our case--so thanks for doing this.

But my impression is that other callers of this function are using it on
a per-connection basis instead of (as in our case) a per-rpc basis.  Is
there any problem with calling it that frequently?  Is it fast enough?
Will it deplete some common entropy pool?

--b.

> 
> Signed-off-by: Kevin Coffman <kwc@citi.umich.edu>
> ---
> 
>  net/sunrpc/auth_gss/gss_krb5_wrap.c |   15 +--------------
>  1 files changed, 1 insertions(+), 14 deletions(-)
> 
> diff --git a/net/sunrpc/auth_gss/gss_krb5_wrap.c b/net/sunrpc/auth_gss/gss_krb5_wrap.c
> index a2c92f1..7a0002f 100644
> --- a/net/sunrpc/auth_gss/gss_krb5_wrap.c
> +++ b/net/sunrpc/auth_gss/gss_krb5_wrap.c
> @@ -90,20 +90,7 @@ out:
>  static inline void
>  make_confounder(char *p, int blocksize)
>  {
> -	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. */
> -
> -	BUG_ON(blocksize != 8);
> -	*q = i++;
> +	get_random_bytes(p, blocksize);
>  }
>  
>  /* Assumptions: the head and tail of inbuf are ours to play with.
> 
> -
> To unsubscribe from this list: send the line "unsubscribe linux-nfs" in
> the body of a message to majordomo@vger.kernel.org
> More majordomo info at  http://vger.kernel.org/majordomo-info.html

^ permalink raw reply	[flat|nested] 31+ messages in thread

* Re: [PATCH 06/19] Use get_random_bytes() to create confounder
  2008-03-12 16:46       ` J. Bruce Fields
@ 2008-03-12 17:50         ` Matt Mackall
  2008-03-12 18:03           ` J. Bruce Fields
  0 siblings, 1 reply; 31+ messages in thread
From: Matt Mackall @ 2008-03-12 17:50 UTC (permalink / raw)
  To: J. Bruce Fields; +Cc: Kevin Coffman, linux-nfs


On Wed, 2008-03-12 at 12:46 -0400, J. Bruce Fields wrote:
> On Thu, Feb 21, 2008 at 01:44:17PM -0500, Kevin Coffman wrote:
> > Instead of using an incementing value for the confounder, use
> > get_random_bytes() which gives us the desired unpredictable value.
> 
> OK, admittedly I was probably nuts to substitute a predictable number
> for a random number in any cryptographic protocol, even if I was pretty
> sure it didn't matter in our case--so thanks for doing this.
> 
> But my impression is that other callers of this function are using it on
> a per-connection basis instead of (as in our case) a per-rpc basis.  Is
> there any problem with calling it that frequently?  Is it fast enough?
> Will it deplete some common entropy pool?

get_random_bytes is in the many megabytes/second range, so it's fast
enough for most things, but considered too slow for per-socket use
(which means the comment above it is quite stale!). If per-rpc means
once per every stat over NFS, then definitely too expensive. It draws
from the non-blocking pool, so no worries about entropy depletion.

Take a look at lib/random32.c for a moderately stong and fast PRND.
Reseeding that periodically with get_random_bytes might be sufficient.
Or look at secure_tcp_sequence_number in random.c for a more ad-hoc
approach.

-- 
Mathematics is the supreme nostalgia of our time.


^ permalink raw reply	[flat|nested] 31+ messages in thread

* Re: [PATCH 06/19] Use get_random_bytes() to create confounder
  2008-03-12 17:50         ` Matt Mackall
@ 2008-03-12 18:03           ` J. Bruce Fields
  2008-03-12 18:37             ` Kevin Coffman
  0 siblings, 1 reply; 31+ messages in thread
From: J. Bruce Fields @ 2008-03-12 18:03 UTC (permalink / raw)
  To: Matt Mackall; +Cc: Kevin Coffman, linux-nfs

On Wed, Mar 12, 2008 at 12:50:38PM -0500, Matt Mackall wrote:
> 
> On Wed, 2008-03-12 at 12:46 -0400, J. Bruce Fields wrote:
> > On Thu, Feb 21, 2008 at 01:44:17PM -0500, Kevin Coffman wrote:
> > > Instead of using an incementing value for the confounder, use
> > > get_random_bytes() which gives us the desired unpredictable value.
> > 
> > OK, admittedly I was probably nuts to substitute a predictable number
> > for a random number in any cryptographic protocol, even if I was pretty
> > sure it didn't matter in our case--so thanks for doing this.
> > 
> > But my impression is that other callers of this function are using it on
> > a per-connection basis instead of (as in our case) a per-rpc basis.  Is
> > there any problem with calling it that frequently?  Is it fast enough?
> > Will it deplete some common entropy pool?
> 
> get_random_bytes is in the many megabytes/second range, so it's fast
> enough for most things, but considered too slow for per-socket use
> (which means the comment above it is quite stale!). If per-rpc means
> once per every stat over NFS,

Yep, that's what I meant.  Of course we are also encrypting every stat
in this particular case, so we're accepting a certain amount of
overhead.

> then definitely too expensive.

OK.

> It draws
> from the non-blocking pool, so no worries about entropy depletion.
> 
> Take a look at lib/random32.c for a moderately stong and fast PRND.
> Reseeding that periodically with get_random_bytes might be sufficient.
> Or look at secure_tcp_sequence_number in random.c for a more ad-hoc
> approach.

OK.  Yes, I'd definitely be happy to sacrifice quality for performance
in this case, at least until I see an argument pointing out some reason
we need good randomness here....

Thanks for the help!

--b.

^ permalink raw reply	[flat|nested] 31+ messages in thread

* Re: [PATCH 06/19] Use get_random_bytes() to create confounder
  2008-03-12 18:03           ` J. Bruce Fields
@ 2008-03-12 18:37             ` Kevin Coffman
       [not found]               ` <4d569c330803121137w755c5c76j4b692aac53d54619-JsoAwUIsXosN+BqQ9rBEUg@public.gmane.org>
  0 siblings, 1 reply; 31+ messages in thread
From: Kevin Coffman @ 2008-03-12 18:37 UTC (permalink / raw)
  To: J. Bruce Fields; +Cc: Matt Mackall, linux-nfs

On Wed, Mar 12, 2008 at 2:03 PM, J. Bruce Fields <bfields@fieldses.org> wrote:
> On Wed, Mar 12, 2008 at 12:50:38PM -0500, Matt Mackall wrote:
>
>  > Take a look at lib/random32.c for a moderately stong and fast PRND.
>  > Reseeding that periodically with get_random_bytes might be sufficient.
>  > Or look at secure_tcp_sequence_number in random.c for a more ad-hoc
>  > approach.
>
>  OK.  Yes, I'd definitely be happy to sacrifice quality for performance
>  in this case, at least until I see an argument pointing out some reason
>  we need good randomness here....
>
>  Thanks for the help!

Yes, thanks Matt.  It looks to me like random32() should be good (and
fast) enough for this.  Do you agree Bruce?

K.C.

^ permalink raw reply	[flat|nested] 31+ messages in thread

* Re: [PATCH 06/19] Use get_random_bytes() to create confounder
       [not found]               ` <4d569c330803121137w755c5c76j4b692aac53d54619-JsoAwUIsXosN+BqQ9rBEUg@public.gmane.org>
@ 2008-03-12 18:39                 ` J. Bruce Fields
  2008-03-12 18:53                   ` Matt Mackall
  0 siblings, 1 reply; 31+ messages in thread
From: J. Bruce Fields @ 2008-03-12 18:39 UTC (permalink / raw)
  To: Kevin Coffman; +Cc: Matt Mackall, linux-nfs

On Wed, Mar 12, 2008 at 02:37:26PM -0400, Kevin Coffman wrote:
> On Wed, Mar 12, 2008 at 2:03 PM, J. Bruce Fields <bfields@fieldses.org> wrote:
> > On Wed, Mar 12, 2008 at 12:50:38PM -0500, Matt Mackall wrote:
> >
> >  > Take a look at lib/random32.c for a moderately stong and fast PRND.
> >  > Reseeding that periodically with get_random_bytes might be sufficient.
> >  > Or look at secure_tcp_sequence_number in random.c for a more ad-hoc
> >  > approach.
> >
> >  OK.  Yes, I'd definitely be happy to sacrifice quality for performance
> >  in this case, at least until I see an argument pointing out some reason
> >  we need good randomness here....
> >
> >  Thanks for the help!
> 
> Yes, thanks Matt.  It looks to me like random32() should be good (and
> fast) enough for this.  Do you agree Bruce?

OK by me.

--b.

^ permalink raw reply	[flat|nested] 31+ messages in thread

* Re: [PATCH 06/19] Use get_random_bytes() to create confounder
  2008-03-12 18:39                 ` J. Bruce Fields
@ 2008-03-12 18:53                   ` Matt Mackall
  0 siblings, 0 replies; 31+ messages in thread
From: Matt Mackall @ 2008-03-12 18:53 UTC (permalink / raw)
  To: J. Bruce Fields; +Cc: Kevin Coffman, linux-nfs


On Wed, 2008-03-12 at 14:39 -0400, J. Bruce Fields wrote:
> On Wed, Mar 12, 2008 at 02:37:26PM -0400, Kevin Coffman wrote:
> > On Wed, Mar 12, 2008 at 2:03 PM, J. Bruce Fields <bfields@fieldses.org> wrote:
> > > On Wed, Mar 12, 2008 at 12:50:38PM -0500, Matt Mackall wrote:
> > >
> > >  > Take a look at lib/random32.c for a moderately stong and fast PRND.
> > >  > Reseeding that periodically with get_random_bytes might be sufficient.
> > >  > Or look at secure_tcp_sequence_number in random.c for a more ad-hoc
> > >  > approach.
> > >
> > >  OK.  Yes, I'd definitely be happy to sacrifice quality for performance
> > >  in this case, at least until I see an argument pointing out some reason
> > >  we need good randomness here....
> > >
> > >  Thanks for the help!
> > 
> > Yes, thanks Matt.  It looks to me like random32() should be good (and
> > fast) enough for this.  Do you agree Bruce?
> 
> OK by me.

Polite users of random32 should call srandom32 with some interesting
values occasionally. At authentication/connection time might be
appropriate.

-- 
Mathematics is the supreme nostalgia of our time.


^ permalink raw reply	[flat|nested] 31+ messages in thread

* Re: [PATCH 08/19] Remove define for KRB5_CKSUM_LENGTH, which will become enctype-dependent
       [not found]     ` <20080221184427.19195.16243.stgit-zTNJhAanYLVZN1qrTdtDg5Vzexx5G7lz@public.gmane.org>
@ 2008-03-12 18:54       ` J. Bruce Fields
  0 siblings, 0 replies; 31+ messages in thread
From: J. Bruce Fields @ 2008-03-12 18:54 UTC (permalink / raw)
  To: Kevin Coffman; +Cc: linux-nfs

On Thu, Feb 21, 2008 at 01:44:27PM -0500, Kevin Coffman wrote:
> cleanup: When adding new encryption types, the checksum length
> can be different for each enctype.  Face the fact that the
> current code only supports DES which has a checksum length of 8.
> 
> Signed-off-by: Kevin Coffman <kwc@citi.umich.edu>

OK; applied.--b.

> ---
> 
>  include/linux/sunrpc/gss_krb5.h     |    2 --
>  net/sunrpc/auth_gss/gss_krb5_seal.c |    3 +--
>  net/sunrpc/auth_gss/gss_krb5_wrap.c |    4 +---
>  3 files changed, 2 insertions(+), 7 deletions(-)
> 
> diff --git a/include/linux/sunrpc/gss_krb5.h b/include/linux/sunrpc/gss_krb5.h
> index 8c38aba..47d2110 100644
> --- a/include/linux/sunrpc/gss_krb5.h
> +++ b/include/linux/sunrpc/gss_krb5.h
> @@ -72,8 +72,6 @@ enum seal_alg {
>  
>  extern struct xdr_netobj krb5_oid;
>  
> -#define KRB5_CKSUM_LENGTH 8
> -
>  #define CKSUMTYPE_CRC32			0x0001
>  #define CKSUMTYPE_RSA_MD4		0x0002
>  #define CKSUMTYPE_RSA_MD4_DES		0x0003
> diff --git a/net/sunrpc/auth_gss/gss_krb5_seal.c b/net/sunrpc/auth_gss/gss_krb5_seal.c
> index b2fa785..e7b2a52 100644
> --- a/net/sunrpc/auth_gss/gss_krb5_seal.c
> +++ b/net/sunrpc/auth_gss/gss_krb5_seal.c
> @@ -109,8 +109,7 @@ gss_get_mic_kerberos(struct gss_ctx *gss_ctx, struct xdr_buf *text,
>  			  md5cksum.data, md5cksum.len))
>  		return GSS_S_FAILURE;
>  
> -	memcpy(krb5_hdr + 16, md5cksum.data + md5cksum.len - KRB5_CKSUM_LENGTH,
> -	       KRB5_CKSUM_LENGTH);
> +	memcpy(krb5_hdr + 16, md5cksum.data + md5cksum.len - 8, 8);
>  
>  	spin_lock(&krb5_seq_lock);
>  	seq_send = ctx->seq_send++;
> diff --git a/net/sunrpc/auth_gss/gss_krb5_wrap.c b/net/sunrpc/auth_gss/gss_krb5_wrap.c
> index 384f470..9763bf1 100644
> --- a/net/sunrpc/auth_gss/gss_krb5_wrap.c
> +++ b/net/sunrpc/auth_gss/gss_krb5_wrap.c
> @@ -160,9 +160,7 @@ gss_wrap_kerberos(struct gss_ctx *ctx, int offset,
>  	if (krb5_encrypt(kctx->seq, NULL, md5cksum.data,
>  			  md5cksum.data, md5cksum.len))
>  		return GSS_S_FAILURE;
> -	memcpy(krb5_hdr + 16,
> -	       md5cksum.data + md5cksum.len - KRB5_CKSUM_LENGTH,
> -	       KRB5_CKSUM_LENGTH);
> +	memcpy(krb5_hdr + 16, md5cksum.data + md5cksum.len - 8, 8);
>  
>  	spin_lock(&krb5_seq_lock);
>  	seq_send = kctx->seq_send++;
> 
> -
> To unsubscribe from this list: send the line "unsubscribe linux-nfs" in
> the body of a message to majordomo@vger.kernel.org
> More majordomo info at  http://vger.kernel.org/majordomo-info.html

^ permalink raw reply	[flat|nested] 31+ messages in thread

end of thread, other threads:[~2008-03-12 18:54 UTC | newest]

Thread overview: 31+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2008-02-21 18:43 [PATCH 00/19] RFC add kernel support for newer encrytpion types Kevin Coffman
     [not found] ` <20080221184208.19195.94518.stgit-zTNJhAanYLVZN1qrTdtDg5Vzexx5G7lz@public.gmane.org>
2008-02-21 18:43   ` [PATCH 01/19] crypto: Add CTS mode required for Kerberos AES support Kevin Coffman
2008-02-21 18:43   ` [PATCH 02/19] rpc: gss: Add oid values to the gss_api mechanism structures Kevin Coffman
2008-02-21 18:44   ` [PATCH 03/19] sunrpc: make token header values less confusing Kevin Coffman
     [not found]     ` <20080221184402.19195.57873.stgit-zTNJhAanYLVZN1qrTdtDg5Vzexx5G7lz@public.gmane.org>
2008-03-12 16:31       ` J. Bruce Fields
2008-03-12 16:44         ` Kevin Coffman
2008-02-21 18:44   ` [PATCH 04/19] Add new pipefs file indicating which Kerberos enctypes the kernel supports Kevin Coffman
     [not found]     ` <20080221184407.19195.62074.stgit-zTNJhAanYLVZN1qrTdtDg5Vzexx5G7lz@public.gmane.org>
2008-03-12 16:37       ` J. Bruce Fields
2008-02-21 18:44   ` [PATCH 05/19] Correct grammer/typos in dprintks Kevin Coffman
     [not found]     ` <20080221184412.19195.93743.stgit-zTNJhAanYLVZN1qrTdtDg5Vzexx5G7lz@public.gmane.org>
2008-03-12 16:38       ` J. Bruce Fields
2008-02-21 18:44   ` [PATCH 06/19] Use get_random_bytes() to create confounder Kevin Coffman
     [not found]     ` <20080221184417.19195.55123.stgit-zTNJhAanYLVZN1qrTdtDg5Vzexx5G7lz@public.gmane.org>
2008-03-12 16:46       ` J. Bruce Fields
2008-03-12 17:50         ` Matt Mackall
2008-03-12 18:03           ` J. Bruce Fields
2008-03-12 18:37             ` Kevin Coffman
     [not found]               ` <4d569c330803121137w755c5c76j4b692aac53d54619-JsoAwUIsXosN+BqQ9rBEUg@public.gmane.org>
2008-03-12 18:39                 ` J. Bruce Fields
2008-03-12 18:53                   ` Matt Mackall
2008-02-21 18:44   ` [PATCH 07/19] Don't expect blocksize to always be 8 when calculating padding Kevin Coffman
2008-02-21 18:44   ` [PATCH 08/19] Remove define for KRB5_CKSUM_LENGTH, which will become enctype-dependent Kevin Coffman
     [not found]     ` <20080221184427.19195.16243.stgit-zTNJhAanYLVZN1qrTdtDg5Vzexx5G7lz@public.gmane.org>
2008-03-12 18:54       ` J. Bruce Fields
2008-02-21 18:44   ` [PATCH 09/19] gss_krb5: split up functions in preparation of adding new enctypes Kevin Coffman
2008-02-21 18:44   ` [PATCH 10/19] gss_krb5: prepare for new context format Kevin Coffman
2008-02-21 18:44   ` [PATCH 11/19] gss_krb5: introduce encryption type framework Kevin Coffman
2008-02-21 18:44   ` [PATCH 12/19] gss_krb5: add ability to have a keyed checksum (hmac) Kevin Coffman
2008-02-21 18:44   ` [PATCH 13/19] gss_krb5: import functionality to derive keys into the kernel Kevin Coffman
2008-02-21 18:44   ` [PATCH 14/19] gss_krb5: use a global static OID value for krb5 Kevin Coffman
2008-02-21 18:45   ` [PATCH 15/19] gss_krb5: handle new context format from gssd Kevin Coffman
2008-02-21 18:45   ` [PATCH 16/19] gss_krb5: add support for triple-des encryption Kevin Coffman
2008-02-21 18:45   ` [PATCH 17/19] xdr: add a new utility function to shift the head data of an xdr buffer Kevin Coffman
2008-02-21 18:45   ` [PATCH 18/19] gss_krb5: add support for new token formats in rfc4121 Kevin Coffman
2008-02-21 18:45   ` [PATCH 19/19] gss_krb5: add remaining pieces to enable AES encryption support Kevin Coffman

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox