mirror of
https://github.com/RfidResearchGroup/proxmark3.git
synced 2025-08-19 21:03:48 -07:00
added rudimentary functions for doing AES authentication against MIFARE UL AES tags. (wip)
This commit is contained in:
parent
cb570cb103
commit
c4c1601446
11 changed files with 330 additions and 27 deletions
|
@ -3,6 +3,7 @@ All notable changes to this project will be documented in this file.
|
|||
This project uses the changelog in accordance with [keepchangelog](http://keepachangelog.com/). Please use this to write notable changes, which is not the same as git commit log...
|
||||
|
||||
## [unreleased][unreleased]
|
||||
- Changed `hf mfu info` - should not try pwd against a UL-AES (@iceman1001)
|
||||
- Fixed `hf mfu info` - tag type identification now properly handles 64bits (@iceman1001)
|
||||
- Changed `hf st info` - reworked the output (@iceman1001)
|
||||
- Rename `smart relay` to `smart pcsc` and add support for contact interface (@gm3197)
|
||||
|
|
|
@ -1639,6 +1639,7 @@ static void PacketReceived(PacketCommandNG *packet) {
|
|||
break;
|
||||
}
|
||||
case CMD_HF_MIFAREU_READBL: {
|
||||
|
||||
MifareUReadBlock(packet->oldarg[0], packet->oldarg[1], packet->data.asBytes);
|
||||
break;
|
||||
}
|
||||
|
@ -1646,6 +1647,16 @@ static void PacketReceived(PacketCommandNG *packet) {
|
|||
MifareUC_Auth(packet->oldarg[0], packet->data.asBytes);
|
||||
break;
|
||||
}
|
||||
case CMD_HF_MIFAREULAES_AUTH: {
|
||||
struct p {
|
||||
bool turn_off_field;
|
||||
uint8_t keyno;
|
||||
uint8_t key[18];
|
||||
} PACKED;
|
||||
struct p *payload = (struct p *) packet->data.asBytes;
|
||||
MifareUL_AES_Auth(payload->turn_off_field, payload->keyno, payload->key);
|
||||
break;
|
||||
}
|
||||
case CMD_HF_MIFAREU_READCARD: {
|
||||
MifareUReadCard(packet->oldarg[0], packet->oldarg[1], packet->oldarg[2], packet->data.asBytes);
|
||||
break;
|
||||
|
@ -1801,8 +1812,6 @@ static void PacketReceived(PacketCommandNG *packet) {
|
|||
break;
|
||||
}
|
||||
case CMD_HF_MIFARE_CIDENT: {
|
||||
|
||||
|
||||
struct p {
|
||||
uint8_t is_mfc;
|
||||
uint8_t keytype;
|
||||
|
@ -2139,7 +2148,7 @@ static void PacketReceived(PacketCommandNG *packet) {
|
|||
struct p {
|
||||
uint32_t waittime;
|
||||
} PACKED;
|
||||
struct p *payload = (struct p *) &packet->data.asBytes;
|
||||
struct p *payload = (struct p *) packet->data.asBytes;
|
||||
|
||||
uint16_t available;
|
||||
uint16_t pre_available = 0;
|
||||
|
@ -2182,7 +2191,7 @@ static void PacketReceived(PacketCommandNG *packet) {
|
|||
uint32_t waittime;
|
||||
uint8_t data[];
|
||||
} PACKED;
|
||||
struct p *payload = (struct p *) &packet->data.asBytes;
|
||||
struct p *payload = (struct p *) packet->data.asBytes;
|
||||
usart_writebuffer_sync(payload->data, packet->length - sizeof(payload));
|
||||
|
||||
uint16_t available;
|
||||
|
@ -2226,7 +2235,7 @@ static void PacketReceived(PacketCommandNG *packet) {
|
|||
uint32_t baudrate;
|
||||
uint8_t parity;
|
||||
} PACKED;
|
||||
struct p *payload = (struct p *) &packet->data.asBytes;
|
||||
struct p *payload = (struct p *) packet->data.asBytes;
|
||||
usart_init(payload->baudrate, payload->parity);
|
||||
reply_ng(CMD_USART_CONFIG, PM3_SUCCESS, NULL, 0);
|
||||
break;
|
||||
|
|
|
@ -119,7 +119,56 @@ void tdes_nxp_send(const void *in, void *out, size_t length, const void *key, un
|
|||
}
|
||||
}
|
||||
|
||||
void aes128_nxp_receive(const void *in, void *out, size_t length, const void *key, unsigned char iv[8]) {
|
||||
if (length % 8) return;
|
||||
|
||||
mbedtls_aes_setkey_dec(&actx, key, 128);
|
||||
|
||||
uint8_t i;
|
||||
unsigned char temp[8];
|
||||
uint8_t *tin = (uint8_t *) in;
|
||||
uint8_t *tout = (uint8_t *) out;
|
||||
|
||||
while (length > 0) {
|
||||
memcpy(temp, tin, 8);
|
||||
|
||||
mbedtls_aes_crypt_ecb(&actx, MBEDTLS_AES_DECRYPT, tin, tout);
|
||||
|
||||
for (i = 0; i < 8; i++) {
|
||||
tout[i] = (unsigned char)(tout[i] ^ iv[i]);
|
||||
}
|
||||
|
||||
memcpy(iv, temp, 8);
|
||||
|
||||
tin += 8;
|
||||
tout += 8;
|
||||
length -= 8;
|
||||
}
|
||||
}
|
||||
|
||||
void aes128_nxp_send(const void *in, void *out, size_t length, const void *key, unsigned char iv[8]) {
|
||||
if (length % 8) return;
|
||||
|
||||
mbedtls_aes_setkey_enc(&actx, key, 128);
|
||||
|
||||
uint8_t i;
|
||||
uint8_t *tin = (uint8_t *) in;
|
||||
uint8_t *tout = (uint8_t *) out;
|
||||
|
||||
while (length > 0) {
|
||||
for (i = 0; i < 8; i++) {
|
||||
tin[i] = (unsigned char)(tin[i] ^ iv[i]);
|
||||
}
|
||||
|
||||
mbedtls_aes_crypt_ecb(&actx, MBEDTLS_AES_ENCRYPT, tin, tout);
|
||||
|
||||
memcpy(iv, tout, 8);
|
||||
|
||||
tin += 8;
|
||||
tout += 8;
|
||||
length -= 8;
|
||||
}
|
||||
}
|
||||
|
||||
void Desfire_des_key_new(const uint8_t value[8], desfirekey_t key) {
|
||||
uint8_t data[8];
|
||||
|
|
|
@ -179,6 +179,10 @@ void des_encrypt(void *out, const void *in, const void *key);
|
|||
void des_decrypt(void *out, const void *in, const void *key);
|
||||
void tdes_nxp_receive(const void *in, void *out, size_t length, const void *key, unsigned char iv[8], int keymode);
|
||||
void tdes_nxp_send(const void *in, void *out, size_t length, const void *key, unsigned char iv[8], int keymode);
|
||||
|
||||
void aes128_nxp_receive(const void *in, void *out, size_t length, const void *key, unsigned char iv[8]);
|
||||
void aes128_nxp_send(const void *in, void *out, size_t length, const void *key, unsigned char iv[8]);
|
||||
|
||||
void Desfire_des_key_new(const uint8_t value[8], desfirekey_t key);
|
||||
void Desfire_3des_key_new(const uint8_t value[16], desfirekey_t key);
|
||||
void Desfire_des_key_new_with_version(const uint8_t value[8], desfirekey_t key);
|
||||
|
|
|
@ -281,6 +281,36 @@ void MifareUC_Auth(uint8_t arg0, uint8_t *keybytes) {
|
|||
reply_mix(CMD_ACK, 1, 0, 0, 0, 0);
|
||||
}
|
||||
|
||||
void MifareUL_AES_Auth(bool turn_off_field, uint8_t keyno, uint8_t *keybytes) {
|
||||
|
||||
LED_A_ON();
|
||||
LED_B_OFF();
|
||||
LED_C_OFF();
|
||||
|
||||
iso14443a_setup(FPGA_HF_ISO14443A_READER_LISTEN);
|
||||
|
||||
clear_trace();
|
||||
set_tracing(true);
|
||||
|
||||
if (!iso14443a_select_card(NULL, NULL, NULL, true, 0, true)) {
|
||||
if (g_dbglevel >= DBG_ERROR) Dbprintf("Can't select card");
|
||||
reply_ng(CMD_HF_MIFAREULAES_AUTH, PM3_ESOFT, NULL, 0);
|
||||
return;
|
||||
};
|
||||
|
||||
if (!mifare_ultra_aes_auth(keyno, keybytes)) {
|
||||
if (g_dbglevel >= DBG_ERROR) Dbprintf("Authentication failed");
|
||||
reply_ng(CMD_HF_MIFAREULAES_AUTH, PM3_ESOFT, NULL, 0);
|
||||
return;
|
||||
}
|
||||
|
||||
if (turn_off_field) {
|
||||
FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF);
|
||||
LEDsoff();
|
||||
}
|
||||
reply_ng(CMD_HF_MIFAREULAES_AUTH, PM3_SUCCESS, NULL, 0);
|
||||
}
|
||||
|
||||
// Arg0 = BlockNo,
|
||||
// Arg1 = UsePwd bool
|
||||
// datain = PWD bytes,
|
||||
|
@ -407,7 +437,7 @@ void MifareUReadCard(uint8_t arg0, uint16_t arg1, uint8_t arg2, uint8_t *datain)
|
|||
break;
|
||||
}
|
||||
|
||||
len = mifare_ultra_readblock(blockNo + i, dataout + 4 * i);
|
||||
len = mifare_ultra_readblock(blockNo + i, dataout + (4 * i));
|
||||
|
||||
if (len) {
|
||||
if (g_dbglevel >= DBG_ERROR) Dbprintf("Read block %d error", i);
|
||||
|
|
|
@ -27,6 +27,8 @@ void MifareValue(uint8_t arg0, uint8_t arg1, uint8_t arg2, uint8_t *datain);
|
|||
|
||||
void MifareUReadBlock(uint8_t arg0, uint8_t arg1, uint8_t *datain);
|
||||
void MifareUC_Auth(uint8_t arg0, uint8_t *keybytes);
|
||||
void MifareUL_AES_Auth(bool turn_off_field, uint8_t keyno, uint8_t *keybytes);
|
||||
|
||||
void MifareUReadCard(uint8_t arg0, uint16_t arg1, uint8_t arg2, uint8_t *datain);
|
||||
void MifareUWriteBlockCompat(uint8_t arg0, uint8_t arg1, uint8_t *datain);
|
||||
void MifareUWriteBlock(uint8_t arg0, uint8_t arg1, uint8_t *datain);
|
||||
|
|
|
@ -378,6 +378,92 @@ int mifare_ultra_auth(uint8_t *keybytes) {
|
|||
return 1;
|
||||
}
|
||||
|
||||
int mifare_ultra_aes_auth(uint8_t keyno, uint8_t *keybytes) {
|
||||
|
||||
/// aes-128
|
||||
uint8_t random_a[8] = {1, 1, 1, 1, 1, 1, 1, 1};
|
||||
uint8_t random_b[8] = {0x00};
|
||||
uint8_t enc_random_b[8] = {0x00};
|
||||
uint8_t rnd_ab[16] = {0x00};
|
||||
uint8_t IV[8] = {0x00};
|
||||
uint8_t key[16] = {0x00};
|
||||
memcpy(key, keybytes, sizeof(key));
|
||||
|
||||
uint16_t len = 0;
|
||||
uint8_t resp[19] = {0x00};
|
||||
uint8_t respPar[3] = {0, 0, 0};
|
||||
|
||||
// REQUEST AUTHENTICATION
|
||||
len = mifare_sendcmd_short(NULL, CRYPT_NONE, MIFARE_ULAES_AUTH_1, keyno, resp, respPar, NULL);
|
||||
if (len != 11) {
|
||||
if (g_dbglevel >= DBG_ERROR) Dbprintf("Cmd Error: %02x", resp[0]);
|
||||
return 0;
|
||||
}
|
||||
|
||||
// tag nonce.
|
||||
memcpy(enc_random_b, resp + 1, 8);
|
||||
|
||||
// decrypt nonce.
|
||||
aes128_nxp_receive((void *)enc_random_b, (void *)random_b, sizeof(random_b), (const void *)key, IV);
|
||||
|
||||
rol(random_b, 8);
|
||||
memcpy(rnd_ab, random_a, 8);
|
||||
memcpy(rnd_ab + 8, random_b, 8);
|
||||
|
||||
if (g_dbglevel >= DBG_EXTENDED) {
|
||||
Dbprintf("enc_B: %02x %02x %02x %02x %02x %02x %02x %02x",
|
||||
enc_random_b[0], enc_random_b[1], enc_random_b[2], enc_random_b[3], enc_random_b[4], enc_random_b[5], enc_random_b[6], enc_random_b[7]);
|
||||
|
||||
Dbprintf(" B: %02x %02x %02x %02x %02x %02x %02x %02x",
|
||||
random_b[0], random_b[1], random_b[2], random_b[3], random_b[4], random_b[5], random_b[6], random_b[7]);
|
||||
|
||||
Dbprintf("rnd_ab: %02x %02x %02x %02x %02x %02x %02x %02x",
|
||||
rnd_ab[0], rnd_ab[1], rnd_ab[2], rnd_ab[3], rnd_ab[4], rnd_ab[5], rnd_ab[6], rnd_ab[7]);
|
||||
|
||||
Dbprintf("rnd_ab: %02x %02x %02x %02x %02x %02x %02x %02x",
|
||||
rnd_ab[8], rnd_ab[9], rnd_ab[10], rnd_ab[11], rnd_ab[12], rnd_ab[13], rnd_ab[14], rnd_ab[15]);
|
||||
}
|
||||
|
||||
// encrypt out, in, length, key, iv
|
||||
aes128_nxp_send(rnd_ab, rnd_ab, sizeof(rnd_ab), key, enc_random_b);
|
||||
|
||||
len = mifare_sendcmd(MIFARE_ULAES_AUTH_2, rnd_ab, sizeof(rnd_ab), resp, respPar, NULL);
|
||||
if (len != 11) {
|
||||
if (g_dbglevel >= DBG_ERROR) Dbprintf("Cmd Error: %02x", resp[0]);
|
||||
return 0;
|
||||
}
|
||||
|
||||
uint8_t enc_resp[8] = { 0, 0, 0, 0, 0, 0, 0, 0 };
|
||||
uint8_t resp_random_a[8] = { 0, 0, 0, 0, 0, 0, 0, 0 };
|
||||
memcpy(enc_resp, resp + 1, 8);
|
||||
|
||||
// decrypt out, in, length, key, iv
|
||||
aes128_nxp_receive(enc_resp, resp_random_a, 8, key, enc_random_b);
|
||||
if (memcmp(resp_random_a, random_a, 8) != 0) {
|
||||
if (g_dbglevel >= DBG_ERROR) Dbprintf("failed authentication");
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (g_dbglevel >= DBG_EXTENDED) {
|
||||
Dbprintf("e_AB: %02x %02x %02x %02x %02x %02x %02x %02x",
|
||||
rnd_ab[0], rnd_ab[1], rnd_ab[2], rnd_ab[3],
|
||||
rnd_ab[4], rnd_ab[5], rnd_ab[6], rnd_ab[7]);
|
||||
|
||||
Dbprintf("e_AB: %02x %02x %02x %02x %02x %02x %02x %02x",
|
||||
rnd_ab[8], rnd_ab[9], rnd_ab[10], rnd_ab[11],
|
||||
rnd_ab[12], rnd_ab[13], rnd_ab[14], rnd_ab[15]);
|
||||
|
||||
Dbprintf("a: %02x %02x %02x %02x %02x %02x %02x %02x",
|
||||
random_a[0], random_a[1], random_a[2], random_a[3],
|
||||
random_a[4], random_a[5], random_a[6], random_a[7]);
|
||||
|
||||
Dbprintf("b: %02x %02x %02x %02x %02x %02x %02x %02x",
|
||||
resp_random_a[0], resp_random_a[1], resp_random_a[2], resp_random_a[3],
|
||||
resp_random_a[4], resp_random_a[5], resp_random_a[6], resp_random_a[7]);
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int mifare_ultra_readblockEx(uint8_t blockNo, uint8_t *blockData) {
|
||||
uint16_t len = 0;
|
||||
uint8_t bt[2] = {0x00, 0x00};
|
||||
|
|
|
@ -87,6 +87,7 @@ int mifare_classic_value(struct Crypto1State *pcs, uint8_t blockNo, uint8_t *blo
|
|||
// Ultralight/NTAG...
|
||||
int mifare_ul_ev1_auth(uint8_t *keybytes, uint8_t *pack);
|
||||
int mifare_ultra_auth(uint8_t *keybytes);
|
||||
int mifare_ultra_aes_auth(uint8_t keyno, uint8_t *keybytes);
|
||||
int mifare_ultra_readblock(uint8_t blockNo, uint8_t *blockData);
|
||||
int mifare_ultra_writeblock_compat(uint8_t blockNo, uint8_t *blockData);
|
||||
int mifare_ultra_writeblock(uint8_t blockNo, uint8_t *blockData);
|
||||
|
|
|
@ -56,6 +56,16 @@
|
|||
|
||||
static int CmdHelp(const char *Cmd);
|
||||
|
||||
static uint8_t default_aes_keys[][16] = {
|
||||
{ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, // all zeroes
|
||||
{ 0x42, 0x52, 0x45, 0x41, 0x4b, 0x4d, 0x45, 0x49, 0x46, 0x59, 0x4f, 0x55, 0x43, 0x41, 0x4e, 0x21 }, // 3des std key
|
||||
{ 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f }, // 0x00-0x0F
|
||||
{ 0x49, 0x45, 0x4D, 0x4B, 0x41, 0x45, 0x52, 0x42, 0x21, 0x4E, 0x41, 0x43, 0x55, 0x4F, 0x59, 0x46 }, // NFC-key
|
||||
{ 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01 }, // all ones
|
||||
{ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF }, // all FF
|
||||
{ 0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88, 0x99, 0xAA, 0xBB, 0xCC, 0xDD, 0xEE, 0xFF } // 11 22 33
|
||||
};
|
||||
|
||||
static uint8_t default_3des_keys[][16] = {
|
||||
{ 0x42, 0x52, 0x45, 0x41, 0x4b, 0x4d, 0x45, 0x49, 0x46, 0x59, 0x4f, 0x55, 0x43, 0x41, 0x4e, 0x21 }, // 3des std key
|
||||
{ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, // all zeroes
|
||||
|
@ -295,14 +305,56 @@ static int ulc_requestAuthentication(uint8_t *nonce, uint16_t nonceLength) {
|
|||
return len;
|
||||
}
|
||||
|
||||
static int ulev1_requestAuthentication(uint8_t *pwd, uint8_t *pack, uint16_t packLength) {
|
||||
|
||||
uint8_t cmd[] = {MIFARE_ULEV1_AUTH, pwd[0], pwd[1], pwd[2], pwd[3]};
|
||||
int len = ul_send_cmd_raw(cmd, sizeof(cmd), pack, packLength);
|
||||
// NACK tables different tags, but between 0-9 is a NEGATIVE response.
|
||||
// ACK == 0xA
|
||||
if (len == 1 && pack[0] <= 0x09)
|
||||
return -1;
|
||||
return len;
|
||||
}
|
||||
|
||||
/*
|
||||
Default AES key is 00-00h. Both the data and UID one.
|
||||
Data key is 00, UID is 01. Authenticity is 02h
|
||||
Auth is 1A[Key ID][CRC] - AF[RndB] - AF[RndA][RndB'] - 00[RndA']
|
||||
*/
|
||||
static int ulaes_requestAuthentication(uint8_t *key, uint8_t keyno, bool switch_off_field) {
|
||||
struct p {
|
||||
bool turn_off_field;
|
||||
uint8_t keyno;
|
||||
uint8_t key[16];
|
||||
} PACKED payload;
|
||||
|
||||
payload.turn_off_field = switch_off_field;
|
||||
payload.keyno = keyno;
|
||||
memcpy(payload.key, key, sizeof(payload.key));
|
||||
|
||||
clearCommandBuffer();
|
||||
SendCommandNG(CMD_HF_MIFAREULAES_AUTH, (uint8_t*)&payload, sizeof(payload));
|
||||
PacketResponseNG resp;
|
||||
if (WaitForResponseTimeout(CMD_HF_MIFAREULAES_AUTH, &resp, 1500) == false) {
|
||||
return PM3_ETIMEOUT;
|
||||
}
|
||||
if (resp.status != PM3_SUCCESS) {
|
||||
return resp.status;
|
||||
}
|
||||
return PM3_SUCCESS;
|
||||
}
|
||||
|
||||
static int ulc_authentication(uint8_t *key, bool switch_off_field) {
|
||||
|
||||
clearCommandBuffer();
|
||||
SendCommandMIX(CMD_HF_MIFAREUC_AUTH, switch_off_field, 0, 0, key, 16);
|
||||
PacketResponseNG resp;
|
||||
if (!WaitForResponseTimeout(CMD_ACK, &resp, 1500)) return 0;
|
||||
if (resp.oldarg[0] == 1) return 1;
|
||||
|
||||
if (WaitForResponseTimeout(CMD_ACK, &resp, 1500) == false) {
|
||||
return 0;
|
||||
}
|
||||
if (resp.oldarg[0] == 1) {
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -394,17 +446,59 @@ static int try_default_3des_keys(uint8_t **correct_key) {
|
|||
return res;
|
||||
}
|
||||
|
||||
static int ulev1_requestAuthentication(uint8_t *pwd, uint8_t *pack, uint16_t packLength) {
|
||||
static int try_default_aes_keys(void) {
|
||||
|
||||
uint8_t cmd[] = {MIFARE_ULEV1_AUTH, pwd[0], pwd[1], pwd[2], pwd[3]};
|
||||
int len = ul_send_cmd_raw(cmd, sizeof(cmd), pack, packLength);
|
||||
// NACK tables different tags, but between 0-9 is a NEGATIVE response.
|
||||
// ACK == 0xA
|
||||
if (len == 1 && pack[0] <= 0x09)
|
||||
return -1;
|
||||
return len;
|
||||
uint8_t dbg_curr = DBG_NONE;
|
||||
if (getDeviceDebugLevel(&dbg_curr) != PM3_SUCCESS) {
|
||||
return PM3_ESOFT;
|
||||
}
|
||||
|
||||
if (setDeviceDebugLevel(DBG_NONE, false) != PM3_SUCCESS) {
|
||||
return PM3_ESOFT;
|
||||
}
|
||||
|
||||
int res = PM3_ESOFT;
|
||||
|
||||
PrintAndLogEx(INFO, "");
|
||||
PrintAndLogEx(SUCCESS, "--- " _CYAN_("Known UL-AES keys"));
|
||||
|
||||
for (uint8_t i = 0; i < ARRAYLEN(default_aes_keys); ++i) {
|
||||
uint8_t *key = default_aes_keys[i];
|
||||
|
||||
for (uint8_t keyno = 0; keyno < 2; keyno++) {
|
||||
|
||||
if (ulaes_requestAuthentication(key, keyno, true) == PM3_SUCCESS) {
|
||||
|
||||
char keystr[20] = {0};
|
||||
switch(keyno) {
|
||||
case 0:
|
||||
sprintf(keystr, "Data key");
|
||||
break;
|
||||
case 1:
|
||||
sprintf(keystr, "UID key");
|
||||
break;
|
||||
case 2:
|
||||
sprintf(keystr, "Authenticity key");
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
PrintAndLogEx(SUCCESS, "Found %s keyno %02X - %s ( "_GREEN_("ok") " )"
|
||||
, keystr
|
||||
, keyno
|
||||
, sprint_hex_inrow(key, 16)
|
||||
);
|
||||
|
||||
res = PM3_SUCCESS;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
setDeviceDebugLevel(dbg_curr, false);
|
||||
return res;
|
||||
}
|
||||
|
||||
|
||||
static int ul_auth_select(iso14a_card_select_t *card, uint64_t tagtype, bool hasAuthKey, uint8_t *authkey, uint8_t *pack, uint8_t packSize) {
|
||||
if (hasAuthKey && (tagtype & MFU_TT_UL_C)) {
|
||||
//will select card automatically and close connection on error
|
||||
|
@ -2026,6 +2120,23 @@ static int CmdHF14AMfUInfo(const char *Cmd) {
|
|||
}
|
||||
}
|
||||
|
||||
// Specific UL-AES
|
||||
if (tagtype & MFU_TT_UL_AES) {
|
||||
|
||||
// print AES configuration etc..
|
||||
|
||||
DropField();
|
||||
PrintAndLogEx(NORMAL, "");
|
||||
PrintAndLogEx(SUCCESS, "--- " _CYAN_("Known AES keys"));
|
||||
|
||||
// also try to diversify default keys.. look into CmdHF14AMfGenDiverseKeys
|
||||
if (try_default_aes_keys() != PM3_SUCCESS) {
|
||||
PrintAndLogEx(INFO, "n/a");
|
||||
}
|
||||
PrintAndLogEx(INFO, "Done!");
|
||||
}
|
||||
|
||||
|
||||
// do counters and signature first (don't neet auth)
|
||||
|
||||
// ul counters are different than ntag counters
|
||||
|
@ -2119,6 +2230,11 @@ static int CmdHF14AMfUInfo(const char *Cmd) {
|
|||
}
|
||||
}
|
||||
|
||||
// Don't check passwords for Ul AES :)
|
||||
if (tagtype == MFU_TT_UL_AES) {
|
||||
goto out;
|
||||
}
|
||||
|
||||
// AUTHLIMIT, (number of failed authentications)
|
||||
// 0 = limitless.
|
||||
// 1-7 = limit. No automatic tries then.
|
||||
|
|
|
@ -692,9 +692,11 @@ typedef struct {
|
|||
#define CMD_HF_MIFARE_MFKEY 0x0631
|
||||
#define CMD_HF_MIFARE_PERSONALIZE_UID 0x0632
|
||||
|
||||
//ultralightC
|
||||
// ultralight-C
|
||||
#define CMD_HF_MIFAREUC_AUTH 0x0724
|
||||
//0x0725 and 0x0726 no longer used
|
||||
// Ultralight AES
|
||||
#define CMD_HF_MIFAREULAES_AUTH 0x0725
|
||||
// 0x0726 no longer used
|
||||
#define CMD_HF_MIFAREUC_SETPWD 0x0727
|
||||
|
||||
// mifare desfire
|
||||
|
|
|
@ -224,6 +224,9 @@ ISO 7816-4 Basic interindustry commands. For command APDU's.
|
|||
#define MIFARE_ULNANO_WRITESIG 0xA9
|
||||
#define MIFARE_ULNANO_LOCKSIG 0xAC
|
||||
|
||||
#define MIFARE_ULAES_AUTH_1 0x1A
|
||||
#define MIFARE_ULAES_AUTH_2 0xAF
|
||||
|
||||
// NTAG i2k 2K uses sector 0, and sector 1 to have access to
|
||||
// block 0x00-0xFF.
|
||||
#define NTAG_I2C_SELECT_SECTOR 0xC2
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue