diff --git a/client/src/mifare/desfirecrypto.c b/client/src/mifare/desfirecrypto.c index e1b0210be..f5c172c8a 100644 --- a/client/src/mifare/desfirecrypto.c +++ b/client/src/mifare/desfirecrypto.c @@ -31,12 +31,13 @@ #include "crc16.h" // crc16 ccitt #include "crc32.h" #include "commonutil.h" -#include "crypto/libpcrypto.h" void DesfireClearContext(DesfireContext *ctx) { ctx->keyNum = 0; ctx->keyType = T_DES; memset(ctx->key, 0, sizeof(ctx->key)); + + LRPClearContext(&ctx->lrpCtx); ctx->secureChannel = DACNone; ctx->cmdSet = DCCNative; @@ -260,11 +261,16 @@ void DesfireCryptoEncDecEx(DesfireContext *ctx, DesfireCryptoOpKeyType key_type, if (key == NULL) return; - size_t offset = 0; - while (offset < srcdatalen) { - DesfireCryptoEncDecSingleBlock(key, ctx->keyType, srcdata + offset, data + offset, xiv, dir_to_send, encode); + if (ctx->secureChannel == DACLRP) { + size_t dstlen = 0; + LRPEncDec(key, iv, encode, srcdata, srcdatalen, data, &dstlen); + } else { + size_t offset = 0; + while (offset < srcdatalen) { + DesfireCryptoEncDecSingleBlock(key, ctx->keyType, srcdata + offset, data + offset, xiv, dir_to_send, encode); - offset += block_size; + offset += block_size; + } } if (iv == NULL) @@ -585,6 +591,31 @@ void DesfireGenSessionKeyEV2(uint8_t *key, uint8_t *rndA, uint8_t *rndB, bool en memcpy(sessionkey, cmac, CRYPTO_AES_BLOCK_SIZE); } +// https://www.nxp.com/docs/en/data-sheet/MF2DLHX0.pdf +// page 35 +void DesfireGenSessionKeyLRP(uint8_t *key, uint8_t *rndA, uint8_t *rndB, bool enckey, uint8_t *sessionkey) { + uint8_t data[64] = {0}; + memset(sessionkey, 0, CRYPTO_AES_BLOCK_SIZE); + + data[1] = 0x01; + data[3] = 0x80; + memcpy(data + 4, rndA, 8); + bin_xor(data + 6, rndB, 6); // xor rndb 6b + memcpy(data + 12, rndB + 6, 10); + memcpy(data + 22, rndA + 8, 8); + data[30] = 0x96; + data[31] = 0x69; + +PrintAndLogEx(INFO, "rndA: %s", sprint_hex(rndA, CRYPTO_AES_BLOCK_SIZE)); +PrintAndLogEx(INFO, "rndB: %s", sprint_hex(rndB, CRYPTO_AES_BLOCK_SIZE)); +PrintAndLogEx(INFO, "data: %s", sprint_hex(data, 32)); + + LRPContext ctx = {0}; + LRPSetKey(&ctx, key, 0, true); + LRPCMAC(&ctx, data, 32, sessionkey); +PrintAndLogEx(INFO, "mk: %s", sprint_hex(sessionkey, CRYPTO_AES_BLOCK_SIZE)); +} + void DesfireEV2FillIV(DesfireContext *ctx, bool ivforcommand, uint8_t *iv) { uint8_t xiv[CRYPTO_AES_BLOCK_SIZE] = {0}; diff --git a/client/src/mifare/desfirecrypto.h b/client/src/mifare/desfirecrypto.h index 57fee9792..817989f75 100644 --- a/client/src/mifare/desfirecrypto.h +++ b/client/src/mifare/desfirecrypto.h @@ -23,6 +23,7 @@ #include "common.h" #include "crypto/libpcrypto.h" +#include "mifare/lrpcrypto.h" #define MAX_CRYPTO_BLOCK_SIZE 16 #define DESFIRE_MAX_CRYPTO_BLOCK_SIZE 16 @@ -36,7 +37,7 @@ enum DESFIRE_CRYPTOALGO { T_DES = 0x00, T_3DES = 0x01, //aka 2K3DES T_3K3DES = 0x02, - T_AES = 0x03 + T_AES = 0x03, }; typedef enum DESFIRE_CRYPTOALGO DesfireCryptoAlgorythm; @@ -76,6 +77,8 @@ typedef struct DesfireContextS { DesfireCryptoAlgorythm keyType; // des/2tdea/3tdea/aes uint8_t key[DESFIRE_MAX_KEY_SIZE]; uint8_t masterKey[DESFIRE_MAX_KEY_SIZE]; // source for kdf + + LRPContext lrpCtx; // KDF finction uint8_t kdfAlgo; @@ -123,6 +126,8 @@ void DesfireCryptoCMAC(DesfireContext *ctx, uint8_t *srcdata, size_t srcdatalen, void DesfireCryptoCMACEx(DesfireContext *ctx, DesfireCryptoOpKeyType key_type, uint8_t *data, size_t len, size_t minlen, uint8_t *cmac); void MifareKdfAn10922(DesfireContext *ctx, DesfireCryptoOpKeyType key_type, const uint8_t *data, size_t len); +void DesfireGenSessionKeyLRP(uint8_t *key, uint8_t *rndA, uint8_t *rndB, bool enckey, uint8_t *sessionkey); + void DesfireDESKeySetVersion(uint8_t *key, DesfireCryptoAlgorythm keytype, uint8_t version); uint8_t DesfireDESKeyGetVersion(uint8_t *key); diff --git a/client/src/mifare/lrpcrypto.c b/client/src/mifare/lrpcrypto.c index 9b1d0e0df..cd4236ca0 100644 --- a/client/src/mifare/lrpcrypto.c +++ b/client/src/mifare/lrpcrypto.c @@ -192,6 +192,16 @@ void LRPDecode(LRPContext *ctx, uint8_t *data, size_t datalen, uint8_t *resp, si } } +void LRPEncDec(uint8_t *key, uint8_t *iv, bool encode, uint8_t *data, size_t datalen, uint8_t *resp, size_t *resplen) { + LRPContext ctx = {0}; + + LRPSetKeyEx(&ctx, key, iv, 4 * 2, 0, false); + if (encode) + LRPEncode(&ctx, data, datalen, resp, resplen); + else + LRPDecode(&ctx, data, datalen, resp, resplen); +} + static bool shiftLeftBe(uint8_t *data, size_t length) { if (length == 0) return false; diff --git a/client/src/mifare/lrpcrypto.h b/client/src/mifare/lrpcrypto.h index d3834b6c6..9b2e8b650 100644 --- a/client/src/mifare/lrpcrypto.h +++ b/client/src/mifare/lrpcrypto.h @@ -54,6 +54,7 @@ void LRPEvalLRP(LRPContext *ctx, uint8_t *iv, size_t ivlen, bool final, uint8_t void LRPIncCounter(uint8_t *ctr, size_t ctrlen); void LRPEncode(LRPContext *ctx, uint8_t *data, size_t datalen, uint8_t *resp, size_t *resplen); void LRPDecode(LRPContext *ctx, uint8_t *data, size_t datalen, uint8_t *resp, size_t *resplen); +void LRPEncDec(uint8_t *key, uint8_t *iv, bool encode, uint8_t *data, size_t datalen, uint8_t *resp, size_t *resplen); void LRPGenSubkeys(uint8_t *key, uint8_t *sk1, uint8_t *sk2); void LRPCMAC(LRPContext *ctx, uint8_t *data, size_t datalen, uint8_t *cmac); void LRPCMAC8(LRPContext *ctx, uint8_t *data, size_t datalen, uint8_t *cmac);