mirror of
https://github.com/RfidResearchGroup/proxmark3.git
synced 2025-01-31 04:20:28 +08:00
core works
This commit is contained in:
parent
92a0639ba8
commit
46a294d585
6 changed files with 96 additions and 14 deletions
|
@ -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") " ");
|
||||
|
|
|
@ -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 : <KeyNo> <PrevKey XOR Newkey> [<AES NewKeyVer>]
|
||||
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
|
||||
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -56,7 +56,8 @@ typedef enum {
|
|||
DCMNone,
|
||||
DCMPlain,
|
||||
DCMMACed,
|
||||
DCMEncrypted
|
||||
DCMEncrypted,
|
||||
DCMEncryptedPlain
|
||||
} DesfireCommunicationMode;
|
||||
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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
|
||||
|
|
Loading…
Reference in a new issue