I am being driven mildly mad by this. I am trying to validate a MAC code produced by a read of data from a DESFire card. After authentication I have:
RNDA: 174067B263D4A2FB
RNDB: 28556156579E6F8D
Which makes a session key of 174067B228556156. I do a read of a file that contains the ASCII 'Hello'. The resultant data is:
48656C6C6F9E34BA18 which makes the MAC 9E34BA18. I cannot reproduce it. My C# code is below. It produces a MAC of 826C10B4DD1F3632 neither top nor bottom 32-bits are the desired MAC.
byte[] data = new byte[] { 0x48, 0x65, 0x6C, 0x6C, 0x6F}; // Hello
var key16 = Slicer.FromHexToBytes(SessionKey + SessionKey);
for (int i = 0; i < 16; i++)
{
key16[i] = (byte)(key16[i] & 0xfe); // bottom bit contains version so set it to 0
}
KeyParameter key = new DesParameters(key16);
var mac = Org.BouncyCastle.Security.MacUtilities.GetMac("DESEDEISO9797ALG1MACWITHISO7816-4PADDING");
mac = new CbcBlockCipherMac(new DesEdeEngine(), 64, new ZeroBytePadding());
mac.Init(key);
mac.BlockUpdate(data, 0, data.Length);
byte[] outBytes = new byte[mac.GetMacSize()];
mac.DoFinal(outBytes, 0);
Debug.Print(outBytes);
Just doubling up the session key seems like a guess but I have seen it mentioned in several places. I hope I am on the right track, can anyone suggest what I am doing wrong?
Looks like DESFire protocol is not public. You will need to reverse engineer it. There are others who have gone down this path before. Take a look at this example project in Python: https://github.com/miohtama/desfire
I apologize that the only code I could find was in a different language. I am glad you were able to extract the logic you needed from it.
The solution you cited is:
It turns out the session key is dependant on the authentication key. The doubling I mention is correct if the authentication key is symmetric which it is for the default 0000....000 key - and which it wasn't in my example.