From 68faa88e6afcc8e17a13f3ffedd054877b17ef8d Mon Sep 17 00:00:00 2001 From: Bjoern Kerler Date: Fri, 10 Apr 2020 21:02:46 +0200 Subject: [PATCH 01/20] 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/20] 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/20] 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/20] 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/20] 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/20] 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/20] 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/20] 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/20] 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/20] 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/20] 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/20] 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/20] 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/20] 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/20] 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 1900f6b16a822057dbce49a73678856f53ca4934 Mon Sep 17 00:00:00 2001 From: mwalker33 Date: Sat, 11 Apr 2020 17:26:43 +1000 Subject: [PATCH 16/20] Overlay --- client/proxguiqt.cpp | 12 ++++++++---- client/proxmark3.c | 2 +- client/settings.c | 20 ++++++++++++++++++++ client/ui.h | 4 ++++ 4 files changed, 33 insertions(+), 5 deletions(-) diff --git a/client/proxguiqt.cpp b/client/proxguiqt.cpp index dd5fd3f24..4e2c9299f 100644 --- a/client/proxguiqt.cpp +++ b/client/proxguiqt.cpp @@ -210,10 +210,14 @@ ProxWidget::ProxWidget(QWidget *parent, ProxGuiQT *master) : QWidget(parent) { // shows plot window on the screen. show(); - // Move controller widget below plot - controlWidget->move(x(), y() + frameSize().height()); - controlWidget->resize(size().width(), 200); - + if (session.settings_loaded) + controlWidget->setGeometry (session.window_overlay_xpos,session.window_overlay_ypos,session.window_overlay_wsize,session.window_overlay_hsize); + else { + // Move controller widget below plot + controlWidget->move(x(), y() + frameSize().height()); + controlWidget->resize(size().width(), 200); + } + // Olverlays / slider window title QString ct = QString("[*]Slider [ %1 ]").arg((char *)gui_serial_port_name); controlWidget->setWindowTitle(ct); diff --git a/client/proxmark3.c b/client/proxmark3.c index 4d36c490b..c5176dd64 100644 --- a/client/proxmark3.c +++ b/client/proxmark3.c @@ -30,7 +30,7 @@ #include "settings.h" // Used to enable/disable use of settings json file -// #define USE_SETTING_FILE +#define USE_SETTING_FILE static void showBanner(void) { diff --git a/client/settings.c b/client/settings.c index c3cb02ad6..4d59382e2 100644 --- a/client/settings.c +++ b/client/settings.c @@ -64,6 +64,10 @@ int settings_load (void) { session.window_plot_ypos = 30; session.window_plot_hsize = 400; session.window_plot_wsize = 800; + session.window_overlay_xpos = session.window_plot_xpos; + session.window_overlay_ypos = 20+session.window_plot_ypos + session.window_plot_hsize; + session.window_overlay_hsize = 200; + session.window_overlay_wsize = session.window_plot_wsize; session.emoji_mode = ALIAS; session.show_hints = false; session.supports_colors = false; @@ -131,6 +135,12 @@ void settings_save_callback (json_t *root) { JsonSaveInt (root,"window.plot.hsize",session.window_plot_hsize); JsonSaveInt (root,"window.plot.wsize",session.window_plot_wsize); + // Overlay/Slider window + JsonSaveInt (root,"window.overlay.xpos",session.window_overlay_xpos); + JsonSaveInt (root,"window.overlay.ypos",session.window_overlay_ypos); + JsonSaveInt (root,"window.overlay.hsize",session.window_overlay_hsize); + JsonSaveInt (root,"window.overlay.wsize",session.window_overlay_wsize); + // Emoji switch (session.emoji_mode) { case ALIAS: JsonSaveStr (root,"show.emoji","alias"); break; @@ -172,6 +182,16 @@ void settings_load_callback (json_t *root) { if (json_unpack_ex(root,&up_error, 0, "{s:i}","window.plot.wsize",&i1) == 0) session.window_plot_wsize = i1; + // overlay/slider plot + if (json_unpack_ex(root,&up_error, 0, "{s:i}","window.overlay.xpos",&i1) == 0) + session.window_overlay_xpos = i1; + if (json_unpack_ex(root,&up_error, 0, "{s:i}","window.overlay.ypos",&i1) == 0) + session.window_overlay_ypos = i1; + if (json_unpack_ex(root,&up_error, 0, "{s:i}","window.overlay.hsize",&i1) == 0) + session.window_overlay_hsize = i1; + if (json_unpack_ex(root,&up_error, 0, "{s:i}","window.overlay.wsize",&i1) == 0) + session.window_overlay_wsize = i1; + // show options if (json_unpack_ex(root,&up_error, 0, "{s:s}","show.emoji",&s1) == 0) { strncpy (tempStr,s1,sizeof(tempStr)-1); diff --git a/client/ui.h b/client/ui.h index 343b55c1f..e5048e751 100644 --- a/client/ui.h +++ b/client/ui.h @@ -34,6 +34,10 @@ typedef struct { int window_plot_ypos; int window_plot_hsize; int window_plot_wsize; + int window_overlay_xpos; + int window_overlay_ypos; + int window_overlay_hsize; + int window_overlay_wsize; clientdebugLevel_t client_debug_level; } session_arg_t; From 637103224da0ebda1b5165507c232cae97c9ddec Mon Sep 17 00:00:00 2001 From: Bjoern Kerler Date: Sat, 11 Apr 2020 11:32:31 +0200 Subject: [PATCH 17/20] 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 //----------------------------------------------------------------------------- From 0c407504b3adcc831b2f11b8e9fa7549d4c61009 Mon Sep 17 00:00:00 2001 From: Bjoern Kerler Date: Sat, 11 Apr 2020 13:14:16 +0200 Subject: [PATCH 18/20] Fix file ids handling --- client/cmdhfmfdes.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/client/cmdhfmfdes.c b/client/cmdhfmfdes.c index 6259ac422..357d82e65 100644 --- a/client/cmdhfmfdes.c +++ b/client/cmdhfmfdes.c @@ -1434,7 +1434,7 @@ static int CmdHF14ADesEnumApplications(const char *Cmd) { uint8_t filesettings[20] = {0}; int fileset_len = 0; - int res = get_desfire_filesettings(j, filesettings, &fileset_len); + int res = get_desfire_filesettings(file_ids[j], filesettings, &fileset_len); int maclen = 0; // To be implemented if (res == PM3_SUCCESS) { if (DecodeFileSettings(filesettings, fileset_len, maclen) != PM3_SUCCESS) { From c9bd43c4b67264eaa0e996ed8cb3d7d1e58b0cd4 Mon Sep 17 00:00:00 2001 From: mwalker33 Date: Sun, 12 Apr 2020 13:07:25 +1000 Subject: [PATCH 19/20] Edit and Updates Changed from settings to preferences. Added UTF8 Banner support Added Show/Edit draft --- client/Makefile | 2 +- client/cmdmain.c | 7 + client/fileutils.c | 6 +- client/preferences.c | 563 +++++++++++++++++++++++++++ client/{settings.h => preferences.h} | 15 +- client/proxguiqt.cpp | 6 +- client/proxmark3.c | 71 +++- client/settings.c | 211 ---------- client/ui.h | 2 +- 9 files changed, 646 insertions(+), 237 deletions(-) create mode 100644 client/preferences.c rename client/{settings.h => preferences.h} (67%) delete mode 100644 client/settings.c diff --git a/client/Makefile b/client/Makefile index 87cf03a19..e46e51eb2 100644 --- a/client/Makefile +++ b/client/Makefile @@ -253,7 +253,7 @@ CMDSRCS = crapto1/crapto1.c \ wiegand_formats.c \ wiegand_formatutils.c \ cardhelper.c \ - settings.c + preferences.c cpu_arch = $(shell uname -m) ifneq ($(findstring 86, $(cpu_arch)), ) diff --git a/client/cmdmain.c b/client/cmdmain.c index 8d4b1c8b7..906a354f6 100644 --- a/client/cmdmain.c +++ b/client/cmdmain.c @@ -37,6 +37,7 @@ #include "ui.h" #include "util_posix.h" #include "commonutil.h" // ARRAYLEN +#include "preferences.h" static int CmdHelp(const char *Cmd); @@ -241,6 +242,11 @@ static int CmdRev(const char *Cmd) { return PM3_SUCCESS; } +static int CmdPref(const char *Cmd) { + CmdPreferences(Cmd); + return PM3_SUCCESS; +} + static command_t CommandTable[] = { {"help", CmdHelp, AlwaysAvailable, "This help. Use ' help' for details of a particular command."}, {"auto", CmdAuto, IfPm3Present, "Automated detection process for unknown tags"}, @@ -259,6 +265,7 @@ static command_t CommandTable[] = { {"wiegand", CmdWiegand, AlwaysAvailable, "{ Wiegand format manipulation... }"}, {"", CmdHelp, AlwaysAvailable, ""}, {"hints", CmdHints, AlwaysAvailable, "Turn hints on / off"}, + {"pref", CmdPref, AlwaysAvailable, "Edit preferences"}, {"msleep", CmdMsleep, AlwaysAvailable, "Add a pause in milliseconds"}, {"rem", CmdRem, AlwaysAvailable, "Add a text line in log file"}, {"quit", CmdQuit, AlwaysAvailable, ""}, diff --git a/client/fileutils.c b/client/fileutils.c index 05a7e8949..1eb82e57c 100644 --- a/client/fileutils.c +++ b/client/fileutils.c @@ -38,7 +38,7 @@ // this define is needed for scandir/alphasort to work #define _GNU_SOURCE #include "fileutils.h" -#include "settings.h" +#include "preferences.h" #include #include @@ -427,7 +427,7 @@ int saveFileJSON(const char *preferredName, JSONFileType ftype, uint8_t *data, s } break; case jsfSettings: - settings_save_callback (root); + preferences_save_callback (root); break; default: break; @@ -868,7 +868,7 @@ int loadFileJSON(const char *preferredName, void *data, size_t maxdatalen, size_ *datalen = sptr; } if (!strcmp(ctype,"settings")) { - settings_load_callback (root); + preferences_load_callback (root); } PrintAndLogEx(SUCCESS, "loaded from JSON file " _YELLOW_("%s"), fileName); out: diff --git a/client/preferences.c b/client/preferences.c new file mode 100644 index 000000000..18882e912 --- /dev/null +++ b/client/preferences.c @@ -0,0 +1,563 @@ +/***************************************************************************** + * WARNING + * + * THIS CODE IS CREATED FOR EXPERIMENTATION AND EDUCATIONAL USE ONLY. + * + * USAGE OF THIS CODE IN OTHER WAYS MAY INFRINGE UPON THE INTELLECTUAL + * PROPERTY OF OTHER PARTIES, SUCH AS INSIDE SECURE AND HID GLOBAL, + * AND MAY EXPOSE YOU TO AN INFRINGEMENT ACTION FROM THOSE PARTIES. + * + * + ***************************************************************************** + * + * This file is part of loclass. It is a reconstructon of the cipher engine + * used in iClass, and RFID techology. + * + * The implementation is based on the work performed by + * Flavio D. Garcia, Gerhard de Koning Gans, Roel Verdult and + * Milosch Meriac in the paper "Dismantling IClass". + * + * Copyright (C) 2014 Martin Holst Swende + * + * This is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as published + * by the Free Software Foundation, or, at your option, any later version. + * + * This file is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with loclass. If not, see . + * + * + ****************************************************************************/ + +//----------------------------------------------------------------------------- +// Preferences Functions +//----------------------------------------------------------------------------- + +//----------------------------------------------------------------------------- +// Notes +// To add a new setting +// Add the new setting to the session_arg_t; in ui.h +// Add the default value for the setting in the settings_load page below +// Update the preferences_load_callback to load your setting into the stucture +// Update the preferences_save_callback to enusre your setting gets saved when needed. +// use the preference as needed : session. +// Can use (session.preferences_loaded) to check if json settings file was used +//----------------------------------------------------------------------------- + +#include "preferences.h" +#include "comms.h" +#include "emv/emvjson.h" +#include +#include "cmdparser.h" +#include + +static int CmdHelp(const char *Cmd); + +// Load all settings into memory (struct) +int preferences_load (void) { + + // Set all defaults + session.client_debug_level = OFF; + session.window_plot_xpos = 10; + session.window_plot_ypos = 30; + session.window_plot_hsize = 400; + session.window_plot_wsize = 800; + session.window_overlay_xpos = session.window_plot_xpos; + session.window_overlay_ypos = 60+session.window_plot_ypos + session.window_plot_hsize; + session.window_overlay_hsize = 200; + session.window_overlay_wsize = session.window_plot_wsize; + session.emoji_mode = ALIAS; + session.show_hints = false; + session.supports_colors = false; + + // loadFileJson wants these, so pass in place holder values, though not used + // in settings load; + uint8_t dummyData = 0x00; + size_t dummyDL = 0x00; + + if (loadFileJSON(preferencesFilename, &dummyData, sizeof(dummyData), &dummyDL) == PM3_SUCCESS) { + session.preferences_loaded = true; + } + // Note, if session.settings_loaded == false then the settings_save + // will be called in main () to save settings as set in defaults and main() checks. + + return PM3_SUCCESS; +} + +// Save all settings from memory (struct) to file +int preferences_save (void) { + // Note sure if backup has value ? + char backupFilename[500]; + + snprintf (backupFilename,sizeof(backupFilename),"%s.bak",preferencesFilename); + + if (fileExists (backupFilename)) { + if (remove (backupFilename) != 0) { + PrintAndLogEx (FAILED, "Error - could not delete old settings backup file \"%s\"",backupFilename); + return PM3_ESOFT; + } + } + + if (fileExists (preferencesFilename)) { + if (rename (preferencesFilename,backupFilename) != 0) { + PrintAndLogEx (FAILED, "Error - could not backup settings file \"%s\" to \"%s\"",preferencesFilename,backupFilename); + return PM3_ESOFT; + } + } + + uint8_t dummyData = 0x00; + size_t dummyDL = 0x00; + + if (saveFileJSON(preferencesFilename, jsfSettings, &dummyData, dummyDL) != PM3_SUCCESS) + PrintAndLogEx (ERR, "Error saving preferences to \"%s\"",preferencesFilename); + + return PM3_SUCCESS; +} + +void preferences_save_callback (json_t *root) { + + JsonSaveStr (root,"FileType","settings"); + + // Log level, convert to text + switch (session.client_debug_level) { + case OFF: JsonSaveStr (root,"client.debug.level","off"); break; + case SIMPLE: JsonSaveStr (root,"client.debug.level","simple"); break; + case FULL: JsonSaveStr (root,"client.debug.level","full"); break; + default: + JsonSaveStr (root,"logging.level","NORMAL"); + } + + // Plot window + JsonSaveInt (root,"window.plot.xpos",session.window_plot_xpos); + JsonSaveInt (root,"window.plot.ypos",session.window_plot_ypos); + JsonSaveInt (root,"window.plot.hsize",session.window_plot_hsize); + JsonSaveInt (root,"window.plot.wsize",session.window_plot_wsize); + + // Overlay/Slider window + JsonSaveInt (root,"window.overlay.xpos",session.window_overlay_xpos); + JsonSaveInt (root,"window.overlay.ypos",session.window_overlay_ypos); + JsonSaveInt (root,"window.overlay.hsize",session.window_overlay_hsize); + JsonSaveInt (root,"window.overlay.wsize",session.window_overlay_wsize); + + // Emoji + switch (session.emoji_mode) { + case ALIAS: JsonSaveStr (root,"show.emoji","alias"); break; + case EMOJI: JsonSaveStr (root,"show.emoji","emoji"); break; + case ALTTEXT: JsonSaveStr (root,"show.emoji","alttext"); break; + case ERASE: JsonSaveStr (root,"show.emoji","erase"); break; + default: + JsonSaveStr (root,"show.emoji","ALIAS"); + } + + JsonSaveBoolean (root,"show.hints",session.show_hints); + + JsonSaveBoolean (root,"os.supports.colors",session.supports_colors); +} + +void preferences_load_callback (json_t *root) { + json_error_t up_error = {0}; + bool b1; + int i1; + const char *s1; + char tempStr [500]; // to use str_lower() since json unpack uses const char * + + // Logging Level + if (json_unpack_ex(root,&up_error, 0, "{s:s}","client.debug.level",&s1) == 0) { + strncpy (tempStr,s1,sizeof(tempStr)-1); + str_lower (tempStr); + if (strncmp (tempStr,"off",3) == 0) session.client_debug_level = OFF; + if (strncmp (tempStr,"simple",6) == 0) session.client_debug_level = SIMPLE; + if (strncmp (tempStr,"full",4) == 0) session.client_debug_level = FULL; + } + + // window plot + if (json_unpack_ex(root,&up_error, 0, "{s:i}","window.plot.xpos",&i1) == 0) + session.window_plot_xpos = i1; + if (json_unpack_ex(root,&up_error, 0, "{s:i}","window.plot.ypos",&i1) == 0) + session.window_plot_ypos = i1; + if (json_unpack_ex(root,&up_error, 0, "{s:i}","window.plot.hsize",&i1) == 0) + session.window_plot_hsize = i1; + if (json_unpack_ex(root,&up_error, 0, "{s:i}","window.plot.wsize",&i1) == 0) + session.window_plot_wsize = i1; + + // overlay/slider plot + if (json_unpack_ex(root,&up_error, 0, "{s:i}","window.overlay.xpos",&i1) == 0) + session.window_overlay_xpos = i1; + if (json_unpack_ex(root,&up_error, 0, "{s:i}","window.overlay.ypos",&i1) == 0) + session.window_overlay_ypos = i1; + if (json_unpack_ex(root,&up_error, 0, "{s:i}","window.overlay.hsize",&i1) == 0) + session.window_overlay_hsize = i1; + if (json_unpack_ex(root,&up_error, 0, "{s:i}","window.overlay.wsize",&i1) == 0) + session.window_overlay_wsize = i1; + + // show options + if (json_unpack_ex(root,&up_error, 0, "{s:s}","show.emoji",&s1) == 0) { + strncpy (tempStr,s1,sizeof(tempStr)-1); + str_lower (tempStr); + if (strncmp (tempStr,"alias",5) == 0) session.emoji_mode = ALIAS; + if (strncmp (tempStr,"emoji",5) == 0) session.emoji_mode = EMOJI; + if (strncmp (tempStr,"alttext",7) == 0) session.emoji_mode = ALTTEXT; + if (strncmp (tempStr,"erase",5) == 0) session.emoji_mode = ERASE; + } + + if (json_unpack_ex(root,&up_error, 0, "{s:b}","show.hints",&b1) == 0) + session.show_hints = b1; + + if (json_unpack_ex(root,&up_error, 0, "{s:b}","os.supports.colors",&b1) == 0) + session.supports_colors = b1; + +} + +// Help Functions +static int usage_pref_set() { + PrintAndLogEx(NORMAL, "Usage: pref set [(h)elp] [(e)moji ...] [(c)olor ...] [(hi)nts ...] [debug ...]"); + PrintAndLogEx(NORMAL, " [(p)lot ...] [(o)verlay ...]"); + PrintAndLogEx(NORMAL, "Options:"); + PrintAndLogEx(NORMAL, " help - This help"); + PrintAndLogEx(NORMAL, " emoji <(ali)as | (em)oji | (alt)text | (er)ase> - Set the level of emoji support"); + PrintAndLogEx(NORMAL, " alias : show alias"); + PrintAndLogEx(NORMAL, " emoji : show emoji"); + PrintAndLogEx(NORMAL, " alttext : show alternative text"); + PrintAndLogEx(NORMAL, " erase : dont show any emoji"); + + PrintAndLogEx(NORMAL, " color <(o)ff|(a)nsi> - Color support level"); + PrintAndLogEx(NORMAL, " off : dont use color"); + PrintAndLogEx(NORMAL, " ansi : use ansi color (linux, mac, windows terminal)"); + + PrintAndLogEx(NORMAL, " hints <(of)f | on> - Show hints on/off"); + + PrintAndLogEx(NORMAL, " debug <(o)ff | (s)imple | (f)ull> - Client debug level"); + PrintAndLogEx(NORMAL, " off : no debug output"); + PrintAndLogEx(NORMAL, " simple : information level debug"); + PrintAndLogEx(NORMAL, " full : full debug information"); + + PrintAndLogEx(NORMAL, " plot [x ] [y ] [h ] [w ] - Position the plot window"); + PrintAndLogEx(NORMAL, " overlay [x ] [y ] [h ] [w ] - Position the overlay/slider window"); + + return PM3_SUCCESS; +} + +static int usage_pref_show() { + PrintAndLogEx(NORMAL, "Usage: pref show [help] [emoji|color]"); + PrintAndLogEx(NORMAL, "Options:"); + PrintAndLogEx(NORMAL, " help - This help"); + PrintAndLogEx(NORMAL, " emoji - show current settings for emoji"); + PrintAndLogEx(NORMAL, " color - show current settings for color"); + + return PM3_SUCCESS; +} + +// Preference Processing Functions +typedef enum preferenceId {prefNONE,prefHELP,prefEMOJI,prefCOLOR,prefPLOT,prefOVERLAY,prefHINTS,prefCLIENTDEBUG} preferenceId_t; + +// Enumerate text to ID +preferenceId_t prefGetID (char* cmdOpt) +{ + str_lower (cmdOpt); + + if (strncmp (cmdOpt,"hi",2) == 0) return prefHINTS; + if (strncmp (cmdOpt,"h",1) == 0) return prefHELP; + if (strncmp (cmdOpt,"e",1) == 0) return prefEMOJI; + if (strncmp (cmdOpt,"c",1) == 0) return prefCOLOR; + if (strncmp (cmdOpt,"p",1) == 0) return prefPLOT; + if (strncmp (cmdOpt,"o",1) == 0) return prefOVERLAY; + if (strncmp (cmdOpt,"d",1) == 0) return prefCLIENTDEBUG; + + return NONE; +} + +void showEmojiState (void) { + switch (session.emoji_mode) { + case ALIAS: PrintAndLogEx(NORMAL, " emoji.................. "_GREEN_("show alias")); + break; + case EMOJI: PrintAndLogEx(NORMAL, " emoji.................. "_GREEN_("show emoji")); + break; + case ALTTEXT: PrintAndLogEx(NORMAL, " emoji.................. "_GREEN_("show alt text")); + break; + case ERASE: PrintAndLogEx(NORMAL, " emoji.................. "_GREEN_("dont show emoji")); + break; + default: + PrintAndLogEx(NORMAL, " emoji.................. "_RED_("unknown")); + } +} + +void showColorState (void) { +/* + switch (session.supports_colors) { + case false: PrintAndLogEx(NORMAL, "Color : "_GREEN_("off")); + break; + case true: PrintAndLogEx(NORMAL, "Color : "_GREEN_("ansi")); + break; + default: + PrintAndLogEx(NORMAL, "Color support set to : "_RED_("unknown")); + } +*/ + // this will change to 1 of a set from bool + if (session.supports_colors) + PrintAndLogEx(NORMAL, " color.................. "_GREEN_("ansi")); + else + PrintAndLogEx(NORMAL, " color.................. "_GREEN_("off")); +} + +void showClientDebugState (void) { + switch (session.client_debug_level) { + case OFF: PrintAndLogEx (NORMAL," client debug........... "_GREEN_("off")); + break; + case SIMPLE: PrintAndLogEx (NORMAL," client debug........... "_GREEN_("simple")); + break; + case FULL: PrintAndLogEx (NORMAL," client debug........... "_GREEN_("full")); + break; + default: + PrintAndLogEx(NORMAL, " client debug........... "_RED_("unknown")); + } +} + +void showPlotPosState (void){ + PrintAndLogEx (NORMAL," Plot window............ X "_GREEN_("%4d")" Y "_GREEN_("%4d")" H "_GREEN_("%4d")" W "_GREEN_("%4d"), + session.window_plot_xpos,session.window_plot_ypos,session.window_plot_hsize,session.window_plot_wsize); +} + +void showOverlayPosState (void){ + PrintAndLogEx (NORMAL," Slider/Overlay window.. X "_GREEN_("%4d")" Y "_GREEN_("%4d")" H "_GREEN_("%4d")" W "_GREEN_("%4d"), + session.window_overlay_xpos,session.window_overlay_ypos,session.window_overlay_hsize,session.window_overlay_wsize); +} + +void showHintsState (void){ + if (session.show_hints) + PrintAndLogEx (NORMAL," Hints.................. "_GREEN_("on")); + else + PrintAndLogEx (NORMAL," Hints.................. "_GREEN_("off")); +} + +static int CmdPrefShow (const char *Cmd) { + uint8_t cmdp = 0; + preferenceId_t CmdPref; + bool errors = false; + char strOpt[50]; + + PrintAndLogEx(NORMAL,""); + PrintAndLogEx(NORMAL,_BLUE_("Preferences")); + + if (!session. preferences_loaded) { + PrintAndLogEx (ERR,"Preferneces not loaded"); + return PM3_ESOFT; + } + + if (param_getchar(Cmd, cmdp) == 0x00) { // No options - Show all + showEmojiState (); + showColorState (); + showPlotPosState (); + showOverlayPosState (); + showClientDebugState(); + showHintsState (); + } + else { + + while ((param_getchar(Cmd, cmdp) != 0x00) && !errors) { + + if (param_getstr(Cmd, cmdp, strOpt, sizeof(strOpt)) != 0) { + CmdPref = prefGetID(strOpt); + } + else + CmdPref = prefNONE; + + switch (CmdPref) { + case prefHELP: + return usage_pref_show(); + case prefEMOJI: + showEmojiState (); + break; + case prefCOLOR: // color + showColorState (); + break; + case prefPLOT: + showPlotPosState (); + break; + case prefOVERLAY: + showOverlayPosState (); + break; + case prefCLIENTDEBUG: + showClientDebugState(); + break; + case prefHINTS: + showHintsState(); + break; + case prefNONE: + PrintAndLogEx (ERR,"Invalid option supplied"); + errors = true; + break; + // errors + } + cmdp ++; + } + } + PrintAndLogEx(NORMAL,""); + return PM3_SUCCESS; +} + +static int CmdPrefSet (const char *Cmd) +{ + uint8_t cmdp = 0; + preferenceId_t CmdPref; + bool errors = false; + // char charOpt; + char strOpt[50]; + int x,y,h,w; + + if (param_getchar(Cmd, cmdp) == 0x00) + return usage_pref_set(); + + while ((param_getchar(Cmd, cmdp) != 0x00) && !errors) { + + if (param_getstr(Cmd, cmdp, strOpt, sizeof(strOpt)) != 0) { + CmdPref = prefGetID(strOpt); + } + else + CmdPref = prefNONE; + + switch (CmdPref) { + case prefHELP: + return usage_pref_set(); + case prefEMOJI: + showEmojiState (); + cmdp++; + if (param_getstr(Cmd, cmdp, strOpt, sizeof(strOpt)) != 0) { + str_lower(strOpt); + if (strncmp (strOpt,"ali",3) == 0) { session.emoji_mode = ALIAS; showEmojiState (); break; } + if (strncmp (strOpt,"em",2) == 0) { session.emoji_mode = EMOJI; showEmojiState (); break; } + if (strncmp (strOpt,"alt",3) == 0) { session.emoji_mode = ALTTEXT; showEmojiState (); break; } + if (strncmp (strOpt,"er",2) == 0) { session.emoji_mode = ERASE; showEmojiState (); break; } + // if we get this far, then an error in the mode + PrintAndLogEx(ERR,"Invalid emoji option"); + errors = true; + } + else + errors = true; + break; + case prefCOLOR: // color + showColorState (); + cmdp++; + if (param_getstr(Cmd, cmdp, strOpt, sizeof(strOpt)) != 0) { + str_lower(strOpt); + if (strncmp(strOpt,"a",1) == 0) { session.supports_colors = true; showColorState (); break; } + if (strncmp(strOpt,"o",1) == 0) { session.supports_colors = false; showColorState (); break; } + // if we get this far, then an error in the mode + PrintAndLogEx(ERR,"Invalid color option"); + errors = true; + } + else + errors = true; + break; + case prefPLOT: + showPlotPosState (); + cmdp++; + x = y = h = w = -99999; // Some invalid value + for (int i = 0; i < 4; i++) { // upto 4 values X, Y, H, WARNING + if (param_getchar(Cmd, cmdp) != 0){ + switch (tolower(param_getchar(Cmd, cmdp++))) { + case 'x': x = param_get32ex(Cmd,cmdp++,-99999,10); break; + case 'y': y = param_get32ex(Cmd,cmdp++,-99999,10); break; + case 'h': h = param_get32ex(Cmd,cmdp++,-99999,10); break; + case 'w': w = param_get32ex(Cmd,cmdp++,-99999,10); break; + default: + errors = true; + } + } + } + if (x != -99999) session.window_plot_xpos = x; + if (y != -99999) session.window_plot_ypos = y; + if (h != -99999) session.window_plot_hsize = h; + if (w != -99999) session.window_plot_wsize = w; + // Need to work out how to change live.... + // calling data plot seems to work + + showPlotPosState (); + break; + case prefOVERLAY: + showOverlayPosState (); + cmdp++; + x = y = h = w = -99999; // Some invalid value + for (int i = 0; i < 4; i++) { // upto 4 values X, Y, H, WARNING + if (param_getchar(Cmd, cmdp) != 0){ + switch (tolower(param_getchar(Cmd, cmdp++))) { + case 'x': x = param_get32ex(Cmd,cmdp++,-99999,10); break; + case 'y': y = param_get32ex(Cmd,cmdp++,-99999,10); break; + case 'h': h = param_get32ex(Cmd,cmdp++,-99999,10); break; + case 'w': w = param_get32ex(Cmd,cmdp++,-99999,10); break; + default: + errors = true; + } + } + } + if (x != -99999) session.window_overlay_xpos = x; + if (y != -99999) session.window_overlay_ypos = y; + if (h != -99999) session.window_overlay_hsize = h; + if (w != -99999) session.window_overlay_wsize = w; + showOverlayPosState (); + // Need to work out how to change live.... + break; + case prefCLIENTDEBUG: + showClientDebugState(); + cmdp++; + if (param_getstr(Cmd, cmdp, strOpt, sizeof(strOpt)) != 0) { + str_lower(strOpt); + if (strncmp(strOpt,"o",1) == 0) { session.client_debug_level = OFF; g_debugMode = OFF; showClientDebugState(); break; } + if (strncmp(strOpt,"s",1) == 0) { session.client_debug_level = SIMPLE; g_debugMode = SIMPLE; showClientDebugState(); break; } + if (strncmp(strOpt,"f",1) == 0) { session.client_debug_level = FULL; g_debugMode = FULL; showClientDebugState(); break; } + // if we get this far, then an error in the mode + PrintAndLogEx(ERR,"Invalid client debug option"); + errors = true; + } + else + errors = true; + break; + case prefHINTS: + showHintsState (); + cmdp++; + if (param_getstr(Cmd, cmdp, strOpt, sizeof(strOpt)) != 0) { + str_lower(strOpt); + if (strncmp(strOpt,"on",2) == 0) { session.show_hints = true; showHintsState (); break; } + if (strncmp(strOpt,"of",2) == 0) { session.show_hints = false; showHintsState (); break; } + // if we get this far, then an error in the mode + PrintAndLogEx(ERR,"Invalid hint option"); + errors = true; + } + else + errors = true; + break; + case prefNONE: + PrintAndLogEx (ERR,"Invalid option supplied"); + errors = true; + break; + } + cmdp ++; + } + preferences_save(); + return PM3_SUCCESS; +} + +static command_t CommandTable[] = { + {"help", CmdHelp, AlwaysAvailable, "This help"}, + {"set", CmdPrefSet, AlwaysAvailable, "Set a preference"}, + {"show", CmdPrefShow, AlwaysAvailable, "Show (a preference)"}, + {NULL, NULL, NULL, NULL} +}; + +static int CmdHelp(const char *Cmd) { + (void)Cmd; // Cmd is not used so far + CmdsHelp(CommandTable); + + return PM3_SUCCESS; +} + +int CmdPreferences (const char *Cmd) +{ + clearCommandBuffer(); + + return CmdsParse(CommandTable, Cmd); +} \ No newline at end of file diff --git a/client/settings.h b/client/preferences.h similarity index 67% rename from client/settings.h rename to client/preferences.h index c404a82e2..7dce07fc6 100644 --- a/client/settings.h +++ b/client/preferences.h @@ -8,17 +8,18 @@ //----------------------------------------------------------------------------- // Settings Functions //----------------------------------------------------------------------------- -#ifndef SETTINGS_H_ -#define SETTINGS_H_ +#ifndef PREFERENCES_H_ +#define PREFERENCES_H_ #include "fileutils.h" -#define settingsFilename "settings.json" +#define preferencesFilename "preferences.json" -int settings_load (void); -int settings_save (void); +int CmdPreferences (const char *Cmd); +int preferences_load (void); +int preferences_save (void); -void settings_save_callback (json_t *root); -void settings_load_callback (json_t *root); +void preferences_save_callback (json_t *root); +void preferences_load_callback (json_t *root); #endif diff --git a/client/proxguiqt.cpp b/client/proxguiqt.cpp index 4e2c9299f..cbe4ade8d 100644 --- a/client/proxguiqt.cpp +++ b/client/proxguiqt.cpp @@ -170,7 +170,7 @@ void ProxWidget::vchange_dthr_down(int v) { ProxWidget::ProxWidget(QWidget *parent, ProxGuiQT *master) : QWidget(parent) { this->master = master; // Set the initail postion and size from settings - if (session.settings_loaded) + if (session.preferences_loaded) setGeometry (session.window_plot_xpos,session.window_plot_ypos,session.window_plot_wsize,session.window_plot_hsize); else resize(800, 400); @@ -210,14 +210,14 @@ ProxWidget::ProxWidget(QWidget *parent, ProxGuiQT *master) : QWidget(parent) { // shows plot window on the screen. show(); - if (session.settings_loaded) + if (session.preferences_loaded) controlWidget->setGeometry (session.window_overlay_xpos,session.window_overlay_ypos,session.window_overlay_wsize,session.window_overlay_hsize); else { // Move controller widget below plot controlWidget->move(x(), y() + frameSize().height()); controlWidget->resize(size().width(), 200); } - + // Olverlays / slider window title QString ct = QString("[*]Slider [ %1 ]").arg((char *)gui_serial_port_name); controlWidget->setWindowTitle(ct); diff --git a/client/proxmark3.c b/client/proxmark3.c index c5176dd64..bfc7b6212 100644 --- a/client/proxmark3.c +++ b/client/proxmark3.c @@ -27,13 +27,58 @@ #include "comms.h" #include "fileutils.h" #include "flash.h" -#include "settings.h" +#include "preferences.h" -// Used to enable/disable use of settings json file -#define USE_SETTING_FILE +// Used to enable/disable use of preferences json file +// #define USE_PREFERENCE_FILE +#ifdef _WIN32 + +static void utf8_showBanner (void) { + + char sq[] = { 0xE2,0x96,0x88,0x00 }; // square block + char tr[] = { 0xE2,0x95,0x97,0x00 }; // top rigth corner + char tl[] = { 0xE2,0x95,0x94,0x00 }; // top left corner + char br[] = { 0xE2,0x95,0x9D,0x00 }; // bottom right corner + char bl[] = { 0xE2,0x95,0x9A,0x00 }; // bottom left corner + char hl[] = { 0xE2,0x95,0x90,0x00 }; // horiz line + char vl[] = { 0xE2,0x95,0x91,0x00 }; // vert line + char msg1 [60]; + char msg2 [60]; + char msg3 [60]; + + strcpy (msg1," :snowflake: iceman@icesql.net :coffee:"); + strcpy (msg2," https://github.com/rfidresearchgroup/proxmark3/"); + strcpy (msg3,"pre-release v4.0"); + + g_printAndLog = PRINTANDLOG_PRINT; + + PrintAndLogEx(NORMAL, "\n"); + + PrintAndLogEx(NORMAL, " " _BLUE_("%s%s%s%s%s%s%s %s%s%s%s %s%s%s%s %s%s%s%s%s "),sq,sq,sq,sq,sq,sq,tr,sq,sq,sq,tr,sq,sq,sq,tr,sq,sq,sq,sq,tr); + PrintAndLogEx(NORMAL, " " _BLUE_("%s%s%s%s%s%s%s%s%s%s%s%s%s %s%s%s%s%s %s%s%s%s"),sq,sq,tl,hl,hl,sq,sq,tr,sq,sq,sq,sq,tr,sq,sq,sq,sq,vl,hl,hl,sq,vl); + PrintAndLogEx(NORMAL, " " _BLUE_("%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s %s%s%s%s%s%s"),sq,sq,sq,sq,sq,sq,tl,br,sq,sq,tl,sq,sq,sq,sq,tl,sq,sq,vl,sq,sq,sq,sq,tl,br); + PrintAndLogEx(NORMAL, " " _BLUE_("%s%s%s%s%s%s%s %s%s%s%s%s%s%s%s%s%s%s %s%s%s%s")"%s",sq,sq,tr,hl,hl,hl,br,sq,sq,vl,bl,sq,sq,tl,br,sq,sq,vl,hl,hl,sq,vl,msg1); + PrintAndLogEx(NORMAL, " " _BLUE_("%s%s%s %s%s%s %s%s%s %s%s%s %s%s%s%s%s%s")"%s",sq,sq,vl,sq,sq,vl,bl,hl,br,sq,sq,vl,sq,sq,sq,sq,tl,br,msg2); + PrintAndLogEx(NORMAL, " " _BLUE_("%s%s%s %s%s%s %s%s%s %s%s%s%s%s ")"%s",bl,hl,br,bl,hl,br,bl,hl,br,bl,hl,hl,hl,br,msg3); + + PrintAndLogEx(NORMAL, ""); + fflush(stdout); + g_printAndLog = PRINTANDLOG_PRINT | PRINTANDLOG_LOG; +} + +#endif static void showBanner(void) { + +#ifdef _WIN32 + // If on windows and using UTF-8 then we need utf-8 ascii art for banner. + if (GetConsoleCP() == 65001) { + utf8_showBanner (); + return; + } +#endif + g_printAndLog = PRINTANDLOG_PRINT; PrintAndLogEx(NORMAL, "\n"); @@ -60,6 +105,7 @@ static void showBanner(void) { g_printAndLog = PRINTANDLOG_PRINT | PRINTANDLOG_LOG; } + static int check_comm(void) { // If communications thread goes down. Device disconnected then this should hook up PM3 again. if (IsCommunicationThreadDead() && session.pm3_present) { @@ -493,7 +539,7 @@ finish2: return ret; } -#ifndef USE_SETTING_FILE +#ifndef USE_PREFERENCE_FILE // Check if windows AnsiColor Support is enabled in the registery // [HKEY_CURRENT_USER\Console] @@ -591,11 +637,14 @@ int main(int argc, char *argv[]) { set_my_executable_path(); set_my_user_directory(); -#ifdef USE_SETTING_FILE +#ifdef USE_PREFERENCE_FILE // Load Settings and assign // This will allow the command line to override the settings.json values - settings_load (); - + preferences_load (); + // Change height/width (Rows,Cols) - Testing + // printf ("\e[8;50;100t"); + // printf ("\e[3;50;50t"); // x,y + //printf ("Path : %s \n",my_user_directory); // quick patch for debug level g_debugMode = session.client_debug_level; // settings_save (); @@ -780,7 +829,7 @@ int main(int argc, char *argv[]) { return 1; } -#ifndef USE_SETTING_FILE +#ifndef USE_PREFERENCE_FILE // comment next 2 lines to use session values set from settings_load session.supports_colors = DetectWindowsAnsiSupport(); session.emoji_mode = ALTTEXT; @@ -854,12 +903,12 @@ int main(int argc, char *argv[]) { if (!script_cmds_file && !script_cmd && session.stdinOnTTY && session.stdoutOnTTY && !flash_mode) showBanner(); -#ifdef USE_SETTING_FILE +#ifdef USE_PREFERENCE_FILE // Save settings if not load from settings json file. // Doing this here will ensure other checks and updates are saved to over rule default // e.g. Linux color use check - if (!session.settings_loaded) - settings_save (); + if (!session.preferences_loaded) + preferences_save (); #endif #ifdef HAVE_GUI diff --git a/client/settings.c b/client/settings.c deleted file mode 100644 index 4d59382e2..000000000 --- a/client/settings.c +++ /dev/null @@ -1,211 +0,0 @@ -/***************************************************************************** - * WARNING - * - * THIS CODE IS CREATED FOR EXPERIMENTATION AND EDUCATIONAL USE ONLY. - * - * USAGE OF THIS CODE IN OTHER WAYS MAY INFRINGE UPON THE INTELLECTUAL - * PROPERTY OF OTHER PARTIES, SUCH AS INSIDE SECURE AND HID GLOBAL, - * AND MAY EXPOSE YOU TO AN INFRINGEMENT ACTION FROM THOSE PARTIES. - * - * THIS CODE SHOULD NEVER BE USED TO INFRINGE PATENTS OR INTELLECTUAL PROPERTY RIGHTS. - * - ***************************************************************************** - * - * This file is part of loclass. It is a reconstructon of the cipher engine - * used in iClass, and RFID techology. - * - * The implementation is based on the work performed by - * Flavio D. Garcia, Gerhard de Koning Gans, Roel Verdult and - * Milosch Meriac in the paper "Dismantling IClass". - * - * Copyright (C) 2014 Martin Holst Swende - * - * This is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as published - * by the Free Software Foundation, or, at your option, any later version. - * - * This file is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with loclass. If not, see . - * - * - ****************************************************************************/ - -//----------------------------------------------------------------------------- -// Settings Functions -//----------------------------------------------------------------------------- - -//----------------------------------------------------------------------------- -// Notes -// To add a new setting -// Add the new setting to the session_arg_t; in ui.h -// Add the default value for the setting in the settings_load page below -// Update the settings_load_callback to load your setting into the stucture -// Update the settings_save_callback to enusre your setting gets saved when needed. -// use the setting as needed : session. -// Can use (session.settings_loaded) to check if json settings file was used -//----------------------------------------------------------------------------- - -#include "settings.h" -#include "comms.h" -#include "emv/emvjson.h" -#include - -// Load all settings into memory (struct) -int settings_load (void) { - - // Set all defaults - session.client_debug_level = OFF; - session.window_plot_xpos = 10; - session.window_plot_ypos = 30; - session.window_plot_hsize = 400; - session.window_plot_wsize = 800; - session.window_overlay_xpos = session.window_plot_xpos; - session.window_overlay_ypos = 20+session.window_plot_ypos + session.window_plot_hsize; - session.window_overlay_hsize = 200; - session.window_overlay_wsize = session.window_plot_wsize; - session.emoji_mode = ALIAS; - session.show_hints = false; - session.supports_colors = false; - - // loadFileJson wants these, so pass in place holder values, though not used - // in settings load; - uint8_t dummyData = 0x00; - size_t dummyDL = 0x00; - - if (loadFileJSON(settingsFilename, &dummyData, sizeof(dummyData), &dummyDL) == PM3_SUCCESS) { - session.settings_loaded = true; - } - // Note, if session.settings_loaded == false then the settings_save - // will be called in main () to save settings as set in defaults and main() checks. - - return PM3_SUCCESS; -} - -// Save all settings from memory (struct) to file -int settings_save (void) { - // Note sure if backup has value ? - char backupFilename[500]; - - snprintf (backupFilename,sizeof(backupFilename),"%s.bak",settingsFilename); - - if (fileExists (backupFilename)) { - if (remove (backupFilename) != 0) { - PrintAndLogEx (FAILED, "Error - could not delete old settings backup file \"%s\"",backupFilename); - return PM3_ESOFT; - } - } - - if (fileExists (settingsFilename)) { - if (rename (settingsFilename,backupFilename) != 0) { - PrintAndLogEx (FAILED, "Error - could not backup settings file \"%s\" to \"%s\"",settingsFilename,backupFilename); - return PM3_ESOFT; - } - } - - uint8_t dummyData = 0x00; - size_t dummyDL = 0x00; - - if (saveFileJSON(settingsFilename, jsfSettings, &dummyData, dummyDL) == PM3_SUCCESS) - PrintAndLogEx (NORMAL, "settings have been saved to \"%s\"",settingsFilename); - - return PM3_SUCCESS; -} - -void settings_save_callback (json_t *root) { - - JsonSaveStr (root,"FileType","settings"); - - // Log level, convert to text - switch (session.client_debug_level) { - case OFF: JsonSaveStr (root,"client.debug.level","off"); break; - case SIMPLE: JsonSaveStr (root,"client.debug.level","simple"); break; - case FULL: JsonSaveStr (root,"client.debug.level","full"); break; - default: - JsonSaveStr (root,"logging.level","NORMAL"); - } - - // Plot window - JsonSaveInt (root,"window.plot.xpos",session.window_plot_xpos); - JsonSaveInt (root,"window.plot.ypos",session.window_plot_ypos); - JsonSaveInt (root,"window.plot.hsize",session.window_plot_hsize); - JsonSaveInt (root,"window.plot.wsize",session.window_plot_wsize); - - // Overlay/Slider window - JsonSaveInt (root,"window.overlay.xpos",session.window_overlay_xpos); - JsonSaveInt (root,"window.overlay.ypos",session.window_overlay_ypos); - JsonSaveInt (root,"window.overlay.hsize",session.window_overlay_hsize); - JsonSaveInt (root,"window.overlay.wsize",session.window_overlay_wsize); - - // Emoji - switch (session.emoji_mode) { - case ALIAS: JsonSaveStr (root,"show.emoji","alias"); break; - case EMOJI: JsonSaveStr (root,"show.emoji","emoji"); break; - case ALTTEXT: JsonSaveStr (root,"show.emoji","alttext"); break; - case ERASE: JsonSaveStr (root,"show.emoji","erase"); break; - default: - JsonSaveStr (root,"show.emoji","ALIAS"); - } - - JsonSaveBoolean (root,"show.hints",session.show_hints); - - JsonSaveBoolean (root,"os.supports.colors",session.supports_colors); -} - -void settings_load_callback (json_t *root) { - json_error_t up_error = {0}; - bool b1; - int i1; - const char *s1; - char tempStr [500]; // to use str_lower() since json unpack uses const char * - - // Logging Level - if (json_unpack_ex(root,&up_error, 0, "{s:s}","client.debug.level",&s1) == 0) { - strncpy (tempStr,s1,sizeof(tempStr)-1); - str_lower (tempStr); - if (strncmp (tempStr,"off",3) == 0) session.client_debug_level = OFF; - if (strncmp (tempStr,"simple",6) == 0) session.client_debug_level = SIMPLE; - if (strncmp (tempStr,"full",4) == 0) session.client_debug_level = FULL; - } - - // window plot - if (json_unpack_ex(root,&up_error, 0, "{s:i}","window.plot.xpos",&i1) == 0) - session.window_plot_xpos = i1; - if (json_unpack_ex(root,&up_error, 0, "{s:i}","window.plot.ypos",&i1) == 0) - session.window_plot_ypos = i1; - if (json_unpack_ex(root,&up_error, 0, "{s:i}","window.plot.hsize",&i1) == 0) - session.window_plot_hsize = i1; - if (json_unpack_ex(root,&up_error, 0, "{s:i}","window.plot.wsize",&i1) == 0) - session.window_plot_wsize = i1; - - // overlay/slider plot - if (json_unpack_ex(root,&up_error, 0, "{s:i}","window.overlay.xpos",&i1) == 0) - session.window_overlay_xpos = i1; - if (json_unpack_ex(root,&up_error, 0, "{s:i}","window.overlay.ypos",&i1) == 0) - session.window_overlay_ypos = i1; - if (json_unpack_ex(root,&up_error, 0, "{s:i}","window.overlay.hsize",&i1) == 0) - session.window_overlay_hsize = i1; - if (json_unpack_ex(root,&up_error, 0, "{s:i}","window.overlay.wsize",&i1) == 0) - session.window_overlay_wsize = i1; - - // show options - if (json_unpack_ex(root,&up_error, 0, "{s:s}","show.emoji",&s1) == 0) { - strncpy (tempStr,s1,sizeof(tempStr)-1); - str_lower (tempStr); - if (strncmp (tempStr,"alias",5) == 0) session.emoji_mode = ALIAS; - if (strncmp (tempStr,"emoji",5) == 0) session.emoji_mode = EMOJI; - if (strncmp (tempStr,"alttext",7) == 0) session.emoji_mode = ALTTEXT; - if (strncmp (tempStr,"erase",5) == 0) session.emoji_mode = ERASE; - } - - if (json_unpack_ex(root,&up_error, 0, "{s:b}","show.hints",&b1) == 0) - session.show_hints = b1; - - if (json_unpack_ex(root,&up_error, 0, "{s:b}","os.supports.colors",&b1) == 0) - session.supports_colors = b1; - -} diff --git a/client/ui.h b/client/ui.h index e5048e751..3875c27c8 100644 --- a/client/ui.h +++ b/client/ui.h @@ -22,7 +22,7 @@ typedef enum emojiMode {ALIAS, EMOJI, ALTTEXT, ERASE} emojiMode_t; typedef enum clientdebugLevel {OFF,SIMPLE,FULL} clientdebugLevel_t; typedef struct { - bool settings_loaded; + bool preferences_loaded; bool stdinOnTTY; bool stdoutOnTTY; bool supports_colors; From ac8c1398676f0e5c5e71b0ff8da89258d651313e Mon Sep 17 00:00:00 2001 From: mwalker33 Date: Sun, 12 Apr 2020 13:08:02 +1000 Subject: [PATCH 20/20] Update preferences.c --- client/preferences.c | 1 + 1 file changed, 1 insertion(+) diff --git a/client/preferences.c b/client/preferences.c index 18882e912..21c38fb2e 100644 --- a/client/preferences.c +++ b/client/preferences.c @@ -7,6 +7,7 @@ * PROPERTY OF OTHER PARTIES, SUCH AS INSIDE SECURE AND HID GLOBAL, * AND MAY EXPOSE YOU TO AN INFRINGEMENT ACTION FROM THOSE PARTIES. * + * THIS CODE SHOULD NEVER BE USED TO INFRINGE PATENTS OR INTELLECTUAL PROPERTY RIGHTS. * ***************************************************************************** *