2

I've been trying to authenticate with a MIFARE DESFire EV1 card with the default key (00000000h) for the last week to no avail. I have followed this blog's instructions to the letter. I implemented Send mode CBC and Receive mode CBC like this:

var
  SendVector, ReceiveVector: UInt64;

procedure ResetVectors;
begin
  SendVector := 0;
  ReceiveVector := 0;
end;

procedure Encrypt(var Data: TBytes; Key: TBytes);
var
  iData, iKey: UInt64;
  i: Integer;
begin
  if Length(Data) mod 8 > 0 then
    SetLength(Data, Length(Data) + (8 - Length(Data) mod 8));

  Move(Key[0], iKey, 8);
  for i := 0 to (Length(Data) - 1) div 8 do
  begin
    Move(Data[i * 8], iData, 8);
    EncryptInt64(iData, iKey);
    Move(iData, Data[i * 8], 8);
  end;
end;

procedure EncryptInt64(var Data, Key: Int64);
begin
  Data := Data xor SendVector;
  DESEncrypt(@Data, @Key);
  SendVector := Data;
end;

procedure Decrypt(var Data: TBytes; Key: TBytes);
var
  iData, iKey: UInt64;
  i: Integer;
begin
  Move(Key[0], iKey, 8);
  for i := 0 to (Length(Data) - 1) div 8 do
  begin
    Move(Data[i * 8], iData, 8);
    DecryptInt64(iData, iKey);
    Move(iData, Data[i * 8], 8);
  end;
end;

procedure DecryptInt64(var Data, Key: Int64);
var
  Tmp: UInt64;
begin
  Tmp := ReceiveVector;
  ReceiveVector := Data;
  DESDecrypt(@Data, @Key);
  Data := Data xor Tmp;
end;

This is the log of APDU commands I sent to the card, and their corresponding responses:

-->90 6A 00 00 00 // List Applications
<--01 02 03 
<--9100 (OK)

-->90 5A 00 00 03 00 00 00 00 // Select PICC
<--9100 (OK)

-->90 1A 00 00 01 00 00 // ISO Authenticate with master key (00000000h)
<--91AF

-->90 AF 00 00 00 // Retreive RndB
<--A4 4C 2B D1 EB 6F 64 0C 
<--9100 (OK)

-->90 AF 00 00 10 0D 9F 27 9B A5 D8 72 60 25 DD 7A 19 63 0F 26 2D 00 // Send DES(RndA + RndB')
<--91AE (AUTHENTICATION_FAILURE)

Here is the whole code of my Authenticate method:

procedure Authenticate;
var
  Key, Data: TBytes;
  s: string;
  b: Byte;
  RndA: UInt64;
  i: Integer;
begin
  ResetVectors;
  Key := HexStringToBuffer('00 00 00 00 00 00 00 00');
  s := '90 1A 00 00 01 00 00';
  s := SendAPDU(s, False);
  Data := HexStringToBuffer(s);
  Decrypt(Data, Key);

  b := Data[0];
  for i := 0 to 6 do
    Data[i] := Data[i + 1];
  Data[7] := b;

  RndA := 1; // not very wise

  SetLength(Data, 16);
  Move(Data[0], Data[8], 8);
  Move(RndA, Data[0], 8);

  Encrypt(Data, Key);
  s := '90 AF 00 00 10 ' + BufferToHexString(Data) + ' 00';
  SendAPDU(s, False);
end;

I'm lost as to why the card is rejecting my authentication attempt flatly. Any thoughts?


Here's the diagram of CBC Send and CBC Receive algorithms as per DESFire EV1 manufacturer instructions: CBC Send CBC Receive

iMan Biglari
  • 4,674
  • 1
  • 38
  • 83
  • The article you link to has no code like this. Do you have any working code? For instance some example C code. Length(Data) mod 8 looks odd. Are you sure? And the FillChar calls can just be := 0. – David Heffernan Jan 06 '14 at 06:02
  • @DavidHeffernan You are right about both SetLength() and FillChar calls. I modified my code to correct it, but I still have the problem. Unfortunately I can not find a _working_ code anywhere... Just code snippets here and there. Here's a link to one: http://stackoverflow.com/questions/11385963/desfire-authentification-decipher – iMan Biglari Jan 06 '14 at 06:27
  • Maybe [this post](http://stackoverflow.com/a/14160507/800214) is helpful? Iman, what DES encrypt library are you using? – whosrdaddy Jan 06 '14 at 10:16
  • @whosrdaddy I'm using a library which I have used with ACOS3X contact smart cards for quite some time now. And I translated the code in that post to Pascal, only to get the same error :-( – iMan Biglari Jan 06 '14 at 12:13

2 Answers2

3

Try replace encrypt to decrypt in DES cipher. Card ALWAYS uses DES ENCRYPT mode (both when recieving and sending data). And the host ALWAYS uses DECRYPT mode.

For more info: https://ridrix.wordpress.com/2009/09/19/mifare-desfire-communication-example/#comment-30

  • 1
    This answer is WRONG. What you write was correct for old Desfire cards with legacy authentication. But Desfire EV1 in ISO or AES mode mixes encryption mode during authentication. – Elmue Jul 11 '16 at 12:23
  • Yes my mistake, thanks for the clarification. I wrote old version of authentication. – Jirka Grigar Jul 14 '16 at 19:33
0

During an ISO or AES authentication the following scheme is used:

  1. Random B is received from the card with RECEIVE + DECIPHER
  2. Random AB is sent to the card with SEND + ENCIPHER
  3. Random A is received with RECEIVE + DECIPHER

IMPORTANT: ALL encryption goes through CBC. The IV of the key used for CBC encryption/decryption is only reset ONCE at the beginning. Then it must be maintained up to date during ALL the following commands.

If you use ISO or AES mode, after a successfull authentication, you MUST also calulcate the CMAC over sent commands and received data, otherwise your IV will not be in sync with the card and you get an Integrity Error each time you use the Session key!

As I was struggeling with the same problems I posted some communication examples that will help you much in testing your code. You find them here on Stackoverflow: Desfire EV1 communication examples There you also find a link to my source code that I recommnd you to study.

Community
  • 1
  • 1
Elmue
  • 7,602
  • 3
  • 47
  • 57