mirror of
https://github.com/RfidResearchGroup/proxmark3.git
synced 2026-05-12 11:18:11 -07:00
Fix secure channel issues with 'hf mfdes createdelegateapp'
This commit is contained in:
@@ -3555,7 +3555,7 @@ static int CmdHF14ADesCreateDelegateApp(const char *Cmd) {
|
||||
arg_str0("i", "kdfi", "<hex>", "KDF input (1-31 hex bytes)"),
|
||||
arg_str0("m", "cmode", "<plain|mac|encrypt>", "Communicaton mode"),
|
||||
arg_str0("c", "ccset", "<native|niso|iso>", "Communicaton command set"),
|
||||
arg_str0(NULL, "schann", "<d40|ev1>", "Secure channel"),
|
||||
arg_str0(NULL, "schann", "<d40|ev1|ev2|lrp>", "Secure channel"),
|
||||
arg_str0(NULL, "aid", "<hex>", "Application ID for create. Mandatory in structured mode. (3 hex bytes, big endian)"),
|
||||
arg_str0(NULL, "damslot", "<hex>", "DAM slot number (2 hex bytes, little endian on card)"),
|
||||
arg_str0(NULL, "damslotver", "<hex>", "DAM slot version (1 hex byte, def: 00)"),
|
||||
@@ -3683,13 +3683,6 @@ static int CmdHF14ADesCreateDelegateApp(const char *Cmd) {
|
||||
uint8_t contdata[250] = {0};
|
||||
size_t contdatalen = 0;
|
||||
|
||||
// Fixing EV2 mac calculation requires changes in multiple places (command chaining, counter increment modification, etc.)
|
||||
// and is not worth the effort at the moment, so we just block it for now.
|
||||
if (securechann == DACEV2) {
|
||||
PrintAndLogEx(ERR, "CreateDelegatedApplication is not currently implemented for EV2 secure channel (EV2 MAC calculation issues)");
|
||||
return PM3_EINVARG;
|
||||
}
|
||||
|
||||
if (appid == 0x000000) {
|
||||
PrintAndLogEx(ERR, "Creating the root aid (0x000000) is " _RED_("forbidden"));
|
||||
return PM3_ESOFT;
|
||||
|
||||
@@ -548,7 +548,7 @@ static int DESFIRESendRaw(bool activate_field, uint8_t *data, size_t datalen, ui
|
||||
return PM3_SUCCESS;
|
||||
}
|
||||
|
||||
static int DesfireExchangeNative(bool activate_field, DesfireContext_t *ctx, uint8_t cmd, uint8_t *data, size_t datalen, uint8_t *respcode, uint8_t *resp, size_t *resplen, bool enable_chaining, size_t splitbysize) {
|
||||
static int DesfireExchangeNative(bool activate_field, DesfireContext_t *ctx, uint8_t cmd, uint8_t *data, size_t datalen, uint8_t *respcode, uint8_t *resp, size_t *resplen, bool enable_chaining, size_t splitbysize, size_t firsttxdatalen) {
|
||||
if (resplen) {
|
||||
*resplen = 0;
|
||||
}
|
||||
@@ -576,11 +576,21 @@ static int DesfireExchangeNative(bool activate_field, DesfireContext_t *ctx, uin
|
||||
|
||||
int res;
|
||||
size_t len;
|
||||
size_t firsttxlen = 0;
|
||||
if (firsttxdatalen > 0 && firsttxdatalen < datalen) {
|
||||
firsttxlen = firsttxdatalen + 1; // +1 for the initial command byte.
|
||||
if (firsttxlen > DESFIRE_TX_FRAME_MAX_LEN) {
|
||||
firsttxlen = DESFIRE_TX_FRAME_MAX_LEN;
|
||||
}
|
||||
}
|
||||
|
||||
// tx chaining
|
||||
size_t sentdatalen = 0;
|
||||
while (cdatalen > sentdatalen) {
|
||||
|
||||
if ((cdatalen - sentdatalen) > DESFIRE_TX_FRAME_MAX_LEN) {
|
||||
if (sentdatalen == 0 && firsttxlen > 0) {
|
||||
len = firsttxlen;
|
||||
} else if ((cdatalen - sentdatalen) > DESFIRE_TX_FRAME_MAX_LEN) {
|
||||
len = DESFIRE_TX_FRAME_MAX_LEN;
|
||||
} else {
|
||||
len = cdatalen - sentdatalen;
|
||||
@@ -683,7 +693,7 @@ static int DesfireExchangeNative(bool activate_field, DesfireContext_t *ctx, uin
|
||||
return PM3_SUCCESS;
|
||||
}
|
||||
|
||||
static int DesfireExchangeISONative(bool activate_field, DesfireContext_t *ctx, uint8_t cmd, uint8_t *data, size_t datalen, uint8_t *respcode, uint8_t *resp, size_t *resplen, bool enable_chaining, size_t splitbysize) {
|
||||
static int DesfireExchangeISONative(bool activate_field, DesfireContext_t *ctx, uint8_t cmd, uint8_t *data, size_t datalen, uint8_t *respcode, uint8_t *resp, size_t *resplen, bool enable_chaining, size_t splitbysize, size_t firsttxdatalen) {
|
||||
if (resplen) {
|
||||
*resplen = 0;
|
||||
}
|
||||
@@ -711,12 +721,22 @@ static int DesfireExchangeISONative(bool activate_field, DesfireContext_t *ctx,
|
||||
};
|
||||
|
||||
int res;
|
||||
size_t firsttxlen = 0;
|
||||
if (firsttxdatalen > 0 && firsttxdatalen < datalen) {
|
||||
firsttxlen = firsttxdatalen;
|
||||
if (firsttxlen > DESFIRE_TX_FRAME_MAX_LEN) {
|
||||
firsttxlen = DESFIRE_TX_FRAME_MAX_LEN;
|
||||
}
|
||||
}
|
||||
|
||||
// tx chaining
|
||||
size_t sentdatalen = 0;
|
||||
bool first_tx_frame = true;
|
||||
while (first_tx_frame || datalen > sentdatalen) {
|
||||
first_tx_frame = false;
|
||||
if (datalen - sentdatalen > DESFIRE_TX_FRAME_MAX_LEN) {
|
||||
if (sentdatalen == 0 && firsttxlen > 0) {
|
||||
apdu.Lc = firsttxlen;
|
||||
} else if (datalen - sentdatalen > DESFIRE_TX_FRAME_MAX_LEN) {
|
||||
apdu.Lc = DESFIRE_TX_FRAME_MAX_LEN;
|
||||
} else {
|
||||
apdu.Lc = datalen - sentdatalen;
|
||||
@@ -876,8 +896,8 @@ static void DesfireSplitBytesToBlock(uint8_t *blockdata, size_t *blockdatacount,
|
||||
}
|
||||
}
|
||||
|
||||
int DesfireExchangeEx(bool activate_field, DesfireContext_t *ctx, uint8_t cmd, uint8_t *data, size_t datalen, uint8_t *respcode,
|
||||
uint8_t *resp, size_t *resplen, bool enable_chaining, size_t splitbysize) {
|
||||
static int DesfireExchangeExSplit(bool activate_field, DesfireContext_t *ctx, uint8_t cmd, uint8_t *data, size_t datalen, uint8_t *respcode,
|
||||
uint8_t *resp, size_t *resplen, bool enable_chaining, size_t splitbysize, size_t firsttxdatalen) {
|
||||
int res = PM3_SUCCESS;
|
||||
|
||||
if (PrintChannelModeWarning(cmd, ctx->secureChannel, ctx->cmdSet, ctx->commMode) == false) {
|
||||
@@ -898,9 +918,9 @@ int DesfireExchangeEx(bool activate_field, DesfireContext_t *ctx, uint8_t cmd, u
|
||||
DesfireSecureChannelEncode(ctx, cmd, data, datalen, databuf, &databuflen);
|
||||
|
||||
if (ctx->cmdSet == DCCNative) {
|
||||
res = DesfireExchangeNative(activate_field, ctx, cmd, databuf, databuflen, respcode, databuf, &databuflen, enable_chaining, splitbysize);
|
||||
res = DesfireExchangeNative(activate_field, ctx, cmd, databuf, databuflen, respcode, databuf, &databuflen, enable_chaining, splitbysize, firsttxdatalen);
|
||||
} else {
|
||||
res = DesfireExchangeISONative(activate_field, ctx, cmd, databuf, databuflen, respcode, databuf, &databuflen, enable_chaining, splitbysize);
|
||||
res = DesfireExchangeISONative(activate_field, ctx, cmd, databuf, databuflen, respcode, databuf, &databuflen, enable_chaining, splitbysize, firsttxdatalen);
|
||||
}
|
||||
|
||||
if (splitbysize) {
|
||||
@@ -928,6 +948,11 @@ int DesfireExchangeEx(bool activate_field, DesfireContext_t *ctx, uint8_t cmd, u
|
||||
return res;
|
||||
}
|
||||
|
||||
int DesfireExchangeEx(bool activate_field, DesfireContext_t *ctx, uint8_t cmd, uint8_t *data, size_t datalen, uint8_t *respcode,
|
||||
uint8_t *resp, size_t *resplen, bool enable_chaining, size_t splitbysize) {
|
||||
return DesfireExchangeExSplit(activate_field, ctx, cmd, data, datalen, respcode, resp, resplen, enable_chaining, splitbysize, 0);
|
||||
}
|
||||
|
||||
int DesfireExchange(DesfireContext_t *ctx, uint8_t cmd, uint8_t *data, size_t datalen, uint8_t *respcode, uint8_t *resp, size_t *resplen) {
|
||||
return DesfireExchangeEx(false, ctx, cmd, data, datalen, respcode, resp, resplen, true, 0);
|
||||
}
|
||||
@@ -2196,18 +2221,24 @@ int DesfireCreateDelegatedApplication(DesfireContext_t *dctx, uint8_t *appdata,
|
||||
return PM3_EINVARG;
|
||||
}
|
||||
|
||||
if (appdatalen == 0 || contdatalen == 0) {
|
||||
return PM3_EINVARG;
|
||||
}
|
||||
|
||||
if (appdatalen > DESFIRE_BUFFER_SIZE - contdatalen) {
|
||||
return PM3_EINVARG;
|
||||
}
|
||||
|
||||
uint8_t fulldata[DESFIRE_BUFFER_SIZE] = {0};
|
||||
memcpy(fulldata, appdata, appdatalen);
|
||||
memcpy(&fulldata[appdatalen], contdata, contdatalen);
|
||||
|
||||
uint8_t resp[DESFIRE_BUFFER_SIZE] = {0};
|
||||
size_t resplen = 0;
|
||||
uint8_t respcode = 0xFF;
|
||||
int res = DesfireExchangeEx(false, dctx, MFDES_CREATE_DELEGATE_APP, appdata, appdatalen, &respcode, resp, &resplen, false, 0);
|
||||
if (res != PM3_SUCCESS) {
|
||||
return res;
|
||||
}
|
||||
if (respcode != MFDES_ADDITIONAL_FRAME) {
|
||||
return PM3_EAPDU_FAIL;
|
||||
}
|
||||
|
||||
res = DesfireExchangeEx(false, dctx, MFDES_ADDITIONAL_FRAME, contdata, contdatalen, &respcode, resp, &resplen, false, 0);
|
||||
// CreateDelegatedApplication must go out as C9 + AF frames, but secure messaging
|
||||
// state (CMAC IV / cmd counter) must be advanced as a single logical command.
|
||||
int res = DesfireExchangeExSplit(false, dctx, MFDES_CREATE_DELEGATE_APP, fulldata, appdatalen + contdatalen, &respcode, resp, &resplen, true, 0, appdatalen);
|
||||
if (res != PM3_SUCCESS) {
|
||||
return res;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user