core works

This commit is contained in:
merlokk 2021-07-15 20:14:02 +03:00
parent 92a0639ba8
commit 46a294d585
6 changed files with 96 additions and 14 deletions

View file

@ -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") " ");

View file

@ -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

View file

@ -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;
}
}
}

View file

@ -56,7 +56,8 @@ typedef enum {
DCMNone,
DCMPlain,
DCMMACed,
DCMEncrypted
DCMEncrypted,
DCMEncryptedPlain
} DesfireCommunicationMode;

View file

@ -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;

View file

@ -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