Topic: question on keystream generation

hi
i'm new to the mifare classic card. recently i'm trying to learn how the authentication is performed.
i have read the paper Dismantling MIFARE Classic, and downloaded the crapto1 lib.

i wrote a simple program to emulate the authentication flow, based on some captured traffics between tag and reader.
based on the traffic, i know:
UID,
nt,
{nr}, {ar},
{at}
and with these, i can reverse Key by use of crapto1 lib. No problem.

Then, i try to forward emulate the authentication process.
calculate ks1 based on UID and nt. Along with {nr}, i should get plain text nr.
calculate ks2 based on nr. the ks2 value should be identical to {ar}^suc_64(nt).
Here's the problem. the nr and ks2 is not correct.

Can anyone tell me what is wrong?

Many Thanks!!

the program is as follows:

#include <stdio.h>
#include <stdint.h>
#include <string.h>
#include "crapto1.h"

typedef struct Crypto1State c1s_t;

// plain text traffics
uint32_t uid  = 0x2A698D43;
uint32_t nt_p = 0x3BAE032D;
// encrypted data
uint32_t nr_c = 0xC494A1D2;
uint32_t ar_c = 0x6E968642;
uint32_t at_c = 0x8466059E;
// decrypted data
uint32_t nr_p = 0xBB041F2D;
uint32_t ar_p = 0x7FCF34C3;
uint32_t at_p = 0x869DBBD5;
// intermedia variable that can be reversed
uint32_t ks1;
uint32_t ks2;
uint32_t ks3;
uint64_t key;
// variables calculated forward
uint32_t ks1a;
uint32_t ks2a;
uint32_t ks3a;
uint32_t nr_a;
uint32_t ar_a;
uint32_t at_a;

void dump_var(char* var_name, uint8_t* ar, uint16_t len) {
  uint16_t  j;
  printf("%s:", var_name);
  for(j=7-strlen((char*)var_name); j; j--)
    printf(" ");
  for(j=len; j; j--) {
    printf("%02X ", ar[j-1]);
  }
  printf("\n");
  return;
}

int main(int argc, char** argv) {
  c1s_t*    pcs;

  dump_var(">uid", (uint8_t*)&uid, 4);
  dump_var(">nt_p", (uint8_t*)&nt_p, 4);
  dump_var(">nr_c", (uint8_t*)&nr_c, 4);
  dump_var(">ar_c", (uint8_t*)&ar_c, 4);
  dump_var(">at_c", (uint8_t*)&at_c, 4);
  printf("\n");

  dump_var("*nr_p", (uint8_t*)&nr_p, 4);
  dump_var("*ar_p", (uint8_t*)&ar_p, 4);
  dump_var("*at_p", (uint8_t*)&at_p, 4);
  printf("\n");

  ks1 = nr_c ^ nr_p;
  ks2 = ar_c ^ prng_successor(nt_p, 64);
  ks3 = at_c ^ prng_successor(nt_p, 96);

  dump_var(" ks1", (uint8_t*)&ks1, 4);
  dump_var(" ks2", (uint8_t*)&ks2, 4);
  dump_var(" ks3", (uint8_t*)&ks3, 4);
  printf("\n");

  pcs = lfsr_recovery64(ks2, ks3);
  lfsr_rollback_word(pcs, 0, 0);
  lfsr_rollback_word(pcs, 0, 0);
  lfsr_rollback_word(pcs, nr_c, 1);
  lfsr_rollback_word(pcs, uid^nt_p, 0);
  crypto1_get_lfsr(pcs, &key);
  crypto1_destroy(pcs);
  dump_var(" Key", (uint8_t*)&key, 6);
  printf("\n");

  pcs = crypto1_create(key);
    ks1a = crypto1_word(pcs, uid^nt_p, 0);
    nr_a = nr_c ^ ks1e;
    ks2a = crypto1_word(pcs, nr_p, 0);
    ks3a = crypto1_word(pcs, 0, 0);
  crypto1_destroy(pcs);

  ar_a = prng_successor(nt_p, 64);
  at_a = prng_successor(nt_p, 96);

  dump_var(" ks1a", (uint8_t*)&ks1a, 4);
  dump_var(" ks2a", (uint8_t*)&ks2a, 4);
  dump_var(" ks3a", (uint8_t*)&ks3a, 4);
  printf("\n");

  dump_var(" ar_a", (uint8_t*)&ar_a, 4);
  dump_var(" at_a", (uint8_t*)&at_a, 4);
  printf("\n");

  return 0;
}

The output is as follows:

$ ./test1.exe
>uid:   2A 69 8D 43
>nt_p:  3B AE 03 2D
>nr_c:  C4 94 A1 D2
>ar_c:  6E 96 86 42
>at_c:  84 66 05 9E

*nr_p:  BB 04 1F 2D
*ar_p:  7F CF 34 C3
*at_p:  86 9D BB D5

 ks1:   7F 90 BE FF
 ks2:   11 59 B2 81
 ks3:   02 FB BE 4B

 Key:   FF FF FF FF FF FF

 ks1a:  FF DF C8 49
 ks2a:  64 E0 CD 11
 ks3a:  F9 67 46 C8

 ar_a:  7F CF 34 C3
 at_a:  86 9D BB D5