Merge pull request #1407 from merlokk/esf_isoauth

Desfire iso authentication
This commit is contained in:
Oleg Moiseenko 2021-07-31 12:57:35 +03:00 committed by GitHub
commit d490485920
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
6 changed files with 284 additions and 16 deletions

View file

@ -3053,6 +3053,7 @@ static int CmdHF14ADesSelectApp(const char *Cmd) {
arg_str0("c", "ccset", "<native/niso/iso>", "Communicaton command set: native/niso/iso"), arg_str0("c", "ccset", "<native/niso/iso>", "Communicaton command set: native/niso/iso"),
arg_str0("s", "schann", "<d40/ev1/ev2>", "Secure channel: d40/ev1/ev2"), arg_str0("s", "schann", "<d40/ev1/ev2>", "Secure channel: d40/ev1/ev2"),
arg_str0(NULL, "aid", "<app id hex>", "Application ID of application for some parameters (3 hex bytes, big endian)"), arg_str0(NULL, "aid", "<app id hex>", "Application ID of application for some parameters (3 hex bytes, big endian)"),
arg_str0(NULL, "dfname", "<df name str>", "Application DF Name (string, max 16 chars). Selects application via ISO SELECT command"),
arg_param_end arg_param_end
}; };
CLIExecWithReturn(ctx, Cmd, argtable, false); CLIExecWithReturn(ctx, Cmd, argtable, false);
@ -3069,9 +3070,34 @@ static int CmdHF14ADesSelectApp(const char *Cmd) {
return res; return res;
} }
uint8_t dfname[32] = {0};
int dfnamelen = 16;
CLIGetStrWithReturn(ctx, 12, dfname, &dfnamelen);
SetAPDULogging(APDULogging); SetAPDULogging(APDULogging);
CLIParserFree(ctx); CLIParserFree(ctx);
if (dctx.cmdSet == DCCISO || dfnamelen > 0) {
uint8_t resp[250] = {0};
size_t resplen = 0;
if (dfnamelen > 0)
res = DesfireISOSelectDF(&dctx, (char *)dfname, resp, &resplen);
else
res = DesfireISOSelect(&dctx, ISSMFDFEF, NULL, 0, resp, &resplen);
if (res != PM3_SUCCESS) {
DropField();
PrintAndLogEx(FAILED, "ISO Select application `%s` " _RED_("failed"), (char *)dfname);
return res;
}
if (resplen > 0)
PrintAndLogEx(FAILED, "Application " _CYAN_("FCI template") " [%zu]%s", resplen, sprint_hex(resp, resplen));
if (dfnamelen > 0)
PrintAndLogEx(SUCCESS, "Application `%s` selected " _GREEN_("succesfully"), (char *)dfname);
else
PrintAndLogEx(SUCCESS, "PICC MF selected " _GREEN_("succesfully"));
} else {
res = DesfireSelectAndAuthenticateEx(&dctx, securechann, appid, true, verbose); res = DesfireSelectAndAuthenticateEx(&dctx, securechann, appid, true, verbose);
if (res != PM3_SUCCESS) { if (res != PM3_SUCCESS) {
DropField(); DropField();
@ -3080,6 +3106,7 @@ static int CmdHF14ADesSelectApp(const char *Cmd) {
} }
PrintAndLogEx(SUCCESS, "Application 0x%06x selected " _GREEN_("succesfully") " ", appid); PrintAndLogEx(SUCCESS, "Application 0x%06x selected " _GREEN_("succesfully") " ", appid);
}
DropField(); DropField();
return res; return res;
@ -6327,12 +6354,9 @@ int CmdHFMFDes(const char *Cmd) {
ISO/IEC 7816 Cmds ISO/IEC 7816 Cmds
----------------- -----------------
'A4' Select
'B0' Read Binary 'B0' Read Binary
'D6' Update Binary 'D6' Update Binary
'B2' Read Records 'B2' Read Records
'E2' Append Records 'E2' Append Records
'84' Get Challenge
'88' Internal Authenticate
'82' External Authenticate
*/ */

View file

@ -19,6 +19,8 @@
#define APDUCODE_TYPE_ERROR 3 #define APDUCODE_TYPE_ERROR 3
#define APDUCODE_TYPE_SECURITY 4 #define APDUCODE_TYPE_SECURITY 4
#define APDU_INCLUDE_LE_00 0x100
typedef struct { typedef struct {
const char *ID; const char *ID;
const uint8_t Type; const uint8_t Type;

View file

@ -261,6 +261,22 @@ const char *DesfireAuthErrorToStr(int error) {
return "Can't select application."; return "Can't select application.";
case 201: case 201:
return "Authentication retured no error but channel not authenticated."; return "Authentication retured no error but channel not authenticated.";
case 301:
return "ISO Get challenge error.";
case 302:
return "ISO Get challenge returned wrong length.";
case 303:
return "Crypto encode piccrnd1 error.";
case 304:
return "External authenticate error.";
case 305:
return "Internal authenticate error.";
case 306:
return "Internal authenticate returned wrong length.";
case 307:
return "Crypto decode piccrnd2 error.";
case 308:
return "Random numbers dont match. Authentication failed.";
default: default:
break; break;
} }
@ -277,6 +293,34 @@ void DesfireAIDUintToByte(uint32_t aid, uint8_t *data) {
data[2] = (aid >> 16) & 0xff; data[2] = (aid >> 16) & 0xff;
} }
static uint8_t DesfireKeyToISOKey(DesfireCryptoAlgorythm keytype) {
switch (keytype) {
case T_DES:
return 0x02;
case T_3DES:
return 0x02;
case T_3K3DES:
return 0x04;
case T_AES:
return 0x09;
}
return 0x00;
}
static uint8_t DesfireGetRndLenForKey(DesfireCryptoAlgorythm keytype) {
switch (keytype) {
case T_DES:
return 0x08;
case T_3DES:
return 0x08;
case T_3K3DES:
return 0x10;
case T_AES:
return 0x10;
}
return 0x00;
}
void DesfirePrintContext(DesfireContext *ctx) { void DesfirePrintContext(DesfireContext *ctx) {
PrintAndLogEx(INFO, "Key num: %d Key algo: %s Key[%d]: %s", PrintAndLogEx(INFO, "Key num: %d Key algo: %s Key[%d]: %s",
ctx->keyNum, ctx->keyNum,
@ -311,7 +355,7 @@ void DesfirePrintContext(DesfireContext *ctx) {
} }
} }
static int DESFIRESendApdu(bool activate_field, sAPDU apdu, uint8_t *result, uint32_t max_result_len, uint32_t *result_len, uint16_t *sw) { static int DESFIRESendApduEx(bool activate_field, sAPDU apdu, uint16_t le, uint8_t *result, uint32_t max_result_len, uint32_t *result_len, uint16_t *sw) {
if (result_len) *result_len = 0; if (result_len) *result_len = 0;
if (sw) *sw = 0; if (sw) *sw = 0;
@ -327,7 +371,7 @@ static int DESFIRESendApdu(bool activate_field, sAPDU apdu, uint8_t *result, uin
// COMPUTE APDU // COMPUTE APDU
int datalen = 0; int datalen = 0;
if (APDUEncodeS(&apdu, false, 0x100, data, &datalen)) { // 100 == with Le if (APDUEncodeS(&apdu, false, le, data, &datalen)) { // 100 == with Le
PrintAndLogEx(ERR, "APDU encoding error."); PrintAndLogEx(ERR, "APDU encoding error.");
return PM3_EAPDU_ENCODEFAIL; return PM3_EAPDU_ENCODEFAIL;
} }
@ -370,6 +414,10 @@ static int DESFIRESendApdu(bool activate_field, sAPDU apdu, uint8_t *result, uin
return PM3_SUCCESS; return PM3_SUCCESS;
} }
static int DESFIRESendApdu(bool activate_field, sAPDU apdu, uint8_t *result, uint32_t max_result_len, uint32_t *result_len, uint16_t *sw) {
return DESFIRESendApduEx(activate_field, apdu, APDU_INCLUDE_LE_00, result, max_result_len, result_len, sw);
}
static int DESFIRESendRaw(bool activate_field, uint8_t *data, size_t datalen, uint8_t *result, uint32_t max_result_len, uint32_t *result_len, uint8_t *respcode) { static int DESFIRESendRaw(bool activate_field, uint8_t *data, size_t datalen, uint8_t *result, uint32_t max_result_len, uint32_t *result_len, uint8_t *respcode) {
*result_len = 0; *result_len = 0;
if (respcode) *respcode = 0xff; if (respcode) *respcode = 0xff;
@ -516,7 +564,7 @@ static int DesfireExchangeNative(bool activate_field, DesfireContext *ctx, uint8
return PM3_SUCCESS; return PM3_SUCCESS;
} }
static int DesfireExchangeISO(bool activate_field, DesfireContext *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 *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) {
if (resplen) if (resplen)
*resplen = 0; *resplen = 0;
if (respcode) if (respcode)
@ -622,6 +670,16 @@ static int DesfireExchangeISO(bool activate_field, DesfireContext *ctx, uint8_t
return PM3_SUCCESS; return PM3_SUCCESS;
} }
static int DesfireExchangeISO(bool activate_field, DesfireContext *ctx, sAPDU apdu, uint16_t le, uint8_t *resp, size_t *resplen, uint16_t *sw) {
uint32_t rlen = 0;
int res = DESFIRESendApduEx(activate_field, apdu, le, resp, 255, &rlen, sw);
if (res == PM3_SUCCESS)
*resplen = rlen;
return res;
}
// move data from blockdata [format: <length, data><length, data>...] to single data block // move data from blockdata [format: <length, data><length, data>...] to single data block
static void DesfireJoinBlockToBytes(uint8_t *blockdata, size_t blockdatacount, size_t blockdatasize, uint8_t *dstdata, size_t *dstdatalen) { static void DesfireJoinBlockToBytes(uint8_t *blockdata, size_t blockdatacount, size_t blockdatasize, uint8_t *dstdata, size_t *dstdatalen) {
*dstdatalen = 0; *dstdatalen = 0;
@ -665,7 +723,7 @@ int DesfireExchangeEx(bool activate_field, DesfireContext *ctx, uint8_t cmd, uin
if (ctx->cmdSet == DCCNative) 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);
else else
res = DesfireExchangeISO(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);
if (splitbysize) { if (splitbysize) {
uint8_t sdata[250 * 5] = {0}; uint8_t sdata[250 * 5] = {0};
@ -715,8 +773,12 @@ int DesfireSelectAID(DesfireContext *ctx, uint8_t *aid1, uint8_t *aid2) {
if (respcode != MFDES_S_OPERATION_OK) if (respcode != MFDES_S_OPERATION_OK)
return PM3_EAPDU_FAIL; return PM3_EAPDU_FAIL;
DesfireClearSession(ctx);
ctx->appSelected = (aid1[0] != 0x00 || aid1[1] != 0x00 || aid1[2] != 0x00);
return PM3_SUCCESS; return PM3_SUCCESS;
} }
return res; return res;
} }
@ -756,6 +818,14 @@ int DesfireSelectAndAuthenticateEx(DesfireContext *dctx, DesfireSecureChannel se
if (verbose) if (verbose)
DesfirePrintContext(dctx); DesfirePrintContext(dctx);
bool isosw = false;
if (dctx->cmdSet == DCCISO) {
dctx->cmdSet = DCCNativeISO;
isosw = true;
if (verbose)
PrintAndLogEx(INFO, "Switch to " _CYAN_("native") " for select");
}
int res = DesfireSelectAIDHex(dctx, aid, false, 0); int res = DesfireSelectAIDHex(dctx, aid, false, 0);
if (res != PM3_SUCCESS) { if (res != PM3_SUCCESS) {
PrintAndLogEx(ERR, "Desfire select " _RED_("error") "."); PrintAndLogEx(ERR, "Desfire select " _RED_("error") ".");
@ -764,6 +834,9 @@ int DesfireSelectAndAuthenticateEx(DesfireContext *dctx, DesfireSecureChannel se
if (verbose) if (verbose)
PrintAndLogEx(INFO, "App %06x " _GREEN_("selected"), aid); PrintAndLogEx(INFO, "App %06x " _GREEN_("selected"), aid);
if (isosw)
dctx->cmdSet = DCCISO;
if (!noauth) { if (!noauth) {
res = DesfireAuthenticate(dctx, secureChannel, verbose); res = DesfireAuthenticate(dctx, secureChannel, verbose);
if (res != PM3_SUCCESS) { if (res != PM3_SUCCESS) {
@ -1201,7 +1274,67 @@ static int DesfireAuthenticateEV2(DesfireContext *dctx, DesfireSecureChannel sec
return PM3_SUCCESS; return PM3_SUCCESS;
} }
static int DesfireAuthenticateISO(DesfireContext *dctx, DesfireSecureChannel secureChannel, bool verbose) {
uint8_t rndlen = DesfireGetRndLenForKey(dctx->keyType);
uint8_t hostrnd[] = {0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16};
uint8_t hostrnd2[] = {0x16, 0x15, 0x14, 0x13, 0x12, 0x11, 0x10, 0x09, 0x08, 0x07, 0x06, 0x05, 0x04, 0x03, 0x02, 0x01};
uint8_t piccrnd[64];
size_t xlen = 0;
int res = DesfireISOGetChallenge(dctx, dctx->keyType, piccrnd, &xlen);
if (res != PM3_SUCCESS)
return 301;
if (xlen != rndlen)
return 302;
uint8_t both[32] = {0};
memcpy(both, hostrnd, rndlen);
memcpy(&both[rndlen], piccrnd, rndlen);
// encode
DesfireClearIV(dctx);
DesfireCryptoEncDec(dctx, false, both, rndlen * 2, both, true); // error 303
// external authenticate
res = DesfireISOExternalAuth(dctx, dctx->appSelected, dctx->keyNum, dctx->keyType, both);
if (res != PM3_SUCCESS)
return 304;
// internal authenticate
uint8_t rnddata[64] = {0};
xlen = 0;
res = DesfireISOInternalAuth(dctx, dctx->appSelected, dctx->keyNum, dctx->keyType, hostrnd2, rnddata, &xlen);
if (res != PM3_SUCCESS)
return 305;
if (xlen != rndlen * 2)
return 306;
// decode rnddata
uint8_t piccrnd2[64] = {0};
DesfireCryptoEncDec(dctx, false, rnddata, rndlen * 2, piccrnd2, false); // error 307
// check
if (memcmp(hostrnd2, &piccrnd2[rndlen], rndlen) != 0)
return 308;
DesfireGenSessionKeyEV1(hostrnd, piccrnd2, dctx->keyType, dctx->sessionKeyEnc);
DesfireClearIV(dctx);
memcpy(dctx->sessionKeyMAC, dctx->sessionKeyEnc, desfire_get_key_length(dctx->keyType));
dctx->secureChannel = secureChannel;
if (verbose)
PrintAndLogEx(INFO, "session key: %s", sprint_hex(dctx->sessionKeyEnc, desfire_get_key_length(dctx->keyType)));
return PM3_SUCCESS;
}
int DesfireAuthenticate(DesfireContext *dctx, DesfireSecureChannel secureChannel, bool verbose) { int DesfireAuthenticate(DesfireContext *dctx, DesfireSecureChannel secureChannel, bool verbose) {
if (dctx->cmdSet == DCCISO && secureChannel != DACEV2)
return DesfireAuthenticateISO(dctx, secureChannel, verbose);
if (secureChannel == DACd40 || secureChannel == DACEV1) if (secureChannel == DACd40 || secureChannel == DACEV1)
return DesfireAuthenticateEV1(dctx, secureChannel, verbose); return DesfireAuthenticateEV1(dctx, secureChannel, verbose);
@ -1382,7 +1515,6 @@ int DesfireFillFileList(DesfireContext *dctx, FileListS FileList, size_t *filesc
return res; return res;
} }
int DesfireCreateFile(DesfireContext *dctx, uint8_t ftype, uint8_t *fdata, size_t fdatalen, bool checklen) { int DesfireCreateFile(DesfireContext *dctx, uint8_t ftype, uint8_t *fdata, size_t fdatalen, bool checklen) {
const DesfireCreateFileCommandsS *rcmd = GetDesfireFileCmdRec(ftype); const DesfireCreateFileCommandsS *rcmd = GetDesfireFileCmdRec(ftype);
if (rcmd == NULL) if (rcmd == NULL)
@ -2087,3 +2219,64 @@ int DesfireSetConfiguration(DesfireContext *dctx, uint8_t paramid, uint8_t *para
return res; return res;
} }
int DesfireISOSelect(DesfireContext *dctx, DesfireISOSelectControl cntr, uint8_t *data, uint8_t datalen, uint8_t *resp, size_t *resplen) {
uint8_t xresp[250] = {0};
size_t xresplen = 0;
uint16_t sw = 0;
int res = DesfireExchangeISO(true, dctx, (sAPDU) {0x00, ISO7816_SELECT_FILE, cntr, ((resp == NULL) ? 0x0C : 0x00), datalen, data}, APDU_INCLUDE_LE_00, xresp, &xresplen, &sw);
if (res == PM3_SUCCESS && sw != 0x9000)
return PM3_ESOFT;
if (resp != NULL && resplen != NULL) {
*resplen = xresplen;
memcpy(resp, xresp, xresplen);
}
DesfireClearSession(dctx);
dctx->appSelected = !( (cntr == ISSMFDFEF && datalen == 0) || (cntr == ISSEFByFileID && datalen == 2 && data[0] == 0 && data[1] == 0) );
return res;
}
int DesfireISOSelectDF(DesfireContext *dctx, char *dfname, uint8_t *resp, size_t *resplen) {
return DesfireISOSelect(dctx, ISSDFName, (uint8_t *)dfname, strnlen(dfname, 16), resp, resplen);
}
int DesfireISOGetChallenge(DesfireContext *dctx, DesfireCryptoAlgorythm keytype, uint8_t *resp, size_t *resplen) {
uint16_t sw = 0;
int res = DesfireExchangeISO(false, dctx, (sAPDU) {0x00, ISO7816_GET_CHALLENGE, 0x00, 0x00, 0x00, NULL}, DesfireGetRndLenForKey(keytype), resp, resplen, &sw);
if (res == PM3_SUCCESS && sw != 0x9000)
return PM3_ESOFT;
return res;
}
int DesfireISOExternalAuth(DesfireContext *dctx, bool app_level, uint8_t keynum, DesfireCryptoAlgorythm keytype, uint8_t *data) {
uint8_t p1 = DesfireKeyToISOKey(keytype);
uint8_t p2 = ((app_level) ? 0x80 : 0x00) | keynum;
uint8_t resp[250] = {0};
size_t resplen = 0;
uint16_t sw = 0;
int res = DesfireExchangeISO(false, dctx, (sAPDU) {0x00, ISO7816_EXTERNAL_AUTHENTICATION, p1, p2, DesfireGetRndLenForKey(keytype) * 2, data}, 0, resp, &resplen, &sw);
if (res == PM3_SUCCESS && sw != 0x9000)
return PM3_ESOFT;
return res;
}
int DesfireISOInternalAuth(DesfireContext *dctx, bool app_level, uint8_t keynum, DesfireCryptoAlgorythm keytype, uint8_t *data, uint8_t *resp, size_t *resplen) {
uint8_t keylen = DesfireGetRndLenForKey(keytype);
uint8_t p1 = DesfireKeyToISOKey(keytype);
uint8_t p2 = ((app_level) ? 0x80 : 0x00) | keynum;
uint16_t sw = 0;
int res = DesfireExchangeISO(false, dctx, (sAPDU) {0x00, ISO7816_INTERNAL_AUTHENTICATION, p1, p2, keylen, data}, keylen * 2, resp, resplen, &sw);
if (res == PM3_SUCCESS && sw != 0x9000)
return PM3_ESOFT;
return res;
}

View file

@ -21,6 +21,15 @@
#define DESFIRE_TX_FRAME_MAX_LEN 54 #define DESFIRE_TX_FRAME_MAX_LEN 54
enum DesfireISOSelectControlEnum {
ISSMFDFEF = 0x00,
ISSChildDF = 0x01,
ISSEFByFileID = 0x02,
ISSParentDF = 0x03,
ISSDFName = 0x04
};
typedef enum DesfireISOSelectControlEnum DesfireISOSelectControl;
typedef struct { typedef struct {
const uint8_t id; const uint8_t id;
const char *text; const char *text;
@ -167,4 +176,10 @@ int DesfireReadRecords(DesfireContext *dctx, uint8_t fnum, uint32_t recnum, uint
int DesfireWriteRecord(DesfireContext *dctx, uint8_t fnum, uint32_t offset, uint32_t len, uint8_t *data); int DesfireWriteRecord(DesfireContext *dctx, uint8_t fnum, uint32_t offset, uint32_t len, uint8_t *data);
int DesfireUpdateRecord(DesfireContext *dctx, uint8_t fnum, uint32_t recnum, uint32_t offset, uint32_t len, uint8_t *data); int DesfireUpdateRecord(DesfireContext *dctx, uint8_t fnum, uint32_t recnum, uint32_t offset, uint32_t len, uint8_t *data);
int DesfireISOSelectDF(DesfireContext *dctx, char *dfname, uint8_t *resp, size_t *resplen);
int DesfireISOSelect(DesfireContext *dctx, DesfireISOSelectControl cntr, uint8_t *data, uint8_t datalen, uint8_t *resp, size_t *resplen);
int DesfireISOGetChallenge(DesfireContext *dctx, DesfireCryptoAlgorythm keytype, uint8_t *resp, size_t *resplen);
int DesfireISOExternalAuth(DesfireContext *dctx, bool app_level, uint8_t keynum, DesfireCryptoAlgorythm keytype, uint8_t *data);
int DesfireISOInternalAuth(DesfireContext *dctx, bool app_level, uint8_t keynum, DesfireCryptoAlgorythm keytype, uint8_t *data, uint8_t *resp, size_t *resplen);
#endif // __DESFIRECORE_H #endif // __DESFIRECORE_H

View file

@ -42,6 +42,8 @@ void DesfireClearContext(DesfireContext *ctx) {
ctx->cmdSet = DCCNative; ctx->cmdSet = DCCNative;
ctx->commMode = DCMNone; ctx->commMode = DCMNone;
ctx->appSelected = false;
ctx->kdfAlgo = 0; ctx->kdfAlgo = 0;
ctx->kdfInputLen = 0; ctx->kdfInputLen = 0;
memset(ctx->kdfInput, 0, sizeof(ctx->kdfInput)); memset(ctx->kdfInput, 0, sizeof(ctx->kdfInput));
@ -389,6 +391,35 @@ uint8_t DesfireCommModeToFileCommMode(DesfireCommunicationMode comm_mode) {
return fmode; return fmode;
} }
void DesfireGenSessionKeyEV1(const uint8_t rnda[], const uint8_t rndb[], DesfireCryptoAlgorythm keytype, uint8_t *key) {
switch (keytype) {
case T_DES:
memcpy(key, rnda, 4);
memcpy(key + 4, rndb, 4);
break;
case T_3DES:
memcpy(key, rnda, 4);
memcpy(key + 4, rndb, 4);
memcpy(key + 8, rnda + 4, 4);
memcpy(key + 12, rndb + 4, 4);
break;
case T_3K3DES:
memcpy(key, rnda, 4);
memcpy(key + 4, rndb, 4);
memcpy(key + 8, rnda + 6, 4);
memcpy(key + 12, rndb + 6, 4);
memcpy(key + 16, rnda + 12, 4);
memcpy(key + 20, rndb + 12, 4);
break;
case T_AES:
memcpy(key, rnda, 4);
memcpy(key + 4, rndb, 4);
memcpy(key + 8, rnda + 12, 4);
memcpy(key + 12, rndb + 12, 4);
break;
}
}
// https://www.nxp.com/docs/en/application-note/AN12343.pdf // https://www.nxp.com/docs/en/application-note/AN12343.pdf
// page 35 // page 35
void DesfireGenSessionKeyEV2(uint8_t *key, uint8_t *rndA, uint8_t *rndB, bool enckey, uint8_t *sessionkey) { void DesfireGenSessionKeyEV2(uint8_t *key, uint8_t *rndA, uint8_t *rndB, bool enckey, uint8_t *sessionkey) {

View file

@ -76,6 +76,8 @@ typedef struct DesfireContextS {
DesfireCommandSet cmdSet; // native/nativeiso/iso DesfireCommandSet cmdSet; // native/nativeiso/iso
DesfireCommunicationMode commMode; // plain/mac/enc DesfireCommunicationMode commMode; // plain/mac/enc
bool appSelected; // for iso auth
uint8_t IV[DESFIRE_MAX_KEY_SIZE]; uint8_t IV[DESFIRE_MAX_KEY_SIZE];
uint8_t sessionKeyMAC[DESFIRE_MAX_KEY_SIZE]; uint8_t sessionKeyMAC[DESFIRE_MAX_KEY_SIZE];
uint8_t sessionKeyEnc[DESFIRE_MAX_KEY_SIZE]; // look at mifare4.h - mf4Session_t uint8_t sessionKeyEnc[DESFIRE_MAX_KEY_SIZE]; // look at mifare4.h - mf4Session_t
@ -108,6 +110,7 @@ uint8_t DesfireDESKeyGetVersion(uint8_t *key);
DesfireCommunicationMode DesfireFileCommModeToCommMode(uint8_t file_comm_mode); DesfireCommunicationMode DesfireFileCommModeToCommMode(uint8_t file_comm_mode);
uint8_t DesfireCommModeToFileCommMode(DesfireCommunicationMode comm_mode); uint8_t DesfireCommModeToFileCommMode(DesfireCommunicationMode comm_mode);
void DesfireGenSessionKeyEV1(const uint8_t rnda[], const uint8_t rndb[], DesfireCryptoAlgorythm keytype, uint8_t *key);
void DesfireGenSessionKeyEV2(uint8_t *key, uint8_t *rndA, uint8_t *rndB, bool enckey, uint8_t *sessionkey); void DesfireGenSessionKeyEV2(uint8_t *key, uint8_t *rndA, uint8_t *rndB, bool enckey, uint8_t *sessionkey);
void DesfireEV2FillIV(DesfireContext *ctx, bool ivforcommand, uint8_t *iv); void DesfireEV2FillIV(DesfireContext *ctx, bool ivforcommand, uint8_t *iv);