Skip to content

Commit

Permalink
---
Browse files Browse the repository at this point in the history
yaml
---
r: 192276
b: refs/heads/master
c: de9c17e
h: refs/heads/master
v: v3
  • Loading branch information
Kevin Coffman authored and Trond Myklebust committed May 14, 2010
1 parent 53da808 commit 39a473d
Show file tree
Hide file tree
Showing 6 changed files with 407 additions and 1 deletion.
2 changes: 1 addition & 1 deletion [refs]
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
---
refs/heads/master: c43abaedaff92a7bcbfe04b593164bb5faba3078
refs/heads/master: de9c17eb4a912c9028f7b470eb80815144883b26
28 changes: 28 additions & 0 deletions trunk/include/linux/sunrpc/gss_krb5.h
Original file line number Diff line number Diff line change
Expand Up @@ -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 */
Expand All @@ -75,6 +77,12 @@ struct gss_krb5_enctype {
u32 (*mk_key) (const 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 */
Expand Down Expand Up @@ -112,6 +120,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,
Expand All @@ -136,6 +156,9 @@ enum seal_alg {
#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)
Expand Down Expand Up @@ -212,6 +235,11 @@ make_checksum(struct krb5_ctx *kctx, char *header, int hdrlen,
struct xdr_buf *body, int body_offset, u8 *cksumkey,
struct xdr_netobj *cksumout);

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 *);

Expand Down
74 changes: 74 additions & 0 deletions trunk/net/sunrpc/auth_gss/gss_krb5_crypto.c
Original file line number Diff line number Diff line change
Expand Up @@ -197,6 +197,80 @@ make_checksum(struct krb5_ctx *kctx, char *header, int hdrlen,
return err ? GSS_S_FAILURE : 0;
}

/*
* 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
* Inclusion of the header data in the calculation of the
* checksum is optional.
*/
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;
if (header != NULL) {
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;
}

struct encryptor_desc {
u8 iv[GSS_KRB5_MAX_BLOCKSIZE];
struct blkcipher_desc desc;
Expand Down
69 changes: 69 additions & 0 deletions trunk/net/sunrpc/auth_gss/gss_krb5_seal.c
Original file line number Diff line number Diff line change
Expand Up @@ -91,6 +91,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 = GSS_KRB5_TOK_HDR_LEN + ctx->gk5e->cksumlength;
return krb5_hdr;
}

static u32
gss_get_mic_v1(struct krb5_ctx *ctx, struct xdr_buf *text,
struct xdr_netobj *token)
Expand Down Expand Up @@ -132,6 +159,45 @@ gss_get_mic_v1(struct krb5_ctx *ctx, struct xdr_buf *text,
return (ctx->endtime < now) ? GSS_S_CONTEXT_EXPIRED : GSS_S_COMPLETE;
}

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__);

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, GSS_KRB5_TOK_HDR_LEN,
text, 0, cksumkey, &cksumobj))
return GSS_S_FAILURE;

memcpy(krb5_hdr + GSS_KRB5_TOK_HDR_LEN, 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)
Expand All @@ -144,6 +210,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);
}
}

61 changes: 61 additions & 0 deletions trunk/net/sunrpc/auth_gss/gss_krb5_unseal.c
Original file line number Diff line number Diff line change
Expand Up @@ -141,6 +141,64 @@ 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, GSS_KRB5_TOK_HDR_LEN, message_buffer, 0,
cksumkey, &cksumobj))
return GSS_S_FAILURE;

if (memcmp(cksumobj.data, ptr + GSS_KRB5_TOK_HDR_LEN,
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_cpup((__be64 *)ptr + 8);

return GSS_S_COMPLETE;
}

u32
gss_verify_mic_kerberos(struct gss_ctx *gss_ctx,
struct xdr_buf *message_buffer,
Expand All @@ -154,6 +212,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);
}
}

Loading

0 comments on commit 39a473d

Please sign in to comment.