ev2 encrypted channel tx works

This commit is contained in:
merlokk 2021-08-04 15:26:40 +03:00
parent fc8e3e8851
commit 51b197c3a6
4 changed files with 33 additions and 24 deletions

View file

@ -1295,7 +1295,7 @@ static int DesfireAuthenticateISO(DesfireContext *dctx, DesfireSecureChannel sec
// encode // encode
DesfireClearIV(dctx); DesfireClearIV(dctx);
DesfireCryptoEncDec(dctx, false, both, rndlen * 2, both, true); // error 303 DesfireCryptoEncDec(dctx, DCOMainKey, both, rndlen * 2, both, true); // error 303
// external authenticate // external authenticate
res = DesfireISOExternalAuth(dctx, dctx->appSelected, dctx->keyNum, dctx->keyType, both); res = DesfireISOExternalAuth(dctx, dctx->appSelected, dctx->keyNum, dctx->keyType, both);
@ -1314,7 +1314,7 @@ static int DesfireAuthenticateISO(DesfireContext *dctx, DesfireSecureChannel sec
// decode rnddata // decode rnddata
uint8_t piccrnd2[64] = {0}; 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 // check
if (memcmp(hostrnd2, &piccrnd2[rndlen], rndlen) != 0) if (memcmp(hostrnd2, &piccrnd2[rndlen], rndlen) != 0)

View file

@ -217,7 +217,7 @@ static void DesfireCryptoEncDecSingleBlock(uint8_t *key, DesfireCryptoAlgorythm
memcpy(dstdata, edata, block_size); 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 data[1024] = {0};
uint8_t xiv[DESFIRE_MAX_CRYPTO_BLOCK_SIZE] = {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; size_t offset = 0;
while (offset < srcdatalen) { 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); 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); DesfireCryptoEncDecSingleBlock(ctx->key, ctx->keyType, srcdata + offset, data + offset, xiv, dir_to_send, encode);
}
offset += block_size; offset += block_size;
} }
@ -250,13 +253,13 @@ void DesfireCryptoEncDecEx(DesfireContext *ctx, bool use_session_key, uint8_t *s
memcpy(dstdata, data, srcdatalen); 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 dir_to_send = encode;
bool xencode = encode; bool xencode = encode;
if (ctx->secureChannel == DACd40) if (ctx->secureChannel == DACd40)
xencode = false; 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) { 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]; uint8_t ivect[kbs];
memset(ivect, 0, 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; 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); bin_xor(buffer + len - kbs, sk1, kbs);
} }
DesfireCryptoEncDec(ctx, true, buffer, len, NULL, true); DesfireCryptoEncDec(ctx, DCOSessionKeyMac, buffer, len, NULL, true);
if (cmac != NULL) if (cmac != NULL)
memcpy(cmac, ctx->IV, kbs); 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) if (data != NULL && datalen > 0)
memcpy(&mdata[7], data, datalen); memcpy(&mdata[7], data, datalen);
mdatalen = 1 + 2 + 4 + datalen; mdatalen = 1 + 2 + 4 + datalen;
return aes_cmac8(NULL, ctx->sessionKeyMAC, mdata, mac, mdatalen); return aes_cmac8(NULL, ctx->sessionKeyMAC, mdata, mac, mdatalen);
} }

View file

@ -61,6 +61,11 @@ typedef enum {
DCMEncryptedPlain DCMEncryptedPlain
} DesfireCommunicationMode; } DesfireCommunicationMode;
typedef enum {
DCOMainKey,
DCOSessionKeyMac,
DCOSessionKeyEnc
} DesfireCryptoOpKeyType;
typedef struct DesfireContextS { typedef struct DesfireContextS {
uint8_t keyNum; 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); 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 DesfireCryptoEncDec(DesfireContext *ctx, DesfireCryptoOpKeyType key_type, 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 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 DesfireCryptoCMAC(DesfireContext *ctx, uint8_t *srcdata, size_t srcdatalen, uint8_t *cmac);
void DesfireDESKeySetVersion(uint8_t *key, DesfireCryptoAlgorythm keytype, uint8_t version); void DesfireDESKeySetVersion(uint8_t *key, DesfireCryptoAlgorythm keytype, uint8_t version);

View file

@ -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)); size_t srcmaclen = padded_data_length(srcdatalen - hdrlen, desfire_get_key_block_length(ctx->keyType));
uint8_t mac[32] = {0}; 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, srcdata, srcdatalen);
memcpy(&dstdata[srcdatalen], mac, DesfireGetMACLength(ctx)); memcpy(&dstdata[srcdatalen], mac, DesfireGetMACLength(ctx));
@ -181,7 +181,7 @@ static void DesfireSecureChannelEncodeD40(DesfireContext *ctx, uint8_t cmd, uint
memcpy(dstdata, srcdata, hdrlen); memcpy(dstdata, srcdata, hdrlen);
//PrintAndLogEx(INFO, "src[%d]: %s", srcdatalen - hdrlen + 2, sprint_hex(data, srcdatalen - hdrlen + 2)); //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; *dstdatalen = rlen;
} else if (ctx->commMode == DCMEncryptedPlain) { } 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; rlen = padded_data_length(srcdatalen - hdrlen, desfire_get_key_block_length(ctx->keyType)) + hdrlen;
memcpy(data, srcdata, srcdatalen); memcpy(data, srcdata, srcdatalen);
memcpy(dstdata, srcdata, hdrlen); 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; *dstdatalen = rlen;
ctx->commMode = DCMEncrypted; ctx->commMode = DCMEncrypted;
} }
@ -227,7 +227,7 @@ static void DesfireSecureChannelEncodeEV1(DesfireContext *ctx, uint8_t cmd, uint
desfire_crc32_append(data, srcdatalen + 1); desfire_crc32_append(data, srcdatalen + 1);
memcpy(dstdata, srcdata, hdrlen); 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; *dstdatalen = hdrlen + rlen;
} else if (ctx->commMode == DCMEncryptedPlain) { } else if (ctx->commMode == DCMEncryptedPlain) {
@ -237,7 +237,7 @@ static void DesfireSecureChannelEncodeEV1(DesfireContext *ctx, uint8_t cmd, uint
memcpy(dstdata, srcdata, hdrlen); memcpy(dstdata, srcdata, hdrlen);
memcpy(data, &srcdata[hdrlen], srcdatalen); memcpy(data, &srcdata[hdrlen], srcdatalen);
rlen = padded_data_length(srcdatalen - hdrlen, desfire_get_key_block_length(ctx->keyType)); 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; *dstdatalen = hdrlen + rlen;
ctx->commMode = DCMEncrypted; ctx->commMode = DCMEncrypted;
} }
@ -270,7 +270,7 @@ static void DesfireSecureChannelEncodeEV2(DesfireContext *ctx, uint8_t cmd, uint
dstdata[0] = cmd; dstdata[0] = cmd;
memcpy(&dstdata[1], srcdata, hdrlen); 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}; uint8_t cmac[DESFIRE_MAX_CRYPTO_BLOCK_SIZE] = {0};
DesfireEV2CalcCMAC(ctx, cmd, &dstdata[1], hdrlen + rlen, cmac); 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}; uint8_t mac[16] = {0};
rlen = padded_data_length(srcdatalen - maclen, desfire_get_key_block_length(ctx->keyType)); rlen = padded_data_length(srcdatalen - maclen, desfire_get_key_block_length(ctx->keyType));
memcpy(data, srcdata, srcdatalen - maclen); 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) { if (memcmp(mac, &srcdata[srcdatalen - maclen], maclen) == 0) {
*dstdatalen = srcdatalen - maclen; *dstdatalen = srcdatalen - maclen;
@ -340,7 +340,7 @@ static void DesfireSecureChannelDecodeD40(DesfireContext *ctx, uint8_t *srcdata,
return; 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)); //PrintAndLogEx(INFO, "decoded[%d]: %s", srcdatalen, sprint_hex(dstdata, srcdatalen));
size_t puredatalen = DesfireSearchCRCPos(dstdata, srcdatalen, respcode, 2); size_t puredatalen = DesfireSearchCRCPos(dstdata, srcdatalen, respcode, 2);
@ -392,7 +392,7 @@ static void DesfireSecureChannelDecodeEV1(DesfireContext *ctx, uint8_t *srcdata,
return; 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)); //PrintAndLogEx(INFO, "decoded[%d]: %s", srcdatalen, sprint_hex(dstdata, srcdatalen));
size_t puredatalen = DesfireSearchCRCPos(dstdata, srcdatalen, respcode, 4); 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(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, " 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))); 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); DesfireCryptoEncDec(ctx, DCOSessionKeyEnc, srcdata, *dstdatalen, dstdata, false);
PrintAndLogEx(INFO, "decoded[%d]: %s", *dstdatalen, sprint_hex(dstdata, *dstdatalen));
size_t puredatalen = FindISO9797M2PaddingDataLen(dstdata, *dstdatalen); size_t puredatalen = FindISO9797M2PaddingDataLen(dstdata, *dstdatalen);
if (puredatalen != 0) { if (puredatalen != 0) {