Computing MS-MPPE-Recv-Key and MS-MPPE-Send-Key in MS-CHAPv2 auth
Hadi Rezaee
rezaee.hadi at gmail.com
Sun Jan 5 19:37:11 UTC 2025
Hello there,
I'm trying to figure out how MS-MPPE-Send-Key and MS-MPPE-Recv-Key are
getting generated by freeradius-server. Here, it is the sample captured
traffic I've for a MS-CHAPv2 (Access-Accept) auth between a radius client
and server:
MS-MPPE-Recv-Key:
a660ce53f31ef08ed6cf209ece137a1dee40aeae5d8e5b9de0f1592324bc92569fc1
MS-MPPE-Send-Key:
a81579eb58f0bd25636599778c8689516129db8b25ec2d1e4c15797862efedabb3c
So, the first thing I noticed here is that the length of the values for
both AVPs are 34 bytes.
I read rfc2548 and rfc3079 for this matter and then tried to find
corresponding implementations in the code-base
(src/modules/rlm_mschap/rlm_mschap.c), and found "mppe_chap2_gen_keys128"
function. The function is being called by "mod_authenticate_resume" :
/* now create MPPE attributes */
if (inst->use_mppe) {
fr_pair_t *vp;
uint8_t mppe_sendkey[34];
uint8_t mppe_recvkey[34];
switch (mschap_version) {
case 1:
RDEBUG2("Generating MS-CHAPv1 MPPE keys");
memset(mppe_sendkey, 0, 32);
/*
* According to RFC 2548 we
* should send NT hash. But in
* practice it doesn't work.
* Instead, we should send nthashhash
*
* This is an error in RFC 2548.
*/
/*
* do_mschap cares to zero nthashhash if NT hash
* is not available.
*/
memcpy(mppe_sendkey + 8, nthashhash, NT_DIGEST_LENGTH);
mppe_add_reply(inst, request, tmpl_attr_tail_da(env_data->chap_mppe_keys),
mppe_sendkey, 24); //-V666
break;
case 2:
RDEBUG2("Generating MS-CHAPv2 MPPE keys");
mppe_chap2_gen_keys128(nthashhash, response->vp_octets + 26, mppe_sendkey,
mppe_recvkey);
mppe_add_reply(inst, request, tmpl_attr_tail_da(env_data->mppe_recv_key),
mppe_recvkey, 16);
mppe_add_reply(inst, request, tmpl_attr_tail_da(env_data->mppe_send_key),
mppe_sendkey, 16);
break;
default:
fr_assert(0);
break;
}
MEM(pair_update_reply(&vp,
tmpl_attr_tail_da(env_data->mppe_encryption_policy)) >= 0);
vp->vp_uint32 = inst->require_encryption ? 2 : 1;
MEM(pair_update_reply(&vp,
tmpl_attr_tail_da(env_data->mppe_encryption_types)) >= 0);
vp->vp_uint32 = inst->require_strong ? 4 : 6;
} /* else we weren't asked to use MPPE */
Correct me if I'm wrong but here I read " mppe_sendkey" and " mppe_recvkey"
variables are initialized with 34 bytes (as i expected!), but later by
calling mppe_chap2_gen_keys128 only 16 bytes are copied. I was expecting
other items (such as 'Salt') to be taken into account too ..
Thanks.
More information about the Freeradius-Devel
mailing list