* [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 an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.