diff --git a/client/src/mifare/desfiretest.c b/client/src/mifare/desfiretest.c index c615b70c3..dac1416ec 100644 --- a/client/src/mifare/desfiretest.c +++ b/client/src/mifare/desfiretest.c @@ -746,6 +746,42 @@ static bool TestLRPDecode(void) { return res; } +static bool TestLRPSubkeys(void) { + bool res = true; + + uint8_t sk1[CRYPTO_AES128_KEY_SIZE] = {0}; + uint8_t sk2[CRYPTO_AES128_KEY_SIZE] = {0}; + + uint8_t key1[] = {0x81, 0x95, 0x08, 0x8C, 0xE6, 0xC3, 0x93, 0x70, 0x8E, 0xBB, 0xE6, 0xC7, 0x91, 0x4E, 0xCB, 0x0B}; + + uint8_t sk1r1[] = {0x16, 0x91, 0x2B, 0x8D, 0x19, 0xD9, 0x4B, 0x2D, 0x4D, 0xA4, 0xFF, 0xA1, 0xCA, 0xD2, 0x18, 0x23}; + uint8_t sk2r1[] = {0x2D, 0x22, 0x57, 0x1A, 0x33, 0xB2, 0x96, 0x5A, 0x9B, 0x49, 0xFF, 0x43, 0x95, 0xA4, 0x30, 0x46}; + + LRPGenSubkeys(key1, sk1, sk2); + res = res && (memcmp(sk1, sk1r1, sizeof(sk1r1)) == 0); + res = res && (memcmp(sk2, sk2r1, sizeof(sk2r1)) == 0); + + + if (res) + PrintAndLogEx(INFO, "LRP subkeys....... " _GREEN_("passed")); + else + PrintAndLogEx(ERR, "LRP subkeys....... " _RED_("fail")); + + return res; +} + +static bool TestLRPCMAC(void) { + bool res = true; + + + if (res) + PrintAndLogEx(INFO, "LRP CMAC.......... " _GREEN_("passed")); + else + PrintAndLogEx(ERR, "LRP CMAC.......... " _RED_("fail")); + + return res; +} + bool DesfireTest(bool verbose) { bool res = true; @@ -770,6 +806,8 @@ bool DesfireTest(bool verbose) { res = res && TestLRPIncCounter(); res = res && TestLRPEncode(); res = res && TestLRPDecode(); + res = res && TestLRPSubkeys(); + res = res && TestLRPCMAC(); PrintAndLogEx(INFO, "---------------------------"); if (res) diff --git a/client/src/mifare/lrpcrypto.c b/client/src/mifare/lrpcrypto.c index 5f5432487..4a7e2eb72 100644 --- a/client/src/mifare/lrpcrypto.c +++ b/client/src/mifare/lrpcrypto.c @@ -181,3 +181,44 @@ void LRPDecode(LRPContext *ctx, uint8_t *data, size_t datalen, uint8_t *resp, si } } } + +static bool shiftLeftBe(uint8_t *data, size_t length) { + if (length == 0) + return false; + + bool carry = false; + for (int i = length - 1; i >= 0; i--) { + uint8_t val = data[i]; + val = (val << 1) | ((carry) ? 1 : 0); + carry = ((data[i] & 0x80) != 0); + data[i] = val; + } + return carry; +} + +// GF(2 ^ 128) +// poly x^128 + x ^ 7 + x ^ 2 + x + 1 +// bit: 1000..0010000111 == 0x1 00 00 .. 00 00 87 +static void shiftPolyLeft(uint8_t *data) { + if (shiftLeftBe(data, 16)) + data[15] = data[15] ^ 0x87; +} + +void LRPGenSubkeys(uint8_t *key, uint8_t *sk1, uint8_t *sk2) { + LRPContext ctx = {0}; + LRPSetKey(&ctx, key, 0, true); + + uint8_t y[CRYPTO_AES128_KEY_SIZE] = {0}; + LRPEvalLRP(&ctx, const00, CRYPTO_AES128_KEY_SIZE * 2, true, y); +PrintAndLogEx(ERR, "--y %s", sprint_hex(y, 16)); + shiftPolyLeft(y); + memcpy(sk1, y, CRYPTO_AES128_KEY_SIZE); +PrintAndLogEx(ERR, "--sk1 %s", sprint_hex(y, 16)); + shiftPolyLeft(y); + memcpy(sk2, y, CRYPTO_AES128_KEY_SIZE); +PrintAndLogEx(ERR, "--sk2 %s", sprint_hex(y, 16)); +} + +void LRPCMAC(LRPContext *ctx, uint8_t *data, size_t datalen, uint8_t *cmac) { + +} diff --git a/client/src/mifare/lrpcrypto.h b/client/src/mifare/lrpcrypto.h index cccf72437..fe0334d9d 100644 --- a/client/src/mifare/lrpcrypto.h +++ b/client/src/mifare/lrpcrypto.h @@ -51,5 +51,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 LRPGenSubkeys(uint8_t *key, uint8_t *sk1, uint8_t *sk2); +void LRPCMAC(LRPContext *ctx, uint8_t *data, size_t datalen, uint8_t *cmac); #endif // __LRPCRYPTO_H