/* * spkm3_read_token() * * only SPKM_MIC_TOK with md5 intg-alg is supported */ u32 spkm3_read_token(struct spkm3_ctx *ctx, 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) { 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: kfree(md5cksum.data); kfree(wire_cksum.data); return ret; }
u32 spkm3_verify_mic_token(unsigned char **tokp, int *mic_hdrlen, unsigned char **cksum) { struct xdr_netobj spkm3_ctx_id = {.len =0, .data = NULL}; unsigned char *ptr = *tokp; int ctxelen; u32 ret = GSS_S_DEFECTIVE_TOKEN; /* spkm3 innercontext token preamble */ if ((ptr[0] != 0xa4) || (ptr[2] != 0x30)) { dprintk("RPC: BAD SPKM ictoken preamble\n"); goto out; } *mic_hdrlen = ptr[3]; /* token type */ if ((ptr[4] != 0x02) || (ptr[5] != 0x02)) { dprintk("RPC: BAD asn1 SPKM3 token type\n"); goto out; } /* only support SPKM_MIC_TOK */ if((ptr[6] != 0x01) || (ptr[7] != 0x01)) { dprintk("RPC: ERROR unsupported SPKM3 token \n"); goto out; } /* contextid */ if (ptr[8] != 0x03) { dprintk("RPC: BAD SPKM3 asn1 context-id type\n"); goto out; } ctxelen = ptr[9]; if (ctxelen > 17) { /* length includes asn1 zbit octet */ dprintk("RPC: BAD SPKM3 contextid len %d\n", ctxelen); goto out; } /* ignore ptr[10] */ if(!decode_asn1_bitstring(&spkm3_ctx_id, &ptr[11], ctxelen - 1, 16)) goto out; /* * in the current implementation: the optional int-alg is not present * so the default int-alg (md5) is used the optional snd-seq field is * also not present */ if (*mic_hdrlen != 6 + ctxelen) { dprintk("RPC: BAD SPKM_ MIC_TOK header len %d: we only " "support default int-alg (should be absent) " "and do not support snd-seq\n", *mic_hdrlen); goto out; } /* checksum */ *cksum = (&ptr[10] + ctxelen); /* ctxelen includes ptr[10] */ ret = GSS_S_COMPLETE; out: kfree(spkm3_ctx_id.data); return ret; }
/* * spkm3_read_token() * * only SPKM_MIC_TOK with md5 intg-alg is supported */ u32 spkm3_read_token(struct spkm3_ctx *ctx, struct xdr_netobj *read_token, /* checksum */ struct xdr_buf *message_buffer, /* signbuf */ int toktype) { s32 checksum_type; s32 code; struct xdr_netobj wire_cksum = {.len =0, .data = NULL}; char cksumdata[16]; struct xdr_netobj md5cksum = {.len = 0, .data = cksumdata}; unsigned char *ptr = (unsigned char *)read_token->data; unsigned char *cksum; int bodysize, md5elen; int mic_hdrlen; u32 ret = GSS_S_DEFECTIVE_TOKEN; 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) { dprintk("RPC: BAD SPKM3 token type: %d\n", toktype); goto out; } 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; if (!g_OID_equal(&ctx->intg_alg, &hmac_md5_oid)) { dprintk("RPC: gss_spkm3_seal: unsupported I-ALG " "algorithm\n"); goto out; } checksum_type = CKSUMTYPE_HMAC_MD5; code = make_spkm3_checksum(checksum_type, &ctx->derived_integ_key, ptr + 2, mic_hdrlen + 2, message_buffer, 0, &md5cksum); if (code) goto out; ret = GSS_S_BAD_SIG; code = memcmp(md5cksum.data, wire_cksum.data, wire_cksum.len); if (code) { dprintk("RPC: bad MIC checksum\n"); goto out; } ret = GSS_S_COMPLETE; out: kfree(wire_cksum.data); return ret; }