libradius: Pad received MSK to at least 64 bytes
authorTobias Brunner <tobias@strongswan.org>
Fri, 26 Jan 2018 08:51:07 +0000 (09:51 +0100)
committerTobias Brunner <tobias@strongswan.org>
Fri, 9 Feb 2018 09:44:52 +0000 (10:44 +0100)
According to RFC 3748 MSKs must be at least 64 bytes, however, that's
not the case for the MSK derived via EAP-MSCHAPv2.  The two key parts
received are only 16 bytes each (derived according to RFC 3079,
section 3.3), so we end up with an MSK of only 32 bytes. The eap-mschapv2
plugin, on the other hand, pads these two parts with 32 zeros.

Interestingly, this is not a problem in many cases as the SHA1/2 based
PRFs used later use a block size that's >= 64 bytes, so the shorter MSK
is just padded with zeros then.  However, with AES-XCBC-PRF-128, for
instance, which uses a block size of 16 bytes, the different MSKs are an
issue as XCBC is applied to both to shorten them, with different results.
This eventually causes the authentication to fail if the client uses a
zero-padded MSK produced by the eap-mschapv2 plugin and the server the 32
byte MSK received via RADIUS.

src/libradius/radius_socket.c

index 115be79..b3d90d3 100644 (file)
@@ -348,7 +348,14 @@ METHOD(radius_socket_t, decrypt_msk, chunk_t,
        enumerator->destroy(enumerator);
        if (send.ptr && recv.ptr)
        {
-               return chunk_cat("mm", recv, send);
+               chunk_t pad = chunk_empty;
+
+               if ((send.len + recv.len) < 64)
+               {       /* zero-pad MSK to at least 64 bytes */
+                       pad = chunk_alloca(64 - send.len - recv.len);
+                       memset(pad.ptr, 0, pad.len);
+               }
+               return chunk_cat("mmc", recv, send, pad);
        }
        chunk_clear(&send);
        chunk_clear(&recv);