From: Trond Myklebust <Trond.Myklebust@netapp.com>
To: linux-nfs@vger.kernel.org
Subject: [PATCH 07/22] gss_krb5: add ability to have a keyed checksum (hmac)
Date: Wed, 14 Apr 2010 13:36:43 -0400 [thread overview]
Message-ID: <1271266618-26016-8-git-send-email-Trond.Myklebust@netapp.com> (raw)
In-Reply-To: <1271266618-26016-7-git-send-email-Trond.Myklebust@netapp.com>
From: Kevin Coffman <kwc@citi.umich.edu>
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>
Signed-off-by: Steve Dickson <steved@redhat.com>
Signed-off-by: Trond Myklebust <Trond.Myklebust@netapp.com>
---
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 | 30 +++++++++++-------
6 files changed, 88 insertions(+), 34 deletions(-)
diff --git a/include/linux/sunrpc/gss_krb5.h b/include/linux/sunrpc/gss_krb5.h
index f949355..abf26ef 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 {
const 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;
@@ -159,9 +163,10 @@ enum seal_alg {
+ GSS_KRB5_TOK_HDR_LEN \
+ GSS_KRB5_MAX_CKSUM_LEN)
-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 ccd5236..cae04d7 100644
--- a/net/sunrpc/auth_gss/gss_krb5_crypto.c
+++ b/net/sunrpc/auth_gss/gss_krb5_crypto.c
@@ -123,21 +123,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;
@@ -149,8 +170,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 a66eb70..6f93f47 100644
--- a/net/sunrpc/auth_gss/gss_krb5_mech.c
+++ b/net/sunrpc/auth_gss/gss_krb5_mech.c
@@ -66,6 +66,7 @@ static const 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 46c6f44..cd51271 100644
--- a/net/sunrpc/auth_gss/gss_krb5_seal.c
+++ b/net/sunrpc/auth_gss/gss_krb5_seal.c
@@ -101,6 +101,7 @@ gss_get_mic_v1(struct krb5_ctx *ctx, struct xdr_buf *text,
void *ptr;
s32 now;
u32 seq_send;
+ u8 *cksumkey;
dprintk("RPC: %s\n", __func__);
BUG_ON(ctx == NULL);
@@ -109,15 +110,15 @@ gss_get_mic_v1(struct krb5_ctx *ctx, struct xdr_buf *text,
ptr = setup_token(ctx, token);
- if (make_checksum((char *)ctx->gk5e->cksum_name, ptr, 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, ptr, 8, text, 0, cksumkey, &md5cksum))
return GSS_S_FAILURE;
- memcpy(ptr + GSS_KRB5_TOK_HDR_LEN, md5cksum.data + md5cksum.len - 8, 8);
+ memcpy(ptr + GSS_KRB5_TOK_HDR_LEN, 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 10ee641..7515bff 100644
--- a/net/sunrpc/auth_gss/gss_krb5_unseal.c
+++ b/net/sunrpc/auth_gss/gss_krb5_unseal.c
@@ -84,6 +84,7 @@ gss_verify_mic_v1(struct krb5_ctx *ctx,
u32 seqnum;
unsigned char *ptr = (unsigned char *)read_token->data;
int bodysize;
+ u8 *cksumkey;
dprintk("RPC: krb5_read_token\n");
@@ -108,14 +109,16 @@ gss_verify_mic_v1(struct krb5_ctx *ctx,
if ((ptr[6] != 0xff) || (ptr[7] != 0xff))
return GSS_S_DEFECTIVE_TOKEN;
- if (make_checksum((char *)ctx->gk5e->cksum_name, ptr, 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, 8, message_buffer, 0,
+ cksumkey, &md5cksum))
return GSS_S_FAILURE;
- if (memcmp(md5cksum.data + 8, ptr + GSS_KRB5_TOK_HDR_LEN,
+ if (memcmp(md5cksum.data, ptr + GSS_KRB5_TOK_HDR_LEN,
ctx->gk5e->cksumlength))
return GSS_S_BAD_SIG;
diff --git a/net/sunrpc/auth_gss/gss_krb5_wrap.c b/net/sunrpc/auth_gss/gss_krb5_wrap.c
index 7188891..2eb3046 100644
--- a/net/sunrpc/auth_gss/gss_krb5_wrap.c
+++ b/net/sunrpc/auth_gss/gss_krb5_wrap.c
@@ -167,6 +167,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__);
@@ -205,18 +206,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, ptr, 8, buf,
- offset + headlen - blocksize, &md5cksum))
+ if (make_checksum(kctx, ptr, 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(ptr + GSS_KRB5_TOK_HDR_LEN, md5cksum.data + md5cksum.len - 8, 8);
+ memcpy(ptr + GSS_KRB5_TOK_HDR_LEN, md5cksum.data, md5cksum.len);
spin_lock(&krb5_seq_lock);
seq_send = kctx->seq_send++;
@@ -252,6 +255,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");
@@ -288,15 +292,17 @@ 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, 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, 8, buf, crypt_offset,
+ cksumkey, &md5cksum))
return GSS_S_FAILURE;
- if (memcmp(md5cksum.data + 8, ptr + GSS_KRB5_TOK_HDR_LEN, 8))
+ if (memcmp(md5cksum.data, ptr + GSS_KRB5_TOK_HDR_LEN,
+ kctx->gk5e->cksumlength))
return GSS_S_BAD_SIG;
/* it got through unscathed. Make sure the context is unexpired */
--
1.6.6.1
next prev parent reply other threads:[~2010-04-14 17:37 UTC|newest]
Thread overview: 36+ messages / expand[flat|nested] mbox.gz Atom feed top
2010-04-14 17:36 [PATCH 00/22] Add support for more RPCSEC_GSS/krb5 enctypes Trond Myklebust
2010-04-14 17:36 ` [PATCH 01/22] gss_krb5: Introduce encryption type framework Trond Myklebust
2010-04-14 17:36 ` [PATCH 02/22] gss_krb5: Added and improved code comments Trond Myklebust
2010-04-14 17:36 ` [PATCH 03/22] gss_krb5: Don't expect blocksize to always be 8 when calculating padding Trond Myklebust
2010-04-14 17:36 ` [PATCH 04/22] gss_krb5: split up functions in preparation of adding new enctypes Trond Myklebust
2010-04-14 17:36 ` [PATCH 05/22] gss_krb5: prepare for new context format Trond Myklebust
2010-04-14 17:36 ` [PATCH 06/22] gss_krb5: introduce encryption type framework Trond Myklebust
2010-04-14 17:36 ` Trond Myklebust [this message]
2010-04-14 17:36 ` [PATCH 08/22] gss_krb5: import functionality to derive keys into the kernel Trond Myklebust
2010-04-14 17:36 ` [PATCH 09/22] gss_krb5: handle new context format from gssd Trond Myklebust
2010-04-14 17:36 ` [PATCH 10/22] gss_krb5: Add upcall info indicating supported kerberos enctypes Trond Myklebust
2010-04-14 17:36 ` [PATCH 11/22] gss_krb5: add support for triple-des encryption Trond Myklebust
2010-04-14 17:36 ` [PATCH 12/22] gss_krb5: Advertise triple-des enctype support in the rpcsec_gss/krb5 upcall Trond Myklebust
2010-04-14 17:36 ` [PATCH 13/22] xdr: Add an export for the helper function write_bytes_to_xdr_buf() Trond Myklebust
2010-04-14 17:36 ` [PATCH 14/22] gss_krb5: add support for new token formats in rfc4121 Trond Myklebust
2010-04-14 17:36 ` [PATCH 15/22] gss_krb5: add remaining pieces to enable AES encryption support Trond Myklebust
2010-04-14 17:36 ` [PATCH 16/22] gss_krb5: Advertise AES enctype support in the rpcsec_gss/krb5 upcall Trond Myklebust
2010-04-14 17:36 ` [PATCH 17/22] gssd_krb5: arcfour-hmac support Trond Myklebust
2010-04-14 17:36 ` [PATCH 18/22] gss_krb5: Save the raw session key in the context Trond Myklebust
2010-04-14 17:36 ` [PATCH 19/22] gssd_krb5: More arcfour-hmac support Trond Myklebust
2010-04-14 17:36 ` [PATCH 20/22] gss_krb5: Use confounder length in wrap code Trond Myklebust
2010-04-14 17:36 ` [PATCH 21/22] gss_krb5: Add support for rc4-hmac encryption Trond Myklebust
2010-04-14 17:36 ` [PATCH 22/22] gss_krb5: Advertise rc4-hmac enctype support in the rpcsec_gss/krb5 upcall Trond Myklebust
2010-04-14 18:30 ` [PATCH 10/22] gss_krb5: Add upcall info indicating supported kerberos enctypes Kevin Coffman
2010-04-14 18:37 ` Trond Myklebust
2010-04-14 18:51 ` Kevin Coffman
2010-04-14 19:32 ` Steve Dickson
2010-04-14 19:50 ` Kevin Coffman
2010-04-14 19:54 ` Steve Dickson
2010-04-15 11:34 ` Steve Dickson
2010-04-15 13:17 ` Kevin Coffman
2010-04-15 13:22 ` Trond Myklebust
2010-04-15 13:31 ` Trond Myklebust
2010-04-14 17:47 ` [PATCH 00/22] Add support for more RPCSEC_GSS/krb5 enctypes J. Bruce Fields
2010-04-14 17:54 ` Trond Myklebust
2010-04-14 19:36 ` Steve Dickson
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=1271266618-26016-8-git-send-email-Trond.Myklebust@netapp.com \
--to=trond.myklebust@netapp.com \
--cc=linux-nfs@vger.kernel.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox