예제 #1
0
int mifare_sendcmd_shortex(struct Crypto1State *pcs, uint8_t crypted, uint8_t cmd, uint8_t data, uint8_t *answer, uint8_t *answer_parity, uint32_t *timing)
{
	uint8_t dcmd[4], ecmd[4];
	uint16_t pos, res;
	uint8_t par[1];			// 1 Byte parity is enough here
	dcmd[0] = cmd;
	dcmd[1] = data;
	AppendCrc14443a(dcmd, 2);
	
	memcpy(ecmd, dcmd, sizeof(dcmd));
	
	if (crypted) {
		par[0] = 0;
		for (pos = 0; pos < 4; pos++)
		{
			ecmd[pos] = crypto1_byte(pcs, 0x00, 0) ^ dcmd[pos];
			par[0] |= (((filter(pcs->odd) ^ oddparity(dcmd[pos])) & 0x01) << (7-pos));
		}	

		ReaderTransmitPar(ecmd, sizeof(ecmd), par, timing);

	} else {
		ReaderTransmit(dcmd, sizeof(dcmd), timing);
	}

	int len = ReaderReceive(answer, par);
	
	if (answer_parity) *answer_parity = par[0];
	
	if (crypted == CRYPT_ALL) {
		if (len == 1) {
			res = 0;
			for (pos = 0; pos < 4; pos++)
				res |= (crypto1_bit(pcs, 0, 0) ^ BIT(answer[0], pos)) << pos;
				
			answer[0] = res;
			
		} else {
			for (pos = 0; pos < len; pos++)
			{
				answer[pos] = crypto1_byte(pcs, 0x00, 0) ^ answer[pos];
			}
		}
	}
	
	return len;
}
예제 #2
0
void mf_crypto1_encrypt(struct Crypto1State *pcs, uint8_t *data, uint16_t len, uint8_t *par) {
	uint8_t bt = 0;
	int i;
	par[0] = 0;
	for (i = 0; i < len; i++) {
		bt = data[i];
		data[i] = crypto1_byte(pcs, 0x00, 0) ^ data[i];
		if((i&0x0007) == 0) par[i>>3] = 0;
		par[i>>3] |= (((filter(pcs->odd) ^ oddparity(bt)) & 0x01)<<(7-(i&0x0007)));
	}	
	return;
}
예제 #3
0
// crypto1 helpers
void mf_crypto1_decrypt(struct Crypto1State *pcs, uint8_t *data, int len){
	uint8_t	bt = 0;
	int i;
	
	if (len != 1) {
		for (i = 0; i < len; i++)
			data[i] = crypto1_byte(pcs, 0x00, 0) ^ data[i];
	} else {
		bt = 0;
		for (i = 0; i < 4; i++)
			bt |= (crypto1_bit(pcs, 0, 0) ^ BIT(data[0], i)) << i;
				
		data[0] = bt;
	}
	return;
}
예제 #4
0
int mifare_classic_writeblock(struct Crypto1State *pcs, uint32_t uid, uint8_t blockNo, uint8_t *blockData) 
{
	// variables
	int len, i;	
	uint32_t pos;
	uint8_t par[3] = {0};		// enough for 18 Bytes to send
	byte_t res;
	
	uint8_t d_block[18], d_block_enc[18];
	uint8_t* receivedAnswer = get_bigbufptr_recvrespbuf();
	uint8_t* receivedAnswerPar = receivedAnswer + MAX_FRAME_SIZE;
	
	// command MIFARE_CLASSIC_WRITEBLOCK
	len = mifare_sendcmd_short(pcs, 1, 0xA0, blockNo, receivedAnswer, receivedAnswerPar, NULL);

	if ((len != 1) || (receivedAnswer[0] != 0x0A)) {   //  0x0a - ACK
		if (MF_DBGLEVEL >= 1)	Dbprintf("Cmd Error: %02x", receivedAnswer[0]);  
		return 1;
	}
	
	memcpy(d_block, blockData, 16);
	AppendCrc14443a(d_block, 16);
	
	// crypto
	for (pos = 0; pos < 18; pos++)
	{
		d_block_enc[pos] = crypto1_byte(pcs, 0x00, 0) ^ d_block[pos];
		par[pos>>3] |= (((filter(pcs->odd) ^ oddparity(d_block[pos])) & 0x01) << (7 - (pos&0x0007)));
	}	

	ReaderTransmitPar(d_block_enc, sizeof(d_block_enc), par, NULL);

	// Receive the response
	len = ReaderReceive(receivedAnswer, receivedAnswerPar);	

	res = 0;
	for (i = 0; i < 4; i++)
		res |= (crypto1_bit(pcs, 0, 0) ^ BIT(receivedAnswer[0], i)) << i;

	if ((len != 1) || (res != 0x0A)) {
		if (MF_DBGLEVEL >= 1)	Dbprintf("Cmd send data2 Error: %02x", res);  
		return 2;
	}
	
	return 0;
}
예제 #5
0
void mf_crypto1_decrypt(struct Crypto1State *pcs, uint8_t *data, int len, bool isEncrypted){
	uint8_t	bt = 0;
	int i;
	
	if (len != 1) {
		for (i = 0; i < len; i++)
			data[i] = crypto1_byte(pcs, 0x00, isEncrypted) ^ data[i];
	} else {
		bt = 0;		
		bt |= (crypto1_bit(pcs, 0, isEncrypted) ^ BIT(data[0], 0)) << 0;
		bt |= (crypto1_bit(pcs, 0, isEncrypted) ^ BIT(data[0], 1)) << 1;
		bt |= (crypto1_bit(pcs, 0, isEncrypted) ^ BIT(data[0], 2)) << 2;
		bt |= (crypto1_bit(pcs, 0, isEncrypted) ^ BIT(data[0], 3)) << 3;			
		data[0] = bt;
	}
	return;
}
예제 #6
0
int mifare_classic_authex(struct Crypto1State *pcs, uint32_t uid, uint8_t blockNo, uint8_t keyType, uint64_t ui64Key, uint8_t isNested, uint32_t *ntptr, uint32_t *timing) 
{
	// variables
	int len;	
	uint32_t pos;
	uint8_t tmp4[4];
	uint8_t par[1] = {0};
	byte_t nr[4];
	uint32_t nt, ntpp; // Supplied tag nonce
	
	uint8_t mf_nr_ar[] = { 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 };
	uint8_t *receivedAnswer = get_bigbufptr_recvrespbuf();
	uint8_t *receivedAnswerPar = receivedAnswer + MAX_FRAME_SIZE;
	
	// Transmit MIFARE_CLASSIC_AUTH
	len = mifare_sendcmd_short(pcs, isNested, 0x60 + (keyType & 0x01), blockNo, receivedAnswer, receivedAnswerPar, timing);
	if (MF_DBGLEVEL >= 4)	Dbprintf("rand tag nonce len: %x", len);  
	if (len != 4) return 1;
	
	// "random" reader nonce:
	nr[0] = 0x55;
	nr[1] = 0x41;
	nr[2] = 0x49;
	nr[3] = 0x92; 
	
	// Save the tag nonce (nt)
	nt = bytes_to_num(receivedAnswer, 4);

	//  ----------------------------- crypto1 create
	if (isNested)
		crypto1_destroy(pcs);

	// Init cipher with key
	crypto1_create(pcs, ui64Key);

	if (isNested == AUTH_NESTED) {
		// decrypt nt with help of new key 
		nt = crypto1_word(pcs, nt ^ uid, 1) ^ nt;
	} else {
		// Load (plain) uid^nt into the cipher
		crypto1_word(pcs, nt ^ uid, 0);
	}

	// some statistic
	if (!ntptr && (MF_DBGLEVEL >= 3))
		Dbprintf("auth uid: %08x nt: %08x", uid, nt);  
	
	// save Nt
	if (ntptr)
		*ntptr = nt;

		
	// Generate (encrypted) nr+parity by loading it into the cipher (Nr)
	par[0] = 0;
	for (pos = 0; pos < 4; pos++)
	{
		mf_nr_ar[pos] = crypto1_byte(pcs, nr[pos], 0) ^ nr[pos];
		par[0] |= (((filter(pcs->odd) ^ oddparity(nr[pos])) & 0x01) << (7-pos));
	}	
		
	// Skip 32 bits in pseudo random generator
	nt = prng_successor(nt,32);

	//  ar+parity
	for (pos = 4; pos < 8; pos++)
	{
		nt = prng_successor(nt,8);
		mf_nr_ar[pos] = crypto1_byte(pcs,0x00,0) ^ (nt & 0xff);
		par[0] |= (((filter(pcs->odd) ^ oddparity(nt & 0xff)) & 0x01) << (7-pos));
	}	
		
	// Transmit reader nonce and reader answer
	ReaderTransmitPar(mf_nr_ar, sizeof(mf_nr_ar), par, NULL);

	// Receive 4 byte tag answer
	len = ReaderReceive(receivedAnswer, receivedAnswerPar);
	if (!len)
	{
		if (MF_DBGLEVEL >= 1)	Dbprintf("Authentication failed. Card timeout.");
		return 2;
	}
	
	memcpy(tmp4, receivedAnswer, 4);
	ntpp = prng_successor(nt, 32) ^ crypto1_word(pcs, 0,0);
	
	if (ntpp != bytes_to_num(tmp4, 4)) {
		if (MF_DBGLEVEL >= 1)	Dbprintf("Authentication failed. Error card response.");
		return 3;
	}

	return 0;
}
예제 #7
0
int main (int argc, char *argv[]) {
  struct Crypto1State *revstate;
  uint64_t key;     // recovered key
  uint32_t uid;     // serial number
  uint32_t nt;      // tag challenge
  uint32_t nr_enc;  // encrypted reader challenge
  uint32_t ar_enc;  // encrypted reader response
  uint32_t at_enc;  // encrypted tag response
  uint32_t ks2;     // keystream used to encrypt reader response
  uint32_t ks3;     // keystream used to encrypt tag response

  printf("MIFARE Classic key recovery - based 64 bits of keystream\n");
  printf("Recover key from only one complete authentication!\n\n");

  if (argc < 6 ) {
    printf(" syntax: %s <uid> <nt> <{nr}> <{ar}> <{at}> [enc] [enc...]\n\n", argv[0]);
    return 1;
  }

  int encc = argc - 6;
  int enclen[encc];
  uint8_t enc[encc][120]; 

  sscanf(argv[1], "%x", &uid);
  sscanf(argv[2], "%x", &nt);
  sscanf(argv[3], "%x", &nr_enc);
  sscanf(argv[4], "%x", &ar_enc);
  sscanf(argv[5], "%x", &at_enc);
  for (int i = 0; i < encc; i++) {
    enclen[i] = strlen(argv[i + 6]) / 2;
    for (int i2 = 0; i2 < enclen[i]; i2++) {
      sscanf(argv[i+6] + i2*2,"%2x", (uint8_t*)&enc[i][i2]);
    }
  }
  printf("Recovering key for:\n");

  printf("  uid: %08x\n", uid);
  printf("   nt: %08x\n", nt);
  printf(" {nr}: %08x\n", nr_enc);
  printf(" {ar}: %08x\n", ar_enc);
  printf(" {at}: %08x\n", at_enc);
  for (int i = 0; i < encc; i++) {
      printf("{enc%d}: ", i);
      for (int i2 = 0; i2 < enclen[i]; i2++) {
          printf("%02x", enc[i][i2]);
      }
      printf("\n");
  }


  /*  
  uint32_t uid                = 0x9c599b32;
  uint32_t tag_challenge      = 0x82a4166c;
  uint32_t nr_enc             = 0xa1e458ce;
  uint32_t reader_response    = 0x6eea41e0;
  uint32_t tag_response       = 0x5cadf439;
*/
  // Generate lfsr succesors of the tag challenge
  printf("\nLFSR succesors of the tag challenge:\n");
  printf("  nt': %08x\n",prng_successor(nt, 64));
  printf(" nt'': %08x\n",prng_successor(nt, 96));

  // Extract the keystream from the messages
  printf("\nKeystream used to generate {ar} and {at}:\n");
  ks2 = ar_enc ^ prng_successor(nt, 64);
  ks3 = at_enc ^ prng_successor(nt, 96);
  printf("  ks2: %08x\n",ks2);
  printf("  ks3: %08x\n",ks3);

  revstate = lfsr_recovery64(ks2, ks3);

  // Decrypting communication using keystream if presented
  if (argc > 6 ) {
  printf("\nDecrypted communication:\n");
  uint8_t ks4; 
  int rollb = 0;
  for (int i = 0; i < encc; i++) {
    printf("{dec%d}: ", i);
    for (int i2 = 0; i2 < enclen[i]; i2++) {  
      ks4 = crypto1_byte(revstate, 0, 0);
      printf("%02x", ks4 ^ enc[i][i2]);
      rollb += 1;
    }
    printf("\n");
  }
  for (int i = 0; i < rollb; i++) {
    lfsr_rollback_byte(revstate, 0, 0);
    }
  }
  
  lfsr_rollback_word(revstate, 0, 0);
  lfsr_rollback_word(revstate, 0, 0);
  lfsr_rollback_word(revstate, nr_enc, 1);
  lfsr_rollback_word(revstate, uid ^ nt, 0);
  crypto1_get_lfsr(revstate, &key);
  printf("\nFound Key: [%012"llx"]\n\n",key);
  crypto1_destroy(revstate);

  return 0;
}