--- linux-2.6.14-rc5-CITI_NFS4_ALL-1/include/linux/sunrpc/gss_spkm3.h 2005-10-24 12:38:49.000000000 -0400 +++ /usr/src/linux/include/linux/sunrpc/gss_spkm3.h 2005-10-24 13:29:07.000000000 -0400 @@ -18,21 +18,24 @@ struct spkm3_ctx { unsigned int ret_flags ; unsigned int req_flags ; struct xdr_netobj share_key; - int conf_alg; - struct crypto_tfm* derived_conf_key; - int intg_alg; - struct crypto_tfm* derived_integ_key; - int keyestb_alg; /* alg used to get share_key */ - int owf_alg; /* one way function */ + struct xdr_netobj conf_alg; + struct xdr_netobj derived_conf_key; + struct xdr_netobj intg_alg; + struct xdr_netobj derived_integ_key; + struct xdr_netobj keyestb_alg; /* alg used to get share_key */ + struct xdr_netobj owf_alg; /* one way function */ }; -/* from openssl/objects.h */ -/* XXX need SEAL_ALG_NONE */ -#define NID_md5 4 -#define NID_dhKeyAgreement 28 -#define NID_des_cbc 31 -#define NID_sha1 64 -#define NID_cast5_cbc 108 +/* OIDs declarations for K-ALG, I-ALG, C-ALG, and OWF-ALG */ +static const struct xdr_netobj dh_oid = {9, "\02A\086\048\086\0F7\00D\001\003\001"}; +static const struct xdr_netobj hmac_md5_oid = { 8, "\02B\006\001\005\005\008\001\001"}; +static const struct xdr_netobj null_mac_oid = { 6, "\02B\006\001\005\003\003"}; +static const struct xdr_netobj md5_rsa_encryption_oid = {9, "\02A\086\048\086\0F7\00D\001\001\004"}; + +static const struct xdr_netobj cast5_cbc_oid = {9, "\02A\086\048\086\0F6\07D\007\042\00A"}; +static const struct xdr_netobj des_cbc_oid = {5, "\02B\00E\003\002\007"}; + +static const struct xdr_netobj sha1_oid = {5, "\02B\00E\003\002\01A"}; /* SPKM InnerContext Token types */ @@ -46,6 +49,7 @@ u32 spkm3_make_token(struct spkm3_ctx *c u32 spkm3_read_token(struct spkm3_ctx *ctx, struct xdr_netobj *read_token, struct xdr_buf *message_buffer, int toktype); #define CKSUMTYPE_RSA_MD5 0x0007 +#define CKSUMTYPE_HMAC_MD5 0x0007 s32 make_checksum(s32 cksumtype, char *header, int hdrlen, struct xdr_buf *body, int body_offset, struct xdr_netobj *cksum); --- linux-2.6.14-rc5-CITI_NFS4_ALL-1/net/sunrpc/auth_gss/gss_spkm3_mech.c 2005-10-24 12:38:49.000000000 -0400 +++ /usr/src/linux/net/sunrpc/auth_gss/gss_spkm3_mech.c 2005-10-21 16:34:12.000000000 -0400 @@ -82,68 +82,10 @@ simple_get_netobj(const void *p, const v return q; } -static inline const void * -get_key(const void *p, const void *end, struct crypto_tfm **res, int *resalg) -{ - struct xdr_netobj key = { 0 }; - int alg_mode,setkey = 0; - char *alg_name; - - p = simple_get_bytes(p, end, resalg, sizeof(*resalg)); - if (IS_ERR(p)) - goto out_err; - p = simple_get_netobj(p, end, &key); - if (IS_ERR(p)) - goto out_err; - switch (*resalg) { - case NID_des_cbc: - alg_name = "des"; - alg_mode = CRYPTO_TFM_MODE_CBC; - setkey = 1; - break; - case NID_cast5_cbc: - /* XXXX here in name only, not used */ - alg_name = "cast5"; - alg_mode = CRYPTO_TFM_MODE_CBC; - setkey = 0; /* XXX will need to set to 1 */ - break; - case NID_md5: - if (key.len == 0) { - dprintk("RPC: SPKM3 get_key: NID_md5 zero Key length\n"); - } - alg_name = "md5"; - alg_mode = 0; - setkey = 0; - break; - default: - dprintk("gss_spkm3_mech: unsupported algorithm %d/n", *resalg); - goto out_err_free_key; - } - if (!(*res = crypto_alloc_tfm(alg_name, alg_mode))) { - printk("gss_spkm3_mech: unable to initialize crypto algorthm %s\n", alg_name); - goto out_err_free_key; - } - if (setkey) { - if (crypto_cipher_setkey(*res, key.data, key.len)) { - printk("gss_spkm3_mech: error setting key for crypto algorthm %s\n", alg_name); - goto out_err_free_tfm; - } - } - - if(key.len > 0) - kfree(key.data); - return p; - -out_err_free_tfm: - crypto_free_tfm(*res); -out_err_free_key: - if(key.len > 0) - kfree(key.data); - p = ERR_PTR(-EINVAL); -out_err: - return p; -} +/* in nfs-utils-1.0.7/utils/gssd/context.c serialize_spkm3_ctx() we + * serialized spkm3 context. here, we read it back. + */ static int gss_import_sec_context_spkm3(const void *p, size_t len, @@ -180,34 +122,50 @@ gss_import_sec_context_spkm3(const void if (IS_ERR(p)) goto out_err_free_s_key; - p = get_key(p, end, &ctx->derived_conf_key, &ctx->conf_alg); + p = simple_get_netobj(p, end, &ctx->conf_alg); if (IS_ERR(p)) - goto out_err_free_s_key; + goto out_err_free_conf_alg; + + p = simple_get_netobj(p, end, &ctx->derived_conf_key); + if (IS_ERR(p)) + goto out_err_free_conf_key; - p = get_key(p, end, &ctx->derived_integ_key, &ctx->intg_alg); + p = simple_get_netobj(p, end, &ctx->intg_alg); if (IS_ERR(p)) - goto out_err_free_key1; + goto out_err_free_intg_alg; - p = simple_get_bytes(p, end, &ctx->keyestb_alg, sizeof(ctx->keyestb_alg)); + p = simple_get_netobj(p, end, &ctx->derived_integ_key); if (IS_ERR(p)) - goto out_err_free_key2; + goto out_err_free_intg_key; - p = simple_get_bytes(p, end, &ctx->owf_alg, sizeof(ctx->owf_alg)); + p = simple_get_netobj(p, end, &ctx->keyestb_alg); if (IS_ERR(p)) - goto out_err_free_key2; + goto out_err_free_keyestb_alg; + + p = simple_get_netobj(p, end, &ctx->owf_alg); + if (IS_ERR(p)) + goto out_err_free_owf_alg; if (p != end) - goto out_err_free_key2; + goto out_err_free_owf_alg; ctx_id->internal_ctx_id = ctx; dprintk("Succesfully imported new spkm context.\n"); return 0; -out_err_free_key2: - crypto_free_tfm(ctx->derived_integ_key); -out_err_free_key1: - crypto_free_tfm(ctx->derived_conf_key); +out_err_free_owf_alg: + kfree(ctx->owf_alg.data); +out_err_free_keyestb_alg: + kfree(ctx->keyestb_alg.data); +out_err_free_intg_key: + kfree(ctx->derived_integ_key.data); +out_err_free_intg_alg: + kfree(ctx->intg_alg.data); +out_err_free_conf_key: + kfree(ctx->derived_conf_key.data); +out_err_free_conf_alg: + kfree(ctx->conf_alg.data); out_err_free_s_key: kfree(ctx->share_key.data); out_err_free_mech: @@ -217,6 +175,7 @@ out_err_free_ctx_id: out_err_free_ctx: kfree(ctx); out_err: + dprintk("Failed to import new spkm context: bad marshalling?\n"); return PTR_ERR(p); } @@ -224,10 +183,15 @@ static void gss_delete_sec_context_spkm3(void *internal_ctx) { struct spkm3_ctx *sctx = internal_ctx; - crypto_free_tfm(sctx->derived_integ_key); - crypto_free_tfm(sctx->derived_conf_key); + kfree(sctx->owf_alg.data); + kfree(sctx->keyestb_alg.data); + kfree(sctx->derived_integ_key.data); + kfree(sctx->intg_alg.data); + kfree(sctx->derived_conf_key.data); + kfree(sctx->conf_alg.data); kfree(sctx->share_key.data); kfree(sctx->mech_used.data); + kfree(sctx->ctx_id.data); kfree(sctx); } @@ -239,7 +203,6 @@ gss_verify_mic_spkm3(struct gss_ctx *ct u32 maj_stat = 0; struct spkm3_ctx *sctx = ctx->internal_ctx_id; - dprintk("RPC: gss_verify_mic_spkm3 calling spkm3_read_token\n"); maj_stat = spkm3_read_token(sctx, checksum, signbuf, SPKM_MIC_TOK); dprintk("RPC: gss_verify_mic_spkm3 returning %d\n", maj_stat); @@ -251,14 +214,14 @@ gss_get_mic_spkm3(struct gss_ctx *ctx, struct xdr_buf *message_buffer, struct xdr_netobj *message_token) { - u32 err = 0; + u32 maj_stat = 0; struct spkm3_ctx *sctx = ctx->internal_ctx_id; - dprintk("RPC: gss_get_mic_spkm3\n"); + maj_stat = spkm3_make_token(sctx, message_buffer, message_token, + SPKM_MIC_TOK); - err = spkm3_make_token(sctx, message_buffer, - message_token, SPKM_MIC_TOK); - return err; + dprintk("RPC: gss_get_mic_spkm3 returning %d\n", maj_stat); + return maj_stat; } static struct gss_api_ops gss_spkm3_ops = { @@ -287,7 +250,7 @@ static int __init init_spkm3_module(void status = gss_mech_register(&gss_spkm3_mech); if (status) - printk("Failed to register spkm3 gss mechanism!\n"); + dprintk("Failed to register spkm3 gss mechanism!\n"); return 0; } --- linux-2.6.14-rc5-CITI_NFS4_ALL-1/net/sunrpc/auth_gss/gss_spkm3_seal.c 2005-10-24 12:38:49.000000000 -0400 +++ /usr/src/linux/net/sunrpc/auth_gss/gss_spkm3_seal.c 2005-10-21 16:46:43.000000000 -0400 @@ -40,10 +40,13 @@ #include #include +#include + #ifdef RPC_DEBUG # define RPCDBG_FACILITY RPCDBG_AUTH #endif +#define CTX_ID_LEN 16 /* * spkm3_make_token() * @@ -52,78 +55,100 @@ u32 spkm3_make_token(struct spkm3_ctx *ctx, - struct xdr_buf * text, struct xdr_netobj * token, - int toktype) + struct xdr_buf * text, struct xdr_netobj * token, + int toktype) { - s32 checksum_type; - char tokhdrbuf[25]; - struct xdr_netobj md5cksum = {.len = 0, .data = NULL}; - struct xdr_netobj mic_hdr = {.len = 0, .data = tokhdrbuf}; - int tokenlen = 0; - unsigned char *ptr; - s32 now; - int ctxelen = 0, ctxzbit = 0; - int md5elen = 0, md5zbit = 0; - - dprintk("RPC: spkm3_make_token\n"); - - now = jiffies; - - if (ctx->ctx_id.len != 16) { - dprintk("RPC: spkm3_make_token BAD ctx_id.len %d\n", - ctx->ctx_id.len); - goto out_err; - } - - switch (ctx->intg_alg) { - case NID_md5: - checksum_type = CKSUMTYPE_RSA_MD5; - break; - default: - dprintk("RPC: gss_spkm3_seal: ctx->signalg %d not" - " supported\n", ctx->intg_alg); - goto out_err; - } - /* XXX since we don't support WRAP, perhaps we don't care... */ - if (ctx->conf_alg != NID_cast5_cbc) { - dprintk("RPC: gss_spkm3_seal: ctx->sealalg %d not supported\n", - ctx->conf_alg); - goto out_err; - } - - if (toktype == SPKM_MIC_TOK) { - /* Calculate checksum over the mic-header */ - asn1_bitstring_len(&ctx->ctx_id, &ctxelen, &ctxzbit); - spkm3_mic_header(&mic_hdr.data, &mic_hdr.len, ctx->ctx_id.data, - ctxelen, ctxzbit); - - if (make_checksum(checksum_type, mic_hdr.data, mic_hdr.len, - text, 0, &md5cksum)) - goto out_err; - - asn1_bitstring_len(&md5cksum, &md5elen, &md5zbit); - tokenlen = 10 + ctxelen + 1 + md5elen + 1; - - /* Create token header using generic routines */ - token->len = g_token_size(&ctx->mech_used, tokenlen); - - ptr = token->data; - g_make_token_header(&ctx->mech_used, tokenlen, &ptr); - - spkm3_make_mic_token(&ptr, tokenlen, &mic_hdr, &md5cksum, md5elen, md5zbit); - } else if (toktype == SPKM_WRAP_TOK) { /* Not Supported */ - dprintk("RPC: gss_spkm3_seal: SPKM_WRAP_TOK not supported\n"); - goto out_err; - } - kfree(md5cksum.data); - - /* XXX need to implement sequence numbers, and ctx->expired */ - - return GSS_S_COMPLETE; -out_err: - if (md5cksum.data) - kfree(md5cksum.data); - token->data = NULL; - token->len = 0; - return GSS_S_FAILURE; + char tokhdrbuf[25]; + struct xdr_netobj cksum = {.len = 0, .data = NULL}; + struct xdr_netobj mic_hdr = {.len = 0, .data = tokhdrbuf}; + int tokenlen = 0; + unsigned char *ptr; + s32 now; + int ctxelen = 0, ctxzbit = 0; + int cksumlen = 0, cksumasnlen = 0; + + now = jiffies; + + if (ctx->ctx_id.len != CTX_ID_LEN) { + dprintk("RPC: spkm3_make_token BAD ctx_id.len %d expecting %d\n", + ctx->ctx_id.len, CTX_ID_LEN); + goto out_err; + } + + if(!g_OID_equal(&ctx->intg_alg, &hmac_md5_oid)) { + dprintk("RPC: gss_spkm3_seal: unsupported I-ALG algorithm." + "only support hmac-md5 I-ALG.\n"); + goto out_err; + } + + /* XXX since we don't support WRAP, perhaps we don't care... */ + if (!g_OID_equal(&ctx->conf_alg, &cast5_cbc_oid)) { + dprintk("RPC: gss_spkm3_seal: unsupported C-ALG algorithm\n"); + goto out_err; + } + + if (toktype == SPKM_MIC_TOK) { + /* Calculate checksum over the mic-header */ + asn1_bitstring_len(&ctx->ctx_id, &ctxelen, &ctxzbit); + spkm3_mic_header(&mic_hdr.data, &mic_hdr.len, ctx->ctx_id.data, + ctxelen, ctxzbit); + + if(g_OID_equal(&ctx->intg_alg, &hmac_md5_oid)) { + struct crypto_tfm *tfm = NULL; + struct scatterlist sg; + + dprintk("RPC: calculating (sender) HMAC-MD5 checksum\n"); + if (!(tfm = crypto_alloc_tfm("md5", CRYPTO_TFM_REQ_MAY_SLEEP))) + goto out_err; + + cksum.len = crypto_tfm_alg_digestsize(tfm); + + if((cksum.data = kmalloc(cksum.len, GFP_KERNEL)) == NULL) { + crypto_free_tfm(tfm); + goto out_err; + } + sg.page = virt_to_page(mic_hdr.data); + sg.offset = offset_in_page(mic_hdr.data); + sg.length = mic_hdr.len; + + crypto_hmac(tfm, ctx->derived_integ_key.data, + &ctx->derived_integ_key.len, &sg, 1, + cksum.data); + + crypto_free_tfm(tfm); + + } + + print_hexl((u32 *)mic_hdr.data, mic_hdr.len, 0); + + asn1_bitstring_len(&cksum, &cksumlen, &cksumasnlen); + tokenlen = 10 + ctxelen + 1 + cksumlen + 1; + + /* Create token header using generic routines */ + token->len = g_token_size(&ctx->mech_used, tokenlen); + + ptr = token->data; + g_make_token_header(&ctx->mech_used, tokenlen, &ptr); + + spkm3_make_mic_token(&ptr, tokenlen, &mic_hdr, &cksum, cksumlen, + cksumasnlen); + + } else if (toktype == SPKM_WRAP_TOK) { /* Not Supported */ + dprintk("RPC: gss_spkm3_seal: SPKM_WRAP_TOK not supported\n"); + goto out_err; + } + kfree(cksum.data); + + /* XXX need to implement sequence numbers, and ctx->expired */ + + dprintk("RPC: spkm3_make_token: END\n"); + + return GSS_S_COMPLETE; + + out_err: + if (cksum.data) + kfree(cksum.data); + token->data = NULL; + token->len = 0; + return GSS_S_FAILURE; } --- linux-2.6.14-rc5-CITI_NFS4_ALL-1/net/sunrpc/auth_gss/gss_spkm3_unseal.c 2005-10-24 12:38:49.000000000 -0400 +++ /usr/src/linux/net/sunrpc/auth_gss/gss_spkm3_unseal.c 2005-10-21 16:58:09.000000000 -0400 @@ -39,6 +39,8 @@ #include #include +#include + #ifdef RPC_DEBUG # define RPCDBG_FACILITY RPCDBG_AUTH #endif @@ -50,79 +52,102 @@ */ u32 spkm3_read_token(struct spkm3_ctx *ctx, - struct xdr_netobj *read_token, /* checksum */ - struct xdr_buf *message_buffer, /* signbuf */ - int toktype) + struct xdr_netobj *read_token, /* checksum */ + struct xdr_buf *message_buffer, /* signbuf */ + int toktype) { - s32 code; - struct xdr_netobj wire_cksum = {.len =0, .data = NULL}; - struct xdr_netobj md5cksum = {.len = 0, .data = NULL}; - unsigned char *ptr = (unsigned char *)read_token->data; - unsigned char *cksum; - int bodysize, md5elen; - int mic_hdrlen; - u32 ret = GSS_S_DEFECTIVE_TOKEN; - - dprintk("RPC: spkm3_read_token read_token->len %d\n", read_token->len); - - if (g_verify_token_header((struct xdr_netobj *) &ctx->mech_used, - &bodysize, &ptr, read_token->len)) - goto out; - - /* decode the token */ - - if (toktype == SPKM_MIC_TOK) { - - if ((ret = spkm3_verify_mic_token(&ptr, &mic_hdrlen, &cksum))) - goto out; - - if (*cksum++ != 0x03) { + s32 code; + struct xdr_netobj wire_cksum = {.len =0, .data = NULL}; + struct xdr_netobj local_cksum = {.len = 0, .data = NULL}; + unsigned char *ptr = (unsigned char *)read_token->data; + unsigned char *cksum; + int bodysize, wire_cksumlen; + int mic_hdrlen; + u32 ret = GSS_S_DEFECTIVE_TOKEN; + + dprintk("RPC: spkm3_read_token read_token->len %d\n", read_token->len); + + if(!g_OID_equal(&ctx->intg_alg, &hmac_md5_oid)) { + dprintk("RPC: gss_spkm3_seal: unsupported I-ALG algorithm." + "only support hmac-md5 I-ALG.\n"); + goto out; + } + + if (g_verify_token_header((struct xdr_netobj *) &ctx->mech_used, + &bodysize, &ptr, read_token->len)) + goto out; + + /* decode the token */ + + if (toktype == SPKM_MIC_TOK) { + + if ((ret = spkm3_verify_mic_token(&ptr, &mic_hdrlen, &cksum))) + goto out; + + if (*cksum++ != 0x03) { dprintk("RPC: spkm3_read_token BAD checksum type\n"); goto out; - } - md5elen = *cksum++; - cksum++; /* move past the zbit */ - - if(!decode_asn1_bitstring(&wire_cksum, cksum, md5elen - 1, 16)) - goto out; - - /* HARD CODED FOR MD5 */ - - /* compute the checksum of the message. - * ptr + 2 = start of header piece of checksum - * mic_hdrlen + 2 = length of header piece of checksum - */ - ret = GSS_S_DEFECTIVE_TOKEN; - code = make_checksum(CKSUMTYPE_RSA_MD5, ptr + 2, - mic_hdrlen + 2, - message_buffer, 0, &md5cksum); - - if (code) - goto out; - - dprintk("RPC: spkm3_read_token: digest wire_cksum.len %d:\n", - wire_cksum.len); - dprintk(" md5cksum.data\n"); - print_hexl((u32 *) md5cksum.data, 16, 0); - dprintk(" cksum.data:\n"); - print_hexl((u32 *) wire_cksum.data, wire_cksum.len, 0); - - ret = GSS_S_BAD_SIG; - code = memcmp(md5cksum.data, wire_cksum.data, wire_cksum.len); - if (code) - goto out; - - } else { - dprintk("RPC: BAD or UNSUPPORTED SPKM3 token type: %d\n",toktype); - goto out; - } - - /* XXX: need to add expiration and sequencing */ - ret = GSS_S_COMPLETE; -out: - if (md5cksum.data) - kfree(md5cksum.data); - if (wire_cksum.data) - kfree(wire_cksum.data); - return ret; + } + wire_cksumlen = *cksum++; + cksum++; /* move past the zbit */ + + if(!decode_asn1_bitstring(&wire_cksum, cksum, wire_cksumlen - 1, 16)) + goto out; + + /* compute the checksum of the message. + * ptr + 2 = start of header piece of checksum + * mic_hdrlen + 2 = length of header piece of checksum + */ + ret = GSS_S_DEFECTIVE_TOKEN; + if(g_OID_equal(&ctx->intg_alg, &hmac_md5_oid)) { + struct crypto_tfm *tfm = NULL; + struct scatterlist sg; + + dprintk("RPC: calculating (receiver) HMAC checksum\n"); + if (!(tfm = crypto_alloc_tfm("md5", CRYPTO_TFM_REQ_MAY_SLEEP))) + goto out; + + local_cksum.len = crypto_tfm_alg_digestsize(tfm); + + if((local_cksum.data = + kmalloc(local_cksum.len, GFP_KERNEL)) == NULL) { + crypto_free_tfm(tfm); + goto out; + } + sg.page = virt_to_page(ptr + 2); + sg.offset = offset_in_page(ptr + 2); + sg.length = mic_hdrlen + 2; + + crypto_hmac(tfm, ctx->derived_integ_key.data, + &ctx->derived_integ_key.len, &sg, 1, + local_cksum.data); + + crypto_free_tfm(tfm); + } + + dprintk("RPC: spkm3_read_token: digest wire_cksum.len %d:\n", + wire_cksum.len); + dprintk(" local_cksum\n"); + print_hexl((u32 *) local_cksum.data, local_cksum.len, 0); + dprintk(" wire_cksum\n"); + print_hexl((u32 *) wire_cksum.data, wire_cksum.len, 0); + + ret = GSS_S_BAD_SIG; + code = memcmp(local_cksum.data, wire_cksum.data, wire_cksum.len); + if (code) + goto out; + + } else { + dprintk("RPC: BAD or UNSUPPORTED SPKM3 token type: %d\n", toktype); + goto out; + } + + /* XXX: need to add expiration and sequencing */ + ret = GSS_S_COMPLETE; + out: + if (local_cksum.data) + kfree(local_cksum.data); + if (wire_cksum.data) + kfree(wire_cksum.data); + return ret; }