TestLRPPlaintexts

This commit is contained in:
merlokk 2021-08-14 00:22:18 +03:00
parent 99bc47c1ac
commit 442bbd38b5
3 changed files with 117 additions and 1 deletions

View file

@ -16,6 +16,7 @@
#include "crypto/libpcrypto.h" #include "crypto/libpcrypto.h"
#include "mifare/desfirecrypto.h" #include "mifare/desfirecrypto.h"
#include "mifare/lrpcrypto.h"
static uint8_t CMACData[] = {0x6B, 0xC1, 0xBE, 0xE2, 0x2E, 0x40, 0x9F, 0x96, static uint8_t CMACData[] = {0x6B, 0xC1, 0xBE, 0xE2, 0x2E, 0x40, 0x9F, 0x96,
0xE9, 0x3D, 0x7E, 0x11, 0x73, 0x93, 0x17, 0x2A, 0xE9, 0x3D, 0x7E, 0x11, 0x73, 0x93, 0x17, 0x2A,
@ -474,6 +475,47 @@ static bool TestTransSessionKeys(void) {
return res; return res;
} }
// https://www.nxp.com/docs/en/application-note/AN12304.pdf
// page 10
static bool TestLRPPlaintexts(void) {
bool res = true;
uint8_t key[] = {0x56, 0x78, 0x26, 0xB8, 0xDA, 0x8E, 0x76, 0x84, 0x32, 0xA9, 0x54, 0x8D, 0xBE, 0x4A, 0xA3, 0xA0};
LRPContext ctx = {0};
LRPSetKey(&ctx, key, 0, false);
uint8_t key0[] = {0xAC, 0x20, 0xD3, 0x9F, 0x53, 0x41, 0xFE, 0x98, 0xDF, 0xCA, 0x21, 0xDA, 0x86, 0xBA, 0x79, 0x14};
res = res && (memcmp(ctx.plaintexts[0], key0, sizeof(key0)) == 0);
uint8_t key1[] = {0x90, 0x7D, 0xA0, 0x3D, 0x67, 0x24, 0x49, 0x16, 0x69, 0x15, 0xE4, 0x56, 0x3E, 0x08, 0x9D, 0x6D};
res = res && (memcmp(ctx.plaintexts[1], key1, sizeof(key1)) == 0);
uint8_t key14[] = {0x37, 0xD7, 0x34, 0xA5, 0x1C, 0x07, 0x6E, 0xB8, 0x03, 0xBD, 0x53, 0x0E, 0x17, 0xEB, 0x87, 0xDC};
res = res && (memcmp(ctx.plaintexts[14], key14, sizeof(key14)) == 0);
uint8_t key15[] = {0x71, 0xB4, 0x44, 0xAF, 0x25, 0x7A, 0x93, 0x21, 0x53, 0x11, 0xD7, 0x58, 0xDD, 0x33, 0x32, 0x47};
res = res && (memcmp(ctx.plaintexts[15], key15, sizeof(key15)) == 0);
if (res)
PrintAndLogEx(INFO, "LRP plaintexts.... " _GREEN_("passed"));
else
PrintAndLogEx(ERR, "LRP plaintexts.... " _RED_("fail"));
return res;
}
static bool TestLRPUpdatedKeys(void) {
bool res = true;
if (res)
PrintAndLogEx(INFO, "LRP updated keys.. " _GREEN_("passed"));
else
PrintAndLogEx(ERR, "LRP updated keys.. " _RED_("fail"));
return res;
}
bool DesfireTest(bool verbose) { bool DesfireTest(bool verbose) {
bool res = true; bool res = true;
@ -492,6 +534,8 @@ bool DesfireTest(bool verbose) {
res = res && TestEV2IVEncode(); res = res && TestEV2IVEncode();
res = res && TestEV2MAC(); res = res && TestEV2MAC();
res = res && TestTransSessionKeys(); res = res && TestTransSessionKeys();
res = res && TestLRPPlaintexts();
res = res && TestLRPUpdatedKeys();
PrintAndLogEx(INFO, "---------------------------"); PrintAndLogEx(INFO, "---------------------------");
if (res) if (res)

View file

@ -26,3 +26,62 @@
#include "aes.h" #include "aes.h"
#include "commonutil.h" #include "commonutil.h"
static uint8_t constAA[] = {0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa};
static uint8_t const55[] = {0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55};
void LRPClearContext(LRPContext *ctx) {
memset(ctx->key, 0, CRYPTO_AES128_KEY_SIZE);
ctx->useBitPadding = false;
ctx->plaintextsCount = 0;
memset(ctx->plaintexts, 0, LRP_MAX_PLAINTEXTS_SIZE * CRYPTO_AES128_KEY_SIZE);
ctx->updatedKeysCount = 0;
memset(ctx->updatedKeys, 0, LRP_MAX_UPDATED_KEYS_SIZE * CRYPTO_AES128_KEY_SIZE);
ctx->useUpdatedKeyNum = 0;
}
void LRPSetKey(LRPContext *ctx, uint8_t *key, size_t updatedKeyNum, bool useBitPadding) {
LRPClearContext(ctx);
memcpy(ctx->key, key, CRYPTO_AES128_KEY_SIZE);
LRPGeneratePlaintexts(ctx, 16);
LRPGenerateUpdatedKeys(ctx, 4);
ctx->useUpdatedKeyNum = updatedKeyNum;
ctx->useBitPadding = useBitPadding;
}
// https://www.nxp.com/docs/en/application-note/AN12304.pdf
// Algorithm 1
void LRPGeneratePlaintexts(LRPContext *ctx, size_t plaintextsCount) {
if (plaintextsCount > LRP_MAX_PLAINTEXTS_SIZE)
return;
uint8_t h[CRYPTO_AES128_KEY_SIZE] = {0};
memcpy(h, ctx->key, CRYPTO_AES128_KEY_SIZE);
for (int i = 0; i < plaintextsCount; i++) {
aes_encode(NULL, h, const55, h, CRYPTO_AES128_KEY_SIZE);
aes_encode(NULL, h, constAA, ctx->plaintexts[i], CRYPTO_AES128_KEY_SIZE);
}
ctx->plaintextsCount = plaintextsCount;
}
// https://www.nxp.com/docs/en/application-note/AN12304.pdf
// Algorithm 2
void LRPGenerateUpdatedKeys(LRPContext *ctx, size_t updatedKeysCount) {
if (updatedKeysCount > LRP_MAX_UPDATED_KEYS_SIZE)
return;
uint8_t h[CRYPTO_AES128_KEY_SIZE] = {0};
aes_encode(NULL, ctx->key, const55, h, CRYPTO_AES128_KEY_SIZE);
for (int i = 0; i < updatedKeysCount; i++) {
aes_encode(NULL, h, constAA, ctx->plaintexts[i], CRYPTO_AES128_KEY_SIZE);
aes_encode(NULL, h, const55, h, CRYPTO_AES128_KEY_SIZE);
}
ctx->updatedKeysCount = updatedKeysCount;
}

View file

@ -23,11 +23,24 @@
#include "common.h" #include "common.h"
#include "crypto/libpcrypto.h" #include "crypto/libpcrypto.h"
#define LRP_MAX_PLAINTEXTS_SIZE 16
#define LRP_MAX_UPDATED_KEYS_SIZE 4
typedef struct { typedef struct {
uint8_t key[CRYPTO_AES128_KEY_SIZE]; uint8_t key[CRYPTO_AES128_KEY_SIZE];
bool useBitPadding;
size_t plaintextsCount;
uint8_t plaintexts[LRP_MAX_PLAINTEXTS_SIZE][CRYPTO_AES128_KEY_SIZE];
size_t updatedKeysCount;
uint8_t updatedKeys[LRP_MAX_UPDATED_KEYS_SIZE][CRYPTO_AES128_KEY_SIZE];
size_t useUpdatedKeyNum;
} LRPContext; } LRPContext;
void LRPSetKey(LRPContext *ctx); void LRPClearContext(LRPContext *ctx);
void LRPSetKey(LRPContext *ctx, uint8_t *key, size_t updatedKeyNum, bool useBitPadding);
void LRPGeneratePlaintexts(LRPContext *ctx, size_t plaintextsCount);
void LRPGenerateUpdatedKeys(LRPContext *ctx, size_t updatedKeysCount);
#endif // __LRPCRYPTO_H #endif // __LRPCRYPTO_H