matsprea/AspNetIdentity_U2F

Counter misuse

caracostea opened this issue · 3 comments

According to FIDO U2F Raw Message specifications, the counter returned in the Authentication Response Message: Success is a 4 bytes big-endian representation. However, in U2F.Codec.RawMessageCodec.DecodeAuthenticateResponse(byte[] data), the codec bytes are converted to an int using BinaryReader.ReadInt32(), which, according to MSDN, "BinaryReader reads this data type in little-endian format.". Hence, a misinterpretation of the counter occurs.

The solution:

  1. Convert to little endian when decoding the authentication response:
    In U2F.Codec.RawMessageCodec.DecodeAuthenticateResponse(byte[] data):
    replace
    var counter = inputStream.ReadInt32();
    with
    byte[] counterBytes = inputStream.ReadBytes(4);
    Array.Reverse(counterBytes);
    var counter = BitConverter.ToInt32(counterBytes, 0);

  2. Reconvert to big endian when encoding the authentication signed bytes:
    In U2F.Codec.RawMessageCodec.EncodeAuthenticateSignedBytes(byte[] applicationSha256, byte userPresence, int counter, byte[] challengeSha256):
    at the beginning of the method add the following:
    byte[] counterBytes = BitConverter.GetBytes(counter);
    Array.Reverse(counterBytes);
    counter = BitConverter.ToInt32(counterBytes, 0);

This way we get a proper and reliable Int32 representation of the counter and still, the signature checking will remain unaffected.

Thanks for reporting!

I'm going to commit a fix in a moment with your solution and a check of the endianess of the platform because the order of the array returned byBitConverter depends on whether the computer architecture is little-endian or big-endian.

You should have a look at which systems run in big-endian by default and then consider if it's even worth bothering with BitConverter.IsLittleEndian :)

I know, it's hard to find BigEndian systems in these days, but since Microsoft is going to release .Net opensource, maybe someone one day will use it on a BigEndian hardware :)