From 68faa88e6afcc8e17a13f3ffedd054877b17ef8d Mon Sep 17 00:00:00 2001 From: Bjoern Kerler Date: Fri, 10 Apr 2020 21:02:46 +0200 Subject: [PATCH 01/16] Auth test --- armsrc/appmain.c | 2 +- armsrc/mifaredesfire.c | 769 ++++++++++++++++++----------------------- armsrc/mifaredesfire.h | 3 +- client/cmdhfmfdes.c | 70 +++- 4 files changed, 387 insertions(+), 457 deletions(-) diff --git a/armsrc/appmain.c b/armsrc/appmain.c index 5bec32364..15eb40f26 100644 --- a/armsrc/appmain.c +++ b/armsrc/appmain.c @@ -1271,7 +1271,7 @@ static void PacketReceived(PacketCommandNG *packet) { break; } case CMD_HF_DESFIRE_AUTH1: { - MifareDES_Auth1(packet->oldarg[0], packet->oldarg[1], packet->oldarg[2], packet->data.asBytes); + MifareDES_Auth1(packet->data.asBytes); break; } case CMD_HF_DESFIRE_AUTH2: { diff --git a/armsrc/mifaredesfire.c b/armsrc/mifaredesfire.c index ba2b20d2d..815c301ac 100644 --- a/armsrc/mifaredesfire.c +++ b/armsrc/mifaredesfire.c @@ -185,178 +185,340 @@ void MifareDesfireGetInformation() { OnSuccess(); } -void MifareDES_Auth1(uint8_t arg0, uint8_t arg1, uint8_t arg2, uint8_t *datain) { - // mode = arg0 - // algo = arg1 - // keyno = arg2 +typedef enum { + MFDES_AUTH_DES = 1, + MFDES_AUTH_ISO = 2, + MFDES_AUTH_AES = 3, + MFDES_AUTH_PICC = 4 +} mifare_des_authmode_t; + +typedef enum { + MFDES_ALGO_DES = 1, + MFDES_ALGO_3DES = 2, + MFDES_ALGO_3K3DES = 3, + MFDES_ALGO_AES = 4 +} mifare_des_authalgo_t; + +void MifareDES_Auth1(uint8_t *datain) { int len = 0; - //uint8_t PICC_MASTER_KEY8[8] = { 0x40,0x41,0x42,0x43,0x44,0x45,0x46,0x47}; - uint8_t PICC_MASTER_KEY16[16] = { 0x40, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48, 0x49, 0x4a, 0x4b, 0x4c, 0x4d, 0x4e, 0x4f }; - //uint8_t null_key_data16[16] = {0x00}; - //uint8_t new_key_data8[8] = { 0x00,0x11,0x22,0x33,0x44,0x55,0x66,0x77}; - //uint8_t new_key_data16[16] = { 0x00,0x11,0x22,0x33,0x44,0x55,0x66,0x77,0x88,0x99,0xAA,0xBB,0xCC,0xDD,0xEE,0xFF}; - - uint8_t resp[256] = {0x00}; - - size_t datalen = datain[0]; - - uint8_t cmd[40] = {0x00}; - uint8_t encRndB[16] = {0x00}; - uint8_t decRndB[16] = {0x00}; - uint8_t both[32] = {0x00}; - - //InitDesfireCard(); - - LED_A_ON(); - LED_B_OFF(); - LED_C_OFF(); + struct p { + uint8_t isOK; + uint8_t mode; + uint8_t algo; + uint8_t keyno; + uint8_t key[24]; + uint8_t keylen; + uint8_t sessionkey[24]; + } PACKED; + struct p *payload = (struct p *) datain; // 3 different way to authenticate AUTH (CRC16) , AUTH_ISO (CRC32) , AUTH_AES (CRC32) // 4 different crypto arg1 DES, 3DES, 3K3DES, AES // 3 different communication modes, PLAIN,MAC,CRYPTO - // des, key 0, - switch (arg0) { - case 1: { - uint8_t keybytes[16]; - uint8_t RndA[8] = {0x00}; - uint8_t RndB[8] = {0x00}; + mbedtls_aes_context ctx; - if (arg1 == 2) { - if (datain[1] == 0xff) { - memcpy(keybytes, PICC_MASTER_KEY16, 16); - } else { - memcpy(keybytes, datain + 1, datalen); - } - } else { - if (arg1 == 1) { - if (datain[1] == 0xff) { - uint8_t null_key_data8[8] = {0x00}; - memcpy(keybytes, null_key_data8, 8); - } else { - memcpy(keybytes, datain + 1, datalen); - } - } + uint8_t keybytes[24]; + uint8_t resp[256] = {0x00}; + uint8_t cmd[40] = {0x00}; + + // Crypt constants + uint8_t IV[16] = {0x00}; + uint8_t RndA[16] = {0x00}; + uint8_t RndB[16] = {0x00}; + uint8_t encRndB[16] = {0x00}; + uint8_t rotRndB[16] = {0x00}; //RndB' + uint8_t both[32] = {0x00}; // ek/dk_keyNo(RndA+RndB') + + // Generate Random Value + uint32_t value = prng_successor(GetTickCount(), 32); + num_to_bytes(value, 4, &RndA[0]); + value = prng_successor(GetTickCount(), 32); + num_to_bytes(value, 4, &RndA[4]); + value = prng_successor(GetTickCount(), 32); + num_to_bytes(value, 4, &RndA[8]); + value = prng_successor(GetTickCount(), 32); + num_to_bytes(value, 4, &RndA[12]); + + // Default Keys + uint8_t PICC_MASTER_KEY8[8] = { 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}; + uint8_t PICC_MASTER_KEY16[16] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; + //uint8_t null_key_data16[16] = {0x00}; + //uint8_t new_key_data8[8] = { 0x00,0x11,0x22,0x33,0x44,0x55,0x66,0x77}; + //uint8_t new_key_data16[16] = { 0x00,0x11,0x22,0x33,0x44,0x55,0x66,0x77,0x88,0x99,0xAA,0xBB,0xCC,0xDD,0xEE,0xFF}; + + + //InitDesfireCard(); + + // Part 1 + LED_A_ON(); + LED_B_OFF(); + LED_C_OFF(); + + if (payload->key==NULL) + { + if (payload->mode==MFDES_AUTH_DES || payload->mode==MFDES_AUTH_PICC) + { + memcpy(keybytes, PICC_MASTER_KEY8, 8); } + else if (payload->mode==MFDES_AUTH_AES) + { + memcpy(keybytes, PICC_MASTER_KEY16, 16); + } + } + else { + memcpy(keybytes, payload->key, payload->keylen); + } - struct desfire_key defaultkey = {0}; - desfirekey_t key = &defaultkey; + struct desfire_key defaultkey = {0}; + desfirekey_t key = &defaultkey; - if (arg1 == 2) - Desfire_3des_key_new_with_version(keybytes, key); - else if (arg1 == 1) - Desfire_des_key_new(keybytes, key); - - cmd[0] = 0x90; - cmd[1] = AUTHENTICATE; - cmd[2] = 0x0; - cmd[3] = 0x0; - cmd[4] = 0x1; - cmd[5] = arg2; //keynumber - cmd[6] = 0x0; - len = DesfireAPDU(cmd, 7, resp); - - if (!len) { - if (DBGLEVEL >= DBG_ERROR) { - DbpString("Authentication failed. Card timeout."); + if (payload->algo==MFDES_ALGO_AES) { + mbedtls_aes_init(&ctx); + if (mbedtls_aes_setkey_dec(&ctx, key->data, 128) != 0) { + if (DBGLEVEL >= DBG_EXTENDED) { + DbpString("mbedtls_aes_setkey_dec failed"); } - OnError(3); + OnErrorNG(CMD_HF_DESFIRE_AUTH1,7); return; } + Desfire_aes_key_new(keybytes, key); + } + else if (payload->algo == MFDES_ALGO_3DES) { + key->type=T_3DES; + Desfire_3des_key_new_with_version(keybytes, key); + } + else if (payload->algo == MFDES_ALGO_DES) { + key->type=T_DES; + Desfire_des_key_new(keybytes, key); + } + else if (payload->algo == MFDES_ALGO_3K3DES) { + Desfire_3k3des_key_new_with_version(keybytes, key); + } - if (resp[2] == (uint8_t)0xaf) { - DbpString("Authentication failed. Invalid key number."); - OnError(3); + uint8_t subcommand=AUTHENTICATE; + + if (payload->mode==MFDES_AUTH_AES) + subcommand=AUTHENTICATE_AES; + else if (payload->mode==MFDES_AUTH_ISO) + subcommand=AUTHENTICATE_ISO; + + if (payload->mode != MFDES_AUTH_PICC) { + // Let's send our auth command + cmd[0] = 0x90; + cmd[1] = subcommand; + cmd[2] = 0x0; + cmd[3] = 0x0; + cmd[4] = 0x1; + cmd[5] = payload->keyno; + cmd[6] = 0x0; + len = DesfireAPDU(cmd, 7, resp); + } + else { + cmd[0] = AUTHENTICATE; + cmd[1] = payload->keyno; + len = DesfireAPDU(cmd, 2, resp); + } + + if (!len) { + if (DBGLEVEL >= DBG_ERROR) { + DbpString("Authentication failed. Card timeout."); + } + OnErrorNG(CMD_HF_DESFIRE_AUTH1,3); + return; + } + + if (resp[2] == (uint8_t)0xaf) { + DbpString("Authentication failed. Invalid key number."); + OnErrorNG(CMD_HF_DESFIRE_AUTH1,3); + return; + } + + // Part 2 + if (payload->mode != MFDES_AUTH_PICC) { + memcpy(encRndB, resp + 1, payload->keylen); + } else { + memcpy(encRndB, resp + 2, payload->keylen); + } + + // Part 3 + if (payload->algo==MFDES_ALGO_AES) + mbedtls_aes_crypt_cbc(&ctx, MBEDTLS_AES_DECRYPT, 16, IV, encRndB, RndB); + else if (payload->algo == MFDES_ALGO_3DES) + tdes_dec(&RndB, &encRndB, key->data); + else if (payload->algo == MFDES_ALGO_DES) + des_dec(&RndB, &encRndB, key->data); + + // - Rotate RndB by 8 bits + memcpy(rotRndB, RndB, payload->keylen); + rol(rotRndB, payload->keylen); + + //memcpy(RndA, decRndA, payload->keylen); + uint8_t encRndA[16] = {0x00}; + + // - Encrypt our response + if (payload->mode==MFDES_AUTH_DES || payload->mode==MFDES_AUTH_PICC) { + if (payload->algo == MFDES_ALGO_3DES) + tdes_dec(&encRndA, &RndA, key->data); + else if (payload->algo == MFDES_ALGO_DES) + des_dec(&encRndA, &RndA, key->data); + + memcpy(both, encRndA, 8); + + for (int x = 0; x < 8; x++) { + rotRndB[x] = rotRndB[x] ^ encRndA[x]; + } + + if (payload->algo == MFDES_ALGO_3DES) + tdes_dec(&encRndB, &rotRndB, key->data); + else if (payload->algo == MFDES_ALGO_DES) + des_dec(&encRndB, &rotRndB, key->data); + + memcpy(both + 8, encRndB, 8); + } + else if (payload->mode==MFDES_AUTH_AES || payload->mode==MFDES_AUTH_ISO) { + uint8_t tmp[32] = {0x00}; + memcpy(tmp, RndA, 16); + memcpy(tmp + 16, rotRndB, 16); + if (payload->algo==MFDES_ALGO_AES) { + if (mbedtls_aes_setkey_enc(&ctx, key->data, 128) != 0) { + if (DBGLEVEL >= DBG_EXTENDED) { + DbpString("mbedtls_aes_setkey_enc failed"); + } + OnErrorNG(CMD_HF_DESFIRE_AUTH1,7); return; } + mbedtls_aes_crypt_cbc(&ctx, MBEDTLS_AES_ENCRYPT, 32, IV, tmp, both); + } + } - memcpy(encRndB, resp + 1, 8); - if (arg1 == 2) - tdes_dec(&decRndB, &encRndB, key->data); - else if (arg1 == 1) - des_dec(&decRndB, &encRndB, key->data); + if (payload->mode != MFDES_AUTH_PICC) { + cmd[0] = 0x90; + cmd[1] = ADDITIONAL_FRAME; + cmd[2] = 0x00; + cmd[3] = 0x00; + cmd[4] = (payload->keylen * 2); + memcpy(cmd + 5, both, payload->keylen * 2); + cmd[(payload->keylen * 2) + 5] = 0x0; + len = DesfireAPDU(cmd, 5 + (payload->keylen * 2) + 1, resp); + } else { + cmd[0] = ADDITIONAL_FRAME; + memcpy(cmd + 1, both, 16); + len = DesfireAPDU(cmd, 1 + 16, resp); + } - memcpy(RndB, decRndB, 8); - rol(decRndB, 8); + if (!len) { + if (DBGLEVEL >= DBG_ERROR) { + DbpString("Authentication failed. Card timeout."); + } + OnErrorNG(CMD_HF_DESFIRE_AUTH1,3); + return; + } - // This should be random - uint8_t decRndA[8] = {0x00}; - uint32_t value = prng_successor(GetTickCount(), 32); - num_to_bytes(value, 4, &decRndA[0]); - value = prng_successor(GetTickCount(), 32); - num_to_bytes(value, 4, &decRndA[4]); + if (payload->mode != MFDES_AUTH_PICC) { + if ((resp[len - 4] != 0x91) || (resp[len - 3] != 0x00)) { + DbpString("Authentication failed."); + OnErrorNG(CMD_HF_DESFIRE_AUTH1,6); + return; + } + } + else { + if (resp[1] != 0x00) { + DbpString("Authentication failed."); + OnErrorNG(CMD_HF_DESFIRE_AUTH1,6); + return; + } + } - memcpy(RndA, decRndA, 8); - uint8_t encRndA[8] = {0x00}; + // Part 4 + struct desfire_key sessionKey = {0}; + desfirekey_t skey = &sessionKey; + Desfire_session_key_new(RndA, RndB, key, skey); + memset(payload->sessionkey,0x0,24); + memcpy(payload->sessionkey,skey->data,payload->keylen); + print_result("SESSION : ", skey->data, payload->keylen); + print_result("SESSION : ", payload->sessionkey, payload->keylen); - if (arg1 == 2) - tdes_dec(&encRndA, &decRndA, key->data); - else if (arg1 == 1) - des_dec(&encRndA, &decRndA, key->data); + if (payload->mode != MFDES_AUTH_PICC) { + memcpy(encRndA, resp + 1, payload->keylen); + } + else { + memcpy(encRndA, resp + 2, payload->keylen); + } - memcpy(both, encRndA, 8); + if (payload->mode==MFDES_AUTH_DES || payload->mode==MFDES_AUTH_PICC) { + if (payload->algo == MFDES_ALGO_3DES) + tdes_dec(&encRndA, &encRndA, key->data); + else if (payload->algo == MFDES_ALGO_DES) + des_dec(&encRndA, &encRndA, key->data); + } + else if (payload->mode==MFDES_AUTH_AES) { + mbedtls_aes_crypt_cbc(&ctx, MBEDTLS_AES_DECRYPT, 16, IV, encRndA, encRndA); + } - for (int x = 0; x < 8; x++) { - decRndB[x] = decRndB[x] ^ encRndA[x]; + rol(RndA, payload->keylen); + print_result("RndA : ", RndA, payload->keylen); + print_result("encRndA : ", encRndA, payload->keylen); + for (int x = 0; x < payload->keylen; x++) { + if (RndA[x] != encRndA[x]) { + DbpString("Authentication failed. Cannot verify Session Key."); + OnErrorNG(CMD_HF_DESFIRE_AUTH1,4); + return; + } + } + //Change the selected key to a new value. - } + /* + // Current key is a 3DES key, change it to a DES key + if (payload->algo == 2) { + cmd[0] = 0x90; + cmd[1] = CHANGE_KEY; + cmd[2] = payload->keyno; - if (arg1 == 2) - tdes_dec(&encRndB, &decRndB, key->data); - else if (arg1 == 1) - des_dec(&encRndB, &decRndB, key->data); + uint8_t newKey[16] = {0x00,0x11,0x22,0x33,0x44,0x55,0x66,0x77,0x00,0x11,0x22,0x33,0x44,0x55,0x66,0x77}; - memcpy(both + 8, encRndB, 8); + uint8_t first, second; + uint8_t buff1[8] = {0x00}; + uint8_t buff2[8] = {0x00}; + uint8_t buff3[8] = {0x00}; - cmd[0] = 0x90; - cmd[1] = ADDITIONAL_FRAME; - cmd[2] = 0x00; - cmd[3] = 0x00; - cmd[4] = 0x10; - memcpy(cmd + 5, both, 16); - cmd[16 + 5] = 0x0; - len = DesfireAPDU(cmd, 5 + 16 + 1, resp); - if (!len) { - if (DBGLEVEL >= DBG_ERROR) { - DbpString("Authentication failed. Card timeout."); - } - OnError(3); - return; - } + memcpy(buff1,newKey, 8); + memcpy(buff2,newKey + 8, 8); - if (resp[len - 3] == 0x00) { + compute_crc(CRC_14443_A, newKey, 16, &first, &second); + memcpy(buff3, &first, 1); + memcpy(buff3 + 1, &second, 1); - struct desfire_key sessionKey = {0}; - desfirekey_t skey = &sessionKey; - Desfire_session_key_new(RndA, RndB, key, skey); - //print_result("SESSION : ", skey->data, 8); + tdes_dec(&buff1, &buff1, skey->data); + memcpy(cmd+2,buff1,8); - memcpy(encRndA, resp + 1, 8); + for (int x = 0; x < 8; x++) { + buff2[x] = buff2[x] ^ buff1[x]; + } + tdes_dec(&buff2, &buff2, skey->data); + memcpy(cmd+10,buff2,8); - if (arg1 == 2) - tdes_dec(&encRndA, &encRndA, key->data); - else if (arg1 == 1) - des_dec(&encRndA, &encRndA, key->data); + for (int x = 0; x < 8; x++) { + buff3[x] = buff3[x] ^ buff2[x]; + } + tdes_dec(&buff3, &buff3, skey->data); + memcpy(cmd+19,buff3,8); - rol(decRndA, 8); - for (int x = 0; x < 8; x++) { - if (decRndA[x] != encRndA[x]) { - DbpString("Authentication failed. Cannot verify PICC."); - OnError(4); - return; - } - } + // The command always times out on the first attempt, this will retry until a response + // is recieved. + len = 0; + while(!len) { + len = DesfireAPDU(cmd,27,resp); + } - //Change the selected key to a new value. - - /* - // Current key is a 3DES key, change it to a DES key - if (arg1 == 2) { + } else { + // Current key is a DES key, change it to a 3DES key + if (payload->algo == 1) { cmd[0] = 0x90; cmd[1] = CHANGE_KEY; - cmd[2] = arg2; + cmd[2] = payload->keyno; - uint8_t newKey[16] = {0x00,0x11,0x22,0x33,0x44,0x55,0x66,0x77,0x00,0x11,0x22,0x33,0x44,0x55,0x66,0x77}; + uint8_t newKey[16] = {0x40,0x41,0x42,0x43,0x44,0x45,0x46,0x47,0x48,0x49,0x4a,0x4b,0x4c,0x4d,0x4e,0x4f}; uint8_t first, second; uint8_t buff1[8] = {0x00}; @@ -370,319 +532,39 @@ void MifareDES_Auth1(uint8_t arg0, uint8_t arg1, uint8_t arg2, uint8_t *datain) memcpy(buff3, &first, 1); memcpy(buff3 + 1, &second, 1); - tdes_dec(&buff1, &buff1, skey->data); - memcpy(cmd+2,buff1,8); + des_dec(&buff1, &buff1, skey->data); + memcpy(cmd+3,buff1,8); - for (int x = 0; x < 8; x++) { - buff2[x] = buff2[x] ^ buff1[x]; - } - tdes_dec(&buff2, &buff2, skey->data); - memcpy(cmd+10,buff2,8); - - for (int x = 0; x < 8; x++) { - buff3[x] = buff3[x] ^ buff2[x]; - } - tdes_dec(&buff3, &buff3, skey->data); - memcpy(cmd+19,buff3,8); - - // The command always times out on the first attempt, this will retry until a response - // is recieved. - len = 0; - while(!len) { - len = DesfireAPDU(cmd,27,resp); - } - - } else { - // Current key is a DES key, change it to a 3DES key - if (arg1 == 1) { - cmd[0] = 0x90; - cmd[1] = CHANGE_KEY; - cmd[2] = arg2; - - uint8_t newKey[16] = {0x40,0x41,0x42,0x43,0x44,0x45,0x46,0x47,0x48,0x49,0x4a,0x4b,0x4c,0x4d,0x4e,0x4f}; - - uint8_t first, second; - uint8_t buff1[8] = {0x00}; - uint8_t buff2[8] = {0x00}; - uint8_t buff3[8] = {0x00}; - - memcpy(buff1,newKey, 8); - memcpy(buff2,newKey + 8, 8); - - compute_crc(CRC_14443_A, newKey, 16, &first, &second); - memcpy(buff3, &first, 1); - memcpy(buff3 + 1, &second, 1); - - des_dec(&buff1, &buff1, skey->data); - memcpy(cmd+3,buff1,8); - - for (int x = 0; x < 8; x++) { - buff2[x] = buff2[x] ^ buff1[x]; - } - des_dec(&buff2, &buff2, skey->data); - memcpy(cmd+11,buff2,8); - - for (int x = 0; x < 8; x++) { - buff3[x] = buff3[x] ^ buff2[x]; - } - des_dec(&buff3, &buff3, skey->data); - memcpy(cmd+19,buff3,8); - - // The command always times out on the first attempt, this will retry until a response - // is recieved. - len = 0; - while(!len) { - len = DesfireAPDU(cmd,27,resp); - } - } - } - */ - - //OnSuccess(); - if (arg1 == 2) - reply_old(CMD_ACK, 1, 0, 0, skey->data, 16); - else if (arg1 == 1) - reply_old(CMD_ACK, 1, 0, 0, skey->data, 8); - } else { - DbpString("Authentication failed."); - OnError(6); - return; - } + for (int x = 0; x < 8; x++) { + buff2[x] = buff2[x] ^ buff1[x]; } - break; - case 2: { - //SendDesfireCommand(AUTHENTICATE_ISO, &arg2, resp); - uint8_t keybytes[16]; - uint8_t RndA[8] = {0x00}; - uint8_t RndB[8] = {0x00}; + des_dec(&buff2, &buff2, skey->data); + memcpy(cmd+11,buff2,8); - if (arg1 == 2) { - if (datain[1] == 0xff) { - memcpy(keybytes, PICC_MASTER_KEY16, 16); - } else { - memcpy(keybytes, datain + 1, datalen); - } - } else { - if (arg1 == 1) { - if (datain[1] == 0xff) { - uint8_t null_key_data8[8] = {0x00}; - memcpy(keybytes, null_key_data8, 8); - } else { - memcpy(keybytes, datain + 1, datalen); - } - } - } - - struct desfire_key defaultkey = {0}; - desfirekey_t key = &defaultkey; - - if (arg1 == 2) - Desfire_3des_key_new_with_version(keybytes, key); - else if (arg1 == 1) - Desfire_des_key_new(keybytes, key); - - cmd[0] = AUTHENTICATE; - cmd[1] = arg2; //keynumber - len = DesfireAPDU(cmd, 2, resp); - - if (!len) { - if (DBGLEVEL >= DBG_ERROR) { - DbpString("Authentication failed. Card timeout."); - } - OnError(3); - return; - } - - if (resp[2] == (uint8_t)0xaf) { - DbpString("Authentication failed. Invalid key number."); - OnError(3); - return; - } - - memcpy(encRndB, resp + 2, 8); - if (arg1 == 2) - tdes_dec(&decRndB, &encRndB, key->data); - else if (arg1 == 1) - des_dec(&decRndB, &encRndB, key->data); - - memcpy(RndB, decRndB, 8); - rol(decRndB, 8); - - // This should be random - uint8_t decRndA[8] = {0x00}; - uint32_t value = prng_successor(GetTickCount(), 32); - num_to_bytes(value, 4, &decRndA[0]); - value = prng_successor(GetTickCount(), 32); - num_to_bytes(value, 4, &decRndA[4]); - - memcpy(RndA, decRndA, 8); - uint8_t encRndA[8] = {0x00}; - - if (arg1 == 2) - tdes_dec(&encRndA, &decRndA, key->data); - else if (arg1 == 1) - des_dec(&encRndA, &decRndA, key->data); - - memcpy(both, encRndA, 8); - - for (int x = 0; x < 8; x++) { - decRndB[x] = decRndB[x] ^ encRndA[x]; - - } - - if (arg1 == 2) - tdes_dec(&encRndB, &decRndB, key->data); - else if (arg1 == 1) - des_dec(&encRndB, &decRndB, key->data); - - memcpy(both + 8, encRndB, 8); - - cmd[0] = ADDITIONAL_FRAME; - memcpy(cmd + 1, both, 16); - len = DesfireAPDU(cmd, 1 + 16, resp); - if (!len) { - if (DBGLEVEL >= DBG_ERROR) { - DbpString("Authentication failed. Card timeout."); - } - OnError(3); - return; - } - - if (resp[1] == 0x00) { - struct desfire_key sessionKey = {0}; - desfirekey_t skey = &sessionKey; - Desfire_session_key_new(RndA, RndB, key, skey); - //print_result("SESSION : ", skey->data, 8); - - memcpy(encRndA, resp + 2, 8); - - if (arg1 == 2) - tdes_dec(&encRndA, &encRndA, key->data); - else if (arg1 == 1) - des_dec(&encRndA, &encRndA, key->data); - - rol(decRndA, 8); - for (int x = 0; x < 8; x++) { - if (decRndA[x] != encRndA[x]) { - DbpString("Authentication failed. Cannot verify PICC."); - OnError(4); - return; - } - } - - //OnSuccess(); - if (arg1 == 2) - reply_old(CMD_ACK, 1, 0, 0, skey->data, 16); - else if (arg1 == 1) - reply_old(CMD_ACK, 1, 0, 0, skey->data, 8); - } else { - DbpString("Authentication failed."); - OnError(6); - return; - } + for (int x = 0; x < 8; x++) { + buff3[x] = buff3[x] ^ buff2[x]; } - break; - case 3: { - //defaultkey - uint8_t keybytes[16] = {0x00}; - if (datain[1] == 0xff) { - memcpy(keybytes, PICC_MASTER_KEY16, 16); - } else { - memcpy(keybytes, datain + 1, datalen); - } + des_dec(&buff3, &buff3, skey->data); + memcpy(cmd+19,buff3,8); - struct desfire_key defaultkey = {0x00}; - desfirekey_t key = &defaultkey; - Desfire_aes_key_new(keybytes, key); - - mbedtls_aes_context ctx; - uint8_t IV[16] = {0x00}; - mbedtls_aes_init(&ctx); - - cmd[0] = 0x90; - cmd[1] = AUTHENTICATE_AES; - cmd[2] = 0x0; - cmd[3] = 0x0; - cmd[4] = 0x1; - cmd[5] = arg2; //keynumber - cmd[6] = 0x0; - len = DesfireAPDU(cmd, 7, resp); - if (!len) { - if (DBGLEVEL >= DBG_ERROR) { - DbpString("Authentication failed. Card timeout."); - } - OnError(3); - return; - } - - memcpy(encRndB, resp + 1, 16); - - // dekryptera tagnonce. - if (mbedtls_aes_setkey_dec(&ctx, key->data, 128) != 0) { - if (DBGLEVEL >= DBG_EXTENDED) { - DbpString("mbedtls_aes_setkey_dec failed"); - } - OnError(7); - return; - } - mbedtls_aes_crypt_cbc(&ctx, MBEDTLS_AES_DECRYPT, 16, IV, encRndB, decRndB); - rol(decRndB, 16); - uint8_t nonce[16] = {0x00}; - uint32_t val = prng_successor(GetTickCount(), 32); - num_to_bytes(val, 4, &nonce[0]); - val = prng_successor(GetTickCount(), 32); - num_to_bytes(val, 4, &nonce[4]); - val = prng_successor(GetTickCount(), 32); - num_to_bytes(val, 4, &nonce[8]); - val = prng_successor(GetTickCount(), 32); - num_to_bytes(val, 4, &nonce[12]); - memcpy(both, nonce, 16); - memcpy(both + 16, decRndB, 16); - uint8_t encBoth[32] = {0x00}; - if (mbedtls_aes_setkey_enc(&ctx, key->data, 128) != 0) { - if (DBGLEVEL >= DBG_EXTENDED) { - DbpString("mbedtls_aes_setkey_enc failed"); - } - OnError(7); - return; - } - mbedtls_aes_crypt_cbc(&ctx, MBEDTLS_AES_ENCRYPT, 32, IV, both, encBoth); - - cmd[0] = 0x90; - cmd[1] = ADDITIONAL_FRAME; - cmd[2] = 0x00; - cmd[3] = 0x00; - cmd[4] = 0x20; - memcpy(cmd + 5, encBoth, 32); - cmd[32 + 5] = 0x0; - - len = DesfireAPDU(cmd, 5 + 32 + 1, resp); - if (!len) { - if (DBGLEVEL >= DBG_ERROR) { - DbpString("Authentication failed. Card timeout."); - } - OnError(3); - return; - } - - if ((resp[1 + 16] == 0x91) && (resp[1 + 16 + 1] == 0x00)) { - // Create AES Session key - struct desfire_key sessionKey = {0}; - desfirekey_t skey = &sessionKey; - Desfire_session_key_new(nonce, decRndB, key, skey); - print_result("SESSION : ", skey->data, 16); - } else { - DbpString("Authentication failed."); - OnError(7); - return; - } - - break; + // The command always times out on the first attempt, this will retry until a response + // is recieved. + len = 0; + while(!len) { + len = DesfireAPDU(cmd,27,resp); } - } + } + } + */ + //OnSuccess(); - reply_mix(CMD_ACK, 1, len, 0, resp, len); + //reply_old(CMD_ACK, 1, 0, 0, skey->data, payload->keylen); + //reply_mix(CMD_ACK, 1, len, 0, resp, len); + + LED_B_ON(); + reply_ng(CMD_HF_DESFIRE_AUTH1, PM3_SUCCESS, (uint8_t *)payload, sizeof(payload)); + LED_B_OFF(); } // 3 different ISO ways to send data to a DESFIRE (direct, capsuled, capsuled ISO) @@ -767,3 +649,8 @@ void OnError(uint8_t reason) { reply_mix(CMD_ACK, 0, reason, 0, 0, 0); OnSuccess(); } + +void OnErrorNG(uint16_t cmd, uint8_t reason) { + reply_ng(cmd, reason, NULL, 0); + OnSuccess(); +} \ No newline at end of file diff --git a/armsrc/mifaredesfire.h b/armsrc/mifaredesfire.h index 8daed69aa..ae4b135c5 100644 --- a/armsrc/mifaredesfire.h +++ b/armsrc/mifaredesfire.h @@ -16,11 +16,12 @@ bool InitDesfireCard(); void MifareSendCommand(uint8_t arg0, uint8_t arg1, uint8_t *datain); void MifareDesfireGetInformation(); -void MifareDES_Auth1(uint8_t arg0, uint8_t arg1, uint8_t arg2, uint8_t *datain); +void MifareDES_Auth1(uint8_t *datain); void ReaderMifareDES(uint32_t param, uint32_t param2, uint8_t *datain); int DesfireAPDU(uint8_t *cmd, size_t cmd_len, uint8_t *dataout); size_t CreateAPDU(uint8_t *datain, size_t len, uint8_t *dataout); void OnSuccess(); void OnError(uint8_t reason); +void OnErrorNG(uint16_t cmd, uint8_t reason); #endif diff --git a/client/cmdhfmfdes.c b/client/cmdhfmfdes.c index 3e21d60be..da56766f6 100644 --- a/client/cmdhfmfdes.c +++ b/client/cmdhfmfdes.c @@ -36,6 +36,20 @@ uint8_t key_picc_data[16] = { 0x40, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, 0x #define status(x) ( ((uint16_t)(0x91<<8)) + x ) +typedef enum { + MFDES_AUTH_DES = 1, + MFDES_AUTH_ISO = 2, + MFDES_AUTH_AES = 3, + MFDES_AUTH_PICC = 4 +} mifare_des_authmode_t; + +typedef enum { + MFDES_ALGO_DES = 1, + MFDES_ALGO_3DES = 2, + MFDES_ALGO_3K3DES = 3, + MFDES_ALGO_AES = 4 +} mifare_des_authalgo_t; + typedef enum { UNKNOWN = 0, MF3ICD40, @@ -838,18 +852,31 @@ static int CmdHF14ADesFormatPICC(const char *Cmd) { uint8_t aid[3] = {0}; int res = get_desfire_select_application(aid); if (res != PM3_SUCCESS) return res; - uint8_t data[25] = {keylen}; // max length: 1 + 24 (3k3DES) - memcpy(data + 1, key, keylen); - SendCommandOLD(CMD_HF_DESFIRE_AUTH1, 2, 1, 0, data, keylen + 1); + struct { + uint8_t isOK; + uint8_t mode; + uint8_t algo; + uint8_t keyno; + uint8_t key[24]; + uint8_t keylen; + uint8_t sessionkey[24]; + } PACKED payload; + payload.keylen=keylen; + memcpy(payload.key,key,keylen); + payload.mode=MFDES_AUTH_PICC; + payload.algo=MFDES_ALGO_DES; + payload.keyno=0; + //SendCommandOLD(CMD_HF_DESFIRE_AUTH1, 2, 1, 0, data, keylen + 1); + SendCommandNG(CMD_HF_DESFIRE_AUTH1,(uint8_t*)&payload,sizeof(payload)); PacketResponseNG resp; - if (!WaitForResponseTimeout(CMD_ACK, &resp, 3000)) { + if (!WaitForResponseTimeout(CMD_HF_DESFIRE_AUTH1, &resp, 3000)) { PrintAndLogEx(WARNING, "Client command execute timeout"); DropField(); return PM3_ETIMEOUT; } - uint8_t isOK = resp.oldarg[0] & 0xff; + uint8_t isOK = (resp.status==PM3_SUCCESS); if (isOK) { uint8_t rdata[] = {0xFC}; // 0xFC SendCommandMIX(CMD_HF_DESFIRE_COMMAND, NONE, sizeof(rdata), 0, rdata, sizeof(rdata)); @@ -1492,28 +1519,43 @@ static int CmdHF14ADesAuth(const char *Cmd) { if (res != PM3_SUCCESS) return res; } - // algo, keylength, - uint8_t data[25] = {keylength}; // max length: 1 + 24 (3k3DES) - memcpy(data + 1, key, keylength); - SendCommandOLD(CMD_HF_DESFIRE_AUTH1, cmdAuthMode, cmdAuthAlgo, cmdKeyNo, data, keylength + 1); + struct { + uint8_t isOK; + uint8_t mode; + uint8_t algo; + uint8_t keyno; + uint8_t key[24]; + uint8_t keylen; + uint8_t sessionkey[24]; + } PACKED payload; + payload.keylen=keylength; + memcpy(payload.key,key,keylength); + payload.mode=cmdAuthMode; + payload.algo=cmdAuthAlgo; + payload.keyno=cmdKeyNo; + //SendCommandOLD(CMD_HF_DESFIRE_AUTH1, 2, 1, 0, data, keylen + 1); + SendCommandNG(CMD_HF_DESFIRE_AUTH1,(uint8_t*)&payload,sizeof(payload)); + + //uint8_t data[25] = {keylength}; // max length: 1 + 24 (3k3DES) + //memcpy(data + 1, key, keylength); + //SendCommandOLD(CMD_HF_DESFIRE_AUTH1, cmdAuthMode, cmdAuthAlgo, cmdKeyNo, data, keylength + 1); PacketResponseNG resp; - if (!WaitForResponseTimeout(CMD_ACK, &resp, 3000)) { + if (!WaitForResponseTimeout(CMD_HF_DESFIRE_AUTH1, &resp, 3000)) { PrintAndLogEx(WARNING, "Client command execute timeout"); DropField(); return PM3_ETIMEOUT; } - uint8_t isOK = resp.oldarg[0] & 0xff; + uint8_t isOK = (resp.status == PM3_SUCCESS); if (isOK) { - uint8_t *session_key = resp.data.asBytes; + uint8_t *session_key = payload.sessionkey; PrintAndLogEx(SUCCESS, " Key : " _GREEN_("%s"), sprint_hex(key, keylength)); PrintAndLogEx(SUCCESS, " SESSION : " _GREEN_("%s"), sprint_hex(session_key, keylength)); PrintAndLogEx(INFO, "-------------------------------------------------------------"); - //PrintAndLogEx(NORMAL, " Expected :B5 21 9E E8 1A A7 49 9D 21 96 68 7E 13 97 38 56"); } else { - PrintAndLogEx(WARNING, _RED_("Client command failed.")); + PrintAndLogEx(WARNING, _RED_("Client command failed, reason: %d."), resp.status); } PrintAndLogEx(INFO, "-------------------------------------------------------------"); return PM3_SUCCESS; From 08469f940af422e07da60e03fbe7bd4f9dff3c62 Mon Sep 17 00:00:00 2001 From: Bjoern Kerler Date: Fri, 10 Apr 2020 22:52:16 +0200 Subject: [PATCH 02/16] Replace MIX and OLD Commands --- armsrc/appmain.c | 2 +- armsrc/mifaredesfire.c | 88 ++++++++++++++++++++++++++++-------------- armsrc/mifaredesfire.h | 2 +- client/cmdhfmfdes.c | 43 +++++++++++---------- 4 files changed, 82 insertions(+), 53 deletions(-) diff --git a/armsrc/appmain.c b/armsrc/appmain.c index 15eb40f26..b44dbc5c5 100644 --- a/armsrc/appmain.c +++ b/armsrc/appmain.c @@ -1287,7 +1287,7 @@ static void PacketReceived(PacketCommandNG *packet) { break; } case CMD_HF_DESFIRE_COMMAND: { - MifareSendCommand(packet->oldarg[0], packet->oldarg[1], packet->data.asBytes); + MifareSendCommand(packet->data.asBytes); break; } case CMD_HF_MIFARE_NACK_DETECT: { diff --git a/armsrc/mifaredesfire.c b/armsrc/mifaredesfire.c index 815c301ac..eddff857a 100644 --- a/armsrc/mifaredesfire.c +++ b/armsrc/mifaredesfire.c @@ -52,29 +52,33 @@ bool InitDesfireCard() { return true; } -void MifareSendCommand(uint8_t arg0, uint8_t arg1, uint8_t *datain) { +void MifareSendCommand(uint8_t *datain) { + struct p { + uint8_t flags; + uint8_t datalen; + uint8_t datain[FRAME_PAYLOAD_SIZE]; + } PACKED; + struct p *payload = (struct p *) datain; - uint8_t flags = arg0; - size_t datalen = arg1; uint8_t resp[RECEIVE_SIZE]; memset(resp, 0, sizeof(resp)); if (DBGLEVEL >= DBG_EXTENDED) { - Dbprintf(" flags : %02X", flags); - Dbprintf(" len : %02X", datalen); - print_result(" RX : ", datain, datalen); + Dbprintf(" flags : %02X", payload->flags); + Dbprintf(" len : %02X", payload->datalen); + print_result(" RX : ", payload->datain, payload->datalen); } - if (flags & CLEARTRACE) + if (payload->flags & CLEARTRACE) clear_trace(); - if (flags & INIT) { + if (payload->flags & INIT) { if (!InitDesfireCard()) { return; } } - int len = DesfireAPDU(datain, datalen, resp); + int len = DesfireAPDU(payload->datain, payload->datalen, resp); if (DBGLEVEL >= DBG_EXTENDED) print_result("RESP <--: ", resp, len); @@ -83,10 +87,21 @@ void MifareSendCommand(uint8_t arg0, uint8_t arg1, uint8_t *datain) { return; } - if (flags & DISCONNECT) + if (payload->flags & DISCONNECT) OnSuccess(); - reply_mix(CMD_ACK, 1, len, 0, resp, len); + //reply_mix(CMD_ACK, 1, len, 0, resp, len); + LED_B_ON(); + struct r { + uint8_t len; + uint8_t data[RECEIVE_SIZE]; + } PACKED; + + struct r rpayload; + rpayload.len=len; + memcpy(rpayload.data,resp,rpayload.len); + reply_ng(CMD_HF_DESFIRE_COMMAND, PM3_SUCCESS, (uint8_t *)&rpayload, sizeof(payload)); + LED_B_OFF(); } void MifareDesfireGetInformation() { @@ -202,13 +217,11 @@ typedef enum { void MifareDES_Auth1(uint8_t *datain) { int len = 0; struct p { - uint8_t isOK; uint8_t mode; uint8_t algo; uint8_t keyno; uint8_t key[24]; uint8_t keylen; - uint8_t sessionkey[24]; } PACKED; struct p *payload = (struct p *) datain; @@ -275,13 +288,6 @@ void MifareDES_Auth1(uint8_t *datain) { if (payload->algo==MFDES_ALGO_AES) { mbedtls_aes_init(&ctx); - if (mbedtls_aes_setkey_dec(&ctx, key->data, 128) != 0) { - if (DBGLEVEL >= DBG_EXTENDED) { - DbpString("mbedtls_aes_setkey_dec failed"); - } - OnErrorNG(CMD_HF_DESFIRE_AUTH1,7); - return; - } Desfire_aes_key_new(keybytes, key); } else if (payload->algo == MFDES_ALGO_3DES) { @@ -342,8 +348,16 @@ void MifareDES_Auth1(uint8_t *datain) { } // Part 3 - if (payload->algo==MFDES_ALGO_AES) + if (payload->algo==MFDES_ALGO_AES) { + if (mbedtls_aes_setkey_dec(&ctx, key->data, 128) != 0) { + if (DBGLEVEL >= DBG_EXTENDED) { + DbpString("mbedtls_aes_setkey_dec failed"); + } + OnErrorNG(CMD_HF_DESFIRE_AUTH1,7); + return; + } mbedtls_aes_crypt_cbc(&ctx, MBEDTLS_AES_DECRYPT, 16, IV, encRndB, RndB); + } else if (payload->algo == MFDES_ALGO_3DES) tdes_dec(&RndB, &encRndB, key->data); else if (payload->algo == MFDES_ALGO_DES) @@ -353,7 +367,6 @@ void MifareDES_Auth1(uint8_t *datain) { memcpy(rotRndB, RndB, payload->keylen); rol(rotRndB, payload->keylen); - //memcpy(RndA, decRndA, payload->keylen); uint8_t encRndA[16] = {0x00}; // - Encrypt our response @@ -434,10 +447,8 @@ void MifareDES_Auth1(uint8_t *datain) { struct desfire_key sessionKey = {0}; desfirekey_t skey = &sessionKey; Desfire_session_key_new(RndA, RndB, key, skey); - memset(payload->sessionkey,0x0,24); - memcpy(payload->sessionkey,skey->data,payload->keylen); - print_result("SESSION : ", skey->data, payload->keylen); - print_result("SESSION : ", payload->sessionkey, payload->keylen); + if (DBGLEVEL >= DBG_EXTENDED) + print_result("SESSIONKEY : ", skey->data, payload->keylen); if (payload->mode != MFDES_AUTH_PICC) { memcpy(encRndA, resp + 1, payload->keylen); @@ -453,12 +464,21 @@ void MifareDES_Auth1(uint8_t *datain) { des_dec(&encRndA, &encRndA, key->data); } else if (payload->mode==MFDES_AUTH_AES) { - mbedtls_aes_crypt_cbc(&ctx, MBEDTLS_AES_DECRYPT, 16, IV, encRndA, encRndA); + if (mbedtls_aes_setkey_dec(&ctx, key->data, 128) != 0) { + if (DBGLEVEL >= DBG_EXTENDED) { + DbpString("mbedtls_aes_setkey_dec failed"); + } + OnErrorNG(CMD_HF_DESFIRE_AUTH1,7); + return; + } + mbedtls_aes_crypt_cbc(&ctx, MBEDTLS_AES_DECRYPT, 16, IV, encRndA, encRndA); } rol(RndA, payload->keylen); - print_result("RndA : ", RndA, payload->keylen); - print_result("encRndA : ", encRndA, payload->keylen); + if (DBGLEVEL >= DBG_EXTENDED) { + print_result("RndA : ", RndA, payload->keylen); + print_result("encRndA : ", encRndA, payload->keylen); + } for (int x = 0; x < payload->keylen; x++) { if (RndA[x] != encRndA[x]) { DbpString("Authentication failed. Cannot verify Session Key."); @@ -563,7 +583,15 @@ void MifareDES_Auth1(uint8_t *datain) { //reply_mix(CMD_ACK, 1, len, 0, resp, len); LED_B_ON(); - reply_ng(CMD_HF_DESFIRE_AUTH1, PM3_SUCCESS, (uint8_t *)payload, sizeof(payload)); + struct r { + uint8_t sessionkeylen; + uint8_t sessionkey[24]; + } PACKED; + + struct r rpayload; + rpayload.sessionkeylen=payload->keylen; + memcpy(rpayload.sessionkey,skey->data,rpayload.sessionkeylen); + reply_ng(CMD_HF_DESFIRE_AUTH1, PM3_SUCCESS, (uint8_t *)&rpayload, sizeof(payload)); LED_B_OFF(); } diff --git a/armsrc/mifaredesfire.h b/armsrc/mifaredesfire.h index ae4b135c5..1e19ec49f 100644 --- a/armsrc/mifaredesfire.h +++ b/armsrc/mifaredesfire.h @@ -14,7 +14,7 @@ #include "common.h" bool InitDesfireCard(); -void MifareSendCommand(uint8_t arg0, uint8_t arg1, uint8_t *datain); +void MifareSendCommand(uint8_t *datain); void MifareDesfireGetInformation(); void MifareDES_Auth1(uint8_t *datain); void ReaderMifareDES(uint32_t param, uint32_t param2, uint8_t *datain); diff --git a/client/cmdhfmfdes.c b/client/cmdhfmfdes.c index da56766f6..b23d78ec3 100644 --- a/client/cmdhfmfdes.c +++ b/client/cmdhfmfdes.c @@ -853,20 +853,17 @@ static int CmdHF14ADesFormatPICC(const char *Cmd) { int res = get_desfire_select_application(aid); if (res != PM3_SUCCESS) return res; struct { - uint8_t isOK; uint8_t mode; uint8_t algo; uint8_t keyno; uint8_t key[24]; uint8_t keylen; - uint8_t sessionkey[24]; } PACKED payload; payload.keylen=keylen; memcpy(payload.key,key,keylen); payload.mode=MFDES_AUTH_PICC; payload.algo=MFDES_ALGO_DES; payload.keyno=0; - //SendCommandOLD(CMD_HF_DESFIRE_AUTH1, 2, 1, 0, data, keylen + 1); SendCommandNG(CMD_HF_DESFIRE_AUTH1,(uint8_t*)&payload,sizeof(payload)); PacketResponseNG resp; @@ -878,14 +875,26 @@ static int CmdHF14ADesFormatPICC(const char *Cmd) { uint8_t isOK = (resp.status==PM3_SUCCESS); if (isOK) { - uint8_t rdata[] = {0xFC}; // 0xFC - SendCommandMIX(CMD_HF_DESFIRE_COMMAND, NONE, sizeof(rdata), 0, rdata, sizeof(rdata)); - if (!WaitForResponseTimeout(CMD_ACK, &resp, 3000)) { + struct { + uint8_t flags; + uint8_t datalen; + uint8_t datain[FRAME_PAYLOAD_SIZE]; + } PACKED payload; + payload.datain[0]=0xFC; + payload.flags=NONE; + payload.datalen=1; + SendCommandNG(CMD_HF_DESFIRE_COMMAND,(uint8_t*)&payload,sizeof(payload)); + if (!WaitForResponseTimeout(CMD_HF_DESFIRE_COMMAND, &resp, 3000)) { PrintAndLogEx(WARNING, "Client reset command execute timeout"); DropField(); return PM3_ETIMEOUT; } - if (resp.oldarg[0] & 0xFF) { + if (resp.status==PM3_SUCCESS) { + /*struct r { + uint8_t len; + uint8_t data[RECEIVE_SIZE]; + } PACKED; + struct r *rpayload = (struct r *)&resp.data.asBytes;*/ PrintAndLogEx(INFO, "Card successfully reset"); return PM3_SUCCESS; } @@ -1407,7 +1416,6 @@ static int CmdHF14ADesAuth(const char *Cmd) { // 2 = 3DES 16 // 3 = 3K 3DES 24 // 4 = AES 16 - //SetAPDULogging(true); uint8_t keylength = 8; CLIParserInit("hf mfdes auth", @@ -1443,14 +1451,12 @@ static int CmdHF14ADesAuth(const char *Cmd) { if ((keylen < 8) || (keylen > 24)) { PrintAndLogEx(ERR, "Specified key must have 16 bytes length."); - //SetAPDULogging(false); return PM3_EINVARG; } // AID if (aidlength != 3) { PrintAndLogEx(WARNING, "aid must include %d HEX symbols", 3); - //SetAPDULogging(false); return PM3_EINVARG; } @@ -1458,27 +1464,23 @@ static int CmdHF14ADesAuth(const char *Cmd) { case 1: if (cmdAuthAlgo != 1 && cmdAuthAlgo != 2) { PrintAndLogEx(NORMAL, "Crypto algo not valid for the auth mode"); - //SetAPDULogging(false); return PM3_EINVARG; } break; case 2: if (cmdAuthAlgo != 1 && cmdAuthAlgo != 2 && cmdAuthAlgo != 3) { PrintAndLogEx(NORMAL, "Crypto algo not valid for the auth mode"); - //SetAPDULogging(false); return PM3_EINVARG; } break; case 3: if (cmdAuthAlgo != 4) { PrintAndLogEx(NORMAL, "Crypto algo not valid for the auth mode"); - //SetAPDULogging(false); return PM3_EINVARG; } break; default: PrintAndLogEx(WARNING, "Wrong Auth mode (%d) -> (1=normal, 2=iso, 3=aes)", cmdAuthMode); - //SetAPDULogging(false); return PM3_EINVARG; } @@ -1520,25 +1522,19 @@ static int CmdHF14ADesAuth(const char *Cmd) { } struct { - uint8_t isOK; uint8_t mode; uint8_t algo; uint8_t keyno; uint8_t key[24]; uint8_t keylen; - uint8_t sessionkey[24]; } PACKED payload; payload.keylen=keylength; memcpy(payload.key,key,keylength); payload.mode=cmdAuthMode; payload.algo=cmdAuthAlgo; payload.keyno=cmdKeyNo; - //SendCommandOLD(CMD_HF_DESFIRE_AUTH1, 2, 1, 0, data, keylen + 1); SendCommandNG(CMD_HF_DESFIRE_AUTH1,(uint8_t*)&payload,sizeof(payload)); - //uint8_t data[25] = {keylength}; // max length: 1 + 24 (3k3DES) - //memcpy(data + 1, key, keylength); - //SendCommandOLD(CMD_HF_DESFIRE_AUTH1, cmdAuthMode, cmdAuthAlgo, cmdKeyNo, data, keylength + 1); PacketResponseNG resp; if (!WaitForResponseTimeout(CMD_HF_DESFIRE_AUTH1, &resp, 3000)) { @@ -1549,8 +1545,13 @@ static int CmdHF14ADesAuth(const char *Cmd) { uint8_t isOK = (resp.status == PM3_SUCCESS); if (isOK) { - uint8_t *session_key = payload.sessionkey; + struct r { + uint8_t sessionkeylen; + uint8_t sessionkey[24]; + } PACKED; + struct r *rpayload = (struct r *)&resp.data.asBytes; + uint8_t *session_key = rpayload->sessionkey; PrintAndLogEx(SUCCESS, " Key : " _GREEN_("%s"), sprint_hex(key, keylength)); PrintAndLogEx(SUCCESS, " SESSION : " _GREEN_("%s"), sprint_hex(session_key, keylength)); PrintAndLogEx(INFO, "-------------------------------------------------------------"); From 8f3a02fc504fa80e6013f96ef017f426e87fae8f Mon Sep 17 00:00:00 2001 From: Bjoern Kerler Date: Fri, 10 Apr 2020 22:56:45 +0200 Subject: [PATCH 03/16] Add Deselect on info and enum --- client/cmdhfmfdes.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/client/cmdhfmfdes.c b/client/cmdhfmfdes.c index b23d78ec3..c3989401f 100644 --- a/client/cmdhfmfdes.c +++ b/client/cmdhfmfdes.c @@ -908,7 +908,7 @@ static int CmdHF14ADesFormatPICC(const char *Cmd) { static int CmdHF14ADesInfo(const char *Cmd) { (void)Cmd; // Cmd is not used so far - + DropField(); SendCommandNG(CMD_HF_DESFIRE_INFO, NULL, 0); PacketResponseNG resp; @@ -1298,7 +1298,7 @@ static int DecodeFileSettings(uint8_t *filesettings, int fileset_len, int maclen static int CmdHF14ADesEnumApplications(const char *Cmd) { (void)Cmd; // Cmd is not used so far - + DropField(); // uint8_t isOK = 0x00; uint8_t aid[3] = {0}; uint8_t app_ids[78] = {0}; From 70b000bc795a98c478271849c9a9eb283cca164e Mon Sep 17 00:00:00 2001 From: Bjoern Kerler Date: Fri, 10 Apr 2020 22:59:55 +0200 Subject: [PATCH 04/16] Make style --- armsrc/mifaredesfire.c | 252 +++++++++++++++++++---------------------- client/cmdhfmfdes.c | 46 ++++---- 2 files changed, 142 insertions(+), 156 deletions(-) diff --git a/armsrc/mifaredesfire.c b/armsrc/mifaredesfire.c index eddff857a..be8889d48 100644 --- a/armsrc/mifaredesfire.c +++ b/armsrc/mifaredesfire.c @@ -98,8 +98,8 @@ void MifareSendCommand(uint8_t *datain) { } PACKED; struct r rpayload; - rpayload.len=len; - memcpy(rpayload.data,resp,rpayload.len); + rpayload.len = len; + memcpy(rpayload.data, resp, rpayload.len); reply_ng(CMD_HF_DESFIRE_COMMAND, PM3_SUCCESS, (uint8_t *)&rpayload, sizeof(payload)); LED_B_OFF(); } @@ -254,7 +254,7 @@ void MifareDES_Auth1(uint8_t *datain) { num_to_bytes(value, 4, &RndA[12]); // Default Keys - uint8_t PICC_MASTER_KEY8[8] = { 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}; + uint8_t PICC_MASTER_KEY8[8] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; uint8_t PICC_MASTER_KEY16[16] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; //uint8_t null_key_data16[16] = {0x00}; //uint8_t new_key_data8[8] = { 0x00,0x11,0x22,0x33,0x44,0x55,0x66,0x77}; @@ -268,46 +268,38 @@ void MifareDES_Auth1(uint8_t *datain) { LED_B_OFF(); LED_C_OFF(); - if (payload->key==NULL) - { - if (payload->mode==MFDES_AUTH_DES || payload->mode==MFDES_AUTH_PICC) - { - memcpy(keybytes, PICC_MASTER_KEY8, 8); - } - else if (payload->mode==MFDES_AUTH_AES) - { - memcpy(keybytes, PICC_MASTER_KEY16, 16); - } - } - else { - memcpy(keybytes, payload->key, payload->keylen); + if (payload->key == NULL) { + if (payload->mode == MFDES_AUTH_DES || payload->mode == MFDES_AUTH_PICC) { + memcpy(keybytes, PICC_MASTER_KEY8, 8); + } else if (payload->mode == MFDES_AUTH_AES) { + memcpy(keybytes, PICC_MASTER_KEY16, 16); } + } else { + memcpy(keybytes, payload->key, payload->keylen); + } struct desfire_key defaultkey = {0}; desfirekey_t key = &defaultkey; - if (payload->algo==MFDES_ALGO_AES) { - mbedtls_aes_init(&ctx); - Desfire_aes_key_new(keybytes, key); - } - else if (payload->algo == MFDES_ALGO_3DES) { - key->type=T_3DES; + if (payload->algo == MFDES_ALGO_AES) { + mbedtls_aes_init(&ctx); + Desfire_aes_key_new(keybytes, key); + } else if (payload->algo == MFDES_ALGO_3DES) { + key->type = T_3DES; Desfire_3des_key_new_with_version(keybytes, key); - } - else if (payload->algo == MFDES_ALGO_DES) { - key->type=T_DES; + } else if (payload->algo == MFDES_ALGO_DES) { + key->type = T_DES; Desfire_des_key_new(keybytes, key); - } - else if (payload->algo == MFDES_ALGO_3K3DES) { + } else if (payload->algo == MFDES_ALGO_3K3DES) { Desfire_3k3des_key_new_with_version(keybytes, key); } - uint8_t subcommand=AUTHENTICATE; + uint8_t subcommand = AUTHENTICATE; - if (payload->mode==MFDES_AUTH_AES) - subcommand=AUTHENTICATE_AES; - else if (payload->mode==MFDES_AUTH_ISO) - subcommand=AUTHENTICATE_ISO; + if (payload->mode == MFDES_AUTH_AES) + subcommand = AUTHENTICATE_AES; + else if (payload->mode == MFDES_AUTH_ISO) + subcommand = AUTHENTICATE_ISO; if (payload->mode != MFDES_AUTH_PICC) { // Let's send our auth command @@ -319,8 +311,7 @@ void MifareDES_Auth1(uint8_t *datain) { cmd[5] = payload->keyno; cmd[6] = 0x0; len = DesfireAPDU(cmd, 7, resp); - } - else { + } else { cmd[0] = AUTHENTICATE; cmd[1] = payload->keyno; len = DesfireAPDU(cmd, 2, resp); @@ -330,13 +321,13 @@ void MifareDES_Auth1(uint8_t *datain) { if (DBGLEVEL >= DBG_ERROR) { DbpString("Authentication failed. Card timeout."); } - OnErrorNG(CMD_HF_DESFIRE_AUTH1,3); + OnErrorNG(CMD_HF_DESFIRE_AUTH1, 3); return; } if (resp[2] == (uint8_t)0xaf) { DbpString("Authentication failed. Invalid key number."); - OnErrorNG(CMD_HF_DESFIRE_AUTH1,3); + OnErrorNG(CMD_HF_DESFIRE_AUTH1, 3); return; } @@ -348,17 +339,16 @@ void MifareDES_Auth1(uint8_t *datain) { } // Part 3 - if (payload->algo==MFDES_ALGO_AES) { + if (payload->algo == MFDES_ALGO_AES) { if (mbedtls_aes_setkey_dec(&ctx, key->data, 128) != 0) { if (DBGLEVEL >= DBG_EXTENDED) { DbpString("mbedtls_aes_setkey_dec failed"); } - OnErrorNG(CMD_HF_DESFIRE_AUTH1,7); + OnErrorNG(CMD_HF_DESFIRE_AUTH1, 7); return; } mbedtls_aes_crypt_cbc(&ctx, MBEDTLS_AES_DECRYPT, 16, IV, encRndB, RndB); - } - else if (payload->algo == MFDES_ALGO_3DES) + } else if (payload->algo == MFDES_ALGO_3DES) tdes_dec(&RndB, &encRndB, key->data); else if (payload->algo == MFDES_ALGO_DES) des_dec(&RndB, &encRndB, key->data); @@ -370,7 +360,7 @@ void MifareDES_Auth1(uint8_t *datain) { uint8_t encRndA[16] = {0x00}; // - Encrypt our response - if (payload->mode==MFDES_AUTH_DES || payload->mode==MFDES_AUTH_PICC) { + if (payload->mode == MFDES_AUTH_DES || payload->mode == MFDES_AUTH_PICC) { if (payload->algo == MFDES_ALGO_3DES) tdes_dec(&encRndA, &RndA, key->data); else if (payload->algo == MFDES_ALGO_DES) @@ -388,17 +378,16 @@ void MifareDES_Auth1(uint8_t *datain) { des_dec(&encRndB, &rotRndB, key->data); memcpy(both + 8, encRndB, 8); - } - else if (payload->mode==MFDES_AUTH_AES || payload->mode==MFDES_AUTH_ISO) { + } else if (payload->mode == MFDES_AUTH_AES || payload->mode == MFDES_AUTH_ISO) { uint8_t tmp[32] = {0x00}; memcpy(tmp, RndA, 16); memcpy(tmp + 16, rotRndB, 16); - if (payload->algo==MFDES_ALGO_AES) { + if (payload->algo == MFDES_ALGO_AES) { if (mbedtls_aes_setkey_enc(&ctx, key->data, 128) != 0) { if (DBGLEVEL >= DBG_EXTENDED) { DbpString("mbedtls_aes_setkey_enc failed"); } - OnErrorNG(CMD_HF_DESFIRE_AUTH1,7); + OnErrorNG(CMD_HF_DESFIRE_AUTH1, 7); return; } mbedtls_aes_crypt_cbc(&ctx, MBEDTLS_AES_ENCRYPT, 32, IV, tmp, both); @@ -424,21 +413,20 @@ void MifareDES_Auth1(uint8_t *datain) { if (DBGLEVEL >= DBG_ERROR) { DbpString("Authentication failed. Card timeout."); } - OnErrorNG(CMD_HF_DESFIRE_AUTH1,3); + OnErrorNG(CMD_HF_DESFIRE_AUTH1, 3); return; } if (payload->mode != MFDES_AUTH_PICC) { if ((resp[len - 4] != 0x91) || (resp[len - 3] != 0x00)) { DbpString("Authentication failed."); - OnErrorNG(CMD_HF_DESFIRE_AUTH1,6); + OnErrorNG(CMD_HF_DESFIRE_AUTH1, 6); return; } - } - else { + } else { if (resp[1] != 0x00) { DbpString("Authentication failed."); - OnErrorNG(CMD_HF_DESFIRE_AUTH1,6); + OnErrorNG(CMD_HF_DESFIRE_AUTH1, 6); return; } } @@ -452,23 +440,21 @@ void MifareDES_Auth1(uint8_t *datain) { if (payload->mode != MFDES_AUTH_PICC) { memcpy(encRndA, resp + 1, payload->keylen); - } - else { + } else { memcpy(encRndA, resp + 2, payload->keylen); } - if (payload->mode==MFDES_AUTH_DES || payload->mode==MFDES_AUTH_PICC) { + if (payload->mode == MFDES_AUTH_DES || payload->mode == MFDES_AUTH_PICC) { if (payload->algo == MFDES_ALGO_3DES) tdes_dec(&encRndA, &encRndA, key->data); else if (payload->algo == MFDES_ALGO_DES) des_dec(&encRndA, &encRndA, key->data); - } - else if (payload->mode==MFDES_AUTH_AES) { + } else if (payload->mode == MFDES_AUTH_AES) { if (mbedtls_aes_setkey_dec(&ctx, key->data, 128) != 0) { if (DBGLEVEL >= DBG_EXTENDED) { DbpString("mbedtls_aes_setkey_dec failed"); } - OnErrorNG(CMD_HF_DESFIRE_AUTH1,7); + OnErrorNG(CMD_HF_DESFIRE_AUTH1, 7); return; } mbedtls_aes_crypt_cbc(&ctx, MBEDTLS_AES_DECRYPT, 16, IV, encRndA, encRndA); @@ -482,100 +468,100 @@ void MifareDES_Auth1(uint8_t *datain) { for (int x = 0; x < payload->keylen; x++) { if (RndA[x] != encRndA[x]) { DbpString("Authentication failed. Cannot verify Session Key."); - OnErrorNG(CMD_HF_DESFIRE_AUTH1,4); + OnErrorNG(CMD_HF_DESFIRE_AUTH1, 4); return; } } - //Change the selected key to a new value. + //Change the selected key to a new value. - /* - // Current key is a 3DES key, change it to a DES key - if (payload->algo == 2) { - cmd[0] = 0x90; - cmd[1] = CHANGE_KEY; - cmd[2] = payload->keyno; + /* + // Current key is a 3DES key, change it to a DES key + if (payload->algo == 2) { + cmd[0] = 0x90; + cmd[1] = CHANGE_KEY; + cmd[2] = payload->keyno; - uint8_t newKey[16] = {0x00,0x11,0x22,0x33,0x44,0x55,0x66,0x77,0x00,0x11,0x22,0x33,0x44,0x55,0x66,0x77}; + uint8_t newKey[16] = {0x00,0x11,0x22,0x33,0x44,0x55,0x66,0x77,0x00,0x11,0x22,0x33,0x44,0x55,0x66,0x77}; - uint8_t first, second; - uint8_t buff1[8] = {0x00}; - uint8_t buff2[8] = {0x00}; - uint8_t buff3[8] = {0x00}; + uint8_t first, second; + uint8_t buff1[8] = {0x00}; + uint8_t buff2[8] = {0x00}; + uint8_t buff3[8] = {0x00}; - memcpy(buff1,newKey, 8); - memcpy(buff2,newKey + 8, 8); + memcpy(buff1,newKey, 8); + memcpy(buff2,newKey + 8, 8); - compute_crc(CRC_14443_A, newKey, 16, &first, &second); - memcpy(buff3, &first, 1); - memcpy(buff3 + 1, &second, 1); + compute_crc(CRC_14443_A, newKey, 16, &first, &second); + memcpy(buff3, &first, 1); + memcpy(buff3 + 1, &second, 1); - tdes_dec(&buff1, &buff1, skey->data); - memcpy(cmd+2,buff1,8); + tdes_dec(&buff1, &buff1, skey->data); + memcpy(cmd+2,buff1,8); - for (int x = 0; x < 8; x++) { - buff2[x] = buff2[x] ^ buff1[x]; - } - tdes_dec(&buff2, &buff2, skey->data); - memcpy(cmd+10,buff2,8); + for (int x = 0; x < 8; x++) { + buff2[x] = buff2[x] ^ buff1[x]; + } + tdes_dec(&buff2, &buff2, skey->data); + memcpy(cmd+10,buff2,8); - for (int x = 0; x < 8; x++) { - buff3[x] = buff3[x] ^ buff2[x]; - } - tdes_dec(&buff3, &buff3, skey->data); - memcpy(cmd+19,buff3,8); + for (int x = 0; x < 8; x++) { + buff3[x] = buff3[x] ^ buff2[x]; + } + tdes_dec(&buff3, &buff3, skey->data); + memcpy(cmd+19,buff3,8); - // The command always times out on the first attempt, this will retry until a response - // is recieved. - len = 0; - while(!len) { - len = DesfireAPDU(cmd,27,resp); - } + // The command always times out on the first attempt, this will retry until a response + // is recieved. + len = 0; + while(!len) { + len = DesfireAPDU(cmd,27,resp); + } - } else { - // Current key is a DES key, change it to a 3DES key - if (payload->algo == 1) { - cmd[0] = 0x90; - cmd[1] = CHANGE_KEY; - cmd[2] = payload->keyno; + } else { + // Current key is a DES key, change it to a 3DES key + if (payload->algo == 1) { + cmd[0] = 0x90; + cmd[1] = CHANGE_KEY; + cmd[2] = payload->keyno; - uint8_t newKey[16] = {0x40,0x41,0x42,0x43,0x44,0x45,0x46,0x47,0x48,0x49,0x4a,0x4b,0x4c,0x4d,0x4e,0x4f}; + uint8_t newKey[16] = {0x40,0x41,0x42,0x43,0x44,0x45,0x46,0x47,0x48,0x49,0x4a,0x4b,0x4c,0x4d,0x4e,0x4f}; - uint8_t first, second; - uint8_t buff1[8] = {0x00}; - uint8_t buff2[8] = {0x00}; - uint8_t buff3[8] = {0x00}; + uint8_t first, second; + uint8_t buff1[8] = {0x00}; + uint8_t buff2[8] = {0x00}; + uint8_t buff3[8] = {0x00}; - memcpy(buff1,newKey, 8); - memcpy(buff2,newKey + 8, 8); + memcpy(buff1,newKey, 8); + memcpy(buff2,newKey + 8, 8); - compute_crc(CRC_14443_A, newKey, 16, &first, &second); - memcpy(buff3, &first, 1); - memcpy(buff3 + 1, &second, 1); + compute_crc(CRC_14443_A, newKey, 16, &first, &second); + memcpy(buff3, &first, 1); + memcpy(buff3 + 1, &second, 1); - des_dec(&buff1, &buff1, skey->data); - memcpy(cmd+3,buff1,8); + des_dec(&buff1, &buff1, skey->data); + memcpy(cmd+3,buff1,8); - for (int x = 0; x < 8; x++) { - buff2[x] = buff2[x] ^ buff1[x]; + for (int x = 0; x < 8; x++) { + buff2[x] = buff2[x] ^ buff1[x]; + } + des_dec(&buff2, &buff2, skey->data); + memcpy(cmd+11,buff2,8); + + for (int x = 0; x < 8; x++) { + buff3[x] = buff3[x] ^ buff2[x]; + } + des_dec(&buff3, &buff3, skey->data); + memcpy(cmd+19,buff3,8); + + // The command always times out on the first attempt, this will retry until a response + // is recieved. + len = 0; + while(!len) { + len = DesfireAPDU(cmd,27,resp); + } } - des_dec(&buff2, &buff2, skey->data); - memcpy(cmd+11,buff2,8); - - for (int x = 0; x < 8; x++) { - buff3[x] = buff3[x] ^ buff2[x]; - } - des_dec(&buff3, &buff3, skey->data); - memcpy(cmd+19,buff3,8); - - // The command always times out on the first attempt, this will retry until a response - // is recieved. - len = 0; - while(!len) { - len = DesfireAPDU(cmd,27,resp); - } - } - } - */ + } + */ //OnSuccess(); @@ -589,8 +575,8 @@ void MifareDES_Auth1(uint8_t *datain) { } PACKED; struct r rpayload; - rpayload.sessionkeylen=payload->keylen; - memcpy(rpayload.sessionkey,skey->data,rpayload.sessionkeylen); + rpayload.sessionkeylen = payload->keylen; + memcpy(rpayload.sessionkey, skey->data, rpayload.sessionkeylen); reply_ng(CMD_HF_DESFIRE_AUTH1, PM3_SUCCESS, (uint8_t *)&rpayload, sizeof(payload)); LED_B_OFF(); } @@ -681,4 +667,4 @@ void OnError(uint8_t reason) { void OnErrorNG(uint16_t cmd, uint8_t reason) { reply_ng(cmd, reason, NULL, 0); OnSuccess(); -} \ No newline at end of file +} diff --git a/client/cmdhfmfdes.c b/client/cmdhfmfdes.c index c3989401f..ec44404a8 100644 --- a/client/cmdhfmfdes.c +++ b/client/cmdhfmfdes.c @@ -853,18 +853,18 @@ static int CmdHF14ADesFormatPICC(const char *Cmd) { int res = get_desfire_select_application(aid); if (res != PM3_SUCCESS) return res; struct { - uint8_t mode; - uint8_t algo; - uint8_t keyno; - uint8_t key[24]; - uint8_t keylen; + uint8_t mode; + uint8_t algo; + uint8_t keyno; + uint8_t key[24]; + uint8_t keylen; } PACKED payload; - payload.keylen=keylen; - memcpy(payload.key,key,keylen); - payload.mode=MFDES_AUTH_PICC; - payload.algo=MFDES_ALGO_DES; - payload.keyno=0; - SendCommandNG(CMD_HF_DESFIRE_AUTH1,(uint8_t*)&payload,sizeof(payload)); + payload.keylen = keylen; + memcpy(payload.key, key, keylen); + payload.mode = MFDES_AUTH_PICC; + payload.algo = MFDES_ALGO_DES; + payload.keyno = 0; + SendCommandNG(CMD_HF_DESFIRE_AUTH1, (uint8_t *)&payload, sizeof(payload)); PacketResponseNG resp; if (!WaitForResponseTimeout(CMD_HF_DESFIRE_AUTH1, &resp, 3000)) { @@ -873,23 +873,23 @@ static int CmdHF14ADesFormatPICC(const char *Cmd) { return PM3_ETIMEOUT; } - uint8_t isOK = (resp.status==PM3_SUCCESS); + uint8_t isOK = (resp.status == PM3_SUCCESS); if (isOK) { struct { uint8_t flags; uint8_t datalen; uint8_t datain[FRAME_PAYLOAD_SIZE]; } PACKED payload; - payload.datain[0]=0xFC; - payload.flags=NONE; - payload.datalen=1; - SendCommandNG(CMD_HF_DESFIRE_COMMAND,(uint8_t*)&payload,sizeof(payload)); + payload.datain[0] = 0xFC; + payload.flags = NONE; + payload.datalen = 1; + SendCommandNG(CMD_HF_DESFIRE_COMMAND, (uint8_t *)&payload, sizeof(payload)); if (!WaitForResponseTimeout(CMD_HF_DESFIRE_COMMAND, &resp, 3000)) { PrintAndLogEx(WARNING, "Client reset command execute timeout"); DropField(); return PM3_ETIMEOUT; } - if (resp.status==PM3_SUCCESS) { + if (resp.status == PM3_SUCCESS) { /*struct r { uint8_t len; uint8_t data[RECEIVE_SIZE]; @@ -1528,12 +1528,12 @@ static int CmdHF14ADesAuth(const char *Cmd) { uint8_t key[24]; uint8_t keylen; } PACKED payload; - payload.keylen=keylength; - memcpy(payload.key,key,keylength); - payload.mode=cmdAuthMode; - payload.algo=cmdAuthAlgo; - payload.keyno=cmdKeyNo; - SendCommandNG(CMD_HF_DESFIRE_AUTH1,(uint8_t*)&payload,sizeof(payload)); + payload.keylen = keylength; + memcpy(payload.key, key, keylength); + payload.mode = cmdAuthMode; + payload.algo = cmdAuthAlgo; + payload.keyno = cmdKeyNo; + SendCommandNG(CMD_HF_DESFIRE_AUTH1, (uint8_t *)&payload, sizeof(payload)); PacketResponseNG resp; From e0338284c0baea4f6e3a7592ee31b9c9b6515fac Mon Sep 17 00:00:00 2001 From: Bjoern Kerler Date: Fri, 10 Apr 2020 23:03:31 +0200 Subject: [PATCH 05/16] Add changelog --- CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index f32ea1497..66fa27ac6 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -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] + - Port 'hf mfdes' Authentification to CommandNG structure, fix auth session key (@bkerler) - Updates `hf mfdes` functions, improved logging and added new commands (@bkerler) - Updated 'legic.lua' and 'legic_clone.lua' script - works with current command set (@Pizza_4u) - Rewrote `hf mfdes` functions and added apdu debugging (@bkerler) From c6323a5fe1e7552ac79faf67ca407428e55c2b64 Mon Sep 17 00:00:00 2001 From: Bjoern Kerler Date: Fri, 10 Apr 2020 23:45:54 +0200 Subject: [PATCH 06/16] Fix bad bug. Don't check dest for NULL --- client/cmdhfmfdes.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/client/cmdhfmfdes.c b/client/cmdhfmfdes.c index d910cb669..1da5bbd20 100644 --- a/client/cmdhfmfdes.c +++ b/client/cmdhfmfdes.c @@ -311,10 +311,10 @@ static int send_desfire_cmd(sAPDU *apdu, bool select, uint8_t *dest, int *recv_l PrintAndLogEx(DEBUG, "APDU=NULL"); return PM3_EINVARG; } - if (dest == NULL) { + /*if (dest == NULL) { PrintAndLogEx(DEBUG, "DEST=NULL"); return PM3_EINVARG; - } + }*/ if (sw == NULL) { PrintAndLogEx(DEBUG, "SW=NULL"); return PM3_EINVARG; @@ -675,7 +675,7 @@ static int get_desfire_select_application(uint8_t *aid) { sAPDU apdu = {0x90, MFDES_SELECT_APPLICATION, 0x00, 0x00, 0x03, aid}; //0x5a int recv_len = 0; uint16_t sw = 0; - int res = send_desfire_cmd(&apdu, true, NULL, &recv_len, &sw, sizeof(dfname_t), true); + int res = send_desfire_cmd(&apdu, true, NONE, &recv_len, &sw, sizeof(dfname_t), true); if (res != PM3_SUCCESS) { PrintAndLogEx(WARNING, _RED_(" Can't select AID 0x%X -> %s"), (aid[0] << 16) + (aid[1] << 8) + aid[2], GetErrorString(res, &sw)); DropField(); From 93e4a6697139b63a489637fd5ddea1cd298d5d8e Mon Sep 17 00:00:00 2001 From: Bjoern Kerler Date: Sat, 11 Apr 2020 00:31:55 +0200 Subject: [PATCH 07/16] Improve UI handling and fix AID/FID display --- client/cmdhfmfdes.c | 76 ++++++++++++++++++++++++--------------------- 1 file changed, 41 insertions(+), 35 deletions(-) diff --git a/client/cmdhfmfdes.c b/client/cmdhfmfdes.c index 1da5bbd20..6d8dc5cf0 100644 --- a/client/cmdhfmfdes.c +++ b/client/cmdhfmfdes.c @@ -236,7 +236,7 @@ static char *getstatus(uint16_t *sw) { return "Application count is limited to 28, not addition CreateApplication possible"; case MFDES_E_DUPLICATE: - return "Duplicate entry: File/Application does already exist"; + return "Duplicate entry: File/Application/ISO Text does already exist"; case MFDES_E_EEPROM: return "Eeprom error due to loss of power, internal backup/rollback mechanism activated"; @@ -677,7 +677,7 @@ static int get_desfire_select_application(uint8_t *aid) { uint16_t sw = 0; int res = send_desfire_cmd(&apdu, true, NONE, &recv_len, &sw, sizeof(dfname_t), true); if (res != PM3_SUCCESS) { - PrintAndLogEx(WARNING, _RED_(" Can't select AID 0x%X -> %s"), (aid[0] << 16) + (aid[1] << 8) + aid[2], GetErrorString(res, &sw)); + PrintAndLogEx(WARNING, _RED_(" Can't select AID 0x%X -> %s"), (aid[2] << 16) + (aid[1] << 8) + aid[0], GetErrorString(res, &sw)); DropField(); return res; } @@ -868,26 +868,37 @@ int getKeySettings(uint8_t *aid) { return PM3_SUCCESS; } +static void swap24(uint8_t* data){ + if (data==NULL) return; + uint8_t tmp=data[0]; + data[0]=data[2]; + data[2]=tmp; +}; + +static void swap16(uint8_t* data){ + if (data==NULL) return; + uint8_t tmp=data[0]; + data[0]=data[1]; + data[1]=tmp; +}; + static int CmdHF14ADesCreateApp(const char *Cmd) { - clearCommandBuffer(); - CLIParserInit("hf mfdes createaid", "Create Application ID", - "Usage:\n\t-m Auth type (1=normal, 2=iso, 3=aes)\n\t-t Crypt algo (1=DES, 2=3DES, 3=3K3DES, 4=aes)\n\t-a aid (3 bytes)\n\t-n keyno\n\t-k key (8-24 bytes)\n\n" - "Example:\n\thf mfdes createaid -a 123456 -f 1122 -k 0F -l 2E -n AppName\n" + "Usage:\n\thf mfdes createaid -a 123456 -f 1122 -k 0F -l 2E -n AppName\n" ); void *argtable[] = { arg_param_begin, - arg_strx0("aA", "aid", "", "App ID to create"), - arg_strx0("fF", "fid", "", "File ID"), + arg_strx0("aA", "aid", "", "App ID to create as hex bytes ("), + arg_strx0("fF", "fid", "", "File ID to create"), arg_strx0("kK", "keysetting1", "", "Key Setting 1 (Application Master Key Settings)"), arg_strx0("lL", "keysetting2", "", "Key Setting 2"), arg_str0("nN", "name", "", "App ISO-4 Name"), arg_param_end }; - CLIExecWithReturn(Cmd, argtable, true); + CLIExecWithReturn(Cmd, argtable, false); /* KeySetting 1 (AMK Setting): 0: Allow change master key 1: Free Directory list access without master key @@ -927,7 +938,9 @@ static int CmdHF14ADesCreateApp(const char *Cmd) { int keylen2 = 1; int namelen = 16; CLIGetHexWithReturn(1, aid, &aidlength); + swap24(aid); CLIGetHexWithReturn(2, fid, &fidlength); + swap16(fid); CLIGetHexWithReturn(3, &keysetting1, &keylen1); CLIGetHexWithReturn(4, &keysetting2, &keylen2); CLIGetStrWithReturn(5, name, &namelen); @@ -935,27 +948,27 @@ static int CmdHF14ADesCreateApp(const char *Cmd) { if (aidlength < 3) { PrintAndLogEx(ERR, "AID must have 3 bytes length."); - return PM3_EINVARG; + return PM3_SNONCES; } if (fidlength < 2) { PrintAndLogEx(ERR, "FID must have 2 bytes length."); - return PM3_EINVARG; + return PM3_SNONCES; } if (keylen1 < 1) { PrintAndLogEx(ERR, "Keysetting1 must have 1 byte length."); - return PM3_EINVARG; + return PM3_SNONCES; } if (keylen1 < 1) { PrintAndLogEx(ERR, "Keysetting2 must have 1 byte length."); - return PM3_EINVARG; + return PM3_SNONCES; } if (namelen > 16) { PrintAndLogEx(ERR, "Name has a max. of 16 bytes length."); - return PM3_EINVARG; + return PM3_SNONCES; } //90 ca 00 00 0e 3cb849 09 22 10e1 d27600 00850101 00 @@ -985,8 +998,6 @@ static int CmdHF14ADesCreateApp(const char *Cmd) { } static int CmdHF14ADesDeleteApp(const char *Cmd) { - clearCommandBuffer(); - CLIParserInit("hf mfdes deleteaid", "Delete Application ID", "Usage:\n\t-a aid (3 bytes)\n\n" @@ -998,7 +1009,7 @@ static int CmdHF14ADesDeleteApp(const char *Cmd) { arg_strx0("aA", "aid", "", "App ID to delete"), arg_param_end }; - CLIExecWithReturn(Cmd, argtable, true); + CLIExecWithReturn(Cmd, argtable, false); int aidlength = 3; uint8_t aid[3] = {0}; CLIGetHexWithReturn(1, aid, &aidlength); @@ -1006,7 +1017,7 @@ static int CmdHF14ADesDeleteApp(const char *Cmd) { if (aidlength < 3) { PrintAndLogEx(ERR, "AID must have 3 bytes length."); - return PM3_EINVARG; + return PM3_SNONCES; } if (memcmp(aid, "\x00\x00\x00", 3) == 0) { @@ -1022,7 +1033,6 @@ static int CmdHF14ADesDeleteApp(const char *Cmd) { static int CmdHF14ADesFormatPICC(const char *Cmd) { - (void) Cmd; // Cmd is not used so far CLIParserInit("hf mfdes formatpicc", "Formats MIFARE DESFire PICC to factory state", "Usage:\n\t-k PICC key (8 bytes)\n\n" @@ -1034,7 +1044,7 @@ static int CmdHF14ADesFormatPICC(const char *Cmd) { arg_str0("kK", "key", "", "Key for checking (HEX 16 bytes)"), arg_param_end }; - CLIExecWithReturn(Cmd, argtable, true); + CLIExecWithReturn(Cmd, argtable, false); uint8_t key[8] = {0}; int keylen = 8; @@ -1043,11 +1053,9 @@ static int CmdHF14ADesFormatPICC(const char *Cmd) { if ((keylen < 8) || (keylen > 8)) { PrintAndLogEx(ERR, "Specified key must have 8 bytes length."); - //SetAPDULogging(false); - return PM3_EINVARG; + return PM3_SNONCES; } - clearCommandBuffer(); DropField(); uint8_t aid[3] = {0}; int res = get_desfire_select_application(aid); @@ -1402,10 +1410,10 @@ static int CmdHF14ADesEnumApplications(const char *Cmd) { PrintAndLogEx(SUCCESS, "--- " _CYAN_("AMK - Application Master Key settings")); } - PrintAndLogEx(SUCCESS, " AID : " _GREEN_("%02X %02X %02X"), aid[0], aid[1], aid[2]); + PrintAndLogEx(SUCCESS, " AID : " _GREEN_("%02X%02X%02X"), aid[2], aid[1], aid[0]); for (int m = 0; m < dfname_count; m++) { if (dfnames[m].aid[0] == aid[0] && dfnames[m].aid[1] == aid[1] && dfnames[m].aid[2] == aid[2]) { - PrintAndLogEx(SUCCESS, " - DF " _YELLOW_("%02X %02X") " Name : " _YELLOW_("%s"), dfnames[m].fid[0], dfnames[m].fid[1], dfnames[m].name); + PrintAndLogEx(SUCCESS, " - DF " _YELLOW_("%02X%02X") " Name : " _YELLOW_("%s"), dfnames[m].fid[1], dfnames[m].fid[0], dfnames[m].name); } } @@ -1467,7 +1475,6 @@ static int CmdHF14ADesEnumApplications(const char *Cmd) { static int CmdHF14ADesAuth(const char *Cmd) { int res = 0; DropField(); - clearCommandBuffer(); // NR DESC KEYLENGHT // ------------------------ // 1 = DES 8 @@ -1491,7 +1498,7 @@ static int CmdHF14ADesAuth(const char *Cmd) { arg_str0("kK", "key", "", "Key for checking (HEX 16 bytes)"), arg_param_end }; - CLIExecWithReturn(Cmd, argtable, true); + CLIExecWithReturn(Cmd, argtable, false); uint8_t cmdAuthMode = arg_get_int_def(1, 0); uint8_t cmdAuthAlgo = arg_get_int_def(2, 0); @@ -1509,37 +1516,37 @@ static int CmdHF14ADesAuth(const char *Cmd) { if ((keylen < 8) || (keylen > 24)) { PrintAndLogEx(ERR, "Specified key must have 16 bytes length."); - return PM3_EINVARG; + return PM3_SNONCES; } // AID if (aidlength != 3) { PrintAndLogEx(WARNING, "aid must include %d HEX symbols", 3); - return PM3_EINVARG; + return PM3_SNONCES; } switch (cmdAuthMode) { case 1: if (cmdAuthAlgo != 1 && cmdAuthAlgo != 2) { PrintAndLogEx(NORMAL, "Crypto algo not valid for the auth mode"); - return PM3_EINVARG; + return PM3_SNONCES; } break; case 2: if (cmdAuthAlgo != 1 && cmdAuthAlgo != 2 && cmdAuthAlgo != 3) { PrintAndLogEx(NORMAL, "Crypto algo not valid for the auth mode"); - return PM3_EINVARG; + return PM3_SNONCES; } break; case 3: if (cmdAuthAlgo != 4) { PrintAndLogEx(NORMAL, "Crypto algo not valid for the auth mode"); - return PM3_EINVARG; + return PM3_SNONCES; } break; default: PrintAndLogEx(WARNING, "Wrong Auth mode (%d) -> (1=normal, 2=iso, 3=aes)", cmdAuthMode); - return PM3_EINVARG; + return PM3_SNONCES; } switch (cmdAuthAlgo) { @@ -1565,7 +1572,7 @@ static int CmdHF14ADesAuth(const char *Cmd) { // KEY if (keylen != keylength) { PrintAndLogEx(WARNING, "Key must include %d HEX symbols", keylength); - return PM3_EINVARG; + return PM3_SNONCES; } @@ -1646,7 +1653,6 @@ static int CmdHelp(const char *Cmd) { } int CmdHFMFDes(const char *Cmd) { - // flush clearCommandBuffer(); return CmdsParse(CommandTable, Cmd); } From 327d8a8bfe2742fca14bd59bdf051bc15ea67c8e Mon Sep 17 00:00:00 2001 From: Bjoern Kerler Date: Sat, 11 Apr 2020 01:38:47 +0200 Subject: [PATCH 08/16] Further aid and auth info fixes --- client/cmdhfmfdes.c | 16 ++++++++++++++-- 1 file changed, 14 insertions(+), 2 deletions(-) diff --git a/client/cmdhfmfdes.c b/client/cmdhfmfdes.c index 6d8dc5cf0..0c7f6b621 100644 --- a/client/cmdhfmfdes.c +++ b/client/cmdhfmfdes.c @@ -1493,7 +1493,7 @@ static int CmdHF14ADesAuth(const char *Cmd) { arg_param_begin, arg_int0("mM", "type", "Auth type (1=normal, 2=iso, 3=aes)", NULL), arg_int0("tT", "algo", "Crypt algo (1=DES, 2=3DES, 3=3K3DES, 4=aes)", NULL), - arg_strx0("aA", "aid", "", "AID used for authentification"), + arg_strx0("aA", "aid", "", "AID used for authentification (HEX 3 bytes)"), arg_int0("nN", "keyno", "Key number used for authentification", NULL), arg_str0("kK", "key", "", "Key for checking (HEX 16 bytes)"), arg_param_end @@ -1506,7 +1506,7 @@ static int CmdHF14ADesAuth(const char *Cmd) { int aidlength = 3; uint8_t aid[3] = {0}; CLIGetHexWithReturn(3, aid, &aidlength); - + swap16(aid); uint8_t cmdKeyNo = arg_get_int_def(4, 0); uint8_t key[24] = {0}; @@ -1643,6 +1643,18 @@ static command_t CommandTable[] = { {"formatpicc", CmdHF14ADesFormatPICC, IfPm3Iso14443a, "Format PICC"}, // {"rdbl", CmdHF14ADesRb, IfPm3Iso14443a, "Read MIFARE DesFire block"}, // {"wrbl", CmdHF14ADesWb, IfPm3Iso14443a, "write MIFARE DesFire block"}, +/* + ISO/IEC 7816 Cmds + 'A4' Select + 'B0' Read Binary + 'D6' Update Binary + 'B2' Read Records + 'E2' Append Records + '84' Get Challenge + '88' Internal Authenticate + '82' External Authenticate + +*/ {NULL, NULL, NULL, NULL} }; From fceae52e68433a36b4e2809808d951971da71624 Mon Sep 17 00:00:00 2001 From: Bjoern Kerler Date: Sat, 11 Apr 2020 01:39:24 +0200 Subject: [PATCH 09/16] Add 3K3 basic support --- armsrc/des.c | 100 ++++++++++++++++++++++++++++++++++++++------------- armsrc/des.h | 2 ++ 2 files changed, 78 insertions(+), 24 deletions(-) diff --git a/armsrc/des.c b/armsrc/des.c index ccd32be7d..af10423f3 100644 --- a/armsrc/des.c +++ b/armsrc/des.c @@ -388,30 +388,6 @@ void tdes_dec(void *out, void *in, const uint8_t *key) { des_dec(out, out, (uint8_t *)key + 0); } -void tdes_2key_enc(void *out, const void *in, size_t length, const void *key, unsigned char iv[8]) { - - if (length % 8) return; - - uint8_t i; - uint8_t *tin = (uint8_t *) in; - uint8_t *tout = (uint8_t *) out; - - while (length > 0) { - for (i = 0; i < 8; i++) - tout[i] = (unsigned char)(tin[i] ^ iv[i]); - - des_enc(tout, tin, (uint8_t *)key + 0); - des_dec(tout, tout, (uint8_t *)key + 8); - des_enc(tout, tout, (uint8_t *)key + 0); - - memcpy(iv, tout, 8); - - tin += 8; - tout += 8; - length -= 8; - } -} - void tdes_2key_dec(void *out, const void *in, size_t length, const void *key, unsigned char iv[8]) { if (length % 8) return; @@ -439,6 +415,82 @@ void tdes_2key_dec(void *out, const void *in, size_t length, const void *key, un } } +void tdes_2key_enc(void *out, const void *in, size_t length, const void *key, unsigned char iv[8]) { + + if (length % 8) return; + + uint8_t i; + uint8_t *tin = (uint8_t *) in; + uint8_t *tout = (uint8_t *) out; + + while (length > 0) { + for (i = 0; i < 8; i++) + tout[i] = (unsigned char)(tin[i] ^ iv[i]); + + des_enc(tout, tin, (uint8_t *)key + 0); + des_dec(tout, tout, (uint8_t *)key + 8); + des_enc(tout, tout, (uint8_t *)key + 0); + + memcpy(iv, tout, 8); + + tin += 8; + tout += 8; + length -= 8; + } +} + +void tdes_3key_enc(void *out, const void *in, size_t length, const void *key, unsigned char iv[8]) { + + if (length % 8) return; + + uint8_t i; + uint8_t *tin = (uint8_t *) in; + uint8_t *tout = (uint8_t *) out; + + while (length > 0) { + for (i = 0; i < 8; i++) + tout[i] = (unsigned char)(tin[i] ^ iv[i]); + + des_enc(tout, tin, (uint8_t *)key + 0); + des_dec(tout, tout, (uint8_t *)key + 8); + des_enc(tout, tout, (uint8_t *)key + 16); + + memcpy(iv, tout, 8); + + tin += 8; + tout += 8; + length -= 8; + } +} + +void tdes_3key_dec(void *out, const void *in, size_t length, const void *key, unsigned char iv[8]) { + + if (length % 8) return; + + 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); + + des_dec(tout, tin, (uint8_t *)key + 0); + des_enc(tout, tout, (uint8_t *)key + 8); + des_dec(tout, tout, (uint8_t *)key + 16); + + for (i = 0; i < 8; i++) + tout[i] = (unsigned char)(tout[i] ^ iv[i]); + + memcpy(iv, temp, 8); + + tin += 8; + tout += 8; + length -= 8; + } +} + + /******************************************************************************/ diff --git a/armsrc/des.h b/armsrc/des.h index 8cf41b8ae..1a0549606 100644 --- a/armsrc/des.h +++ b/armsrc/des.h @@ -104,6 +104,8 @@ void tdes_dec(void *out, void *in, const uint8_t *key); void tdes_2key_enc(void *out, const void *in, size_t length, const void *key, unsigned char iv[8]); void tdes_2key_dec(void *out, const void *in, size_t length, const void *key, unsigned char iv[8]); +void tdes_3key_enc(void *out, const void *in, size_t length, const void *key, unsigned char iv[8]); +void tdes_3key_dec(void *out, const void *in, size_t length, const void *key, unsigned char iv[8]); // Copied from des.h in desfire imp. typedef unsigned long DES_KS[16][2]; /* Single-key DES key schedule */ From 9b26fab1c2926335a5ea92e8cdb0d1e511c536f4 Mon Sep 17 00:00:00 2001 From: Bjoern Kerler Date: Sat, 11 Apr 2020 01:41:39 +0200 Subject: [PATCH 10/16] Further auth info fixes --- client/cmdhfmfdes.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/client/cmdhfmfdes.c b/client/cmdhfmfdes.c index 0c7f6b621..51acf8a5e 100644 --- a/client/cmdhfmfdes.c +++ b/client/cmdhfmfdes.c @@ -1491,7 +1491,7 @@ static int CmdHF14ADesAuth(const char *Cmd) { void *argtable[] = { arg_param_begin, - arg_int0("mM", "type", "Auth type (1=normal, 2=iso, 3=aes)", NULL), + arg_int0("mM", "type", "Auth type (1=normal, 2=iso, 3=aes, 4=picc)", NULL), arg_int0("tT", "algo", "Crypt algo (1=DES, 2=3DES, 3=3K3DES, 4=aes)", NULL), arg_strx0("aA", "aid", "", "AID used for authentification (HEX 3 bytes)"), arg_int0("nN", "keyno", "Key number used for authentification", NULL), From 4c2f98ac3d87574afc27f75fc35f2c19754df729 Mon Sep 17 00:00:00 2001 From: Bjoern Kerler Date: Sat, 11 Apr 2020 02:32:55 +0200 Subject: [PATCH 11/16] Add first 3K3 support. Improve algo error handling --- armsrc/mifaredesfire.c | 65 ++++++++++++++++++++++++-------- client/cmdhfmfdes.c | 84 +++++++++++++++++++++--------------------- 2 files changed, 92 insertions(+), 57 deletions(-) diff --git a/armsrc/mifaredesfire.c b/armsrc/mifaredesfire.c index af902e868..3543bcc3a 100644 --- a/armsrc/mifaredesfire.c +++ b/armsrc/mifaredesfire.c @@ -132,7 +132,7 @@ void MifareDesfireGetInformation() { clear_trace(); set_tracing(true); iso14443a_setup(FPGA_HF_ISO14443A_READER_LISTEN); - + // reset the pcb_blocknum, pcb_blocknum = 0; @@ -259,6 +259,7 @@ void MifareDES_Auth1(uint8_t *datain) { // Default Keys uint8_t PICC_MASTER_KEY8[8] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; uint8_t PICC_MASTER_KEY16[16] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; + uint8_t PICC_MASTER_KEY24[24] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; //uint8_t null_key_data16[16] = {0x00}; //uint8_t new_key_data8[8] = { 0x00,0x11,0x22,0x33,0x44,0x55,0x66,0x77}; //uint8_t new_key_data16[16] = { 0x00,0x11,0x22,0x33,0x44,0x55,0x66,0x77,0x88,0x99,0xAA,0xBB,0xCC,0xDD,0xEE,0xFF}; @@ -272,10 +273,12 @@ void MifareDES_Auth1(uint8_t *datain) { LED_C_OFF(); if (payload->key == NULL) { - if (payload->mode == MFDES_AUTH_DES || payload->mode == MFDES_AUTH_PICC) { + if (payload->algo == MFDES_AUTH_DES) { memcpy(keybytes, PICC_MASTER_KEY8, 8); - } else if (payload->mode == MFDES_AUTH_AES) { + } else if (payload->algo == MFDES_ALGO_AES || payload->algo == MFDES_ALGO_3DES) { memcpy(keybytes, PICC_MASTER_KEY16, 16); + } else if (payload->algo == MFDES_ALGO_3DES) { + memcpy(keybytes, PICC_MASTER_KEY24, 24); } } else { memcpy(keybytes, payload->key, payload->keylen); @@ -334,6 +337,20 @@ void MifareDES_Auth1(uint8_t *datain) { return; } + int expectedlen = 1 + 8 + 2 + 2; + if (payload->algo == MFDES_ALGO_AES || payload->algo == MFDES_ALGO_3K3DES) { + expectedlen = 1 + 16 + 2 + 2; + } + + if (len != expectedlen) { + if (DBGLEVEL >= DBG_ERROR) { + DbpString("Authentication failed. Length of answer doesn't match algo."); + print_result("Res-Buffer: ", resp, len); + } + OnErrorNG(CMD_HF_DESFIRE_AUTH1, 3); + return; + } + // Part 2 if (payload->mode != MFDES_AUTH_PICC) { memcpy(encRndB, resp + 1, payload->keylen); @@ -355,6 +372,8 @@ void MifareDES_Auth1(uint8_t *datain) { tdes_dec(&RndB, &encRndB, key->data); else if (payload->algo == MFDES_ALGO_DES) des_dec(&RndB, &encRndB, key->data); + else if (payload->algo == MFDES_ALGO_3K3DES) + tdes_3key_dec(&RndB, &encRndB, 16, key->data, IV); // - Rotate RndB by 8 bits memcpy(rotRndB, RndB, payload->keylen); @@ -363,25 +382,35 @@ void MifareDES_Auth1(uint8_t *datain) { uint8_t encRndA[16] = {0x00}; // - Encrypt our response - if (payload->mode == MFDES_AUTH_DES || payload->mode == MFDES_AUTH_PICC) { - if (payload->algo == MFDES_ALGO_3DES) + if (payload->mode == MFDES_AUTH_DES || payload->mode == MFDES_AUTH_ISO || payload->mode == MFDES_AUTH_PICC) { + if (payload->algo == MFDES_ALGO_3DES) { tdes_dec(&encRndA, &RndA, key->data); - else if (payload->algo == MFDES_ALGO_DES) + memcpy(both, encRndA, 8); + } else if (payload->algo == MFDES_ALGO_DES) { des_dec(&encRndA, &RndA, key->data); + memcpy(both, encRndA, 8); + } else if (payload->algo == MFDES_ALGO_3K3DES) { + tdes_3key_dec(&encRndA, &RndA, 16, key->data, IV); + memcpy(both, encRndA, 16); + } - memcpy(both, encRndA, 8); for (int x = 0; x < 8; x++) { rotRndB[x] = rotRndB[x] ^ encRndA[x]; } - if (payload->algo == MFDES_ALGO_3DES) + if (payload->algo == MFDES_ALGO_3DES) { tdes_dec(&encRndB, &rotRndB, key->data); - else if (payload->algo == MFDES_ALGO_DES) + memcpy(both + 8, encRndB, 8); + } else if (payload->algo == MFDES_ALGO_DES) { des_dec(&encRndB, &rotRndB, key->data); + memcpy(both + 8, encRndB, 8); + } else if (payload->algo == MFDES_ALGO_3K3DES) { + tdes_3key_dec(&encRndB, &rotRndB, 16, key->data, IV); + memcpy(both + 16, encRndB, 16); + } - memcpy(both + 8, encRndB, 8); - } else if (payload->mode == MFDES_AUTH_AES || payload->mode == MFDES_AUTH_ISO) { + } else if (payload->mode == MFDES_AUTH_AES) { uint8_t tmp[32] = {0x00}; memcpy(tmp, RndA, 16); memcpy(tmp + 16, rotRndB, 16); @@ -397,15 +426,19 @@ void MifareDES_Auth1(uint8_t *datain) { } } + int bothlen = 16; + if (payload->algo == MFDES_ALGO_AES || payload->algo == MFDES_ALGO_3K3DES) { + bothlen = 32; + } if (payload->mode != MFDES_AUTH_PICC) { cmd[0] = 0x90; cmd[1] = ADDITIONAL_FRAME; cmd[2] = 0x00; cmd[3] = 0x00; - cmd[4] = (payload->keylen * 2); - memcpy(cmd + 5, both, payload->keylen * 2); - cmd[(payload->keylen * 2) + 5] = 0x0; - len = DesfireAPDU(cmd, 5 + (payload->keylen * 2) + 1, resp); + cmd[4] = bothlen; + memcpy(cmd + 5, both, bothlen); + cmd[bothlen + 5] = 0x0; + len = DesfireAPDU(cmd, 5 + bothlen + 1, resp); } else { cmd[0] = ADDITIONAL_FRAME; memcpy(cmd + 1, both, 16); @@ -452,6 +485,8 @@ void MifareDES_Auth1(uint8_t *datain) { tdes_dec(&encRndA, &encRndA, key->data); else if (payload->algo == MFDES_ALGO_DES) des_dec(&encRndA, &encRndA, key->data); + else if (payload->algo == MFDES_ALGO_3K3DES) + tdes_3key_dec(&encRndA, &encRndA, 16, key->data, IV); } else if (payload->mode == MFDES_AUTH_AES) { if (mbedtls_aes_setkey_dec(&ctx, key->data, 128) != 0) { if (DBGLEVEL >= DBG_EXTENDED) { diff --git a/client/cmdhfmfdes.c b/client/cmdhfmfdes.c index 51acf8a5e..d43c2a654 100644 --- a/client/cmdhfmfdes.c +++ b/client/cmdhfmfdes.c @@ -92,13 +92,13 @@ static char *getCardSizeStr(uint8_t fsize) { static char *getProtocolStr(uint8_t id, bool hw) { - static char buf[50] = {0x00}; + static char buf[50] = {0x00}; char *retStr = buf; if (id == 0x04) { sprintf(retStr, "0x%02X ( " _YELLOW_("ISO 14443-3 MIFARE, 14443-4") ")", id); } else if (id == 0x05) { - if (hw) + if (hw) sprintf(retStr, "0x%02X ( " _YELLOW_("ISO 14443-2, 14443-3") ")", id); else sprintf(retStr, "0x%02X ( " _YELLOW_("ISO 14443-3, 14443-4") ")", id); @@ -308,7 +308,7 @@ static char *GetErrorString(int res, uint16_t *sw) { static int send_desfire_cmd(sAPDU *apdu, bool select, uint8_t *dest, int *recv_len, uint16_t *sw, int splitbysize, bool readalldata) { if (apdu == NULL) { - PrintAndLogEx(DEBUG, "APDU=NULL"); + PrintAndLogEx(DEBUG, "APDU=NULL"); return PM3_EINVARG; } /*if (dest == NULL) { @@ -362,7 +362,7 @@ static int send_desfire_cmd(sAPDU *apdu, bool select, uint8_t *dest, int *recv_l PrintAndLogEx(DEBUG, "%s", GetErrorString(res, sw)); return res; } - + if (dest != NULL) { if (splitbysize) { memcpy(&dest[i * splitbysize], data, resplen); @@ -376,7 +376,7 @@ static int send_desfire_cmd(sAPDU *apdu, bool select, uint8_t *dest, int *recv_l if (*sw != status(MFDES_ADDITIONAL_FRAME)) break; } - *recv_len = (splitbysize) ? i : pos; + *recv_len = (splitbysize) ? i : pos; return PM3_SUCCESS; } @@ -392,7 +392,7 @@ static nxp_cardtype_t getCardType(uint8_t major, uint8_t minor) { // return DESFIRE_EV3; if (major == 0x30 && minor == 0x00) return DESFIRE_LIGHT; - if (major == 0x11 && minor == 0x00 ) + if (major == 0x11 && minor == 0x00) return PLUS_EV1; return UNKNOWN; @@ -442,12 +442,12 @@ static int get_desfire_freemem(uint32_t *free_mem) { int res = send_desfire_cmd(&apdu, true, fmem, &recv_len, &sw, 0, true); - if (res != PM3_SUCCESS ) + if (res != PM3_SUCCESS) return res; - + if (sw != status(MFDES_S_OPERATION_OK)) return PM3_ESOFT; - + *free_mem = le24toh(fmem); return res; } @@ -587,7 +587,7 @@ static int get_desfire_keysettings(uint8_t *key_settings, uint8_t *num_keys) { uint8_t data[2] = {0}; int res = send_desfire_cmd(&apdu, false, data, &recv_len, &sw, 0, true); - if (res != PM3_SUCCESS ) + if (res != PM3_SUCCESS) return res; if (sw != status(MFDES_S_OPERATION_OK)) return PM3_ESOFT; @@ -612,8 +612,8 @@ static int get_desfire_keyversion(uint8_t curr_key, uint8_t *num_versions) { int recv_len = 0; uint16_t sw = 0; int res = send_desfire_cmd(&apdu, false, num_versions, &recv_len, &sw, 0, true); - - if (res != PM3_SUCCESS ) + + if (res != PM3_SUCCESS) return res; if (sw != status(MFDES_S_OPERATION_OK)) @@ -625,8 +625,8 @@ static int get_desfire_keyversion(uint8_t curr_key, uint8_t *num_versions) { // --- GET APPIDS static int get_desfire_appids(uint8_t *dest, uint8_t *app_ids_len) { if (dest == NULL) { - PrintAndLogEx(DEBUG, "DEST=NULL"); - return PM3_EINVARG; + PrintAndLogEx(DEBUG, "DEST=NULL"); + return PM3_EINVARG; } if (app_ids_len == NULL) { PrintAndLogEx(DEBUG, "APP_IDS_LEN=NULL"); @@ -637,8 +637,8 @@ static int get_desfire_appids(uint8_t *dest, uint8_t *app_ids_len) { int recv_len = 0; uint16_t sw = 0; int res = send_desfire_cmd(&apdu, true, dest, &recv_len, &sw, 0, true); - - if (res != PM3_SUCCESS ) + + if (res != PM3_SUCCESS) return res; if (sw != status(MFDES_S_OPERATION_OK)) @@ -868,18 +868,18 @@ int getKeySettings(uint8_t *aid) { return PM3_SUCCESS; } -static void swap24(uint8_t* data){ - if (data==NULL) return; - uint8_t tmp=data[0]; - data[0]=data[2]; - data[2]=tmp; +static void swap24(uint8_t *data) { + if (data == NULL) return; + uint8_t tmp = data[0]; + data[0] = data[2]; + data[2] = tmp; }; -static void swap16(uint8_t* data){ - if (data==NULL) return; - uint8_t tmp=data[0]; - data[0]=data[1]; - data[1]=tmp; +static void swap16(uint8_t *data) { + if (data == NULL) return; + uint8_t tmp = data[0]; + data[0] = data[1]; + data[1] = tmp; }; @@ -1151,7 +1151,7 @@ static int CmdHF14ADesInfo(const char *Cmd) { } return PM3_ESOFT; } - + nxp_cardtype_t cardtype = getCardType(package->versionHW[3], package->versionHW[4]); if (cardtype == PLUS_EV1) { PrintAndLogEx(INFO, "Card seems to be MIFARE Plus EV1. Try " _YELLOW_("`hf mfp info`")); @@ -1209,7 +1209,7 @@ static int CmdHF14ADesInfo(const char *Cmd) { size_t signature_len = 0; PrintAndLogEx(NORMAL, ""); - PrintAndLogEx(INFO, "--- " _CYAN_("Tag Signature")); + PrintAndLogEx(INFO, "--- " _CYAN_("Tag Signature")); if (get_desfire_signature(signature, &signature_len) == PM3_SUCCESS) { desfire_print_signature(package->uid, signature, signature_len, cardtype); } else { @@ -1322,7 +1322,7 @@ static void DecodeAccessRights(uint16_t accrights) { char *rwa = DecodeAccessValue(read_write_access); if (rwa == NULL) return; - + char *wa = DecodeAccessValue(write_access); if (wa == NULL) return; @@ -1515,7 +1515,7 @@ static int CmdHF14ADesAuth(const char *Cmd) { CLIParserFree(); if ((keylen < 8) || (keylen > 24)) { - PrintAndLogEx(ERR, "Specified key must have 16 bytes length."); + PrintAndLogEx(ERR, "Specified key must have %d bytes length.", keylen); return PM3_SNONCES; } @@ -1621,7 +1621,7 @@ static int CmdHF14ADesAuth(const char *Cmd) { PrintAndLogEx(SUCCESS, " SESSION : " _GREEN_("%s"), sprint_hex(session_key, keylength)); PrintAndLogEx(INFO, "-------------------------------------------------------------"); } else { - PrintAndLogEx(WARNING, _RED_("Client command failed, reason: %d."), resp.status); + PrintAndLogEx(WARNING, _RED_("Auth command failed, reason: %d."), resp.status); } PrintAndLogEx(INFO, "-------------------------------------------------------------"); return PM3_SUCCESS; @@ -1643,18 +1643,18 @@ static command_t CommandTable[] = { {"formatpicc", CmdHF14ADesFormatPICC, IfPm3Iso14443a, "Format PICC"}, // {"rdbl", CmdHF14ADesRb, IfPm3Iso14443a, "Read MIFARE DesFire block"}, // {"wrbl", CmdHF14ADesWb, IfPm3Iso14443a, "write MIFARE DesFire block"}, -/* - ISO/IEC 7816 Cmds - 'A4' Select - 'B0' Read Binary - 'D6' Update Binary - 'B2' Read Records - 'E2' Append Records - '84' Get Challenge - '88' Internal Authenticate - '82' External Authenticate + /* + ISO/IEC 7816 Cmds + 'A4' Select + 'B0' Read Binary + 'D6' Update Binary + 'B2' Read Records + 'E2' Append Records + '84' Get Challenge + '88' Internal Authenticate + '82' External Authenticate -*/ + */ {NULL, NULL, NULL, NULL} }; From 37aa19ad6c1b6cac1f417ee11df09d820edc80f0 Mon Sep 17 00:00:00 2001 From: Bjoern Kerler Date: Sat, 11 Apr 2020 02:56:08 +0200 Subject: [PATCH 12/16] Add 2k3 des iso support preparation --- armsrc/desfire.h | 3 ++- armsrc/desfire_key.c | 15 ++++++++++++++ armsrc/desfire_key.h | 1 + client/cmdhfmfdes.c | 47 +++++++++++++++++++++++++++----------------- 4 files changed, 47 insertions(+), 19 deletions(-) diff --git a/armsrc/desfire.h b/armsrc/desfire.h index e753106e7..507bda424 100644 --- a/armsrc/desfire.h +++ b/armsrc/desfire.h @@ -61,7 +61,8 @@ enum DESFIRE_CRYPTOALGO { T_DES = 0x00, T_3DES = 0x01, T_3K3DES = 0x02, - T_AES = 0x03 + T_AES = 0x03, + T_2K3DES = 0x04 }; diff --git a/armsrc/desfire_key.c b/armsrc/desfire_key.c index 272f18562..d9db46efa 100644 --- a/armsrc/desfire_key.c +++ b/armsrc/desfire_key.c @@ -74,6 +74,14 @@ void Desfire_3k3des_key_new(const uint8_t value[24], desfirekey_t key) { Desfire_3k3des_key_new_with_version(data, key); } +void Desfire_2k3des_key_new_with_version(const uint8_t value[16], desfirekey_t key) { + if (key != NULL) { + key->type = T_2K3DES; + memcpy(key->data, value, 16); + update_key_schedules(key); + } +} + void Desfire_3k3des_key_new_with_version(const uint8_t value[24], desfirekey_t key) { if (key != NULL) { key->type = T_3K3DES; @@ -136,6 +144,13 @@ void Desfire_session_key_new(const uint8_t rnda[], const uint8_t rndb[], desfire memcpy(buffer + 12, rndb + 4, 4); Desfire_3des_key_new_with_version(buffer, key); break; + case T_2K3DES: + memcpy(buffer, rnda, 4); + memcpy(buffer + 4, rndb, 4); + memcpy(buffer + 8, rnda + 4, 4); + memcpy(buffer + 12, rndb + 4, 4); + Desfire_3des_key_new_with_version(buffer, key); + break; case T_3K3DES: memcpy(buffer, rnda, 4); memcpy(buffer + 4, rndb, 4); diff --git a/armsrc/desfire_key.h b/armsrc/desfire_key.h index 603fd5663..286d47178 100644 --- a/armsrc/desfire_key.h +++ b/armsrc/desfire_key.h @@ -9,6 +9,7 @@ void Desfire_des_key_new_with_version(const uint8_t value[8], desfirekey_t key); void Desfire_3des_key_new_with_version(const uint8_t value[16], desfirekey_t key); void Desfire_3k3des_key_new(const uint8_t value[24], desfirekey_t key); void Desfire_3k3des_key_new_with_version(const uint8_t value[24], desfirekey_t key); +void Desfire_2k3des_key_new_with_version(const uint8_t value[16], desfirekey_t key); void Desfire_aes_key_new(const uint8_t value[16], desfirekey_t key); void Desfire_aes_key_new_with_version(const uint8_t value[16], uint8_t version, desfirekey_t key); uint8_t Desfire_key_get_version(desfirekey_t key); diff --git a/client/cmdhfmfdes.c b/client/cmdhfmfdes.c index d43c2a654..afbb0634e 100644 --- a/client/cmdhfmfdes.c +++ b/client/cmdhfmfdes.c @@ -46,8 +46,9 @@ typedef enum { typedef enum { MFDES_ALGO_DES = 1, MFDES_ALGO_3DES = 2, - MFDES_ALGO_3K3DES = 3, - MFDES_ALGO_AES = 4 + MFDES_ALGO_2K3DES = 3, + MFDES_ALGO_3K3DES = 4, + MFDES_ALGO_AES = 5 } mifare_des_authalgo_t; typedef enum { @@ -1485,14 +1486,14 @@ static int CmdHF14ADesAuth(const char *Cmd) { CLIParserInit("hf mfdes auth", "Authenticates Mifare DESFire using Key", - "Usage:\n\t-m Auth type (1=normal, 2=iso, 3=aes)\n\t-t Crypt algo (1=DES, 2=3DES, 3=3K3DES, 4=aes)\n\t-a aid (3 bytes)\n\t-n keyno\n\t-k key (8-24 bytes)\n\n" - "Example:\n\thf mfdes auth -m 3 -t 4 -a 018380 -n 0 -k 404142434445464748494a4b4c4d4e4f\n" + "Usage:\n\t-m Auth type (1=normal, 2=iso, 3=aes)\n\t-t Crypt algo (1=DES, 2=3DES, 3=2K3DES, 4=3K3DES, 5=AES)\n\t-a aid (3 bytes)\n\t-n keyno\n\t-k key (8-24 bytes)\n\n" + "Example:\n\thf mfdes auth -m 3 -t 5 -a 018380 -n 0 -k 00000000000000000000000000000000\n" ); void *argtable[] = { arg_param_begin, arg_int0("mM", "type", "Auth type (1=normal, 2=iso, 3=aes, 4=picc)", NULL), - arg_int0("tT", "algo", "Crypt algo (1=DES, 2=3DES, 3=3K3DES, 4=aes)", NULL), + arg_int0("tT", "algo", "Crypt algo (1=DES, 2=3DES, 3=2K3DES, 4=3K3DES, 5=AES)", NULL), arg_strx0("aA", "aid", "", "AID used for authentification (HEX 3 bytes)"), arg_int0("nN", "keyno", "Key number used for authentification", NULL), arg_str0("kK", "key", "", "Key for checking (HEX 16 bytes)"), @@ -1526,21 +1527,27 @@ static int CmdHF14ADesAuth(const char *Cmd) { } switch (cmdAuthMode) { - case 1: - if (cmdAuthAlgo != 1 && cmdAuthAlgo != 2) { - PrintAndLogEx(NORMAL, "Crypto algo not valid for the auth mode"); + case MFDES_AUTH_DES: + if (cmdAuthAlgo != MFDES_ALGO_DES && cmdAuthAlgo != MFDES_ALGO_3DES) { + PrintAndLogEx(NORMAL, "Crypto algo not valid for the auth des mode"); return PM3_SNONCES; } break; - case 2: - if (cmdAuthAlgo != 1 && cmdAuthAlgo != 2 && cmdAuthAlgo != 3) { - PrintAndLogEx(NORMAL, "Crypto algo not valid for the auth mode"); + case MFDES_AUTH_ISO: + if (cmdAuthAlgo != MFDES_ALGO_2K3DES && cmdAuthAlgo != MFDES_ALGO_3K3DES) { + PrintAndLogEx(NORMAL, "Crypto algo not valid for the auth iso mode"); return PM3_SNONCES; } break; - case 3: - if (cmdAuthAlgo != 4) { - PrintAndLogEx(NORMAL, "Crypto algo not valid for the auth mode"); + case MFDES_AUTH_AES: + if (cmdAuthAlgo != MFDES_ALGO_AES) { + PrintAndLogEx(NORMAL, "Crypto algo not valid for the auth aes mode"); + return PM3_SNONCES; + } + break; + case MFDES_AUTH_PICC: + if (cmdAuthAlgo != MFDES_AUTH_DES) { + PrintAndLogEx(NORMAL, "Crypto algo not valid for the auth picc mode"); return PM3_SNONCES; } break; @@ -1550,20 +1557,24 @@ static int CmdHF14ADesAuth(const char *Cmd) { } switch (cmdAuthAlgo) { - case 2: + case MFDES_ALGO_2K3DES: + keylength = 16; + PrintAndLogEx(NORMAL, "2 key 3DES selected"); + break; + case MFDES_ALGO_3DES: keylength = 16; PrintAndLogEx(NORMAL, "3DES selected"); break; - case 3: + case MFDES_ALGO_3K3DES: keylength = 24; PrintAndLogEx(NORMAL, "3 key 3DES selected"); break; - case 4: + case MFDES_ALGO_AES: keylength = 16; PrintAndLogEx(NORMAL, "AES selected"); break; default: - cmdAuthAlgo = 1; + cmdAuthAlgo = MFDES_ALGO_DES; keylength = 8; PrintAndLogEx(NORMAL, "DES selected"); break; From 6afc8d39a495ed3140d6f0b964ce4f91f8c07cc9 Mon Sep 17 00:00:00 2001 From: Bjoern Kerler Date: Sat, 11 Apr 2020 02:56:48 +0200 Subject: [PATCH 13/16] Add 2k3 des iso support preparation --- armsrc/mifaredesfire.c | 23 +++++++++++++++++------ 1 file changed, 17 insertions(+), 6 deletions(-) diff --git a/armsrc/mifaredesfire.c b/armsrc/mifaredesfire.c index 3543bcc3a..a1da5643d 100644 --- a/armsrc/mifaredesfire.c +++ b/armsrc/mifaredesfire.c @@ -213,8 +213,9 @@ typedef enum { typedef enum { MFDES_ALGO_DES = 1, MFDES_ALGO_3DES = 2, - MFDES_ALGO_3K3DES = 3, - MFDES_ALGO_AES = 4 + MFDES_ALGO_2K3DES = 3, + MFDES_ALGO_3K3DES = 4, + MFDES_ALGO_AES = 5 } mifare_des_authalgo_t; void MifareDES_Auth1(uint8_t *datain) { @@ -273,9 +274,9 @@ void MifareDES_Auth1(uint8_t *datain) { LED_C_OFF(); if (payload->key == NULL) { - if (payload->algo == MFDES_AUTH_DES) { + if (payload->algo == MFDES_AUTH_DES) { memcpy(keybytes, PICC_MASTER_KEY8, 8); - } else if (payload->algo == MFDES_ALGO_AES || payload->algo == MFDES_ALGO_3DES) { + } else if (payload->algo == MFDES_ALGO_AES || payload->algo == MFDES_ALGO_3DES || payload->algo == MFDES_ALGO_2K3DES) { memcpy(keybytes, PICC_MASTER_KEY16, 16); } else if (payload->algo == MFDES_ALGO_3DES) { memcpy(keybytes, PICC_MASTER_KEY24, 24); @@ -291,11 +292,11 @@ void MifareDES_Auth1(uint8_t *datain) { mbedtls_aes_init(&ctx); Desfire_aes_key_new(keybytes, key); } else if (payload->algo == MFDES_ALGO_3DES) { - key->type = T_3DES; Desfire_3des_key_new_with_version(keybytes, key); } else if (payload->algo == MFDES_ALGO_DES) { - key->type = T_DES; Desfire_des_key_new(keybytes, key); + } else if (payload->algo == MFDES_ALGO_2K3DES) { + Desfire_2k3des_key_new_with_version(keybytes, key); } else if (payload->algo == MFDES_ALGO_3K3DES) { Desfire_3k3des_key_new_with_version(keybytes, key); } @@ -372,6 +373,8 @@ void MifareDES_Auth1(uint8_t *datain) { tdes_dec(&RndB, &encRndB, key->data); else if (payload->algo == MFDES_ALGO_DES) des_dec(&RndB, &encRndB, key->data); + else if (payload->algo == MFDES_ALGO_2K3DES) + tdes_2key_dec(&RndB, &encRndB, 8, key->data, IV); else if (payload->algo == MFDES_ALGO_3K3DES) tdes_3key_dec(&RndB, &encRndB, 16, key->data, IV); @@ -389,6 +392,9 @@ void MifareDES_Auth1(uint8_t *datain) { } else if (payload->algo == MFDES_ALGO_DES) { des_dec(&encRndA, &RndA, key->data); memcpy(both, encRndA, 8); + } else if (payload->algo == MFDES_ALGO_2K3DES) { + tdes_2key_dec(&encRndA, &RndA, 8, key->data, IV); + memcpy(both, encRndA, 8); } else if (payload->algo == MFDES_ALGO_3K3DES) { tdes_3key_dec(&encRndA, &RndA, 16, key->data, IV); memcpy(both, encRndA, 16); @@ -405,6 +411,9 @@ void MifareDES_Auth1(uint8_t *datain) { } else if (payload->algo == MFDES_ALGO_DES) { des_dec(&encRndB, &rotRndB, key->data); memcpy(both + 8, encRndB, 8); + } else if (payload->algo == MFDES_ALGO_2K3DES) { + tdes_2key_dec(&encRndB, &rotRndB, 8, key->data, IV); + memcpy(both + 8, encRndB, 8); } else if (payload->algo == MFDES_ALGO_3K3DES) { tdes_3key_dec(&encRndB, &rotRndB, 16, key->data, IV); memcpy(both + 16, encRndB, 16); @@ -485,6 +494,8 @@ void MifareDES_Auth1(uint8_t *datain) { tdes_dec(&encRndA, &encRndA, key->data); else if (payload->algo == MFDES_ALGO_DES) des_dec(&encRndA, &encRndA, key->data); + else if (payload->algo == MFDES_ALGO_2K3DES) + tdes_2key_dec(&encRndA, &encRndA, 8, key->data, IV); else if (payload->algo == MFDES_ALGO_3K3DES) tdes_3key_dec(&encRndA, &encRndA, 16, key->data, IV); } else if (payload->mode == MFDES_AUTH_AES) { From 63c7710976da3c8c29903436eea25bd8038ccb12 Mon Sep 17 00:00:00 2001 From: Bjoern Kerler Date: Sat, 11 Apr 2020 03:05:46 +0200 Subject: [PATCH 14/16] Fix 2k3 key handling --- armsrc/desfire_key.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/armsrc/desfire_key.c b/armsrc/desfire_key.c index d9db46efa..3bab33f50 100644 --- a/armsrc/desfire_key.c +++ b/armsrc/desfire_key.c @@ -147,9 +147,9 @@ void Desfire_session_key_new(const uint8_t rnda[], const uint8_t rndb[], desfire case T_2K3DES: memcpy(buffer, rnda, 4); memcpy(buffer + 4, rndb, 4); - memcpy(buffer + 8, rnda + 4, 4); - memcpy(buffer + 12, rndb + 4, 4); - Desfire_3des_key_new_with_version(buffer, key); + memcpy(buffer + 8, rnda+4, 4); + memcpy(buffer + 12, rndb+4, 4); + Desfire_2k3des_key_new_with_version(buffer, key); break; case T_3K3DES: memcpy(buffer, rnda, 4); From f71e7438f7a23a9fa741b03f3300f7787ab6ae24 Mon Sep 17 00:00:00 2001 From: Bjoern Kerler Date: Sat, 11 Apr 2020 03:10:02 +0200 Subject: [PATCH 15/16] Improve DecodeFileSettings log --- client/cmdhfmfdes.c | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/client/cmdhfmfdes.c b/client/cmdhfmfdes.c index afbb0634e..17ff33410 100644 --- a/client/cmdhfmfdes.c +++ b/client/cmdhfmfdes.c @@ -1359,6 +1359,15 @@ static int DecodeFileSettings(uint8_t *src, int src_len, int maclen) { DecodeAccessRights(accrights); PrintAndLogEx(INFO, " Lower limit: %d - Upper limit: %d - limited credit value: %d - limited credit enabled: %d", lowerlimit, upperlimit, limitcredvalue, limited_credit_enabled); return PM3_SUCCESS; + } else if (src_len == 1 + 1 + 2 + 3 + 3 + 3 + maclen) { + int recordsize = (src[7] << 16) + (src[6] << 8) + src[5]; + int maxrecords = (src[10] << 16) + (src[9] << 8) + src[8]; + int currentrecord = (src[13] << 16) + (src[12] << 8) + src[11]; + DecodeFileType(filetype); + DecodeComSet(comset); + DecodeAccessRights(accrights); + PrintAndLogEx(INFO, " Record size: %d - MaxNumberRecords: %d - Current Number Records: %d", recordsize, maxrecords, currentrecord); + return PM3_SUCCESS; } return PM3_ESOFT; } From 637103224da0ebda1b5165507c232cae97c9ddec Mon Sep 17 00:00:00 2001 From: Bjoern Kerler Date: Sat, 11 Apr 2020 11:32:31 +0200 Subject: [PATCH 16/16] Fixes --- armsrc/desfire_key.c | 5 ++- armsrc/mifaredesfire.c | 80 ++++++++++++++++--------------------- client/cmdhfmfdes.c | 89 +++++++++++++++++------------------------- include/mifare.h | 16 ++++++++ 4 files changed, 88 insertions(+), 102 deletions(-) diff --git a/armsrc/desfire_key.c b/armsrc/desfire_key.c index 3bab33f50..60219260a 100644 --- a/armsrc/desfire_key.c +++ b/armsrc/desfire_key.c @@ -19,6 +19,7 @@ #include "desfire_key.h" #include "string.h" +#include "dbprint.h" static inline void update_key_schedules(desfirekey_t key); @@ -147,8 +148,8 @@ void Desfire_session_key_new(const uint8_t rnda[], const uint8_t rndb[], desfire case T_2K3DES: memcpy(buffer, rnda, 4); memcpy(buffer + 4, rndb, 4); - memcpy(buffer + 8, rnda+4, 4); - memcpy(buffer + 12, rndb+4, 4); + memcpy(buffer + 8, rnda + 4, 4); + memcpy(buffer + 12, rndb + 4, 4); Desfire_2k3des_key_new_with_version(buffer, key); break; case T_3K3DES: diff --git a/armsrc/mifaredesfire.c b/armsrc/mifaredesfire.c index a1da5643d..10a7a3204 100644 --- a/armsrc/mifaredesfire.c +++ b/armsrc/mifaredesfire.c @@ -52,6 +52,11 @@ bool InitDesfireCard() { return true; } +typedef struct { + uint8_t len; + uint8_t data[RECEIVE_SIZE]; +} cmdres_t; + void MifareSendCommand(uint8_t *datain) { struct p { uint8_t flags; @@ -92,15 +97,12 @@ void MifareSendCommand(uint8_t *datain) { //reply_mix(CMD_ACK, 1, len, 0, resp, len); LED_B_ON(); - struct r { - uint8_t len; - uint8_t data[RECEIVE_SIZE]; - } PACKED; - struct r rpayload; + + cmdres_t rpayload; rpayload.len = len; memcpy(rpayload.data, resp, rpayload.len); - reply_ng(CMD_HF_DESFIRE_COMMAND, PM3_SUCCESS, (uint8_t *)&rpayload, sizeof(payload)); + reply_ng(CMD_HF_DESFIRE_COMMAND, PM3_SUCCESS, (uint8_t *)&rpayload, sizeof(rpayload)); LED_B_OFF(); } @@ -203,20 +205,10 @@ void MifareDesfireGetInformation() { OnSuccess(); } -typedef enum { - MFDES_AUTH_DES = 1, - MFDES_AUTH_ISO = 2, - MFDES_AUTH_AES = 3, - MFDES_AUTH_PICC = 4 -} mifare_des_authmode_t; - -typedef enum { - MFDES_ALGO_DES = 1, - MFDES_ALGO_3DES = 2, - MFDES_ALGO_2K3DES = 3, - MFDES_ALGO_3K3DES = 4, - MFDES_ALGO_AES = 5 -} mifare_des_authalgo_t; +typedef struct { + uint8_t sessionkeylen; + uint8_t sessionkey[24]; +} authres_t; void MifareDES_Auth1(uint8_t *datain) { int len = 0; @@ -224,8 +216,8 @@ void MifareDES_Auth1(uint8_t *datain) { uint8_t mode; uint8_t algo; uint8_t keyno; - uint8_t key[24]; uint8_t keylen; + uint8_t key[24]; } PACKED; struct p *payload = (struct p *) datain; @@ -370,13 +362,13 @@ void MifareDES_Auth1(uint8_t *datain) { } mbedtls_aes_crypt_cbc(&ctx, MBEDTLS_AES_DECRYPT, 16, IV, encRndB, RndB); } else if (payload->algo == MFDES_ALGO_3DES) - tdes_dec(&RndB, &encRndB, key->data); + tdes_dec(RndB, encRndB, key->data); else if (payload->algo == MFDES_ALGO_DES) - des_dec(&RndB, &encRndB, key->data); + des_dec(RndB, encRndB, key->data); else if (payload->algo == MFDES_ALGO_2K3DES) - tdes_2key_dec(&RndB, &encRndB, 8, key->data, IV); + tdes_2key_dec(RndB, encRndB, 8, key->data, IV); else if (payload->algo == MFDES_ALGO_3K3DES) - tdes_3key_dec(&RndB, &encRndB, 16, key->data, IV); + tdes_3key_dec(RndB, encRndB, 16, key->data, IV); // - Rotate RndB by 8 bits memcpy(rotRndB, RndB, payload->keylen); @@ -387,16 +379,16 @@ void MifareDES_Auth1(uint8_t *datain) { // - Encrypt our response if (payload->mode == MFDES_AUTH_DES || payload->mode == MFDES_AUTH_ISO || payload->mode == MFDES_AUTH_PICC) { if (payload->algo == MFDES_ALGO_3DES) { - tdes_dec(&encRndA, &RndA, key->data); + tdes_dec(encRndA, RndA, key->data); memcpy(both, encRndA, 8); } else if (payload->algo == MFDES_ALGO_DES) { - des_dec(&encRndA, &RndA, key->data); + des_dec(encRndA, RndA, key->data); memcpy(both, encRndA, 8); } else if (payload->algo == MFDES_ALGO_2K3DES) { - tdes_2key_dec(&encRndA, &RndA, 8, key->data, IV); + tdes_2key_dec(encRndA, RndA, 8, key->data, IV); memcpy(both, encRndA, 8); } else if (payload->algo == MFDES_ALGO_3K3DES) { - tdes_3key_dec(&encRndA, &RndA, 16, key->data, IV); + tdes_3key_dec(encRndA, RndA, 16, key->data, IV); memcpy(both, encRndA, 16); } @@ -406,16 +398,16 @@ void MifareDES_Auth1(uint8_t *datain) { } if (payload->algo == MFDES_ALGO_3DES) { - tdes_dec(&encRndB, &rotRndB, key->data); + tdes_dec(encRndB, rotRndB, key->data); memcpy(both + 8, encRndB, 8); } else if (payload->algo == MFDES_ALGO_DES) { - des_dec(&encRndB, &rotRndB, key->data); + des_dec(encRndB, rotRndB, key->data); memcpy(both + 8, encRndB, 8); } else if (payload->algo == MFDES_ALGO_2K3DES) { - tdes_2key_dec(&encRndB, &rotRndB, 8, key->data, IV); + tdes_2key_dec(encRndB, rotRndB, 8, key->data, IV); memcpy(both + 8, encRndB, 8); } else if (payload->algo == MFDES_ALGO_3K3DES) { - tdes_3key_dec(&encRndB, &rotRndB, 16, key->data, IV); + tdes_3key_dec(encRndB, rotRndB, 16, key->data, IV); memcpy(both + 16, encRndB, 16); } @@ -481,7 +473,7 @@ void MifareDES_Auth1(uint8_t *datain) { desfirekey_t skey = &sessionKey; Desfire_session_key_new(RndA, RndB, key, skey); if (DBGLEVEL >= DBG_EXTENDED) - print_result("SESSIONKEY : ", skey->data, payload->keylen); + print_result("SESSIONKEY : ", sessionKey.data, payload->keylen); if (payload->mode != MFDES_AUTH_PICC) { memcpy(encRndA, resp + 1, payload->keylen); @@ -491,13 +483,13 @@ void MifareDES_Auth1(uint8_t *datain) { if (payload->mode == MFDES_AUTH_DES || payload->mode == MFDES_AUTH_PICC) { if (payload->algo == MFDES_ALGO_3DES) - tdes_dec(&encRndA, &encRndA, key->data); + tdes_dec(encRndA, encRndA, key->data); else if (payload->algo == MFDES_ALGO_DES) - des_dec(&encRndA, &encRndA, key->data); + des_dec(encRndA, encRndA, key->data); else if (payload->algo == MFDES_ALGO_2K3DES) - tdes_2key_dec(&encRndA, &encRndA, 8, key->data, IV); + tdes_2key_dec(encRndA, encRndA, 8, key->data, IV); else if (payload->algo == MFDES_ALGO_3K3DES) - tdes_3key_dec(&encRndA, &encRndA, 16, key->data, IV); + tdes_3key_dec(encRndA, encRndA, 16, key->data, IV); } else if (payload->mode == MFDES_AUTH_AES) { if (mbedtls_aes_setkey_dec(&ctx, key->data, 128) != 0) { if (DBGLEVEL >= DBG_EXTENDED) { @@ -512,6 +504,7 @@ void MifareDES_Auth1(uint8_t *datain) { rol(RndA, payload->keylen); if (DBGLEVEL >= DBG_EXTENDED) { print_result("RndA : ", RndA, payload->keylen); + print_result("RndB: ", RndB, payload->keylen); print_result("encRndA : ", encRndA, payload->keylen); } for (int x = 0; x < payload->keylen; x++) { @@ -618,15 +611,10 @@ void MifareDES_Auth1(uint8_t *datain) { //reply_mix(CMD_ACK, 1, len, 0, resp, len); LED_B_ON(); - struct r { - uint8_t sessionkeylen; - uint8_t sessionkey[24]; - } PACKED; - - struct r rpayload; + authres_t rpayload; rpayload.sessionkeylen = payload->keylen; - memcpy(rpayload.sessionkey, skey->data, rpayload.sessionkeylen); - reply_ng(CMD_HF_DESFIRE_AUTH1, PM3_SUCCESS, (uint8_t *)&rpayload, sizeof(payload)); + memcpy(rpayload.sessionkey, sessionKey.data, rpayload.sessionkeylen); + reply_ng(CMD_HF_DESFIRE_AUTH1, PM3_SUCCESS, (uint8_t *)&rpayload, sizeof(rpayload)); LED_B_OFF(); } diff --git a/client/cmdhfmfdes.c b/client/cmdhfmfdes.c index 17ff33410..6259ac422 100644 --- a/client/cmdhfmfdes.c +++ b/client/cmdhfmfdes.c @@ -34,23 +34,21 @@ uint8_t key_ones_data[16] = { 0x01 }; uint8_t key_defa_data[16] = { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f }; uint8_t key_picc_data[16] = { 0x40, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48, 0x49, 0x4a, 0x4b, 0x4c, 0x4d, 0x4e, 0x4f }; +typedef struct { + uint8_t mode; + uint8_t algo; + uint8_t keyno; + uint8_t keylen; + uint8_t key[24]; +} mfdes_authinput_t; + +typedef struct mfdes_auth_res { + uint8_t sessionkeylen; + uint8_t sessionkey[24]; +} mfdes_auth_res_t; + #define status(x) ( ((uint16_t)(0x91<<8)) + x ) -typedef enum { - MFDES_AUTH_DES = 1, - MFDES_AUTH_ISO = 2, - MFDES_AUTH_AES = 3, - MFDES_AUTH_PICC = 4 -} mifare_des_authmode_t; - -typedef enum { - MFDES_ALGO_DES = 1, - MFDES_ALGO_3DES = 2, - MFDES_ALGO_2K3DES = 3, - MFDES_ALGO_3K3DES = 4, - MFDES_ALGO_AES = 5 -} mifare_des_authalgo_t; - typedef enum { UNKNOWN = 0, DESFIRE_MF3ICD40, @@ -949,27 +947,27 @@ static int CmdHF14ADesCreateApp(const char *Cmd) { if (aidlength < 3) { PrintAndLogEx(ERR, "AID must have 3 bytes length."); - return PM3_SNONCES; + return PM3_EINVARG; } if (fidlength < 2) { PrintAndLogEx(ERR, "FID must have 2 bytes length."); - return PM3_SNONCES; + return PM3_EINVARG; } if (keylen1 < 1) { PrintAndLogEx(ERR, "Keysetting1 must have 1 byte length."); - return PM3_SNONCES; + return PM3_EINVARG; } if (keylen1 < 1) { PrintAndLogEx(ERR, "Keysetting2 must have 1 byte length."); - return PM3_SNONCES; + return PM3_EINVARG; } if (namelen > 16) { PrintAndLogEx(ERR, "Name has a max. of 16 bytes length."); - return PM3_SNONCES; + return PM3_EINVARG; } //90 ca 00 00 0e 3cb849 09 22 10e1 d27600 00850101 00 @@ -1018,7 +1016,7 @@ static int CmdHF14ADesDeleteApp(const char *Cmd) { if (aidlength < 3) { PrintAndLogEx(ERR, "AID must have 3 bytes length."); - return PM3_SNONCES; + return PM3_EINVARG; } if (memcmp(aid, "\x00\x00\x00", 3) == 0) { @@ -1054,20 +1052,15 @@ static int CmdHF14ADesFormatPICC(const char *Cmd) { if ((keylen < 8) || (keylen > 8)) { PrintAndLogEx(ERR, "Specified key must have 8 bytes length."); - return PM3_SNONCES; + return PM3_EINVARG; } DropField(); uint8_t aid[3] = {0}; int res = get_desfire_select_application(aid); if (res != PM3_SUCCESS) return res; - struct { - uint8_t mode; - uint8_t algo; - uint8_t keyno; - uint8_t key[24]; - uint8_t keylen; - } PACKED payload; + + mfdes_authinput_t payload; payload.keylen = keylen; memcpy(payload.key, key, keylen); payload.mode = MFDES_AUTH_PICC; @@ -1496,7 +1489,7 @@ static int CmdHF14ADesAuth(const char *Cmd) { CLIParserInit("hf mfdes auth", "Authenticates Mifare DESFire using Key", "Usage:\n\t-m Auth type (1=normal, 2=iso, 3=aes)\n\t-t Crypt algo (1=DES, 2=3DES, 3=2K3DES, 4=3K3DES, 5=AES)\n\t-a aid (3 bytes)\n\t-n keyno\n\t-k key (8-24 bytes)\n\n" - "Example:\n\thf mfdes auth -m 3 -t 5 -a 018380 -n 0 -k 00000000000000000000000000000000\n" + "Example:\n\thf mfdes auth -m 3 -t 5 -a 838001 -n 0 -k 00000000000000000000000000000000\n" ); void *argtable[] = { @@ -1516,7 +1509,7 @@ static int CmdHF14ADesAuth(const char *Cmd) { int aidlength = 3; uint8_t aid[3] = {0}; CLIGetHexWithReturn(3, aid, &aidlength); - swap16(aid); + swap24(aid); uint8_t cmdKeyNo = arg_get_int_def(4, 0); uint8_t key[24] = {0}; @@ -1526,43 +1519,43 @@ static int CmdHF14ADesAuth(const char *Cmd) { if ((keylen < 8) || (keylen > 24)) { PrintAndLogEx(ERR, "Specified key must have %d bytes length.", keylen); - return PM3_SNONCES; + return PM3_EINVARG; } // AID if (aidlength != 3) { PrintAndLogEx(WARNING, "aid must include %d HEX symbols", 3); - return PM3_SNONCES; + return PM3_EINVARG; } switch (cmdAuthMode) { case MFDES_AUTH_DES: if (cmdAuthAlgo != MFDES_ALGO_DES && cmdAuthAlgo != MFDES_ALGO_3DES) { PrintAndLogEx(NORMAL, "Crypto algo not valid for the auth des mode"); - return PM3_SNONCES; + return PM3_EINVARG; } break; case MFDES_AUTH_ISO: if (cmdAuthAlgo != MFDES_ALGO_2K3DES && cmdAuthAlgo != MFDES_ALGO_3K3DES) { PrintAndLogEx(NORMAL, "Crypto algo not valid for the auth iso mode"); - return PM3_SNONCES; + return PM3_EINVARG; } break; case MFDES_AUTH_AES: if (cmdAuthAlgo != MFDES_ALGO_AES) { PrintAndLogEx(NORMAL, "Crypto algo not valid for the auth aes mode"); - return PM3_SNONCES; + return PM3_EINVARG; } break; case MFDES_AUTH_PICC: if (cmdAuthAlgo != MFDES_AUTH_DES) { PrintAndLogEx(NORMAL, "Crypto algo not valid for the auth picc mode"); - return PM3_SNONCES; + return PM3_EINVARG; } break; default: PrintAndLogEx(WARNING, "Wrong Auth mode (%d) -> (1=normal, 2=iso, 3=aes)", cmdAuthMode); - return PM3_SNONCES; + return PM3_EINVARG; } switch (cmdAuthAlgo) { @@ -1592,7 +1585,7 @@ static int CmdHF14ADesAuth(const char *Cmd) { // KEY if (keylen != keylength) { PrintAndLogEx(WARNING, "Key must include %d HEX symbols", keylength); - return PM3_SNONCES; + return PM3_EINVARG; } @@ -1606,13 +1599,7 @@ static int CmdHF14ADesAuth(const char *Cmd) { if (res != PM3_SUCCESS) return res; } - struct { - uint8_t mode; - uint8_t algo; - uint8_t keyno; - uint8_t key[24]; - uint8_t keylen; - } PACKED payload; + mfdes_authinput_t payload; payload.keylen = keylength; memcpy(payload.key, key, keylength); payload.mode = cmdAuthMode; @@ -1630,15 +1617,9 @@ static int CmdHF14ADesAuth(const char *Cmd) { uint8_t isOK = (resp.status == PM3_SUCCESS); if (isOK) { - struct r { - uint8_t sessionkeylen; - uint8_t sessionkey[24]; - } PACKED; - - struct r *rpayload = (struct r *)&resp.data.asBytes; - uint8_t *session_key = rpayload->sessionkey; + struct mfdes_auth_res *rpayload = (struct mfdes_auth_res *)&resp.data.asBytes; PrintAndLogEx(SUCCESS, " Key : " _GREEN_("%s"), sprint_hex(key, keylength)); - PrintAndLogEx(SUCCESS, " SESSION : " _GREEN_("%s"), sprint_hex(session_key, keylength)); + PrintAndLogEx(SUCCESS, " SESSION : " _GREEN_("%s"), sprint_hex(rpayload->sessionkey, keylength)); PrintAndLogEx(INFO, "-------------------------------------------------------------"); } else { PrintAndLogEx(WARNING, _RED_("Auth command failed, reason: %d."), resp.status); diff --git a/include/mifare.h b/include/mifare.h index b8df9a2ec..5cca91cbc 100644 --- a/include/mifare.h +++ b/include/mifare.h @@ -80,6 +80,22 @@ typedef enum DESFIRE_COMMAND { BAR = 0x10, } desfire_command_t; +typedef enum { + MFDES_AUTH_DES = 1, + MFDES_AUTH_ISO = 2, + MFDES_AUTH_AES = 3, + MFDES_AUTH_PICC = 4 +} mifare_des_authmode_t; + +typedef enum { + MFDES_ALGO_DES = 1, + MFDES_ALGO_3DES = 2, + MFDES_ALGO_2K3DES = 3, + MFDES_ALGO_3K3DES = 4, + MFDES_ALGO_AES = 5 +} mifare_des_authalgo_t; + + //----------------------------------------------------------------------------- // ISO 14443B //-----------------------------------------------------------------------------