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:
-
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); -
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 :)