3

I have been reading through RFC 3579 as I am implementing a RADIUS service that supports EAP-MD5 authentication. Unfortunately I am a little unsure how to interpret the RFC, particularly when trying to calculate the Message-Authenticator.

I basically create an HMAC-MD5 object (I am using C#) use the shared secret of the NAS for the key and concatenate Type (one byte) + Identifier (one byte) + Length (two bytes) + Request Authenticator (16 bytes) + All Attributes (Except the Message-Authenticator in the Access-Request) but the calculated value does not match the value in the packet.

Following the RFC this seems correct. Am I interpreting the RFC correctly?

Here is the code:

RadiusPacket packet = Objects.Packet;

byte[] toHMAC;
toHMAC = new byte[1] { (byte)packet.Code };
toHMAC = ByteArray.Combine(toHMAC, new byte[1] { packet.Identifier });
// reversed to match endian of packet
toHMAC = ByteArray.Combine(toHMAC, ByteArray.Reverse(packet.LengthAsBytes));
toHMAC = ByteArray.Combine(toHMAC, packet.Authenticator);

for (int i = 0; i < packet.Attributes.Length; i++)
{
    if (packet.Attributes[i].Type != RadiusAttributeType.MessageAuthenticator)
    {
        toHMAC = ByteArray.Combine(toHMAC, packet.Attributes[i].RawData);
    }
}

HMACMD5 md5 = new HMACMD5(Encoding.ASCII.GetBytes(Objects.NAS.SharedSecret));

// this DOES NOT match what is in the received packet...
byte[] hmac = md5.ComputeHash(toHMAC);

Any help would be much appreciated.

erickson
  • 265,237
  • 58
  • 395
  • 493
John Tear
  • 51
  • 1
  • 4

2 Answers2

2

I found the answer by a combination of re-reading the RFC and looking at some source code in JQuery. Here is what I found for anybody else that has the same is

The RFC (3579) reads:

'When the message integrity check is calculated the signature string should be considered to be sixteen octets of zero.'

Upon recieiving the Access-Request packet I replaced the existing Message-Authenticator with 16 zero bytes then HMAC-MD5 the entire packet and compare the calculated value with the Message-Authenticator in the packet.

The code is much simpler (I created a test packet from a wireshark capture):

// a radius-eap packet captured from wireshark
RadiusPacket packet = new RadiusPacket(ByteArray.FromHex("017600ad375be8f596e90bcffc5e32929d14275b04060a3e01ee05060000c3513d060000000f011f686f73742f64727377696e377472616379702e6472736c2e636f2e756b1e1330302d31322d30302d45332d34312d43311f1342342d39392d42412d46322d38412d44360606000000020c06000005dc4f240200002201686f73742f64727377696e377472616379702e6472736c2e636f2e756b5012c93ef628690a578b31709b0bbccade41"));

// identical packet that I can zero out MA for testing
RadiusPacket radiusPacketCopy = new RadiusPacket(ByteArray.FromHex("017600ad375be8f596e90bcffc5e32929d14275b04060a3e01ee05060000c3513d060000000f011f686f73742f64727377696e377472616379702e6472736c2e636f2e756b1e1330302d31322d30302d45332d34312d43311f1342342d39392d42412d46322d38412d44360606000000020c06000005dc4f240200002201686f73742f64727377696e377472616379702e6472736c2e636f2e756b5012c93ef628690a578b31709b0bbccade41"));

// zero out MA
radiusPacketCopy.ZeroMessageAuthenticator();

// hash it up
HMACMD5 md5 = new HMACMD5(Encoding.ASCII.GetBytes("mykey"));
byte[] hmac = md5.ComputeHash(radiusPacketCopy.RawPacket);

// the message authenticator MUST be correct
if (!ByteArray.AreEqual(hmac, packet.MessageAuthenticator))
{
    // etc
John Tear
  • 51
  • 1
  • 4
0

Your code is close, but not quite there. You are stripping out the Message-Authenticator attribute completely.

Instead, it should remain in its original position within the packet, but the 16-byte value field of that attribute should be over-written with zeros.

erickson
  • 265,237
  • 58
  • 395
  • 493