From e7414e127d44746c14bceb7f07ea95f5ca6f9778 Mon Sep 17 00:00:00 2001 From: merlokk <807634+merlokk@users.noreply.github.com> Date: Tue, 3 Aug 2021 17:41:55 +0300 Subject: [PATCH 1/9] test --- client/src/mifare/desfiretest.c | 35 +++++++++++++++++++++++++++++++++ 1 file changed, 35 insertions(+) diff --git a/client/src/mifare/desfiretest.c b/client/src/mifare/desfiretest.c index c08d7600d..aa9ffebad 100644 --- a/client/src/mifare/desfiretest.c +++ b/client/src/mifare/desfiretest.c @@ -269,6 +269,40 @@ static bool TestEV2IVEncode(void) { return res; } +static bool TestEV2MAC(void) { + bool res = true; + + uint8_t key[] = {0x93, 0x66, 0xFA, 0x19, 0x5E, 0xB5, 0x66, 0xF5, 0xBD, 0x2B, 0xAD, 0x40, 0x20, 0xB8, 0x30, 0x02}; + uint8_t ti[] = {0xE2, 0xD3, 0xAF, 0x69}; + uint8_t cmd = 8D; + uint8_t cmddata = {0x00, 0x00, 0x00, 0x00, 0x19, 0x00, 0x00, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, + 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22} + uint8_t macres[] = {0x68, 0xF2, 0xC2, 0x8C, 0x57, 0x5A, 0x16, 0x28}; + + DesfireContext ctx = {0}; + ctx.keyType = T_AES; + memcpy(ctx.sessionKeyMAC, key, 16); + memcpy(ctx.TI, ti, 4); + ctx.cmdCntr = 0; + + uint8_t mac[16] = {0}; + DesfireEV2CalcCMAC(&ctx, cmd, cmddata, sizeof(cmddata), mac); + res = res && (memcmp(mac, macres, sizeof(macres)) == 0); + + memset(mac, 0, sizeof(mac)); + uint8_t macres2[] = {0x08, 0x20, 0xF6, 0x88, 0x98, 0xC2, 0xA7, 0xF1}; + uint8_t rc = 0; + ctx.cmdCntr++; + DesfireEV2CalcCMAC(&ctx, rc, NULL, 0, mac); + res = res && (memcmp(mac, macres2, sizeof(macres2)) == 0); + + if (res) + PrintAndLogEx(INFO, "EV2 MAC calc...... " _GREEN_("passed")); + else + PrintAndLogEx(ERR, "EV2 MAC calc...... " _RED_("fail")); + + return res; + bool DesfireTest(bool verbose) { bool res = true; @@ -281,6 +315,7 @@ bool DesfireTest(bool verbose) { res = res && TestCMACDES(); res = res && TestEV2SessionKeys(); res = res && TestEV2IVEncode(); + res = res && TestEV2MAC(); PrintAndLogEx(INFO, "---------------------------"); if (res) From fa309476988bfdc3cd616764d29e1ad91c48f177 Mon Sep 17 00:00:00 2001 From: merlokk <807634+merlokk@users.noreply.github.com> Date: Tue, 3 Aug 2021 17:55:28 +0300 Subject: [PATCH 2/9] mac calc --- client/src/mifare/desfirecrypto.c | 13 +++++++++++++ client/src/mifare/desfirecrypto.h | 1 + 2 files changed, 14 insertions(+) diff --git a/client/src/mifare/desfirecrypto.c b/client/src/mifare/desfirecrypto.c index ba82cdae0..7501de141 100644 --- a/client/src/mifare/desfirecrypto.c +++ b/client/src/mifare/desfirecrypto.c @@ -474,6 +474,19 @@ void DesfireEV2FillIV(DesfireContext *ctx, bool ivforcommand, uint8_t *iv) { memcpy(iv, xiv, CRYPTO_AES_BLOCK_SIZE); } +int DesfireEV2CalcCMAC(DesfireContext *ctx, uint8_t cmd, uint8_t *data, size_t datalen, uint8_t *mac) { + uint8_t mdata[1050] = {0}; + size_t mdatalen = 0; + + mdata[0] = cmd; + Uint2byteToMemLe(&mdata[1], ctx->cmdCntr); + memcpy(&mdata[3], ctx->TI, 4); + if (data != NULL && datalen > 0) + memcpy(&mdata[7], data, datalen); + mdatalen = 1 + 2 + 4 + datalen; + + return aes_cmac8(NULL, ctx->sessionKeyMAC, mdata, mac, mdatalen); +} 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 a336f9e3f..2de188981 100644 --- a/client/src/mifare/desfirecrypto.h +++ b/client/src/mifare/desfirecrypto.h @@ -113,6 +113,7 @@ 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 DesfireEV2FillIV(DesfireContext *ctx, bool ivforcommand, uint8_t *iv); +int DesfireEV2CalcCMAC(DesfireContext *ctx, uint8_t cmd, uint8_t *data, size_t datalen, uint8_t *mac); 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); From 22c2b4601075a2321eae9ea26f95398599876be3 Mon Sep 17 00:00:00 2001 From: merlokk <807634+merlokk@users.noreply.github.com> Date: Tue, 3 Aug 2021 18:03:17 +0300 Subject: [PATCH 3/9] add tests --- client/src/mifare/desfiretest.c | 30 +++++++++++++++++++++++++++--- 1 file changed, 27 insertions(+), 3 deletions(-) diff --git a/client/src/mifare/desfiretest.c b/client/src/mifare/desfiretest.c index aa9ffebad..350cad4f8 100644 --- a/client/src/mifare/desfiretest.c +++ b/client/src/mifare/desfiretest.c @@ -269,26 +269,31 @@ static bool TestEV2IVEncode(void) { return res; } +// https://www.nxp.com/docs/en/application-note/AN12343.pdf +// page 54 static bool TestEV2MAC(void) { bool res = true; uint8_t key[] = {0x93, 0x66, 0xFA, 0x19, 0x5E, 0xB5, 0x66, 0xF5, 0xBD, 0x2B, 0xAD, 0x40, 0x20, 0xB8, 0x30, 0x02}; uint8_t ti[] = {0xE2, 0xD3, 0xAF, 0x69}; - uint8_t cmd = 8D; - uint8_t cmddata = {0x00, 0x00, 0x00, 0x00, 0x19, 0x00, 0x00, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, - 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22} + uint8_t cmd = 0x8D; + uint8_t cmddata[] = {0x00, 0x00, 0x00, 0x00, 0x19, 0x00, 0x00, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, + 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22}; uint8_t macres[] = {0x68, 0xF2, 0xC2, 0x8C, 0x57, 0x5A, 0x16, 0x28}; + // init DesfireContext ctx = {0}; ctx.keyType = T_AES; memcpy(ctx.sessionKeyMAC, key, 16); memcpy(ctx.TI, ti, 4); ctx.cmdCntr = 0; + // tx 1 uint8_t mac[16] = {0}; DesfireEV2CalcCMAC(&ctx, cmd, cmddata, sizeof(cmddata), mac); res = res && (memcmp(mac, macres, sizeof(macres)) == 0); + // rx 1 memset(mac, 0, sizeof(mac)); uint8_t macres2[] = {0x08, 0x20, 0xF6, 0x88, 0x98, 0xC2, 0xA7, 0xF1}; uint8_t rc = 0; @@ -296,12 +301,31 @@ static bool TestEV2MAC(void) { DesfireEV2CalcCMAC(&ctx, rc, NULL, 0, mac); res = res && (memcmp(mac, macres2, sizeof(macres2)) == 0); + // tx 2 + memset(mac, 0, sizeof(mac)); + cmd = 0xAD; + uint8_t cmddata3[] = {0x00, 0x00, 0x00, 0x00, 0x30, 0x00, 0x00}; + uint8_t macres3[] = {0x0D, 0x9B, 0xE1, 0x91, 0xD5, 0x96, 0x08, 0x34}; + DesfireEV2CalcCMAC(&ctx, cmd, cmddata3, sizeof(cmddata3), mac); + res = res && (memcmp(mac, macres3, sizeof(macres3)) == 0); + + // rx 2 + rc = 0; + ctx.cmdCntr++; + uint8_t cmddata4[] = {0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, + 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; + uint8_t macres4[] = {0xA4, 0x9A, 0x44, 0x22, 0x2D, 0x92, 0x66, 0x66}; + DesfireEV2CalcCMAC(&ctx, rc, cmddata4, sizeof(cmddata4), mac); + res = res && (memcmp(mac, macres4, sizeof(macres4)) == 0); + if (res) PrintAndLogEx(INFO, "EV2 MAC calc...... " _GREEN_("passed")); else PrintAndLogEx(ERR, "EV2 MAC calc...... " _RED_("fail")); return res; +} bool DesfireTest(bool verbose) { bool res = true; From 58e8693b49d25910dbea9b7fbe2b3c3f30933af2 Mon Sep 17 00:00:00 2001 From: merlokk <807634+merlokk@users.noreply.github.com> Date: Tue, 3 Aug 2021 18:33:06 +0300 Subject: [PATCH 4/9] ev2 tx channel sketch --- client/src/mifare/desfiresecurechan.c | 38 +++++++++++++++++++++++++++ 1 file changed, 38 insertions(+) diff --git a/client/src/mifare/desfiresecurechan.c b/client/src/mifare/desfiresecurechan.c index 73aba69a6..c0ee5273f 100644 --- a/client/src/mifare/desfiresecurechan.c +++ b/client/src/mifare/desfiresecurechan.c @@ -244,9 +244,47 @@ static void DesfireSecureChannelEncodeEV1(DesfireContext *ctx, uint8_t cmd, uint } static void DesfireSecureChannelEncodeEV2(DesfireContext *ctx, uint8_t cmd, uint8_t *srcdata, size_t srcdatalen, uint8_t *dstdata, size_t *dstdatalen) { + uint8_t data[1050] = {0}; + size_t rlen = 0; + memcpy(dstdata, srcdata, srcdatalen); *dstdatalen = srcdatalen; + uint8_t hdrlen = DesfireGetCmdHeaderLen(cmd); + + if (ctx->commMode == DCMPlain || ctx->commMode == DCMMACed || (ctx->commMode == DCMEncrypted && srcdatalen <= hdrlen)) { + + if (srcdatalen > hdrlen && ctx->commMode == DCMMACed) { + uint8_t cmac[DESFIRE_MAX_CRYPTO_BLOCK_SIZE] = {0}; + DesfireEV2CalcCMAC(ctx, cmd, data, srcdatalen, cmac); + + memcpy(&dstdata[srcdatalen], cmac, DesfireGetMACLength(ctx)); + *dstdatalen = srcdatalen + DesfireGetMACLength(ctx); + } + } else if (ctx->commMode == DCMEncrypted) { + //uint8_t iv[CRYPTO_AES_BLOCK_SIZE] = {0}; + DesfireEV2FillIV(ctx, true, NULL); // fill IV to ctx + + rlen = padded_data_length(srcdatalen + 1 - hdrlen, desfire_get_key_block_length(ctx->keyType)); + memcpy(data, &srcdata[hdrlen], srcdatalen - hdrlen); + data[hdrlen] = 0x80; // padding + + dstdata[0] = cmd; + memcpy(&dstdata[1], srcdata, hdrlen); + DesfireCryptoEncDec(ctx, true, data, rlen, &dstdata[1 + hdrlen], true); + + uint8_t cmac[DESFIRE_MAX_CRYPTO_BLOCK_SIZE] = {0}; + DesfireEV2CalcCMAC(ctx, cmd, &dstdata[1], hdrlen + rlen, cmac); + + memcpy(&dstdata[ + hdrlen + rlen], cmac, DesfireGetMACLength(ctx)); + + *dstdatalen = hdrlen + rlen + DesfireGetMACLength(ctx); + } else if (ctx->commMode == DCMEncryptedPlain) { + if (srcdatalen <= hdrlen) + return; + + // TODO !!! + } } void DesfireSecureChannelEncode(DesfireContext *ctx, uint8_t cmd, uint8_t *srcdata, size_t srcdatalen, uint8_t *dstdata, size_t *dstdatalen) { From 8d84e967169672eab582d869831408fd96072fda Mon Sep 17 00:00:00 2001 From: merlokk <807634+merlokk@users.noreply.github.com> Date: Tue, 3 Aug 2021 18:49:52 +0300 Subject: [PATCH 5/9] ev2 rx channel sketch --- client/src/mifare/desfiresecurechan.c | 48 ++++++++++++++++++++++++++- 1 file changed, 47 insertions(+), 1 deletion(-) diff --git a/client/src/mifare/desfiresecurechan.c b/client/src/mifare/desfiresecurechan.c index c0ee5273f..bd732e6a8 100644 --- a/client/src/mifare/desfiresecurechan.c +++ b/client/src/mifare/desfiresecurechan.c @@ -262,7 +262,6 @@ static void DesfireSecureChannelEncodeEV2(DesfireContext *ctx, uint8_t cmd, uint *dstdatalen = srcdatalen + DesfireGetMACLength(ctx); } } else if (ctx->commMode == DCMEncrypted) { - //uint8_t iv[CRYPTO_AES_BLOCK_SIZE] = {0}; DesfireEV2FillIV(ctx, true, NULL); // fill IV to ctx rlen = padded_data_length(srcdatalen + 1 - hdrlen, desfire_get_key_block_length(ctx->keyType)); @@ -415,6 +414,53 @@ static void DesfireSecureChannelDecodeEV2(DesfireContext *ctx, uint8_t *srcdata, memcpy(dstdata, srcdata, srcdatalen); *dstdatalen = srcdatalen; + uint8_t cmac[DESFIRE_MAX_CRYPTO_BLOCK_SIZE] = {0}; + + // if comm mode = plain --> response with MAC + // if request is not zero length --> response MAC + if (ctx->commMode == DCMPlain || ctx->commMode == DCMMACed || (ctx->commMode == DCMEncrypted && !ctx->lastRequestZeroLen)) { + if (srcdatalen < DesfireGetMACLength(ctx)) { + memcpy(dstdata, srcdata, srcdatalen); + *dstdatalen = srcdatalen; + return; + } + + memcpy(dstdata, srcdata, srcdatalen - DesfireGetMACLength(ctx)); + *dstdatalen = srcdatalen - DesfireGetMACLength(ctx); + + DesfireEV2CalcCMAC(ctx, 0x00, srcdata, *dstdatalen, cmac); + if (memcmp(&srcdata[*dstdatalen], cmac, DesfireGetMACLength(ctx)) != 0) { + PrintAndLogEx(WARNING, "Received MAC is not match with calculated"); + PrintAndLogEx(INFO, " received MAC: %s", sprint_hex(&srcdata[*dstdatalen], desfire_get_key_block_length(ctx->keyType))); + PrintAndLogEx(INFO, " calculated MAC: %s", sprint_hex(cmac, desfire_get_key_block_length(ctx->keyType))); + } + } else if (ctx->commMode == DCMEncrypted) { + if (srcdatalen < desfire_get_key_block_length(ctx->keyType) + DesfireGetMACLength(ctx)) { + memcpy(dstdata, srcdata, srcdatalen); + *dstdatalen = srcdatalen; + return; + } + + *dstdatalen = srcdatalen - DesfireGetMACLength(ctx); + DesfireEV2CalcCMAC(ctx, 0x00, srcdata, *dstdatalen, cmac); + if (memcmp(&srcdata[*dstdatalen], cmac, DesfireGetMACLength(ctx)) != 0) { + PrintAndLogEx(WARNING, "Received MAC is not match with calculated"); + PrintAndLogEx(INFO, " received MAC: %s", sprint_hex(&srcdata[*dstdatalen], desfire_get_key_block_length(ctx->keyType))); + PrintAndLogEx(INFO, " calculated MAC: %s", sprint_hex(cmac, desfire_get_key_block_length(ctx->keyType))); + } + + DesfireEV2FillIV(ctx, true, NULL); // fill IV to ctx + + DesfireCryptoEncDec(ctx, true, srcdata, *dstdatalen, dstdata, false); + PrintAndLogEx(INFO, "decoded[%d]: %s", *dstdatalen, sprint_hex(dstdata, *dstdatalen)); + + size_t puredatalen = FindISO9797M2PaddingDataLen(dstdata, *dstdatalen); + if (puredatalen != 0) { + *dstdatalen = puredatalen; + } else { + PrintAndLogEx(WARNING, "Padding search error."); + } + } } void DesfireSecureChannelDecode(DesfireContext *ctx, uint8_t *srcdata, size_t srcdatalen, uint8_t respcode, uint8_t *dstdata, size_t *dstdatalen) { From fd5afbdfac4bbdea4c64cb3df84b66ea462e42b0 Mon Sep 17 00:00:00 2001 From: merlokk <807634+merlokk@users.noreply.github.com> Date: Tue, 3 Aug 2021 18:58:39 +0300 Subject: [PATCH 6/9] encode fix --- client/src/mifare/desfiresecurechan.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/client/src/mifare/desfiresecurechan.c b/client/src/mifare/desfiresecurechan.c index bd732e6a8..2314f7df5 100644 --- a/client/src/mifare/desfiresecurechan.c +++ b/client/src/mifare/desfiresecurechan.c @@ -254,7 +254,7 @@ static void DesfireSecureChannelEncodeEV2(DesfireContext *ctx, uint8_t cmd, uint if (ctx->commMode == DCMPlain || ctx->commMode == DCMMACed || (ctx->commMode == DCMEncrypted && srcdatalen <= hdrlen)) { - if (srcdatalen > hdrlen && ctx->commMode == DCMMACed) { + if (ctx->commMode == DCMMACed || ctx->commMode == DCMEncrypted) { uint8_t cmac[DESFIRE_MAX_CRYPTO_BLOCK_SIZE] = {0}; DesfireEV2CalcCMAC(ctx, cmd, data, srcdatalen, cmac); From 645985a1f90045387183d34058f131505e1dbd1a Mon Sep 17 00:00:00 2001 From: merlokk <807634+merlokk@users.noreply.github.com> Date: Tue, 3 Aug 2021 19:08:30 +0300 Subject: [PATCH 7/9] check mode in ev2 like ev1 --- client/src/mifare/desfirecore.c | 2 +- client/src/mifare/desfiresecurechan.c | 11 ++++++++++- 2 files changed, 11 insertions(+), 2 deletions(-) diff --git a/client/src/mifare/desfirecore.c b/client/src/mifare/desfirecore.c index e60093317..869be3d0e 100644 --- a/client/src/mifare/desfirecore.c +++ b/client/src/mifare/desfirecore.c @@ -347,7 +347,7 @@ void DesfirePrintContext(DesfireContext *ctx) { desfire_get_key_block_length(ctx->keyType), sprint_hex(ctx->IV, desfire_get_key_block_length(ctx->keyType))); if (ctx->secureChannel == DACEV2) { - PrintAndLogEx(INFO, " TI: %s cmdCntr: 0x%08x", + PrintAndLogEx(INFO, " TI: %s cmdCntr: 0x%04x", sprint_hex(ctx->TI, 4), ctx->cmdCntr); } diff --git a/client/src/mifare/desfiresecurechan.c b/client/src/mifare/desfiresecurechan.c index 2314f7df5..1fc5ed78a 100644 --- a/client/src/mifare/desfiresecurechan.c +++ b/client/src/mifare/desfiresecurechan.c @@ -256,7 +256,7 @@ static void DesfireSecureChannelEncodeEV2(DesfireContext *ctx, uint8_t cmd, uint if (ctx->commMode == DCMMACed || ctx->commMode == DCMEncrypted) { uint8_t cmac[DESFIRE_MAX_CRYPTO_BLOCK_SIZE] = {0}; - DesfireEV2CalcCMAC(ctx, cmd, data, srcdatalen, cmac); + DesfireEV2CalcCMAC(ctx, cmd, srcdata, srcdatalen, cmac); memcpy(&dstdata[srcdatalen], cmac, DesfireGetMACLength(ctx)); *dstdatalen = srcdatalen + DesfireGetMACLength(ctx); @@ -515,6 +515,15 @@ bool PrintChannelModeWarning(uint8_t cmd, DesfireSecureChannel secureChannel, De break; } + // ev2 like ev1 + if (secureChannel == DACEV2 && + AllowedChannelModes[i].secureChannel == DACEV1 && + (AllowedChannelModes[i].cmdSet == cmdSet || (AllowedChannelModes[i].cmdSet == DCCNative && cmdSet == DCCNativeISO)) && + AllowedChannelModes[i].commMode == commMode) { + + found = true; + break; + } } if (!found) From fc8e3e8851bfb11b037de3afc838d97f108056fd Mon Sep 17 00:00:00 2001 From: merlokk <807634+merlokk@users.noreply.github.com> Date: Wed, 4 Aug 2021 14:58:07 +0300 Subject: [PATCH 8/9] fix ev2 auth. ev2/enc/nodata works --- client/src/mifare/desfirecore.c | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/client/src/mifare/desfirecore.c b/client/src/mifare/desfirecore.c index 869be3d0e..1a1890b11 100644 --- a/client/src/mifare/desfirecore.c +++ b/client/src/mifare/desfirecore.c @@ -1153,6 +1153,7 @@ static int DesfireAuthenticateEV2(DesfireContext *dctx, DesfireSecureChannel sec uint8_t RndA[CRYPTO_AES_BLOCK_SIZE] = {0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16}; uint8_t RndB[CRYPTO_AES_BLOCK_SIZE] = {0}; uint8_t encRndB[CRYPTO_AES_BLOCK_SIZE] = {0}; + uint8_t rotRndA[CRYPTO_AES_BLOCK_SIZE] = {0}; //RndA' uint8_t rotRndB[CRYPTO_AES_BLOCK_SIZE] = {0}; //RndB' uint8_t both[CRYPTO_AES_BLOCK_SIZE * 2 + 1] = {0}; // ek/dk_keyNo(RndA+RndB') @@ -1201,8 +1202,6 @@ static int DesfireAuthenticateEV2(DesfireContext *dctx, DesfireSecureChannel sec memcpy(rotRndB, RndB, CRYPTO_AES_BLOCK_SIZE); rol(rotRndB, CRYPTO_AES_BLOCK_SIZE); - uint8_t encRndA[16] = {0x00}; - // - Encrypt our response uint8_t tmp[32] = {0x00}; memcpy(tmp, RndA, CRYPTO_AES_BLOCK_SIZE); @@ -1232,20 +1231,21 @@ static int DesfireAuthenticateEV2(DesfireContext *dctx, DesfireSecureChannel sec } // Part 4 - memcpy(encRndA, recv_data, CRYPTO_AES_BLOCK_SIZE); - uint8_t data[32] = {0}; if (aes_decode(IV, key, recv_data, data, recv_len)) return 10; - rol(RndA, CRYPTO_AES_BLOCK_SIZE); + // rotate rndA to check + memcpy(rotRndA, RndA, CRYPTO_AES_BLOCK_SIZE); + rol(rotRndA, CRYPTO_AES_BLOCK_SIZE); + uint8_t *recRndA = (firstauth) ? &data[4] : data; - if (memcmp(RndA, recRndA, CRYPTO_AES_BLOCK_SIZE) != 0) { + if (memcmp(rotRndA, recRndA, CRYPTO_AES_BLOCK_SIZE) != 0) { if (g_debugMode > 1) { - PrintAndLogEx(DEBUG, "Expected_RndA : %s", sprint_hex(RndA, CRYPTO_AES_BLOCK_SIZE)); - PrintAndLogEx(DEBUG, "Generated_RndA : %s", sprint_hex(recRndA, CRYPTO_AES_BLOCK_SIZE)); + PrintAndLogEx(DEBUG, "Expected_RndA' : %s", sprint_hex(rotRndA, CRYPTO_AES_BLOCK_SIZE)); + PrintAndLogEx(DEBUG, "Generated_RndA' : %s", sprint_hex(recRndA, CRYPTO_AES_BLOCK_SIZE)); } return 11; } From 51b197c3a60adc091b7aff6363d1fece4ae8c128 Mon Sep 17 00:00:00 2001 From: merlokk <807634+merlokk@users.noreply.github.com> Date: Wed, 4 Aug 2021 15:26:40 +0300 Subject: [PATCH 9/9] ev2 encrypted channel tx works --- client/src/mifare/desfirecore.c | 4 ++-- client/src/mifare/desfirecrypto.c | 19 +++++++++++-------- client/src/mifare/desfirecrypto.h | 9 +++++++-- client/src/mifare/desfiresecurechan.c | 25 +++++++++++++------------ 4 files changed, 33 insertions(+), 24 deletions(-) diff --git a/client/src/mifare/desfirecore.c b/client/src/mifare/desfirecore.c index 1a1890b11..454616643 100644 --- a/client/src/mifare/desfirecore.c +++ b/client/src/mifare/desfirecore.c @@ -1295,7 +1295,7 @@ static int DesfireAuthenticateISO(DesfireContext *dctx, DesfireSecureChannel sec // encode DesfireClearIV(dctx); - DesfireCryptoEncDec(dctx, false, both, rndlen * 2, both, true); // error 303 + DesfireCryptoEncDec(dctx, DCOMainKey, both, rndlen * 2, both, true); // error 303 // external authenticate res = DesfireISOExternalAuth(dctx, dctx->appSelected, dctx->keyNum, dctx->keyType, both); @@ -1314,7 +1314,7 @@ static int DesfireAuthenticateISO(DesfireContext *dctx, DesfireSecureChannel sec // decode rnddata uint8_t piccrnd2[64] = {0}; - DesfireCryptoEncDec(dctx, false, rnddata, rndlen * 2, piccrnd2, false); // error 307 + DesfireCryptoEncDec(dctx, DCOMainKey, rnddata, rndlen * 2, piccrnd2, false); // error 307 // check if (memcmp(hostrnd2, &piccrnd2[rndlen], rndlen) != 0) diff --git a/client/src/mifare/desfirecrypto.c b/client/src/mifare/desfirecrypto.c index 7501de141..95dc95b0e 100644 --- a/client/src/mifare/desfirecrypto.c +++ b/client/src/mifare/desfirecrypto.c @@ -217,7 +217,7 @@ static void DesfireCryptoEncDecSingleBlock(uint8_t *key, DesfireCryptoAlgorythm memcpy(dstdata, edata, block_size); } -void DesfireCryptoEncDecEx(DesfireContext *ctx, bool use_session_key, uint8_t *srcdata, size_t srcdatalen, uint8_t *dstdata, bool dir_to_send, bool encode, uint8_t *iv) { +void DesfireCryptoEncDecEx(DesfireContext *ctx, DesfireCryptoOpKeyType key_type, uint8_t *srcdata, size_t srcdatalen, uint8_t *dstdata, bool dir_to_send, bool encode, uint8_t *iv) { uint8_t data[1024] = {0}; uint8_t xiv[DESFIRE_MAX_CRYPTO_BLOCK_SIZE] = {0}; @@ -234,10 +234,13 @@ void DesfireCryptoEncDecEx(DesfireContext *ctx, bool use_session_key, uint8_t *s size_t offset = 0; while (offset < srcdatalen) { - if (use_session_key) + if (key_type == DCOSessionKeyMac) { DesfireCryptoEncDecSingleBlock(ctx->sessionKeyMAC, ctx->keyType, srcdata + offset, data + offset, xiv, dir_to_send, encode); - else + } else if (key_type == DCOSessionKeyEnc) { + DesfireCryptoEncDecSingleBlock(ctx->sessionKeyEnc, ctx->keyType, srcdata + offset, data + offset, xiv, dir_to_send, encode); + } else { DesfireCryptoEncDecSingleBlock(ctx->key, ctx->keyType, srcdata + offset, data + offset, xiv, dir_to_send, encode); + } offset += block_size; } @@ -250,13 +253,13 @@ void DesfireCryptoEncDecEx(DesfireContext *ctx, bool use_session_key, uint8_t *s memcpy(dstdata, data, srcdatalen); } -void DesfireCryptoEncDec(DesfireContext *ctx, bool use_session_key, uint8_t *srcdata, size_t srcdatalen, uint8_t *dstdata, bool encode) { +void DesfireCryptoEncDec(DesfireContext *ctx, DesfireCryptoOpKeyType key_type, uint8_t *srcdata, size_t srcdatalen, uint8_t *dstdata, bool encode) { bool dir_to_send = encode; bool xencode = encode; if (ctx->secureChannel == DACd40) xencode = false; - DesfireCryptoEncDecEx(ctx, use_session_key, srcdata, srcdatalen, dstdata, dir_to_send, xencode, NULL); + DesfireCryptoEncDecEx(ctx, key_type, srcdata, srcdatalen, dstdata, dir_to_send, xencode, NULL); } static void DesfireCMACGenerateSubkeys(DesfireContext *ctx, uint8_t *sk1, uint8_t *sk2) { @@ -269,7 +272,7 @@ static void DesfireCMACGenerateSubkeys(DesfireContext *ctx, uint8_t *sk1, uint8_ uint8_t ivect[kbs]; memset(ivect, 0, kbs); - DesfireCryptoEncDecEx(ctx, true, l, kbs, l, true, true, ivect); + DesfireCryptoEncDecEx(ctx, DCOSessionKeyMac, l, kbs, l, true, true, ivect); bool txor = false; @@ -314,7 +317,7 @@ void DesfireCryptoCMAC(DesfireContext *ctx, uint8_t *data, size_t len, uint8_t * bin_xor(buffer + len - kbs, sk1, kbs); } - DesfireCryptoEncDec(ctx, true, buffer, len, NULL, true); + DesfireCryptoEncDec(ctx, DCOSessionKeyMac, buffer, len, NULL, true); if (cmac != NULL) memcpy(cmac, ctx->IV, kbs); @@ -484,7 +487,7 @@ int DesfireEV2CalcCMAC(DesfireContext *ctx, uint8_t cmd, uint8_t *data, size_t d if (data != NULL && datalen > 0) memcpy(&mdata[7], data, datalen); mdatalen = 1 + 2 + 4 + datalen; - + return aes_cmac8(NULL, ctx->sessionKeyMAC, mdata, mac, mdatalen); } diff --git a/client/src/mifare/desfirecrypto.h b/client/src/mifare/desfirecrypto.h index 2de188981..dfc9a0685 100644 --- a/client/src/mifare/desfirecrypto.h +++ b/client/src/mifare/desfirecrypto.h @@ -61,6 +61,11 @@ typedef enum { DCMEncryptedPlain } DesfireCommunicationMode; +typedef enum { + DCOMainKey, + DCOSessionKeyMac, + DCOSessionKeyEnc +} DesfireCryptoOpKeyType; typedef struct DesfireContextS { uint8_t keyNum; @@ -100,8 +105,8 @@ size_t DesfireGetMACLength(DesfireContext *ctx); size_t DesfireSearchCRCPos(uint8_t *data, size_t datalen, uint8_t respcode, uint8_t crclen); -void DesfireCryptoEncDec(DesfireContext *ctx, bool use_session_key, uint8_t *srcdata, size_t srcdatalen, uint8_t *dstdata, bool encode); -void DesfireCryptoEncDecEx(DesfireContext *ctx, bool use_session_key, uint8_t *srcdata, size_t srcdatalen, uint8_t *dstdata, bool dir_to_send, bool encode, uint8_t *iv); +void DesfireCryptoEncDec(DesfireContext *ctx, DesfireCryptoOpKeyType key_type, uint8_t *srcdata, size_t srcdatalen, uint8_t *dstdata, bool encode); +void DesfireCryptoEncDecEx(DesfireContext *ctx, DesfireCryptoOpKeyType key_type, uint8_t *srcdata, size_t srcdatalen, uint8_t *dstdata, bool dir_to_send, 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); diff --git a/client/src/mifare/desfiresecurechan.c b/client/src/mifare/desfiresecurechan.c index 1fc5ed78a..0f6ad2bd4 100644 --- a/client/src/mifare/desfiresecurechan.c +++ b/client/src/mifare/desfiresecurechan.c @@ -166,7 +166,7 @@ static void DesfireSecureChannelEncodeD40(DesfireContext *ctx, uint8_t cmd, uint size_t srcmaclen = padded_data_length(srcdatalen - hdrlen, desfire_get_key_block_length(ctx->keyType)); uint8_t mac[32] = {0}; - DesfireCryptoEncDecEx(ctx, true, data, srcmaclen, NULL, true, true, mac); + DesfireCryptoEncDecEx(ctx, DCOSessionKeyMac, data, srcmaclen, NULL, true, true, mac); memcpy(dstdata, srcdata, srcdatalen); memcpy(&dstdata[srcdatalen], mac, DesfireGetMACLength(ctx)); @@ -181,7 +181,7 @@ static void DesfireSecureChannelEncodeD40(DesfireContext *ctx, uint8_t cmd, uint memcpy(dstdata, srcdata, hdrlen); //PrintAndLogEx(INFO, "src[%d]: %s", srcdatalen - hdrlen + 2, sprint_hex(data, srcdatalen - hdrlen + 2)); - DesfireCryptoEncDec(ctx, true, data, rlen - hdrlen, &dstdata[hdrlen], true); + DesfireCryptoEncDec(ctx, DCOSessionKeyEnc, data, rlen - hdrlen, &dstdata[hdrlen], true); *dstdatalen = rlen; } else if (ctx->commMode == DCMEncryptedPlain) { @@ -191,7 +191,7 @@ static void DesfireSecureChannelEncodeD40(DesfireContext *ctx, uint8_t cmd, uint 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); + DesfireCryptoEncDec(ctx, DCOSessionKeyEnc, &data[hdrlen], rlen - hdrlen, &dstdata[hdrlen], true); *dstdatalen = rlen; ctx->commMode = DCMEncrypted; } @@ -227,7 +227,7 @@ static void DesfireSecureChannelEncodeEV1(DesfireContext *ctx, uint8_t cmd, uint desfire_crc32_append(data, srcdatalen + 1); memcpy(dstdata, srcdata, hdrlen); - DesfireCryptoEncDec(ctx, true, &data[1 + hdrlen], rlen, &dstdata[hdrlen], true); + DesfireCryptoEncDec(ctx, DCOSessionKeyEnc, &data[1 + hdrlen], rlen, &dstdata[hdrlen], true); *dstdatalen = hdrlen + rlen; } else if (ctx->commMode == DCMEncryptedPlain) { @@ -237,7 +237,7 @@ static void DesfireSecureChannelEncodeEV1(DesfireContext *ctx, uint8_t cmd, uint memcpy(dstdata, srcdata, hdrlen); memcpy(data, &srcdata[hdrlen], srcdatalen); rlen = padded_data_length(srcdatalen - hdrlen, desfire_get_key_block_length(ctx->keyType)); - DesfireCryptoEncDec(ctx, true, data, rlen, &dstdata[hdrlen], true); + DesfireCryptoEncDec(ctx, DCOSessionKeyEnc, data, rlen, &dstdata[hdrlen], true); *dstdatalen = hdrlen + rlen; ctx->commMode = DCMEncrypted; } @@ -270,7 +270,7 @@ static void DesfireSecureChannelEncodeEV2(DesfireContext *ctx, uint8_t cmd, uint dstdata[0] = cmd; memcpy(&dstdata[1], srcdata, hdrlen); - DesfireCryptoEncDec(ctx, true, data, rlen, &dstdata[1 + hdrlen], true); + DesfireCryptoEncDec(ctx, DCOSessionKeyEnc, data, rlen, &dstdata[1 + hdrlen], true); uint8_t cmac[DESFIRE_MAX_CRYPTO_BLOCK_SIZE] = {0}; DesfireEV2CalcCMAC(ctx, cmd, &dstdata[1], hdrlen + rlen, cmac); @@ -321,7 +321,7 @@ static void DesfireSecureChannelDecodeD40(DesfireContext *ctx, uint8_t *srcdata, uint8_t mac[16] = {0}; rlen = padded_data_length(srcdatalen - maclen, desfire_get_key_block_length(ctx->keyType)); memcpy(data, srcdata, srcdatalen - maclen); - DesfireCryptoEncDecEx(ctx, true, data, rlen, NULL, true, true, mac); + DesfireCryptoEncDecEx(ctx, DCOSessionKeyMac, data, rlen, NULL, true, true, mac); if (memcmp(mac, &srcdata[srcdatalen - maclen], maclen) == 0) { *dstdatalen = srcdatalen - maclen; @@ -340,7 +340,7 @@ static void DesfireSecureChannelDecodeD40(DesfireContext *ctx, uint8_t *srcdata, return; } - DesfireCryptoEncDec(ctx, true, srcdata, srcdatalen, dstdata, false); + DesfireCryptoEncDec(ctx, DCOSessionKeyEnc, srcdata, srcdatalen, dstdata, false); //PrintAndLogEx(INFO, "decoded[%d]: %s", srcdatalen, sprint_hex(dstdata, srcdatalen)); size_t puredatalen = DesfireSearchCRCPos(dstdata, srcdatalen, respcode, 2); @@ -392,7 +392,7 @@ static void DesfireSecureChannelDecodeEV1(DesfireContext *ctx, uint8_t *srcdata, return; } - DesfireCryptoEncDec(ctx, true, srcdata, srcdatalen, dstdata, false); + DesfireCryptoEncDec(ctx, DCOSessionKeyEnc, srcdata, srcdatalen, dstdata, false); //PrintAndLogEx(INFO, "decoded[%d]: %s", srcdatalen, sprint_hex(dstdata, srcdatalen)); size_t puredatalen = DesfireSearchCRCPos(dstdata, srcdatalen, respcode, 4); @@ -447,12 +447,13 @@ static void DesfireSecureChannelDecodeEV2(DesfireContext *ctx, uint8_t *srcdata, PrintAndLogEx(WARNING, "Received MAC is not match with calculated"); PrintAndLogEx(INFO, " received MAC: %s", sprint_hex(&srcdata[*dstdatalen], desfire_get_key_block_length(ctx->keyType))); PrintAndLogEx(INFO, " calculated MAC: %s", sprint_hex(cmac, desfire_get_key_block_length(ctx->keyType))); + } else { + //PrintAndLogEx(INFO, "Received MAC OK"); } - DesfireEV2FillIV(ctx, true, NULL); // fill IV to ctx + DesfireEV2FillIV(ctx, false, NULL); // fill response IV to ctx - DesfireCryptoEncDec(ctx, true, srcdata, *dstdatalen, dstdata, false); - PrintAndLogEx(INFO, "decoded[%d]: %s", *dstdatalen, sprint_hex(dstdata, *dstdatalen)); + DesfireCryptoEncDec(ctx, DCOSessionKeyEnc, srcdata, *dstdatalen, dstdata, false); size_t puredatalen = FindISO9797M2PaddingDataLen(dstdata, *dstdatalen); if (puredatalen != 0) {