From 3eb8523079fa4f9c3399dc68df99f0b17a24fd9d Mon Sep 17 00:00:00 2001 From: merlokk <807634+merlokk@users.noreply.github.com> Date: Thu, 15 Jul 2021 14:53:48 +0300 Subject: [PATCH 01/18] key version --- client/src/mifare/desfirecrypto.c | 31 +++++++++++++++++++++++++++++++ client/src/mifare/desfirecrypto.h | 3 +++ 2 files changed, 34 insertions(+) diff --git a/client/src/mifare/desfirecrypto.c b/client/src/mifare/desfirecrypto.c index 11b29b9db..355a60b26 100644 --- a/client/src/mifare/desfirecrypto.c +++ b/client/src/mifare/desfirecrypto.c @@ -311,7 +311,38 @@ void DesfireCryptoCMAC(DesfireContext *ctx, uint8_t *data, size_t len, uint8_t * memcpy(cmac, ctx->IV, kbs); } +void DesfireDESKeySetVersion(uint8_t *key, DesfireCryptoAlgorythm keytype, uint8_t version) { + if (keytype == T_AES) + return; + // clear version + for (int n = 0; n < desfire_get_key_length(keytype); n++) + key[n] &= 0xFE; + + // set version + for (int n = 0; n < 8; n++) { + uint8_t version_bit = ((version & (1 << (7 - n))) >> (7 - n)); + + key[n] &= 0xFE; + key[n] |= version_bit; + + if (keytype == T_DES) { + key[n + 8] = key->data[n]; + } else { + // Write ~version to avoid turning a 3DES key into a DES key + key->data[n + 8] &= 0xFE; + key->data[n + 8] |= ~version_bit; + } + } +} + +uint8_t DesfireDESKeyGetVersion(uint8_t *key) { + uint8_t version = 0; + for (int n = 0; n < 8; n++) { + version = version << 1; + version |= (key[n] & 0xFE); + } +} void desfire_crc32(const uint8_t *data, const size_t len, uint8_t *crc) { crc32_ex(data, len, crc); } diff --git a/client/src/mifare/desfirecrypto.h b/client/src/mifare/desfirecrypto.h index 6bffa376e..c83720d80 100644 --- a/client/src/mifare/desfirecrypto.h +++ b/client/src/mifare/desfirecrypto.h @@ -101,6 +101,9 @@ void DesfireCryptoEncDec(DesfireContext *ctx, bool use_session_key, uint8_t *src void DesfireCryptoEncDecEx(DesfireContext *ctx, bool use_session_key, uint8_t *srcdata, size_t srcdatalen, uint8_t *dstdata, bool encode, uint8_t *iv); void DesfireCryptoCMAC(DesfireContext *ctx, uint8_t *srcdata, size_t srcdatalen, uint8_t *cmac); +void DesfireDESKeySetVersion(uint8_t *key, DesfireCryptoAlgorythm keytype, uint8_t version); +uint8_t DesfireDESKeyGetVersion(uint8_t *key); + void desfire_crc32(const uint8_t *data, const size_t len, uint8_t *crc); void desfire_crc32_append(uint8_t *data, const size_t len); bool desfire_crc32_check(uint8_t *data, const size_t len, uint8_t *crc); From 557fc5bb97adfa754590d86f2148dcdcbc062f47 Mon Sep 17 00:00:00 2001 From: merlokk <807634+merlokk@users.noreply.github.com> Date: Thu, 15 Jul 2021 14:54:15 +0300 Subject: [PATCH 02/18] changekey command sketch --- client/src/mifare/desfirecore.c | 78 +++++++++++++++++++++++++++++++++ client/src/mifare/desfirecore.h | 3 ++ 2 files changed, 81 insertions(+) diff --git a/client/src/mifare/desfirecore.c b/client/src/mifare/desfirecore.c index b0c4d9b8d..96ced89fc 100644 --- a/client/src/mifare/desfirecore.c +++ b/client/src/mifare/desfirecore.c @@ -988,6 +988,10 @@ int DesfireChangeKeySettings(DesfireContext *dctx, uint8_t *data, size_t len) { return DesfireCommandTxData(dctx, MFDES_CHANGE_KEY_SETTINGS, data, len); } +int DesfireChangeKeyCmd(DesfireContext *dctx, uint8_t *data, size_t len, uint8_t *resp, size_t *resplen) { + return DesfireCommand(dctx, MFDES_GET_KEY_VERSION, data, len, resp, resplen, -1); +} + uint8_t DesfireKeyAlgoToType(DesfireCryptoAlgorythm keyType) { switch (keyType) { case T_DES: @@ -1074,3 +1078,77 @@ void PrintKeySettings(uint8_t keysettings, uint8_t numkeys, bool applevel, bool else PrintKeySettingsPICC(keysettings, numkeys, print2ndbyte); } + +int DesfireChangeKey(DesfireContext *dctx, uint8_t newkeynum, DesfireCryptoAlgorythm newkeytype, uint32_t newkeyver, uint8_t *newkey, DesfireCryptoAlgorythm oldkeytype, uint8_t *oldkey) { + + uint_8t okeybuf[DESFIRE_MAX_KEY_SIZE] = {0}; + uint_8t nkeybuf[DESFIRE_MAX_KEY_SIZE] = {0}; + uint_8t cdata[DESFIRE_MAX_KEY_SIZE + 10] = {0}; + + // DES -> 2TDEA + memcpy(okeybuf, oldkey, desfire_get_key_length(oldkeytype)); + if (oldkeytype == MFDES_ALGO_DES) { + memcpy(&okeybuf[8], oldkey, 8); + oldkeytype = MFDES_ALGO_3DES; + } + + memcpy(nkeybuf, newkey, desfire_get_key_length(newkeytype)); + if (newkeytype == MFDES_ALGO_DES) { + memcpy(&nkeybuf[8], newkey, 8); + newkeytype = MFDES_ALGO_3DES; + } + size_t nkeylen = desfire_get_key_length(newkeytype); + + // set key version for DES. if newkeyver > 0xff - setting key version is disabled + if (newkeytype != MFDES_ALGO_AES && newkeyver < 0x100) + DesfireDESKeySetVersion(nkeybuf, newkeytype, newkeyver); + + // xor if we change current auth key + if (newkeynum == dctx->keyNum) { + memcpy(cdata, nkeybuf, nkeylen); + } else { + memcpy(cdata, nkeybuf, nkeylen); + binxor(cdata, okeybuf, nkeylen) + } + + // add key version for AES + size_t cdatalen = nkeylen; + if (newkeytype == MFDES_ALGO_AES) { + cdata[cdatalen] = newkeyversion; + cdatalen++; + } + + // add crc||crc_new_key + if (dctx->secureChannel == DACd40) { + iso14443a_crc_append(cdata, cdatalen); + cdatalen += 2; + if (newkeynum != dctx->keyNum) { + iso14443a_crc(nkeybuf, nkeylen, &cdata[cdatalen]); + cdatalen += 2; + } + } else { + desfire_crc32_append(cdata, cdatalen); + cdatalen += 4; + if (newkeynum != dctx->keyNum) { + desfire_crc32(nkeybuf, nkeylen, &cdata[cdatalen]); + cdatalen += 4; + } + } + + // get padded data length + size_t rlen = padded_data_length(cdatalen, desfire_get_key_block_length(ctx->keyType)); + + // send command + uint8_t resp[257] = {0}; + size_t resplen = 0; + int res = DesfireChangeKeyCmd(dctx, cdata, rlen, resp, resplen); + + // check response + + // clear auth + if (newkeynum == dctx->keyNum) + DesfireClearSession(dctx); + + return PM3_SUCCESS; +} + diff --git a/client/src/mifare/desfirecore.h b/client/src/mifare/desfirecore.h index c6b092b59..fb04d21f0 100644 --- a/client/src/mifare/desfirecore.h +++ b/client/src/mifare/desfirecore.h @@ -55,4 +55,7 @@ int DesfireChangeKeySettings(DesfireContext *dctx, uint8_t *data, size_t len); void PrintKeySettings(uint8_t keysettings, uint8_t numkeys, bool applevel, bool print2ndbyte); uint8_t DesfireKeyAlgoToType(DesfireCryptoAlgorythm keyType); +int DesfireChangeKeyCmd(DesfireContext *dctx, uint8_t *data, size_t datalen, uint8_t *resp, size_t *resplen); +int DesfireChangeKey(DesfireContext *dctx, uint8_t newkeynum, DesfireCryptoAlgorythm newkeytype, uint32_t newkeyver, uint8_t *newkey, DesfireCryptoAlgorythm oldkeytype, uint8_t *oldkey); + #endif // __DESFIRECORE_H From 92a0639ba8019d1bf3bf5422d79e1178f583788f Mon Sep 17 00:00:00 2001 From: merlokk <807634+merlokk@users.noreply.github.com> Date: Thu, 15 Jul 2021 15:26:25 +0300 Subject: [PATCH 03/18] fix --- client/src/cmdhfmfdes.c | 229 +++++++++++++++++++++++++++--- client/src/mifare/desfirecore.c | 28 ++-- client/src/mifare/desfirecrypto.c | 15 +- 3 files changed, 232 insertions(+), 40 deletions(-) diff --git a/client/src/cmdhfmfdes.c b/client/src/cmdhfmfdes.c index 3c4cce49a..f2b75f31d 100644 --- a/client/src/cmdhfmfdes.c +++ b/client/src/cmdhfmfdes.c @@ -369,7 +369,7 @@ typedef struct aidhdr { static int CmdHelp(const char *Cmd); -static const char *getEncryptionAlgoStr(uint8_t algo) { +/*static const char *getEncryptionAlgoStr(uint8_t algo) { switch (algo) { case MFDES_ALGO_AES : return "AES"; @@ -382,7 +382,7 @@ static const char *getEncryptionAlgoStr(uint8_t algo) { default : return ""; } -} +}*/ /* The 7 MSBits (= n) code the storage size itself based on 2^n, the LSBit is set to '0' if the size is exactly 2^n @@ -1051,7 +1051,7 @@ static int handler_desfire_freemem(uint32_t *free_mem) { return res; } -static int mifare_desfire_change_key(uint8_t key_no, uint8_t *new_key, uint8_t new_algo, uint8_t *old_key, uint8_t old_algo, uint8_t aes_version) { +/*static int mifare_desfire_change_key(uint8_t key_no, uint8_t *new_key, uint8_t new_algo, uint8_t *old_key, uint8_t old_algo, uint8_t aes_version) { if (new_key == NULL || old_key == NULL) { return PM3_EINVARG; @@ -1060,10 +1060,10 @@ static int mifare_desfire_change_key(uint8_t key_no, uint8_t *new_key, uint8_t n // AID == 000000 6bits LSB needs to be 0 key_no &= 0x0F; - /* + Desfire treats Des keys as TDes but with the first half = 2nd half As such, we should be able to convert the Des to TDes then run the code as TDes - */ + if (new_algo == MFDES_ALGO_DES) { memcpy(&new_key[8], new_key, 8); new_algo = MFDES_ALGO_3DES; @@ -1074,10 +1074,10 @@ static int mifare_desfire_change_key(uint8_t key_no, uint8_t *new_key, uint8_t n old_algo = MFDES_ALGO_3DES; } - /* + * * Because new crypto methods can be setup only at application creation, * changing the card master key to one of them require a key_no tweak. - */ + * if (0x000000 == tag->selected_application) { // PICC master key, 6bits LSB needs to be 0 @@ -1096,13 +1096,13 @@ static int mifare_desfire_change_key(uint8_t key_no, uint8_t *new_key, uint8_t n break; } } - /* + * keyno 1b key 8b cpy 8b crc 2b padding - */ + * // Variable length ciphered key data 24-42 bytes plus padding.. uint8_t data[64] = {key_no}; @@ -1113,13 +1113,13 @@ static int mifare_desfire_change_key(uint8_t key_no, uint8_t *new_key, uint8_t n uint8_t new_key_length = 16; switch (new_algo) { - /* + * // We have converted the DES to 3DES above,so this will never hit case MFDES_ALGO_DES: memcpy(data + cmdcnt + 1, new_key, new_key_length); memcpy(data + cmdcnt + 1 + new_key_length, new_key, new_key_length); break; - */ + * case MFDES_ALGO_3DES: case MFDES_ALGO_AES: new_key_length = 16; @@ -1251,12 +1251,12 @@ static int mifare_desfire_change_key(uint8_t key_no, uint8_t *new_key, uint8_t n DropFieldDesfire(); if (!p) { - /* + * Note in my testing on an EV1, the AES password did change, with the number of returned bytes was 8, expected 9 <8 byte cmac> As such !p is true and the code reports "Error on changing key"; so comment back to user until its fixed. Note: as at 19 May 2021, with the sn = 1 patch above, this should no longer be reachable! - */ + * if (new_algo == MFDES_ALGO_AES) { PrintAndLogEx(WARNING, "AES Key may have been changed, please check new password with the auth command."); } @@ -1264,17 +1264,17 @@ static int mifare_desfire_change_key(uint8_t key_no, uint8_t *new_key, uint8_t n return PM3_ESOFT; } - /* + * * If we changed the current authenticated key, we are not authenticated * anymore. - */ + * if (key_no == tag->authenticated_key_no) { free(tag->session_key); tag->session_key = NULL; } return PM3_SUCCESS; -} +}*/ // --- GET SIGNATURE static int desfire_print_signature(uint8_t *uid, uint8_t uidlen, uint8_t *signature, size_t signature_len, nxp_cardtype_t card_type) { @@ -3805,7 +3805,7 @@ static int CmdHF14ADesBruteApps(const char *Cmd) { DropFieldDesfire(); return PM3_SUCCESS; } - +/* static int CmdHF14ADesChangeKey(const char *Cmd) { CLIParserContext *ctx; CLIParserInit(&ctx, "hf mfdes changekey", @@ -3900,7 +3900,7 @@ static int CmdHF14ADesChangeKey(const char *Cmd) { PrintAndLogEx(FAILED, "Change key ( " _RED_("fail") " )"); } return res; -} +}*/ // MIAFRE DESFire Authentication @@ -4885,6 +4885,197 @@ static int CmdHF14ADesDefault(const char *Cmd) { return PM3_SUCCESS; } +static int CmdHF14ADesChangeKey(const char *Cmd) { + CLIParserContext *ctx; + CLIParserInit(&ctx, "hf mfdes changekey", + "Change PICC/Application key. Needs to provide keynum/key for a valid authentication (may get from default parameters).", + "hf mfdes changekey --aid 123456 -> execute with default factory setup"); + + void *argtable[] = { + arg_param_begin, + arg_lit0("a", "apdu", "show APDU requests and responses"), + arg_lit0("v", "verbose", "show technical data"), + arg_int0("n", "keyno", "", "Key number"), + arg_str0("t", "algo", "", "Crypt algo: DES, 2TDEA, 3TDEA, AES"), + arg_str0("k", "key", "", "Key for authenticate (HEX 8(DES), 16(2TDEA or AES) or 24(3TDEA) bytes)"), + arg_str0("f", "kdf", "", "Key Derivation Function (KDF): None, AN10922, Gallagher"), + arg_str0("i", "kdfi", "", "KDF input (HEX 1-31 bytes)"), + arg_str0("m", "cmode", "", "Communicaton mode: plain/mac/encrypt"), + arg_str0("c", "ccset", "", "Communicaton command set: native/niso/iso"), + arg_str0("s", "schann", "", "Secure channel: d40/ev1/ev2"), + arg_str0(NULL, "aid", "", "Application ID of application (3 hex bytes, big endian)"), + arg_str0(NULL, "oldalgo", "", "Old key crypto algorithm: DES, 2TDEA, 3TDEA, AES"), + arg_str0(NULL, "oldkey", "", "Old key (HEX 8(DES), 16(2TDEA or AES) or 24(3TDEA) bytes)"), + arg_int0(NULL, "newkeyno","", "Key number for change"), + arg_str0(NULL, "newalgo", "", "New key crypto algorithm: DES, 2TDEA, 3TDEA, AES"), + arg_str0(NULL, "newkey", "", "New key (HEX 8(DES), 16(2TDEA or AES) or 24(3TDEA) bytes)"), + arg_str0(NULL, "newver", "", "New key's version (1 hex byte)"), + arg_param_end + }; + CLIExecWithReturn(ctx, Cmd, argtable, false); + + bool APDULogging = arg_get_lit(ctx, 1); + bool verbose = arg_get_lit(ctx, 2); + + DesfireContext dctx; + int securechann = defaultSecureChannel; + uint32_t appid = 0x000000; + int res = CmdDesGetSessionParameters(ctx, &dctx, 3, 4, 5, 6, 7, 8, 9, 10, 11, &securechann, DCMEncrypted, &appid); + if (res) { + CLIParserFree(ctx); + return res; + } + + int oldkeytype = T_DES; + if (CLIGetOptionList(arg_get_str(ctx, 12), DesfireAlgoOpts, &oldkeytype)) + return PM3_ESOFT; + + uint8_t oldkey[DESFIRE_MAX_KEY_SIZE] = {0}; + + uint8_t newkeynum = arg_get_int_def(ctx, 14, 0); + + int newkeytype = T_DES; + if (CLIGetOptionList(arg_get_str(ctx, 15), DesfireAlgoOpts, &newkeytype)) + return PM3_ESOFT; + + uint8_t newkey[DESFIRE_MAX_KEY_SIZE] = {0}; + + uint8_t newkeyver = arg_get_int_def(ctx, 17, 0x100); + + SetAPDULogging(APDULogging); + CLIParserFree(ctx); + + if (appid == 0x000000) { + PrintAndLogEx(WARNING, "Changing the root aid (0x000000)"); + return PM3_ESOFT; // TODO!!!! + } + + res = DesfireSelectAndAuthenticate(&dctx, securechann, appid, verbose); + if (res != PM3_SUCCESS) { + DropField(); + return res; + } + + res = DesfireChangeKey(&dctx, newkeynum, newkeytype, newkeyver, newkey, oldkeytype, oldkey); + if (res == PM3_SUCCESS) { + PrintAndLogEx(SUCCESS, "Change key " _GREEN_("ok") " "); + } else { + PrintAndLogEx(FAILED, "Change key " _RED_("failed") " "); + } + + DropField(); + return res; + + return PM3_SUCCESS; + + + + + + + + + + + + + + +/* CLIParserContext *ctx; + CLIParserInit(&ctx, "hf mfdes changekey", + "Change MIFARE DESFire Key.\n" + "Make sure to select aid or authenticate aid before running this command.", + "hf mfdes changekey -n 0 -t 1 -k 0000000000000000 -u 1 -j 0102030405060708 -> DES, keynumber 0" + ); + + void *argtable[] = { + arg_param_begin, + arg_int0("n", "keyno", "", "Key number used for authentification"), + arg_int0("t", "algo", "", "Current key algo (1 = DES, 2 = 3DES(2K2DES), 3 = 3K3DES, 4 = AES)"), + arg_str0("k", "key", "", "Current Key (HEX 8-24 bytes)"), + arg_int0("u", "newalgo", "", "New key algo (1 = DES, 2 = 3DES(2K2DES), 3 = 3K3DES, 4 = AES)"), + arg_str0("j", "newkey", "", "New Key (HEX 8-24 bytes)"), + arg_int0("v", "aesver", "", "AES version (if AES is used)"), + arg_param_end + }; + CLIExecWithReturn(ctx, Cmd, argtable, false); + + uint8_t cmdKeyNo = arg_get_int_def(ctx, 1, 0); + uint8_t cmdAuthAlgo = arg_get_int_def(ctx, 2, 0); + uint8_t key[24] = {0}; + int keylen = 0; + int res_klen = CLIParamHexToBuf(arg_get_str(ctx, 3), key, 24, &keylen); + + uint8_t newcmdAuthAlgo = arg_get_int_def(ctx, 4, 0); + uint8_t newkey[24] = {0}; + int newkeylen = 0; + int res_newklen = CLIParamHexToBuf(arg_get_str(ctx, 5), newkey, 24, &newkeylen); + + uint8_t aesversion = arg_get_int_def(ctx, 6, 0); + CLIParserFree(ctx); + + //DropFieldDesfire(); + // NR DESC KEYLENGHT + // ------------------------ + // 1 = DES 8 + // 2 = 3DES 16 + // 3 = 3K 3DES 24 + // 4 = AES 16 + uint8_t keylength = 8; + if (cmdAuthAlgo == MFDES_ALGO_AES) { + keylength = 16; + } else if (cmdAuthAlgo == MFDES_ALGO_3DES) { + keylength = 16; + } else if (cmdAuthAlgo == MFDES_ALGO_DES) { + keylength = 8; + } else if (cmdAuthAlgo == MFDES_ALGO_3K3DES) { + keylength = 24; + } + + uint8_t newkeylength = 8; + if (newcmdAuthAlgo == MFDES_ALGO_AES) { + newkeylength = 16; + } else if (newcmdAuthAlgo == MFDES_ALGO_3DES) { + newkeylength = 16; + } else if (newcmdAuthAlgo == MFDES_ALGO_DES) { + newkeylength = 8; + } else if (newcmdAuthAlgo == MFDES_ALGO_3K3DES) { + newkeylength = 24; + } + + if (res_klen || (keylen < 8) || (keylen > 24)) { + PrintAndLogEx(ERR, "Specified key must have %d bytes length", keylen); + return PM3_EINVARG; + } + + if (res_newklen || (newkeylen < 8) || (newkeylen > 24)) { + PrintAndLogEx(ERR, "Specified new key must have %d bytes length", newkeylen); + return PM3_EINVARG; + } + + if (keylen != keylength) { + PrintAndLogEx(WARNING, "Key must include %d hex symbols, got %d", keylength, keylen); + return PM3_EINVARG; + } + + if (newkeylen != newkeylength) { + PrintAndLogEx(WARNING, "New key must include %d hex symbols, got %d", keylength, newkeylen); + return PM3_EINVARG; + } + + PrintAndLogEx(INFO, "changing key number " _YELLOW_("0x%02x"), cmdKeyNo); + PrintAndLogEx(INFO, "old key: %s ( %s )", sprint_hex_inrow(key, keylen), getEncryptionAlgoStr(cmdAuthAlgo)); + PrintAndLogEx(INFO, "new key: %s ( %s )", sprint_hex_inrow(newkey, newkeylen), getEncryptionAlgoStr(newcmdAuthAlgo)); + + int res = mifare_desfire_change_key(cmdKeyNo, newkey, newcmdAuthAlgo, key, cmdAuthAlgo, aesversion); + if (res == PM3_SUCCESS) { + PrintAndLogEx(SUCCESS, "Change key ( " _GREEN_("ok") " )"); + } else { + PrintAndLogEx(FAILED, "Change key ( " _RED_("fail") " )"); + } + return res;*/ +} + static int CmdHF14ADesCreateApp(const char *Cmd) { CLIParserContext *ctx; CLIParserInit(&ctx, "hf mfdes createapp", @@ -5767,7 +5958,7 @@ static command_t CommandTable[] = { // {"ndefread", CmdHF14aDesNDEFRead, IfPm3Iso14443a, "Prints NDEF records from card"}, // {"mad", CmdHF14aDesMAD, IfPm3Iso14443a, "Prints MAD records from card"}, {"-----------", CmdHelp, IfPm3Iso14443a, "------------------------ " _CYAN_("Keys") " -----------------------"}, - {"changekey", CmdHF14ADesChangeKey, IfPm3Iso14443a, "Change Key"}, + {"changekey", CmdHF14ADesChangeKey, IfPm3Iso14443a, "[new]Change Key"}, {"chkeysettings", CmdHF14ADesChKeySettings, IfPm3Iso14443a, "[new]Change Key Settings"}, {"getkeysettings", CmdHF14ADesGetKeySettings, IfPm3Iso14443a, "[new]Get Key Settings"}, {"getkeyversions", CmdHF14ADesGetKeyVersions, IfPm3Iso14443a, "[new]Get Key Versions"}, diff --git a/client/src/mifare/desfirecore.c b/client/src/mifare/desfirecore.c index 96ced89fc..27401944f 100644 --- a/client/src/mifare/desfirecore.c +++ b/client/src/mifare/desfirecore.c @@ -1081,26 +1081,26 @@ void PrintKeySettings(uint8_t keysettings, uint8_t numkeys, bool applevel, bool int DesfireChangeKey(DesfireContext *dctx, uint8_t newkeynum, DesfireCryptoAlgorythm newkeytype, uint32_t newkeyver, uint8_t *newkey, DesfireCryptoAlgorythm oldkeytype, uint8_t *oldkey) { - uint_8t okeybuf[DESFIRE_MAX_KEY_SIZE] = {0}; - uint_8t nkeybuf[DESFIRE_MAX_KEY_SIZE] = {0}; - uint_8t cdata[DESFIRE_MAX_KEY_SIZE + 10] = {0}; + uint8_t okeybuf[DESFIRE_MAX_KEY_SIZE] = {0}; + uint8_t nkeybuf[DESFIRE_MAX_KEY_SIZE] = {0}; + uint8_t cdata[DESFIRE_MAX_KEY_SIZE + 10] = {0}; // DES -> 2TDEA memcpy(okeybuf, oldkey, desfire_get_key_length(oldkeytype)); - if (oldkeytype == MFDES_ALGO_DES) { + if (oldkeytype == T_DES) { memcpy(&okeybuf[8], oldkey, 8); - oldkeytype = MFDES_ALGO_3DES; + oldkeytype = T_3DES; } memcpy(nkeybuf, newkey, desfire_get_key_length(newkeytype)); - if (newkeytype == MFDES_ALGO_DES) { + if (newkeytype == T_DES) { memcpy(&nkeybuf[8], newkey, 8); - newkeytype = MFDES_ALGO_3DES; + newkeytype = T_3DES; } size_t nkeylen = desfire_get_key_length(newkeytype); // set key version for DES. if newkeyver > 0xff - setting key version is disabled - if (newkeytype != MFDES_ALGO_AES && newkeyver < 0x100) + if (newkeytype != T_AES && newkeyver < 0x100) DesfireDESKeySetVersion(nkeybuf, newkeytype, newkeyver); // xor if we change current auth key @@ -1108,13 +1108,13 @@ int DesfireChangeKey(DesfireContext *dctx, uint8_t newkeynum, DesfireCryptoAlgor memcpy(cdata, nkeybuf, nkeylen); } else { memcpy(cdata, nkeybuf, nkeylen); - binxor(cdata, okeybuf, nkeylen) + bin_xor(cdata, okeybuf, nkeylen); } // add key version for AES size_t cdatalen = nkeylen; - if (newkeytype == MFDES_ALGO_AES) { - cdata[cdatalen] = newkeyversion; + if (newkeytype == T_AES) { + cdata[cdatalen] = newkeyver; cdatalen++; } @@ -1136,12 +1136,12 @@ int DesfireChangeKey(DesfireContext *dctx, uint8_t newkeynum, DesfireCryptoAlgor } // get padded data length - size_t rlen = padded_data_length(cdatalen, desfire_get_key_block_length(ctx->keyType)); + size_t rlen = padded_data_length(cdatalen, desfire_get_key_block_length(newkeytype)); // send command uint8_t resp[257] = {0}; size_t resplen = 0; - int res = DesfireChangeKeyCmd(dctx, cdata, rlen, resp, resplen); + int res = DesfireChangeKeyCmd(dctx, cdata, rlen, resp, &resplen); // check response @@ -1149,6 +1149,6 @@ int DesfireChangeKey(DesfireContext *dctx, uint8_t newkeynum, DesfireCryptoAlgor if (newkeynum == dctx->keyNum) DesfireClearSession(dctx); - return PM3_SUCCESS; + return res; } diff --git a/client/src/mifare/desfirecrypto.c b/client/src/mifare/desfirecrypto.c index 355a60b26..51bfc6eb4 100644 --- a/client/src/mifare/desfirecrypto.c +++ b/client/src/mifare/desfirecrypto.c @@ -327,22 +327,23 @@ void DesfireDESKeySetVersion(uint8_t *key, DesfireCryptoAlgorythm keytype, uint8 key[n] |= version_bit; if (keytype == T_DES) { - key[n + 8] = key->data[n]; + key[n + 8] = key[n]; } else { // Write ~version to avoid turning a 3DES key into a DES key - key->data[n + 8] &= 0xFE; - key->data[n + 8] |= ~version_bit; + key[n + 8] &= 0xFE; + key[n + 8] |= ~version_bit; } } } uint8_t DesfireDESKeyGetVersion(uint8_t *key) { uint8_t version = 0; - for (int n = 0; n < 8; n++) { - version = version << 1; - version |= (key[n] & 0xFE); - } + for (int n = 0; n < 8; n++) + version |= ((key[n] & 1) << (7 - n)); + + return version; } + void desfire_crc32(const uint8_t *data, const size_t len, uint8_t *crc) { crc32_ex(data, len, crc); } From 46a294d585933c3a98b26ab50d6c2cafbc91c192 Mon Sep 17 00:00:00 2001 From: merlokk <807634+merlokk@users.noreply.github.com> Date: Thu, 15 Jul 2021 20:14:02 +0300 Subject: [PATCH 04/18] core works --- client/src/cmdhfmfdes.c | 26 +++++++++++++- client/src/mifare/desfirecore.c | 28 +++++++++++---- client/src/mifare/desfirecrypto.c | 2 +- client/src/mifare/desfirecrypto.h | 3 +- client/src/mifare/desfiresecurechan.c | 50 ++++++++++++++++++++++++--- include/protocols.h | 1 + 6 files changed, 96 insertions(+), 14 deletions(-) diff --git a/client/src/cmdhfmfdes.c b/client/src/cmdhfmfdes.c index f2b75f31d..b1ac5ce8a 100644 --- a/client/src/cmdhfmfdes.c +++ b/client/src/cmdhfmfdes.c @@ -4931,6 +4931,15 @@ static int CmdHF14ADesChangeKey(const char *Cmd) { return PM3_ESOFT; uint8_t oldkey[DESFIRE_MAX_KEY_SIZE] = {0}; + uint8_t keydata[200] = {0}; + int keylen = sizeof(keydata); + CLIGetHexWithReturn(ctx, 13, keydata, &keylen); + if (keylen && keylen != desfire_get_key_length(oldkeytype)) { + PrintAndLogEx(ERR, "%s old key must have %d bytes length instead of %d.", CLIGetOptionListStr(DesfireAlgoOpts, oldkeytype), desfire_get_key_length(oldkeytype), keylen); + return PM3_EINVARG; + } + if (keylen) + memcpy(oldkey, keydata, keylen); uint8_t newkeynum = arg_get_int_def(ctx, 14, 0); @@ -4939,8 +4948,22 @@ static int CmdHF14ADesChangeKey(const char *Cmd) { return PM3_ESOFT; uint8_t newkey[DESFIRE_MAX_KEY_SIZE] = {0}; + memset(keydata, 0x00, sizeof(keydata)); + CLIGetHexWithReturn(ctx, 16, keydata, &keylen); + if (keylen && keylen != desfire_get_key_length(newkeytype)) { + PrintAndLogEx(ERR, "%s new key must have %d bytes length instead of %d.", CLIGetOptionListStr(DesfireAlgoOpts, newkeytype), desfire_get_key_length(newkeytype), keylen); + return PM3_EINVARG; + } + if (keylen) + memcpy(newkey, keydata, keylen); - uint8_t newkeyver = arg_get_int_def(ctx, 17, 0x100); + uint32_t newkeyver = 0x100; + res = arg_get_u32_hexstr_def_nlen(ctx, 17, 0x100, &newkeyver, 1, true); + if (res == 2) { + PrintAndLogEx(ERR, "Key version must have 1 bytes length"); + CLIParserFree(ctx); + return PM3_EINVARG; + } SetAPDULogging(APDULogging); CLIParserFree(ctx); @@ -4956,6 +4979,7 @@ static int CmdHF14ADesChangeKey(const char *Cmd) { return res; } + DesfireSetCommMode(&dctx, DCMEncryptedPlain); res = DesfireChangeKey(&dctx, newkeynum, newkeytype, newkeyver, newkey, oldkeytype, oldkey); if (res == PM3_SUCCESS) { PrintAndLogEx(SUCCESS, "Change key " _GREEN_("ok") " "); diff --git a/client/src/mifare/desfirecore.c b/client/src/mifare/desfirecore.c index 27401944f..42d52e4c7 100644 --- a/client/src/mifare/desfirecore.c +++ b/client/src/mifare/desfirecore.c @@ -989,7 +989,7 @@ int DesfireChangeKeySettings(DesfireContext *dctx, uint8_t *data, size_t len) { } int DesfireChangeKeyCmd(DesfireContext *dctx, uint8_t *data, size_t len, uint8_t *resp, size_t *resplen) { - return DesfireCommand(dctx, MFDES_GET_KEY_VERSION, data, len, resp, resplen, -1); + return DesfireCommand(dctx, MFDES_CHANGE_KEY, data, len, resp, resplen, -1); } uint8_t DesfireKeyAlgoToType(DesfireCryptoAlgorythm keyType) { @@ -1083,26 +1083,35 @@ int DesfireChangeKey(DesfireContext *dctx, uint8_t newkeynum, DesfireCryptoAlgor uint8_t okeybuf[DESFIRE_MAX_KEY_SIZE] = {0}; uint8_t nkeybuf[DESFIRE_MAX_KEY_SIZE] = {0}; - uint8_t cdata[DESFIRE_MAX_KEY_SIZE + 10] = {0}; + uint8_t pckcdata[DESFIRE_MAX_KEY_SIZE + 10] = {0}; + uint8_t *cdata = &pckcdata[2]; + uint8_t keynodata = newkeynum & 0x3f; + keynodata |= (DesfireKeyAlgoToType(newkeytype) & 0x03) << 6; + pckcdata[0] = MFDES_CHANGE_KEY; // TODO + pckcdata[1] = keynodata; // DES -> 2TDEA memcpy(okeybuf, oldkey, desfire_get_key_length(oldkeytype)); if (oldkeytype == T_DES) { memcpy(&okeybuf[8], oldkey, 8); - oldkeytype = T_3DES; } memcpy(nkeybuf, newkey, desfire_get_key_length(newkeytype)); + size_t nkeylen = desfire_get_key_length(newkeytype); if (newkeytype == T_DES) { memcpy(&nkeybuf[8], newkey, 8); - newkeytype = T_3DES; + nkeylen = desfire_get_key_length(T_3DES); } - size_t nkeylen = desfire_get_key_length(newkeytype); + +PrintAndLogEx(SUCCESS, "--oldk [%d]: %s", desfire_get_key_length(oldkeytype), sprint_hex(okeybuf, desfire_get_key_length(oldkeytype))); +PrintAndLogEx(SUCCESS, "--newk [%d]: %s", nkeylen, sprint_hex(nkeybuf, nkeylen)); // set key version for DES. if newkeyver > 0xff - setting key version is disabled if (newkeytype != T_AES && newkeyver < 0x100) DesfireDESKeySetVersion(nkeybuf, newkeytype, newkeyver); +PrintAndLogEx(SUCCESS, "--newk [%d]: %s", nkeylen, sprint_hex(nkeybuf, nkeylen)); + // xor if we change current auth key if (newkeynum == dctx->keyNum) { memcpy(cdata, nkeybuf, nkeylen); @@ -1113,10 +1122,12 @@ int DesfireChangeKey(DesfireContext *dctx, uint8_t newkeynum, DesfireCryptoAlgor // add key version for AES size_t cdatalen = nkeylen; +PrintAndLogEx(SUCCESS, "--cdata [%d]: %s kv = 0x%02x", cdatalen, sprint_hex(cdata, cdatalen), newkeyver); if (newkeytype == T_AES) { cdata[cdatalen] = newkeyver; cdatalen++; } +PrintAndLogEx(SUCCESS, "--cdata [%d]: %s", cdatalen, sprint_hex(cdata, cdatalen)); // add crc||crc_new_key if (dctx->secureChannel == DACd40) { @@ -1127,13 +1138,15 @@ int DesfireChangeKey(DesfireContext *dctx, uint8_t newkeynum, DesfireCryptoAlgor cdatalen += 2; } } else { - desfire_crc32_append(cdata, cdatalen); + // EV1 Checksum must cover : [] + desfire_crc32_append(pckcdata, cdatalen + 2); cdatalen += 4; if (newkeynum != dctx->keyNum) { desfire_crc32(nkeybuf, nkeylen, &cdata[cdatalen]); cdatalen += 4; } } +PrintAndLogEx(SUCCESS, "--cdata [%d]: %s", cdatalen, sprint_hex(cdata, cdatalen)); // get padded data length size_t rlen = padded_data_length(cdatalen, desfire_get_key_block_length(newkeytype)); @@ -1141,7 +1154,8 @@ int DesfireChangeKey(DesfireContext *dctx, uint8_t newkeynum, DesfireCryptoAlgor // send command uint8_t resp[257] = {0}; size_t resplen = 0; - int res = DesfireChangeKeyCmd(dctx, cdata, rlen, resp, &resplen); +PrintAndLogEx(SUCCESS, "--pckdata [%d]: %s", rlen + 1, sprint_hex(&pckcdata[1], rlen + 1)); + int res = DesfireChangeKeyCmd(dctx, &pckcdata[1], rlen + 1, resp, &resplen); // check response diff --git a/client/src/mifare/desfirecrypto.c b/client/src/mifare/desfirecrypto.c index 51bfc6eb4..79604f5eb 100644 --- a/client/src/mifare/desfirecrypto.c +++ b/client/src/mifare/desfirecrypto.c @@ -331,7 +331,7 @@ void DesfireDESKeySetVersion(uint8_t *key, DesfireCryptoAlgorythm keytype, uint8 } else { // Write ~version to avoid turning a 3DES key into a DES key key[n + 8] &= 0xFE; - key[n + 8] |= ~version_bit; + key[n + 8] |= (~version_bit) & 0x01; } } } diff --git a/client/src/mifare/desfirecrypto.h b/client/src/mifare/desfirecrypto.h index c83720d80..0ec729a04 100644 --- a/client/src/mifare/desfirecrypto.h +++ b/client/src/mifare/desfirecrypto.h @@ -56,7 +56,8 @@ typedef enum { DCMNone, DCMPlain, DCMMACed, - DCMEncrypted + DCMEncrypted, + DCMEncryptedPlain } DesfireCommunicationMode; diff --git a/client/src/mifare/desfiresecurechan.c b/client/src/mifare/desfiresecurechan.c index 2e49ce5ac..c5b90c29d 100644 --- a/client/src/mifare/desfiresecurechan.c +++ b/client/src/mifare/desfiresecurechan.c @@ -52,6 +52,9 @@ AllowedChannelModesS AllowedChannelModes[] = { {MFDES_READ_DATA, DACd40, DCCNative, DCMEncrypted}, {MFDES_WRITE_DATA, DACd40, DCCNative, DCMEncrypted}, + {MFDES_CHANGE_KEY, DACd40, DCCNative, DCMEncryptedPlain}, + {MFDES_CHANGE_KEY_EV2, DACd40, DCCNative, DCMEncryptedPlain}, + {MFDES_GET_KEY_VERSION, DACEV1, DCCNative, DCMPlain}, {MFDES_GET_FREE_MEMORY, DACEV1, DCCNative, DCMPlain}, @@ -63,14 +66,28 @@ AllowedChannelModesS AllowedChannelModes[] = { {MFDES_GET_UID, DACEV1, DCCNative, DCMEncrypted}, {MFDES_CHANGE_KEY_SETTINGS, DACEV1, DCCNative, DCMEncrypted}, + + {MFDES_CHANGE_KEY, DACEV1, DCCNative, DCMEncryptedPlain}, + {MFDES_CHANGE_KEY_EV2, DACEV1, DCCNative, DCMEncryptedPlain}, }; +static uint8_t DesfireGetCmdHeaderLen(uint8_t cmd) { + if (cmd == MFDES_CHANGE_KEY || cmd == MFDES_CHANGE_CONFIGURATION) + return 1; + + if (cmd == MFDES_CHANGE_KEY_EV2) + return 2; + + return 0; +} + static void DesfireSecureChannelEncodeD40(DesfireContext *ctx, uint8_t cmd, uint8_t *srcdata, size_t srcdatalen, uint8_t *dstdata, size_t *dstdatalen) { memcpy(dstdata, srcdata, srcdatalen); *dstdatalen = srcdatalen; uint8_t data[1024] = {0}; size_t rlen = 0; + uint8_t hdrlen = DesfireGetCmdHeaderLen(cmd); switch (ctx->commMode) { case DCMPlain: @@ -89,7 +106,7 @@ static void DesfireSecureChannelEncodeD40(DesfireContext *ctx, uint8_t cmd, uint *dstdatalen = rlen; break; case DCMEncrypted: - if (srcdatalen == 0) + if (srcdatalen == 0 || srcdatalen <= hdrlen) break; rlen = padded_data_length(srcdatalen + 2, desfire_get_key_block_length(ctx->keyType)); // 2 - crc16 @@ -98,6 +115,16 @@ static void DesfireSecureChannelEncodeD40(DesfireContext *ctx, uint8_t cmd, uint DesfireCryptoEncDec(ctx, true, data, rlen, dstdata, true); *dstdatalen = rlen; break; + case DCMEncryptedPlain: + if (srcdatalen == 0 || srcdatalen <= hdrlen) + break; + + rlen = padded_data_length(srcdatalen - hdrlen, desfire_get_key_block_length(ctx->keyType)) + hdrlen; + memcpy(data, srcdata, srcdatalen); + memcpy(dstdata, srcdata, hdrlen); + DesfireCryptoEncDec(ctx, true, &data[hdrlen], rlen - hdrlen, &dstdata[hdrlen], true); + *dstdatalen = rlen; + break; case DCMNone: ; } @@ -107,6 +134,10 @@ static void DesfireSecureChannelEncodeEV1(DesfireContext *ctx, uint8_t cmd, uint uint8_t data[1024] = {0}; size_t rlen = 0; + memcpy(dstdata, srcdata, srcdatalen); + *dstdatalen = srcdatalen; + uint8_t hdrlen = DesfireGetCmdHeaderLen(cmd); + // we calc MAC anyway // if encypted channel and no data - we only calc MAC if (ctx->commMode == DCMPlain || ctx->commMode == DCMMACed || (ctx->commMode == DCMEncrypted && srcdatalen == 0)) { @@ -130,9 +161,19 @@ static void DesfireSecureChannelEncodeEV1(DesfireContext *ctx, uint8_t cmd, uint DesfireCryptoEncDec(ctx, true, &data[1], rlen, dstdata, true); *dstdatalen = rlen; - } else { - memcpy(dstdata, srcdata, srcdatalen); - *dstdatalen = srcdatalen; + } else if (ctx->commMode == DCMEncryptedPlain) { + if (srcdatalen == 0 || srcdatalen <= hdrlen) + return; + +PrintAndLogEx(SUCCESS, "--ch hdrlen: %d, cmd: %02x", hdrlen, cmd); + //dstdata[0] = cmd; + memcpy(&dstdata[0], srcdata, hdrlen); + memcpy(data, &srcdata[hdrlen], srcdatalen); + rlen = padded_data_length(srcdatalen - hdrlen, desfire_get_key_block_length(ctx->keyType)); +PrintAndLogEx(SUCCESS, "--ch src rlen: %d data: %s", rlen, sprint_hex(data, rlen)); + DesfireCryptoEncDec(ctx, true, data, rlen, &dstdata[hdrlen], true); + *dstdatalen = hdrlen + rlen; +PrintAndLogEx(SUCCESS, "--ch dst len: %d data: %s", *dstdatalen, sprint_hex(dstdata, *dstdatalen)); } } @@ -184,6 +225,7 @@ static void DesfireSecureChannelDecodeD40(DesfireContext *ctx, uint8_t *srcdata, break; case DCMPlain: case DACNone: + case DCMEncryptedPlain: memcpy(dstdata, srcdata, srcdatalen); *dstdatalen = srcdatalen; break; diff --git a/include/protocols.h b/include/protocols.h index 58bd7e90f..efa3e0a78 100644 --- a/include/protocols.h +++ b/include/protocols.h @@ -424,6 +424,7 @@ ISO 7816-4 Basic interindustry commands. For command APDU's. #define MFDES_INIT_KEY_SETTINGS 0x56 #define MFDES_FINALIZE_KEY_SETTINGS 0x57 #define MFDES_SELECT_APPLICATION 0x5A +#define MFDES_CHANGE_CONFIGURATION 0x5C #define MFDES_CHANGE_FILE_SETTINGS 0x5F #define MFDES_GET_VERSION 0x60 #define MFDES_GET_ISOFILE_IDS 0x61 From bbc4f378abfb3767518fec2ec870f41161a89c2d Mon Sep 17 00:00:00 2001 From: merlokk <807634+merlokk@users.noreply.github.com> Date: Thu, 15 Jul 2021 20:41:34 +0300 Subject: [PATCH 05/18] some info --- client/src/cmdhfmfdes.c | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/client/src/cmdhfmfdes.c b/client/src/cmdhfmfdes.c index b1ac5ce8a..a0ff539b7 100644 --- a/client/src/cmdhfmfdes.c +++ b/client/src/cmdhfmfdes.c @@ -4972,6 +4972,18 @@ static int CmdHF14ADesChangeKey(const char *Cmd) { PrintAndLogEx(WARNING, "Changing the root aid (0x000000)"); return PM3_ESOFT; // TODO!!!! } + + if (appid) + PrintAndLogEx(INFO, _CYAN_("Changing key in the application: ") _YELLOW_("%06x"), appid); + else + PrintAndLogEx(INFO, _CYAN_("Changing PICC key")); + PrintAndLogEx(INFO, "auth key %d: %s [%d] %s", dctx.keyNum, CLIGetOptionListStr(DesfireAlgoOpts, dctx.keyType), desfire_get_key_length(dctx.keyType), sprint_hex(dctx.key, desfire_get_key_length(dctx.keyType))); + PrintAndLogEx(INFO, "changing key number " _YELLOW_("0x%02x") " (%d)", newkeynum, newkeynum); + PrintAndLogEx(INFO, "old key: %s [%d] %s", CLIGetOptionListStr(DesfireAlgoOpts, newkeytype), desfire_get_key_length(oldkeytype), sprint_hex(oldkey, desfire_get_key_length(oldkeytype))); + PrintAndLogEx(INFO, "new key: %s [%d] %s", CLIGetOptionListStr(DesfireAlgoOpts, newkeytype), desfire_get_key_length(newkeytype), sprint_hex(newkey, desfire_get_key_length(newkeytype))); + if (newkeyver < 0x100 || newkeytype == T_AES) + PrintAndLogEx(INFO, "new key version: 0x%02x", newkeyver & 0x00); + res = DesfireSelectAndAuthenticate(&dctx, securechann, appid, verbose); if (res != PM3_SUCCESS) { From a35e185b5ba6de10891f1283eea8bb97af43d299 Mon Sep 17 00:00:00 2001 From: merlokk <807634+merlokk@users.noreply.github.com> Date: Fri, 16 Jul 2021 19:57:11 +0300 Subject: [PATCH 06/18] add setup oldkey if we change the same key --- client/src/cmdhfmfdes.c | 19 +++++++++++++------ 1 file changed, 13 insertions(+), 6 deletions(-) diff --git a/client/src/cmdhfmfdes.c b/client/src/cmdhfmfdes.c index a0ff539b7..706c093dc 100644 --- a/client/src/cmdhfmfdes.c +++ b/client/src/cmdhfmfdes.c @@ -4932,14 +4932,14 @@ static int CmdHF14ADesChangeKey(const char *Cmd) { uint8_t oldkey[DESFIRE_MAX_KEY_SIZE] = {0}; uint8_t keydata[200] = {0}; - int keylen = sizeof(keydata); - CLIGetHexWithReturn(ctx, 13, keydata, &keylen); - if (keylen && keylen != desfire_get_key_length(oldkeytype)) { - PrintAndLogEx(ERR, "%s old key must have %d bytes length instead of %d.", CLIGetOptionListStr(DesfireAlgoOpts, oldkeytype), desfire_get_key_length(oldkeytype), keylen); + int oldkeylen = sizeof(keydata); + CLIGetHexWithReturn(ctx, 13, keydata, &oldkeylen); + if (oldkeylen && oldkeylen != desfire_get_key_length(oldkeytype)) { + PrintAndLogEx(ERR, "%s old key must have %d bytes length instead of %d.", CLIGetOptionListStr(DesfireAlgoOpts, oldkeytype), desfire_get_key_length(oldkeytype), oldkeylen); return PM3_EINVARG; } - if (keylen) - memcpy(oldkey, keydata, keylen); + if (oldkeylen) + memcpy(oldkey, keydata, oldkeylen); uint8_t newkeynum = arg_get_int_def(ctx, 14, 0); @@ -4949,6 +4949,7 @@ static int CmdHF14ADesChangeKey(const char *Cmd) { uint8_t newkey[DESFIRE_MAX_KEY_SIZE] = {0}; memset(keydata, 0x00, sizeof(keydata)); + int keylen = sizeof(keydata); CLIGetHexWithReturn(ctx, 16, keydata, &keylen); if (keylen && keylen != desfire_get_key_length(newkeytype)) { PrintAndLogEx(ERR, "%s new key must have %d bytes length instead of %d.", CLIGetOptionListStr(DesfireAlgoOpts, newkeytype), desfire_get_key_length(newkeytype), keylen); @@ -4967,6 +4968,12 @@ static int CmdHF14ADesChangeKey(const char *Cmd) { SetAPDULogging(APDULogging); CLIParserFree(ctx); + + // if we change the same key + if (oldkeylen == 0 && newkeynum == dctx.keyNum) { + oldkeytype = dctx.keyType; + memcpy(oldkey, dctx.key, desfire_get_key_length(dctx.keyType)); + } if (appid == 0x000000) { PrintAndLogEx(WARNING, "Changing the root aid (0x000000)"); From bdac4cb48d2b3d7ba9ad164253cd1ebaafff07ab Mon Sep 17 00:00:00 2001 From: merlokk <807634+merlokk@users.noreply.github.com> Date: Fri, 16 Jul 2021 20:05:14 +0300 Subject: [PATCH 07/18] print the new key if we put the key version into the des key --- client/src/cmdhfmfdes.c | 3 +-- client/src/mifare/desfirecore.c | 7 +++++-- client/src/mifare/desfirecore.h | 2 +- 3 files changed, 7 insertions(+), 5 deletions(-) diff --git a/client/src/cmdhfmfdes.c b/client/src/cmdhfmfdes.c index 706c093dc..431508777 100644 --- a/client/src/cmdhfmfdes.c +++ b/client/src/cmdhfmfdes.c @@ -4991,7 +4991,6 @@ static int CmdHF14ADesChangeKey(const char *Cmd) { if (newkeyver < 0x100 || newkeytype == T_AES) PrintAndLogEx(INFO, "new key version: 0x%02x", newkeyver & 0x00); - res = DesfireSelectAndAuthenticate(&dctx, securechann, appid, verbose); if (res != PM3_SUCCESS) { DropField(); @@ -4999,7 +4998,7 @@ static int CmdHF14ADesChangeKey(const char *Cmd) { } DesfireSetCommMode(&dctx, DCMEncryptedPlain); - res = DesfireChangeKey(&dctx, newkeynum, newkeytype, newkeyver, newkey, oldkeytype, oldkey); + res = DesfireChangeKey(&dctx, newkeynum, newkeytype, newkeyver, newkey, oldkeytype, oldkey, true); if (res == PM3_SUCCESS) { PrintAndLogEx(SUCCESS, "Change key " _GREEN_("ok") " "); } else { diff --git a/client/src/mifare/desfirecore.c b/client/src/mifare/desfirecore.c index 42d52e4c7..2554e9288 100644 --- a/client/src/mifare/desfirecore.c +++ b/client/src/mifare/desfirecore.c @@ -1079,7 +1079,7 @@ void PrintKeySettings(uint8_t keysettings, uint8_t numkeys, bool applevel, bool PrintKeySettingsPICC(keysettings, numkeys, print2ndbyte); } -int DesfireChangeKey(DesfireContext *dctx, uint8_t newkeynum, DesfireCryptoAlgorythm newkeytype, uint32_t newkeyver, uint8_t *newkey, DesfireCryptoAlgorythm oldkeytype, uint8_t *oldkey) { +int DesfireChangeKey(DesfireContext *dctx, uint8_t newkeynum, DesfireCryptoAlgorythm newkeytype, uint32_t newkeyver, uint8_t *newkey, DesfireCryptoAlgorythm oldkeytype, uint8_t *oldkey, bool verbose) { uint8_t okeybuf[DESFIRE_MAX_KEY_SIZE] = {0}; uint8_t nkeybuf[DESFIRE_MAX_KEY_SIZE] = {0}; @@ -1107,8 +1107,11 @@ PrintAndLogEx(SUCCESS, "--oldk [%d]: %s", desfire_get_key_length(oldkeytype), sp PrintAndLogEx(SUCCESS, "--newk [%d]: %s", nkeylen, sprint_hex(nkeybuf, nkeylen)); // set key version for DES. if newkeyver > 0xff - setting key version is disabled - if (newkeytype != T_AES && newkeyver < 0x100) + if (newkeytype != T_AES && newkeyver < 0x100) { DesfireDESKeySetVersion(nkeybuf, newkeytype, newkeyver); + if (verbose) + PrintAndLogEx(INFO, "changed new key: %s [%d] %s", CLIGetOptionListStr(DesfireAlgoOpts, newkeytype), desfire_get_key_length(newkeytype), sprint_hex(newkey, desfire_get_key_length(newkeytype))); + } PrintAndLogEx(SUCCESS, "--newk [%d]: %s", nkeylen, sprint_hex(nkeybuf, nkeylen)); diff --git a/client/src/mifare/desfirecore.h b/client/src/mifare/desfirecore.h index fb04d21f0..31053162a 100644 --- a/client/src/mifare/desfirecore.h +++ b/client/src/mifare/desfirecore.h @@ -56,6 +56,6 @@ void PrintKeySettings(uint8_t keysettings, uint8_t numkeys, bool applevel, bool uint8_t DesfireKeyAlgoToType(DesfireCryptoAlgorythm keyType); int DesfireChangeKeyCmd(DesfireContext *dctx, uint8_t *data, size_t datalen, uint8_t *resp, size_t *resplen); -int DesfireChangeKey(DesfireContext *dctx, uint8_t newkeynum, DesfireCryptoAlgorythm newkeytype, uint32_t newkeyver, uint8_t *newkey, DesfireCryptoAlgorythm oldkeytype, uint8_t *oldkey); +int DesfireChangeKey(DesfireContext *dctx, uint8_t newkeynum, DesfireCryptoAlgorythm newkeytype, uint32_t newkeyver, uint8_t *newkey, DesfireCryptoAlgorythm oldkeytype, uint8_t *oldkey, bool verbose); #endif // __DESFIRECORE_H From cf63b9e022bb36ea4237e8b4acdbd128b85cffaf Mon Sep 17 00:00:00 2001 From: merlokk <807634+merlokk@users.noreply.github.com> Date: Fri, 16 Jul 2021 20:11:41 +0300 Subject: [PATCH 08/18] make style --- client/src/cmdhfmfdes.c | 178 +++++++++++++------------- client/src/mifare/desfirecore.c | 40 +++--- client/src/mifare/desfiresecurechan.c | 10 +- 3 files changed, 114 insertions(+), 114 deletions(-) diff --git a/client/src/cmdhfmfdes.c b/client/src/cmdhfmfdes.c index 431508777..2f3bcf30b 100644 --- a/client/src/cmdhfmfdes.c +++ b/client/src/cmdhfmfdes.c @@ -1060,10 +1060,10 @@ static int handler_desfire_freemem(uint32_t *free_mem) { // AID == 000000 6bits LSB needs to be 0 key_no &= 0x0F; - + Desfire treats Des keys as TDes but with the first half = 2nd half As such, we should be able to convert the Des to TDes then run the code as TDes - + if (new_algo == MFDES_ALGO_DES) { memcpy(&new_key[8], new_key, 8); new_algo = MFDES_ALGO_3DES; @@ -4906,7 +4906,7 @@ static int CmdHF14ADesChangeKey(const char *Cmd) { arg_str0(NULL, "aid", "", "Application ID of application (3 hex bytes, big endian)"), arg_str0(NULL, "oldalgo", "", "Old key crypto algorithm: DES, 2TDEA, 3TDEA, AES"), arg_str0(NULL, "oldkey", "", "Old key (HEX 8(DES), 16(2TDEA or AES) or 24(3TDEA) bytes)"), - arg_int0(NULL, "newkeyno","", "Key number for change"), + arg_int0(NULL, "newkeyno", "", "Key number for change"), arg_str0(NULL, "newalgo", "", "New key crypto algorithm: DES, 2TDEA, 3TDEA, AES"), arg_str0(NULL, "newkey", "", "New key (HEX 8(DES), 16(2TDEA or AES) or 24(3TDEA) bytes)"), arg_str0(NULL, "newver", "", "New key's version (1 hex byte)"), @@ -4929,7 +4929,7 @@ static int CmdHF14ADesChangeKey(const char *Cmd) { int oldkeytype = T_DES; if (CLIGetOptionList(arg_get_str(ctx, 12), DesfireAlgoOpts, &oldkeytype)) return PM3_ESOFT; - + uint8_t oldkey[DESFIRE_MAX_KEY_SIZE] = {0}; uint8_t keydata[200] = {0}; int oldkeylen = sizeof(keydata); @@ -4940,7 +4940,7 @@ static int CmdHF14ADesChangeKey(const char *Cmd) { } if (oldkeylen) memcpy(oldkey, keydata, oldkeylen); - + uint8_t newkeynum = arg_get_int_def(ctx, 14, 0); int newkeytype = T_DES; @@ -4968,7 +4968,7 @@ static int CmdHF14ADesChangeKey(const char *Cmd) { SetAPDULogging(APDULogging); CLIParserFree(ctx); - + // if we change the same key if (oldkeylen == 0 && newkeynum == dctx.keyNum) { oldkeytype = dctx.keyType; @@ -4979,7 +4979,7 @@ static int CmdHF14ADesChangeKey(const char *Cmd) { PrintAndLogEx(WARNING, "Changing the root aid (0x000000)"); return PM3_ESOFT; // TODO!!!! } - + if (appid) PrintAndLogEx(INFO, _CYAN_("Changing key in the application: ") _YELLOW_("%06x"), appid); else @@ -4990,7 +4990,7 @@ static int CmdHF14ADesChangeKey(const char *Cmd) { PrintAndLogEx(INFO, "new key: %s [%d] %s", CLIGetOptionListStr(DesfireAlgoOpts, newkeytype), desfire_get_key_length(newkeytype), sprint_hex(newkey, desfire_get_key_length(newkeytype))); if (newkeyver < 0x100 || newkeytype == T_AES) PrintAndLogEx(INFO, "new key version: 0x%02x", newkeyver & 0x00); - + res = DesfireSelectAndAuthenticate(&dctx, securechann, appid, verbose); if (res != PM3_SUCCESS) { DropField(); @@ -5023,99 +5023,99 @@ static int CmdHF14ADesChangeKey(const char *Cmd) { -/* CLIParserContext *ctx; - CLIParserInit(&ctx, "hf mfdes changekey", - "Change MIFARE DESFire Key.\n" - "Make sure to select aid or authenticate aid before running this command.", - "hf mfdes changekey -n 0 -t 1 -k 0000000000000000 -u 1 -j 0102030405060708 -> DES, keynumber 0" - ); + /* CLIParserContext *ctx; + CLIParserInit(&ctx, "hf mfdes changekey", + "Change MIFARE DESFire Key.\n" + "Make sure to select aid or authenticate aid before running this command.", + "hf mfdes changekey -n 0 -t 1 -k 0000000000000000 -u 1 -j 0102030405060708 -> DES, keynumber 0" + ); - void *argtable[] = { - arg_param_begin, - arg_int0("n", "keyno", "", "Key number used for authentification"), - arg_int0("t", "algo", "", "Current key algo (1 = DES, 2 = 3DES(2K2DES), 3 = 3K3DES, 4 = AES)"), - arg_str0("k", "key", "", "Current Key (HEX 8-24 bytes)"), - arg_int0("u", "newalgo", "", "New key algo (1 = DES, 2 = 3DES(2K2DES), 3 = 3K3DES, 4 = AES)"), - arg_str0("j", "newkey", "", "New Key (HEX 8-24 bytes)"), - arg_int0("v", "aesver", "", "AES version (if AES is used)"), - arg_param_end - }; - CLIExecWithReturn(ctx, Cmd, argtable, false); + void *argtable[] = { + arg_param_begin, + arg_int0("n", "keyno", "", "Key number used for authentification"), + arg_int0("t", "algo", "", "Current key algo (1 = DES, 2 = 3DES(2K2DES), 3 = 3K3DES, 4 = AES)"), + arg_str0("k", "key", "", "Current Key (HEX 8-24 bytes)"), + arg_int0("u", "newalgo", "", "New key algo (1 = DES, 2 = 3DES(2K2DES), 3 = 3K3DES, 4 = AES)"), + arg_str0("j", "newkey", "", "New Key (HEX 8-24 bytes)"), + arg_int0("v", "aesver", "", "AES version (if AES is used)"), + arg_param_end + }; + CLIExecWithReturn(ctx, Cmd, argtable, false); - uint8_t cmdKeyNo = arg_get_int_def(ctx, 1, 0); - uint8_t cmdAuthAlgo = arg_get_int_def(ctx, 2, 0); - uint8_t key[24] = {0}; - int keylen = 0; - int res_klen = CLIParamHexToBuf(arg_get_str(ctx, 3), key, 24, &keylen); + uint8_t cmdKeyNo = arg_get_int_def(ctx, 1, 0); + uint8_t cmdAuthAlgo = arg_get_int_def(ctx, 2, 0); + uint8_t key[24] = {0}; + int keylen = 0; + int res_klen = CLIParamHexToBuf(arg_get_str(ctx, 3), key, 24, &keylen); - uint8_t newcmdAuthAlgo = arg_get_int_def(ctx, 4, 0); - uint8_t newkey[24] = {0}; - int newkeylen = 0; - int res_newklen = CLIParamHexToBuf(arg_get_str(ctx, 5), newkey, 24, &newkeylen); + uint8_t newcmdAuthAlgo = arg_get_int_def(ctx, 4, 0); + uint8_t newkey[24] = {0}; + int newkeylen = 0; + int res_newklen = CLIParamHexToBuf(arg_get_str(ctx, 5), newkey, 24, &newkeylen); - uint8_t aesversion = arg_get_int_def(ctx, 6, 0); - CLIParserFree(ctx); + uint8_t aesversion = arg_get_int_def(ctx, 6, 0); + CLIParserFree(ctx); - //DropFieldDesfire(); - // NR DESC KEYLENGHT - // ------------------------ - // 1 = DES 8 - // 2 = 3DES 16 - // 3 = 3K 3DES 24 - // 4 = AES 16 - uint8_t keylength = 8; - if (cmdAuthAlgo == MFDES_ALGO_AES) { - keylength = 16; - } else if (cmdAuthAlgo == MFDES_ALGO_3DES) { - keylength = 16; - } else if (cmdAuthAlgo == MFDES_ALGO_DES) { - keylength = 8; - } else if (cmdAuthAlgo == MFDES_ALGO_3K3DES) { - keylength = 24; - } + //DropFieldDesfire(); + // NR DESC KEYLENGHT + // ------------------------ + // 1 = DES 8 + // 2 = 3DES 16 + // 3 = 3K 3DES 24 + // 4 = AES 16 + uint8_t keylength = 8; + if (cmdAuthAlgo == MFDES_ALGO_AES) { + keylength = 16; + } else if (cmdAuthAlgo == MFDES_ALGO_3DES) { + keylength = 16; + } else if (cmdAuthAlgo == MFDES_ALGO_DES) { + keylength = 8; + } else if (cmdAuthAlgo == MFDES_ALGO_3K3DES) { + keylength = 24; + } - uint8_t newkeylength = 8; - if (newcmdAuthAlgo == MFDES_ALGO_AES) { - newkeylength = 16; - } else if (newcmdAuthAlgo == MFDES_ALGO_3DES) { - newkeylength = 16; - } else if (newcmdAuthAlgo == MFDES_ALGO_DES) { - newkeylength = 8; - } else if (newcmdAuthAlgo == MFDES_ALGO_3K3DES) { - newkeylength = 24; - } + uint8_t newkeylength = 8; + if (newcmdAuthAlgo == MFDES_ALGO_AES) { + newkeylength = 16; + } else if (newcmdAuthAlgo == MFDES_ALGO_3DES) { + newkeylength = 16; + } else if (newcmdAuthAlgo == MFDES_ALGO_DES) { + newkeylength = 8; + } else if (newcmdAuthAlgo == MFDES_ALGO_3K3DES) { + newkeylength = 24; + } - if (res_klen || (keylen < 8) || (keylen > 24)) { - PrintAndLogEx(ERR, "Specified key must have %d bytes length", keylen); - return PM3_EINVARG; - } + if (res_klen || (keylen < 8) || (keylen > 24)) { + PrintAndLogEx(ERR, "Specified key must have %d bytes length", keylen); + return PM3_EINVARG; + } - if (res_newklen || (newkeylen < 8) || (newkeylen > 24)) { - PrintAndLogEx(ERR, "Specified new key must have %d bytes length", newkeylen); - return PM3_EINVARG; - } + if (res_newklen || (newkeylen < 8) || (newkeylen > 24)) { + PrintAndLogEx(ERR, "Specified new key must have %d bytes length", newkeylen); + return PM3_EINVARG; + } - if (keylen != keylength) { - PrintAndLogEx(WARNING, "Key must include %d hex symbols, got %d", keylength, keylen); - return PM3_EINVARG; - } + if (keylen != keylength) { + PrintAndLogEx(WARNING, "Key must include %d hex symbols, got %d", keylength, keylen); + return PM3_EINVARG; + } - if (newkeylen != newkeylength) { - PrintAndLogEx(WARNING, "New key must include %d hex symbols, got %d", keylength, newkeylen); - return PM3_EINVARG; - } + if (newkeylen != newkeylength) { + PrintAndLogEx(WARNING, "New key must include %d hex symbols, got %d", keylength, newkeylen); + return PM3_EINVARG; + } - PrintAndLogEx(INFO, "changing key number " _YELLOW_("0x%02x"), cmdKeyNo); - PrintAndLogEx(INFO, "old key: %s ( %s )", sprint_hex_inrow(key, keylen), getEncryptionAlgoStr(cmdAuthAlgo)); - PrintAndLogEx(INFO, "new key: %s ( %s )", sprint_hex_inrow(newkey, newkeylen), getEncryptionAlgoStr(newcmdAuthAlgo)); + PrintAndLogEx(INFO, "changing key number " _YELLOW_("0x%02x"), cmdKeyNo); + PrintAndLogEx(INFO, "old key: %s ( %s )", sprint_hex_inrow(key, keylen), getEncryptionAlgoStr(cmdAuthAlgo)); + PrintAndLogEx(INFO, "new key: %s ( %s )", sprint_hex_inrow(newkey, newkeylen), getEncryptionAlgoStr(newcmdAuthAlgo)); - int res = mifare_desfire_change_key(cmdKeyNo, newkey, newcmdAuthAlgo, key, cmdAuthAlgo, aesversion); - if (res == PM3_SUCCESS) { - PrintAndLogEx(SUCCESS, "Change key ( " _GREEN_("ok") " )"); - } else { - PrintAndLogEx(FAILED, "Change key ( " _RED_("fail") " )"); - } - return res;*/ + int res = mifare_desfire_change_key(cmdKeyNo, newkey, newcmdAuthAlgo, key, cmdAuthAlgo, aesversion); + if (res == PM3_SUCCESS) { + PrintAndLogEx(SUCCESS, "Change key ( " _GREEN_("ok") " )"); + } else { + PrintAndLogEx(FAILED, "Change key ( " _RED_("fail") " )"); + } + return res;*/ } static int CmdHF14ADesCreateApp(const char *Cmd) { diff --git a/client/src/mifare/desfirecore.c b/client/src/mifare/desfirecore.c index 2554e9288..0045ca1b0 100644 --- a/client/src/mifare/desfirecore.c +++ b/client/src/mifare/desfirecore.c @@ -1080,7 +1080,7 @@ void PrintKeySettings(uint8_t keysettings, uint8_t numkeys, bool applevel, bool } int DesfireChangeKey(DesfireContext *dctx, uint8_t newkeynum, DesfireCryptoAlgorythm newkeytype, uint32_t newkeyver, uint8_t *newkey, DesfireCryptoAlgorythm oldkeytype, uint8_t *oldkey, bool verbose) { - + uint8_t okeybuf[DESFIRE_MAX_KEY_SIZE] = {0}; uint8_t nkeybuf[DESFIRE_MAX_KEY_SIZE] = {0}; uint8_t pckcdata[DESFIRE_MAX_KEY_SIZE + 10] = {0}; @@ -1089,22 +1089,22 @@ int DesfireChangeKey(DesfireContext *dctx, uint8_t newkeynum, DesfireCryptoAlgor keynodata |= (DesfireKeyAlgoToType(newkeytype) & 0x03) << 6; pckcdata[0] = MFDES_CHANGE_KEY; // TODO pckcdata[1] = keynodata; - + // DES -> 2TDEA memcpy(okeybuf, oldkey, desfire_get_key_length(oldkeytype)); if (oldkeytype == T_DES) { memcpy(&okeybuf[8], oldkey, 8); - } + } memcpy(nkeybuf, newkey, desfire_get_key_length(newkeytype)); size_t nkeylen = desfire_get_key_length(newkeytype); if (newkeytype == T_DES) { memcpy(&nkeybuf[8], newkey, 8); nkeylen = desfire_get_key_length(T_3DES); - } + } -PrintAndLogEx(SUCCESS, "--oldk [%d]: %s", desfire_get_key_length(oldkeytype), sprint_hex(okeybuf, desfire_get_key_length(oldkeytype))); -PrintAndLogEx(SUCCESS, "--newk [%d]: %s", nkeylen, sprint_hex(nkeybuf, nkeylen)); + PrintAndLogEx(SUCCESS, "--oldk [%d]: %s", desfire_get_key_length(oldkeytype), sprint_hex(okeybuf, desfire_get_key_length(oldkeytype))); + PrintAndLogEx(SUCCESS, "--newk [%d]: %s", nkeylen, sprint_hex(nkeybuf, nkeylen)); // set key version for DES. if newkeyver > 0xff - setting key version is disabled if (newkeytype != T_AES && newkeyver < 0x100) { @@ -1112,9 +1112,9 @@ PrintAndLogEx(SUCCESS, "--newk [%d]: %s", nkeylen, sprint_hex(nkeybuf, nkeylen)) if (verbose) PrintAndLogEx(INFO, "changed new key: %s [%d] %s", CLIGetOptionListStr(DesfireAlgoOpts, newkeytype), desfire_get_key_length(newkeytype), sprint_hex(newkey, desfire_get_key_length(newkeytype))); } - -PrintAndLogEx(SUCCESS, "--newk [%d]: %s", nkeylen, sprint_hex(nkeybuf, nkeylen)); - + + PrintAndLogEx(SUCCESS, "--newk [%d]: %s", nkeylen, sprint_hex(nkeybuf, nkeylen)); + // xor if we change current auth key if (newkeynum == dctx->keyNum) { memcpy(cdata, nkeybuf, nkeylen); @@ -1122,16 +1122,16 @@ PrintAndLogEx(SUCCESS, "--newk [%d]: %s", nkeylen, sprint_hex(nkeybuf, nkeylen)) memcpy(cdata, nkeybuf, nkeylen); bin_xor(cdata, okeybuf, nkeylen); } - + // add key version for AES size_t cdatalen = nkeylen; -PrintAndLogEx(SUCCESS, "--cdata [%d]: %s kv = 0x%02x", cdatalen, sprint_hex(cdata, cdatalen), newkeyver); + PrintAndLogEx(SUCCESS, "--cdata [%d]: %s kv = 0x%02x", cdatalen, sprint_hex(cdata, cdatalen), newkeyver); if (newkeytype == T_AES) { cdata[cdatalen] = newkeyver; cdatalen++; } -PrintAndLogEx(SUCCESS, "--cdata [%d]: %s", cdatalen, sprint_hex(cdata, cdatalen)); - + PrintAndLogEx(SUCCESS, "--cdata [%d]: %s", cdatalen, sprint_hex(cdata, cdatalen)); + // add crc||crc_new_key if (dctx->secureChannel == DACd40) { iso14443a_crc_append(cdata, cdatalen); @@ -1149,23 +1149,23 @@ PrintAndLogEx(SUCCESS, "--cdata [%d]: %s", cdatalen, sprint_hex(cdata, cdatalen) cdatalen += 4; } } -PrintAndLogEx(SUCCESS, "--cdata [%d]: %s", cdatalen, sprint_hex(cdata, cdatalen)); - + PrintAndLogEx(SUCCESS, "--cdata [%d]: %s", cdatalen, sprint_hex(cdata, cdatalen)); + // get padded data length size_t rlen = padded_data_length(cdatalen, desfire_get_key_block_length(newkeytype)); - + // send command uint8_t resp[257] = {0}; size_t resplen = 0; -PrintAndLogEx(SUCCESS, "--pckdata [%d]: %s", rlen + 1, sprint_hex(&pckcdata[1], rlen + 1)); + PrintAndLogEx(SUCCESS, "--pckdata [%d]: %s", rlen + 1, sprint_hex(&pckcdata[1], rlen + 1)); int res = DesfireChangeKeyCmd(dctx, &pckcdata[1], rlen + 1, resp, &resplen); - + // check response - + // clear auth if (newkeynum == dctx->keyNum) DesfireClearSession(dctx); - + return res; } diff --git a/client/src/mifare/desfiresecurechan.c b/client/src/mifare/desfiresecurechan.c index c5b90c29d..c5407f627 100644 --- a/client/src/mifare/desfiresecurechan.c +++ b/client/src/mifare/desfiresecurechan.c @@ -74,10 +74,10 @@ AllowedChannelModesS AllowedChannelModes[] = { static uint8_t DesfireGetCmdHeaderLen(uint8_t cmd) { if (cmd == MFDES_CHANGE_KEY || cmd == MFDES_CHANGE_CONFIGURATION) return 1; - + if (cmd == MFDES_CHANGE_KEY_EV2) return 2; - + return 0; } @@ -165,15 +165,15 @@ static void DesfireSecureChannelEncodeEV1(DesfireContext *ctx, uint8_t cmd, uint if (srcdatalen == 0 || srcdatalen <= hdrlen) return; -PrintAndLogEx(SUCCESS, "--ch hdrlen: %d, cmd: %02x", hdrlen, cmd); + PrintAndLogEx(SUCCESS, "--ch hdrlen: %d, cmd: %02x", hdrlen, cmd); //dstdata[0] = cmd; memcpy(&dstdata[0], srcdata, hdrlen); memcpy(data, &srcdata[hdrlen], srcdatalen); rlen = padded_data_length(srcdatalen - hdrlen, desfire_get_key_block_length(ctx->keyType)); -PrintAndLogEx(SUCCESS, "--ch src rlen: %d data: %s", rlen, sprint_hex(data, rlen)); + PrintAndLogEx(SUCCESS, "--ch src rlen: %d data: %s", rlen, sprint_hex(data, rlen)); DesfireCryptoEncDec(ctx, true, data, rlen, &dstdata[hdrlen], true); *dstdatalen = hdrlen + rlen; -PrintAndLogEx(SUCCESS, "--ch dst len: %d data: %s", *dstdatalen, sprint_hex(dstdata, *dstdatalen)); + PrintAndLogEx(SUCCESS, "--ch dst len: %d data: %s", *dstdatalen, sprint_hex(dstdata, *dstdatalen)); } } From 1699d8a90e988035b6450fd52945d68b49a46059 Mon Sep 17 00:00:00 2001 From: merlokk <807634+merlokk@users.noreply.github.com> Date: Fri, 16 Jul 2021 20:45:03 +0300 Subject: [PATCH 09/18] add des3 to libcrypto --- client/src/crypto/libpcrypto.c | 48 ++++++++++++++++++++++++++++++++++ client/src/crypto/libpcrypto.h | 2 ++ 2 files changed, 50 insertions(+) diff --git a/client/src/crypto/libpcrypto.c b/client/src/crypto/libpcrypto.c index 32686b199..8c4bdd8fc 100644 --- a/client/src/crypto/libpcrypto.c +++ b/client/src/crypto/libpcrypto.c @@ -65,6 +65,54 @@ void des_decrypt_cbc(void *out, const void *in, const int length, const void *ke mbedtls_des_crypt_cbc(&ctx, MBEDTLS_DES_DECRYPT, length, iv, in, out); } +void des3_encrypt(void *out, const void *in, const void *key, uint8_t keycount) { + switch (keycount) { + case 1: + des_encrypt(out, in, key); + break; + case 2: { + mbedtls_des3_context ctx3; + mbedtls_des3_set2key_enc(&ctx3, key); + mbedtls_des3_crypt_ecb(&ctx3, in, out); + mbedtls_des3_free(&ctx3); + break; + } + case 3: { + mbedtls_des3_context ctx3; + mbedtls_des3_set3key_enc(&ctx3, key); + mbedtls_des3_crypt_ecb(&ctx3, in, out); + mbedtls_des3_free(&ctx3); + break; + } + default: + break; + } +} + +void des3_decrypt(void *out, const void *in, const void *key, uint8_t keycount) { + switch (keycount) { + case 1: + des_encrypt(out, in, key); + break; + case 2: { + mbedtls_des3_context ctx3; + mbedtls_des3_set2key_dec(&ctx3, key); + mbedtls_des3_crypt_ecb(&ctx3, in, out); + mbedtls_des3_free(&ctx3); + break; + } + case 3: { + mbedtls_des3_context ctx3; + mbedtls_des3_set3key_dec(&ctx3, key); + mbedtls_des3_crypt_ecb(&ctx3, in, out); + mbedtls_des3_free(&ctx3); + break; + } + default: + break; + } +} + // NIST Special Publication 800-38A — Recommendation for block cipher modes of operation: methods and techniques, 2001. int aes_encode(uint8_t *iv, uint8_t *key, uint8_t *input, uint8_t *output, int length) { uint8_t iiv[16] = {0}; diff --git a/client/src/crypto/libpcrypto.h b/client/src/crypto/libpcrypto.h index 3f3bdb45b..0a9cb01ce 100644 --- a/client/src/crypto/libpcrypto.h +++ b/client/src/crypto/libpcrypto.h @@ -22,6 +22,8 @@ void des_encrypt_ecb(void *out, const void *in, const int length, const void *ke void des_decrypt_ecb(void *out, const void *in, const int length, const void *key); void des_encrypt_cbc(void *out, const void *in, const int length, const void *key, uint8_t *iv); void des_decrypt_cbc(void *out, const void *in, const int length, const void *key, uint8_t *iv); +void des3_encrypt(void *out, const void *in, const void *key, uint8_t keycount); +void des3_decrypt(void *out, const void *in, const void *key, uint8_t keycount); int aes_encode(uint8_t *iv, uint8_t *key, uint8_t *input, uint8_t *output, int length); int aes_decode(uint8_t *iv, uint8_t *key, uint8_t *input, uint8_t *output, int length); From 6a6ec86791ee95eebd43a51163894ba338e8ff7c Mon Sep 17 00:00:00 2001 From: merlokk <807634+merlokk@users.noreply.github.com> Date: Fri, 16 Jul 2021 20:45:32 +0300 Subject: [PATCH 10/18] fix 2tdea/d40 authentication --- client/src/cmdhfmfdes.c | 2 +- client/src/mifare/desfirecore.c | 15 +++++++++++++-- 2 files changed, 14 insertions(+), 3 deletions(-) diff --git a/client/src/cmdhfmfdes.c b/client/src/cmdhfmfdes.c index 2f3bcf30b..6889465e8 100644 --- a/client/src/cmdhfmfdes.c +++ b/client/src/cmdhfmfdes.c @@ -4986,7 +4986,7 @@ static int CmdHF14ADesChangeKey(const char *Cmd) { PrintAndLogEx(INFO, _CYAN_("Changing PICC key")); PrintAndLogEx(INFO, "auth key %d: %s [%d] %s", dctx.keyNum, CLIGetOptionListStr(DesfireAlgoOpts, dctx.keyType), desfire_get_key_length(dctx.keyType), sprint_hex(dctx.key, desfire_get_key_length(dctx.keyType))); PrintAndLogEx(INFO, "changing key number " _YELLOW_("0x%02x") " (%d)", newkeynum, newkeynum); - PrintAndLogEx(INFO, "old key: %s [%d] %s", CLIGetOptionListStr(DesfireAlgoOpts, newkeytype), desfire_get_key_length(oldkeytype), sprint_hex(oldkey, desfire_get_key_length(oldkeytype))); + PrintAndLogEx(INFO, "old key: %s [%d] %s", CLIGetOptionListStr(DesfireAlgoOpts, oldkeytype), desfire_get_key_length(oldkeytype), sprint_hex(oldkey, desfire_get_key_length(oldkeytype))); PrintAndLogEx(INFO, "new key: %s [%d] %s", CLIGetOptionListStr(DesfireAlgoOpts, newkeytype), desfire_get_key_length(newkeytype), sprint_hex(newkey, desfire_get_key_length(newkeytype))); if (newkeyver < 0x100 || newkeytype == T_AES) PrintAndLogEx(INFO, "new key version: 0x%02x", newkeyver & 0x00); diff --git a/client/src/mifare/desfirecore.c b/client/src/mifare/desfirecore.c index 0045ca1b0..8dd599142 100644 --- a/client/src/mifare/desfirecore.c +++ b/client/src/mifare/desfirecore.c @@ -764,7 +764,15 @@ int DesfireAuthenticate(DesfireContext *dctx, DesfireSecureChannel secureChannel des_decrypt(encRndB, rotRndB, key->data); memcpy(both + rndlen, encRndB, rndlen); } else if (dctx->keyType == T_3DES) { - //TODO + des3_decrypt(encRndA, RndA, key->data, 2); + memcpy(both, encRndA, rndlen); + + for (uint32_t x = 0; x < rndlen; x++) { + rotRndB[x] = rotRndB[x] ^ encRndA[x]; + } + + des3_decrypt(encRndB, rotRndB, key->data, 2); + memcpy(both + rndlen, encRndB, rndlen); } } else if (secureChannel == DACEV1 && dctx->keyType != T_AES) { if (dctx->keyType == T_DES) { @@ -857,7 +865,10 @@ int DesfireAuthenticate(DesfireContext *dctx, DesfireSecureChannel secureChannel if (secureChannel == DACEV1) des_decrypt_cbc(encRndA, encRndA, rndlen, key->data, IV); } else if (dctx->keyType == T_3DES) - tdes_nxp_receive(encRndA, encRndA, rndlen, key->data, IV, 2); + if (secureChannel == DACd40) + des3_decrypt(encRndA, encRndA, key->data, 2); + else + tdes_nxp_receive(encRndA, encRndA, rndlen, key->data, IV, 2); else if (dctx->keyType == T_3K3DES) tdes_nxp_receive(encRndA, encRndA, rndlen, key->data, IV, 3); else if (dctx->keyType == T_AES) { From 31334da0c4d138f20bbd979b4e3f94bb702abecf Mon Sep 17 00:00:00 2001 From: merlokk <807634+merlokk@users.noreply.github.com> Date: Mon, 19 Jul 2021 09:38:32 +0300 Subject: [PATCH 11/18] fix key type defsults --- client/src/cmdhfmfdes.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/client/src/cmdhfmfdes.c b/client/src/cmdhfmfdes.c index 6889465e8..309444220 100644 --- a/client/src/cmdhfmfdes.c +++ b/client/src/cmdhfmfdes.c @@ -4926,7 +4926,7 @@ static int CmdHF14ADesChangeKey(const char *Cmd) { return res; } - int oldkeytype = T_DES; + int oldkeytype = dctx.keyType; if (CLIGetOptionList(arg_get_str(ctx, 12), DesfireAlgoOpts, &oldkeytype)) return PM3_ESOFT; @@ -4943,7 +4943,7 @@ static int CmdHF14ADesChangeKey(const char *Cmd) { uint8_t newkeynum = arg_get_int_def(ctx, 14, 0); - int newkeytype = T_DES; + int newkeytype = oldkeytype; if (CLIGetOptionList(arg_get_str(ctx, 15), DesfireAlgoOpts, &newkeytype)) return PM3_ESOFT; From 4c686799ab80eff0fb66534d4c7da8b7b332bbcb Mon Sep 17 00:00:00 2001 From: merlokk <807634+merlokk@users.noreply.github.com> Date: Mon, 19 Jul 2021 17:33:35 +0300 Subject: [PATCH 12/18] add allowed secure channel check --- client/src/mifare/desfiresecurechan.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/client/src/mifare/desfiresecurechan.c b/client/src/mifare/desfiresecurechan.c index c5407f627..4c3dcd76b 100644 --- a/client/src/mifare/desfiresecurechan.c +++ b/client/src/mifare/desfiresecurechan.c @@ -46,6 +46,7 @@ AllowedChannelModesS AllowedChannelModes[] = { {MFDES_FINALIZE_KEY_SETTINGS, DACd40, DCCNative, DCMMACed}, {MFDES_ROLL_KEY_SETTINGS, DACd40, DCCNative, DCMMACed}, {MFDES_COMMIT_READER_ID, DACd40, DCCNative, DCMMACed}, + {MFDES_FORMAT_PICC, DACd40, DCCNative, DCMMACed}, {MFDES_GET_UID, DACd40, DCCNative, DCMEncrypted}, {MFDES_CHANGE_KEY_SETTINGS, DACd40, DCCNative, DCMEncrypted}, @@ -63,6 +64,7 @@ AllowedChannelModesS AllowedChannelModes[] = { {MFDES_GET_APPLICATION_IDS, DACEV1, DCCNative, DCMMACed}, {MFDES_GET_DF_NAMES, DACEV1, DCCNative, DCMMACed}, {MFDES_GET_KEY_SETTINGS, DACEV1, DCCNative, DCMMACed}, + {MFDES_FORMAT_PICC, DACEV1, DCCNative, DCMMACed}, {MFDES_GET_UID, DACEV1, DCCNative, DCMEncrypted}, {MFDES_CHANGE_KEY_SETTINGS, DACEV1, DCCNative, DCMEncrypted}, From 449f4edcb048295dfa0a6c515fb35c923fb98ff1 Mon Sep 17 00:00:00 2001 From: merlokk <807634+merlokk@users.noreply.github.com> Date: Mon, 19 Jul 2021 18:32:10 +0300 Subject: [PATCH 13/18] restrict change key algo --- client/src/cmdhfmfdes.c | 2 +- client/src/mifare/desfirecore.c | 12 ++++++++++-- client/src/mifare/desfirecore.h | 2 +- 3 files changed, 12 insertions(+), 4 deletions(-) diff --git a/client/src/cmdhfmfdes.c b/client/src/cmdhfmfdes.c index 309444220..ab25aa2d7 100644 --- a/client/src/cmdhfmfdes.c +++ b/client/src/cmdhfmfdes.c @@ -4998,7 +4998,7 @@ static int CmdHF14ADesChangeKey(const char *Cmd) { } DesfireSetCommMode(&dctx, DCMEncryptedPlain); - res = DesfireChangeKey(&dctx, newkeynum, newkeytype, newkeyver, newkey, oldkeytype, oldkey, true); + res = DesfireChangeKey(&dctx, (appid == 0x000000), newkeynum, newkeytype, newkeyver, newkey, oldkeytype, oldkey, true); if (res == PM3_SUCCESS) { PrintAndLogEx(SUCCESS, "Change key " _GREEN_("ok") " "); } else { diff --git a/client/src/mifare/desfirecore.c b/client/src/mifare/desfirecore.c index 8dd599142..a222e093d 100644 --- a/client/src/mifare/desfirecore.c +++ b/client/src/mifare/desfirecore.c @@ -1090,14 +1090,22 @@ void PrintKeySettings(uint8_t keysettings, uint8_t numkeys, bool applevel, bool PrintKeySettingsPICC(keysettings, numkeys, print2ndbyte); } -int DesfireChangeKey(DesfireContext *dctx, uint8_t newkeynum, DesfireCryptoAlgorythm newkeytype, uint32_t newkeyver, uint8_t *newkey, DesfireCryptoAlgorythm oldkeytype, uint8_t *oldkey, bool verbose) { +int DesfireChangeKey(DesfireContext *dctx, bool change_master_key, uint8_t newkeynum, DesfireCryptoAlgorythm newkeytype, uint32_t newkeyver, uint8_t *newkey, DesfireCryptoAlgorythm oldkeytype, uint8_t *oldkey, bool verbose) { uint8_t okeybuf[DESFIRE_MAX_KEY_SIZE] = {0}; uint8_t nkeybuf[DESFIRE_MAX_KEY_SIZE] = {0}; uint8_t pckcdata[DESFIRE_MAX_KEY_SIZE + 10] = {0}; uint8_t *cdata = &pckcdata[2]; uint8_t keynodata = newkeynum & 0x3f; - keynodata |= (DesfireKeyAlgoToType(newkeytype) & 0x03) << 6; + + /* + * Because new crypto methods can be setup only at application creation, + * changing the card master key to one of them require a key_no tweak. + */ + if (change_master_key) { + keynodata |= (DesfireKeyAlgoToType(newkeytype) & 0x03) << 6; + } + pckcdata[0] = MFDES_CHANGE_KEY; // TODO pckcdata[1] = keynodata; diff --git a/client/src/mifare/desfirecore.h b/client/src/mifare/desfirecore.h index 31053162a..611a3c8cd 100644 --- a/client/src/mifare/desfirecore.h +++ b/client/src/mifare/desfirecore.h @@ -56,6 +56,6 @@ void PrintKeySettings(uint8_t keysettings, uint8_t numkeys, bool applevel, bool uint8_t DesfireKeyAlgoToType(DesfireCryptoAlgorythm keyType); int DesfireChangeKeyCmd(DesfireContext *dctx, uint8_t *data, size_t datalen, uint8_t *resp, size_t *resplen); -int DesfireChangeKey(DesfireContext *dctx, uint8_t newkeynum, DesfireCryptoAlgorythm newkeytype, uint32_t newkeyver, uint8_t *newkey, DesfireCryptoAlgorythm oldkeytype, uint8_t *oldkey, bool verbose); +int DesfireChangeKey(DesfireContext *dctx, bool change_master_key, uint8_t newkeynum, DesfireCryptoAlgorythm newkeytype, uint32_t newkeyver, uint8_t *newkey, DesfireCryptoAlgorythm oldkeytype, uint8_t *oldkey, bool verbose); #endif // __DESFIRECORE_H From d50c72b30e8c013ddd3b340499c9dc48eb83d21e Mon Sep 17 00:00:00 2001 From: merlokk <807634+merlokk@users.noreply.github.com> Date: Mon, 19 Jul 2021 18:40:24 +0300 Subject: [PATCH 14/18] fix create app defaults --- client/src/cmdhfmfdes.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/client/src/cmdhfmfdes.c b/client/src/cmdhfmfdes.c index ab25aa2d7..e8fb349e0 100644 --- a/client/src/cmdhfmfdes.c +++ b/client/src/cmdhfmfdes.c @@ -5171,7 +5171,7 @@ static int CmdHF14ADesCreateApp(const char *Cmd) { arg_str0(NULL, "aid", "", "Application ID for create. Mandatory. (3 hex bytes, big endian)"), arg_str0(NULL, "fid", "", "ISO file ID. Forbidden values: 0000 3F00, 3FFF, FFFF. (2 hex bytes, big endian). If specified - enable iso file id over all the files in the app."), arg_str0(NULL, "dfname", "", "ISO DF Name 1..16 chars string"), - arg_str0(NULL, "ks1", "", "Key settings 1 (HEX 1 byte). Application Master Key Settings. default 0x2f"), + arg_str0(NULL, "ks1", "", "Key settings 1 (HEX 1 byte). Application Master Key Settings. default 0x0f"), arg_str0(NULL, "ks2", "", "Key settings 2 (HEX 1 byte). default 0x0e"), arg_str0(NULL, "dstalgo", "", "Application key crypt algo: DES, 2TDEA, 3TDEA, AES. default DES"), arg_int0(NULL, "numkeys", "", "Keys count. 0x00..0x0e. default 0x0e"), @@ -5207,8 +5207,8 @@ static int CmdHF14ADesCreateApp(const char *Cmd) { int dfnamelen = 16; CLIGetStrWithReturn(ctx, 14, dfname, &dfnamelen); - uint32_t ks1 = 0x2f; - res = arg_get_u32_hexstr_def_nlen(ctx, 15, 0x2f, &ks1, 1, true); + uint32_t ks1 = 0x0f; + res = arg_get_u32_hexstr_def_nlen(ctx, 15, 0x0f, &ks1, 1, true); if (res == 2) { PrintAndLogEx(ERR, "Key settings 1 must have 1 byte length"); return PM3_EINVARG; From 1e1c3ec210ee63fd6dc9c1d3742a2362eba7d835 Mon Sep 17 00:00:00 2001 From: merlokk <807634+merlokk@users.noreply.github.com> Date: Mon, 19 Jul 2021 18:46:35 +0300 Subject: [PATCH 15/18] add helptext --- client/src/mifare/desfirecore.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/client/src/mifare/desfirecore.c b/client/src/mifare/desfirecore.c index a222e093d..9a1747d2f 100644 --- a/client/src/mifare/desfirecore.c +++ b/client/src/mifare/desfirecore.c @@ -1061,9 +1061,10 @@ static void PrintKeySettingsApp(uint8_t keysettings, uint8_t numkeys, bool print break; default: PrintAndLogEx(SUCCESS, - "-- Authentication with the specified key is necessary to change any key.\n" + "-- Authentication with the specified key " _YELLOW_("(0x%02x)") " is necessary to change any key.\n" "A change key and a PICC master key (CMK) can only be changed after authentication with the master key.\n" - "For keys other then the master or change key, an authentication with the same key is needed." + "For keys other then the master or change key, an authentication with the same key is needed.", + (rights >> 4) & 0x0f ); break; } From 0b06600e72e92f30246e534fe0c779f75ac69bd2 Mon Sep 17 00:00:00 2001 From: merlokk <807634+merlokk@users.noreply.github.com> Date: Mon, 19 Jul 2021 18:47:16 +0300 Subject: [PATCH 16/18] fix --- client/src/mifare/desfirecore.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/client/src/mifare/desfirecore.c b/client/src/mifare/desfirecore.c index 9a1747d2f..40f77fb03 100644 --- a/client/src/mifare/desfirecore.c +++ b/client/src/mifare/desfirecore.c @@ -1064,7 +1064,7 @@ static void PrintKeySettingsApp(uint8_t keysettings, uint8_t numkeys, bool print "-- Authentication with the specified key " _YELLOW_("(0x%02x)") " is necessary to change any key.\n" "A change key and a PICC master key (CMK) can only be changed after authentication with the master key.\n" "For keys other then the master or change key, an authentication with the same key is needed.", - (rights >> 4) & 0x0f + rights & 0x0f ); break; } From b6a65405a06413f7ce513159521e7a8028aaf5ea Mon Sep 17 00:00:00 2001 From: merlokk <807634+merlokk@users.noreply.github.com> Date: Mon, 19 Jul 2021 19:05:07 +0300 Subject: [PATCH 17/18] remove debug --- client/src/cmdhfmfdes.c | 110 -------------------------- client/src/mifare/desfirecore.c | 11 +-- client/src/mifare/desfiresecurechan.c | 4 - 3 files changed, 1 insertion(+), 124 deletions(-) diff --git a/client/src/cmdhfmfdes.c b/client/src/cmdhfmfdes.c index e8fb349e0..6b429cd47 100644 --- a/client/src/cmdhfmfdes.c +++ b/client/src/cmdhfmfdes.c @@ -4977,7 +4977,6 @@ static int CmdHF14ADesChangeKey(const char *Cmd) { if (appid == 0x000000) { PrintAndLogEx(WARNING, "Changing the root aid (0x000000)"); - return PM3_ESOFT; // TODO!!!! } if (appid) @@ -5007,115 +5006,6 @@ static int CmdHF14ADesChangeKey(const char *Cmd) { DropField(); return res; - - return PM3_SUCCESS; - - - - - - - - - - - - - - - /* CLIParserContext *ctx; - CLIParserInit(&ctx, "hf mfdes changekey", - "Change MIFARE DESFire Key.\n" - "Make sure to select aid or authenticate aid before running this command.", - "hf mfdes changekey -n 0 -t 1 -k 0000000000000000 -u 1 -j 0102030405060708 -> DES, keynumber 0" - ); - - void *argtable[] = { - arg_param_begin, - arg_int0("n", "keyno", "", "Key number used for authentification"), - arg_int0("t", "algo", "", "Current key algo (1 = DES, 2 = 3DES(2K2DES), 3 = 3K3DES, 4 = AES)"), - arg_str0("k", "key", "", "Current Key (HEX 8-24 bytes)"), - arg_int0("u", "newalgo", "", "New key algo (1 = DES, 2 = 3DES(2K2DES), 3 = 3K3DES, 4 = AES)"), - arg_str0("j", "newkey", "", "New Key (HEX 8-24 bytes)"), - arg_int0("v", "aesver", "", "AES version (if AES is used)"), - arg_param_end - }; - CLIExecWithReturn(ctx, Cmd, argtable, false); - - uint8_t cmdKeyNo = arg_get_int_def(ctx, 1, 0); - uint8_t cmdAuthAlgo = arg_get_int_def(ctx, 2, 0); - uint8_t key[24] = {0}; - int keylen = 0; - int res_klen = CLIParamHexToBuf(arg_get_str(ctx, 3), key, 24, &keylen); - - uint8_t newcmdAuthAlgo = arg_get_int_def(ctx, 4, 0); - uint8_t newkey[24] = {0}; - int newkeylen = 0; - int res_newklen = CLIParamHexToBuf(arg_get_str(ctx, 5), newkey, 24, &newkeylen); - - uint8_t aesversion = arg_get_int_def(ctx, 6, 0); - CLIParserFree(ctx); - - //DropFieldDesfire(); - // NR DESC KEYLENGHT - // ------------------------ - // 1 = DES 8 - // 2 = 3DES 16 - // 3 = 3K 3DES 24 - // 4 = AES 16 - uint8_t keylength = 8; - if (cmdAuthAlgo == MFDES_ALGO_AES) { - keylength = 16; - } else if (cmdAuthAlgo == MFDES_ALGO_3DES) { - keylength = 16; - } else if (cmdAuthAlgo == MFDES_ALGO_DES) { - keylength = 8; - } else if (cmdAuthAlgo == MFDES_ALGO_3K3DES) { - keylength = 24; - } - - uint8_t newkeylength = 8; - if (newcmdAuthAlgo == MFDES_ALGO_AES) { - newkeylength = 16; - } else if (newcmdAuthAlgo == MFDES_ALGO_3DES) { - newkeylength = 16; - } else if (newcmdAuthAlgo == MFDES_ALGO_DES) { - newkeylength = 8; - } else if (newcmdAuthAlgo == MFDES_ALGO_3K3DES) { - newkeylength = 24; - } - - if (res_klen || (keylen < 8) || (keylen > 24)) { - PrintAndLogEx(ERR, "Specified key must have %d bytes length", keylen); - return PM3_EINVARG; - } - - if (res_newklen || (newkeylen < 8) || (newkeylen > 24)) { - PrintAndLogEx(ERR, "Specified new key must have %d bytes length", newkeylen); - return PM3_EINVARG; - } - - if (keylen != keylength) { - PrintAndLogEx(WARNING, "Key must include %d hex symbols, got %d", keylength, keylen); - return PM3_EINVARG; - } - - if (newkeylen != newkeylength) { - PrintAndLogEx(WARNING, "New key must include %d hex symbols, got %d", keylength, newkeylen); - return PM3_EINVARG; - } - - PrintAndLogEx(INFO, "changing key number " _YELLOW_("0x%02x"), cmdKeyNo); - PrintAndLogEx(INFO, "old key: %s ( %s )", sprint_hex_inrow(key, keylen), getEncryptionAlgoStr(cmdAuthAlgo)); - PrintAndLogEx(INFO, "new key: %s ( %s )", sprint_hex_inrow(newkey, newkeylen), getEncryptionAlgoStr(newcmdAuthAlgo)); - - int res = mifare_desfire_change_key(cmdKeyNo, newkey, newcmdAuthAlgo, key, cmdAuthAlgo, aesversion); - if (res == PM3_SUCCESS) { - PrintAndLogEx(SUCCESS, "Change key ( " _GREEN_("ok") " )"); - } else { - PrintAndLogEx(FAILED, "Change key ( " _RED_("fail") " )"); - } - return res;*/ } static int CmdHF14ADesCreateApp(const char *Cmd) { diff --git a/client/src/mifare/desfirecore.c b/client/src/mifare/desfirecore.c index 40f77fb03..476728505 100644 --- a/client/src/mifare/desfirecore.c +++ b/client/src/mifare/desfirecore.c @@ -1123,18 +1123,13 @@ int DesfireChangeKey(DesfireContext *dctx, bool change_master_key, uint8_t newke nkeylen = desfire_get_key_length(T_3DES); } - PrintAndLogEx(SUCCESS, "--oldk [%d]: %s", desfire_get_key_length(oldkeytype), sprint_hex(okeybuf, desfire_get_key_length(oldkeytype))); - PrintAndLogEx(SUCCESS, "--newk [%d]: %s", nkeylen, sprint_hex(nkeybuf, nkeylen)); - // set key version for DES. if newkeyver > 0xff - setting key version is disabled if (newkeytype != T_AES && newkeyver < 0x100) { DesfireDESKeySetVersion(nkeybuf, newkeytype, newkeyver); if (verbose) - PrintAndLogEx(INFO, "changed new key: %s [%d] %s", CLIGetOptionListStr(DesfireAlgoOpts, newkeytype), desfire_get_key_length(newkeytype), sprint_hex(newkey, desfire_get_key_length(newkeytype))); + PrintAndLogEx(INFO, "changed new key: %s [%d] %s", CLIGetOptionListStr(DesfireAlgoOpts, newkeytype), desfire_get_key_length(newkeytype), sprint_hex(nkeybuf, desfire_get_key_length(newkeytype))); } - PrintAndLogEx(SUCCESS, "--newk [%d]: %s", nkeylen, sprint_hex(nkeybuf, nkeylen)); - // xor if we change current auth key if (newkeynum == dctx->keyNum) { memcpy(cdata, nkeybuf, nkeylen); @@ -1145,12 +1140,10 @@ int DesfireChangeKey(DesfireContext *dctx, bool change_master_key, uint8_t newke // add key version for AES size_t cdatalen = nkeylen; - PrintAndLogEx(SUCCESS, "--cdata [%d]: %s kv = 0x%02x", cdatalen, sprint_hex(cdata, cdatalen), newkeyver); if (newkeytype == T_AES) { cdata[cdatalen] = newkeyver; cdatalen++; } - PrintAndLogEx(SUCCESS, "--cdata [%d]: %s", cdatalen, sprint_hex(cdata, cdatalen)); // add crc||crc_new_key if (dctx->secureChannel == DACd40) { @@ -1169,7 +1162,6 @@ int DesfireChangeKey(DesfireContext *dctx, bool change_master_key, uint8_t newke cdatalen += 4; } } - PrintAndLogEx(SUCCESS, "--cdata [%d]: %s", cdatalen, sprint_hex(cdata, cdatalen)); // get padded data length size_t rlen = padded_data_length(cdatalen, desfire_get_key_block_length(newkeytype)); @@ -1177,7 +1169,6 @@ int DesfireChangeKey(DesfireContext *dctx, bool change_master_key, uint8_t newke // send command uint8_t resp[257] = {0}; size_t resplen = 0; - PrintAndLogEx(SUCCESS, "--pckdata [%d]: %s", rlen + 1, sprint_hex(&pckcdata[1], rlen + 1)); int res = DesfireChangeKeyCmd(dctx, &pckcdata[1], rlen + 1, resp, &resplen); // check response diff --git a/client/src/mifare/desfiresecurechan.c b/client/src/mifare/desfiresecurechan.c index 4c3dcd76b..f63659ec1 100644 --- a/client/src/mifare/desfiresecurechan.c +++ b/client/src/mifare/desfiresecurechan.c @@ -167,15 +167,11 @@ static void DesfireSecureChannelEncodeEV1(DesfireContext *ctx, uint8_t cmd, uint if (srcdatalen == 0 || srcdatalen <= hdrlen) return; - PrintAndLogEx(SUCCESS, "--ch hdrlen: %d, cmd: %02x", hdrlen, cmd); - //dstdata[0] = cmd; memcpy(&dstdata[0], srcdata, hdrlen); memcpy(data, &srcdata[hdrlen], srcdatalen); rlen = padded_data_length(srcdatalen - hdrlen, desfire_get_key_block_length(ctx->keyType)); - PrintAndLogEx(SUCCESS, "--ch src rlen: %d data: %s", rlen, sprint_hex(data, rlen)); DesfireCryptoEncDec(ctx, true, data, rlen, &dstdata[hdrlen], true); *dstdatalen = hdrlen + rlen; - PrintAndLogEx(SUCCESS, "--ch dst len: %d data: %s", *dstdatalen, sprint_hex(dstdata, *dstdatalen)); } } From b415ee086d26045f90dfa32ecd422a7640f188f6 Mon Sep 17 00:00:00 2001 From: merlokk <807634+merlokk@users.noreply.github.com> Date: Mon, 19 Jul 2021 19:54:51 +0300 Subject: [PATCH 18/18] remove double padding --- client/src/cmdhfmfdes.c | 2 +- client/src/mifare/desfirecore.c | 7 +++---- 2 files changed, 4 insertions(+), 5 deletions(-) diff --git a/client/src/cmdhfmfdes.c b/client/src/cmdhfmfdes.c index 6b429cd47..8c59ff80f 100644 --- a/client/src/cmdhfmfdes.c +++ b/client/src/cmdhfmfdes.c @@ -4997,7 +4997,7 @@ static int CmdHF14ADesChangeKey(const char *Cmd) { } DesfireSetCommMode(&dctx, DCMEncryptedPlain); - res = DesfireChangeKey(&dctx, (appid == 0x000000), newkeynum, newkeytype, newkeyver, newkey, oldkeytype, oldkey, true); + res = DesfireChangeKey(&dctx, (appid == 0x000000) && (newkeynum == 0) && (dctx.keyNum == 0), newkeynum, newkeytype, newkeyver, newkey, oldkeytype, oldkey, true); if (res == PM3_SUCCESS) { PrintAndLogEx(SUCCESS, "Change key " _GREEN_("ok") " "); } else { diff --git a/client/src/mifare/desfirecore.c b/client/src/mifare/desfirecore.c index 476728505..47046095c 100644 --- a/client/src/mifare/desfirecore.c +++ b/client/src/mifare/desfirecore.c @@ -1163,15 +1163,14 @@ int DesfireChangeKey(DesfireContext *dctx, bool change_master_key, uint8_t newke } } - // get padded data length - size_t rlen = padded_data_length(cdatalen, desfire_get_key_block_length(newkeytype)); - // send command uint8_t resp[257] = {0}; size_t resplen = 0; - int res = DesfireChangeKeyCmd(dctx, &pckcdata[1], rlen + 1, resp, &resplen); + int res = DesfireChangeKeyCmd(dctx, &pckcdata[1], cdatalen, resp, &resplen); // check response + if (res == 0 && resplen > 0) + res = -20; // clear auth if (newkeynum == dctx->keyNum)