iccard: aime authenticity

This commit is contained in:
Hay1tsme 2024-06-24 16:51:38 -04:00
parent 7051b849fa
commit 5becf8798c
4 changed files with 174 additions and 4 deletions

View File

@ -4,6 +4,7 @@
#include "iccard/aime.h"
#include "iccard/mifare.h"
#include "iccard/solitaire.h"
#include "util/dprintf.h"
@ -14,6 +15,9 @@ HRESULT aime_card_populate(
{
uint8_t b;
size_t i;
char accessCode[21];
char hashed_id_wrk[9];
char id_wrk[9];
assert(mifare != NULL);
assert(luid != NULL);
@ -36,12 +40,30 @@ HRESULT aime_card_populate(
mifare->sectors[0].blocks[2].bytes[6 + i] = b;
}
// Set the card ID, nothing else matters in the first block
mifare->sectors[0].blocks[0].bytes[0] = luid[0];
mifare->sectors[0].blocks[0].bytes[1] = luid[1];
mifare->sectors[0].blocks[0].bytes[2] = luid[2];
mifare->sectors[0].blocks[0].bytes[3] = luid[3];
/* TODO An authentic Aime pass has a checksum of the LUID in the last few
bytes of block 1. The output of this function fails authenticity check
in its current form. */
sprintf_s(accessCode, sizeof accessCode, "%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x",
luid[0], luid[1], luid[2], luid[3], luid[4], luid[5], luid[6], luid[7], luid[8], luid[9]);
dprintf("AiMe IC: WARNING: Authenticity hash not yet implemented!\n");
memcpy_s(hashed_id_wrk, sizeof(hashed_id_wrk), &accessCode[5],
8);
hashed_id_wrk[8] = '\0';
SolitaireCipherDecode(&accessCode[13], hashed_id_wrk, id_wrk);
DWORD nSerial = atoi(id_wrk);
mifare->sectors[0].blocks[1].bytes[12] = (nSerial >> 24) & 0xff;
mifare->sectors[0].blocks[1].bytes[13] = (nSerial >> 16) & 0xff;
mifare->sectors[0].blocks[1].bytes[14] = (nSerial >> 8) & 0xff;
mifare->sectors[0].blocks[1].bytes[15] = nSerial & 0xff;
return S_OK;
}

View File

@ -12,5 +12,7 @@ iccard_lib = static_library(
'felica.c',
'felica.h',
'mifare.h',
'solitaire.c',
'solitaire.h',
],
)

143
iccard/solitaire.c Normal file
View File

@ -0,0 +1,143 @@
#include "solitaire.h"
#include <memory.h>
#define DECK_SIZE 22
#define JOKER_A 21
#define JOKER_B 22
typedef struct {
char m_Deck[DECK_SIZE];
} DECK, *PDECK;
static DECK SOL_INIT_DECK = {
.m_Deck = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22 },
};
#define char2num(c) ((c) - '0' + 1)
static inline char num2char(char num) {
while (num < 1) num = num + 10;
return (num - 1) % 10 + '0';
}
static void SolMoveCard(PDECK lpDeck, char card) {
int p = 0;
for (int i = 0; i < DECK_SIZE; i++) {
if (lpDeck->m_Deck[i] == card) {
p = i;
break;
}
}
if (p < DECK_SIZE - 1) {
lpDeck->m_Deck[p] = lpDeck->m_Deck[p + 1];
lpDeck->m_Deck[p + 1] = card;
} else {
for (int i = DECK_SIZE - 1; i > 1; i--) lpDeck->m_Deck[i] = lpDeck->m_Deck[i - 1];
lpDeck->m_Deck[1] = card;
}
}
static void SolCutDeck(PDECK lpDeck, char point) {
DECK tmp;
memcpy(tmp.m_Deck, &lpDeck->m_Deck[(size_t)point], DECK_SIZE - point - 1);
memcpy(&tmp.m_Deck[DECK_SIZE - point - 1], lpDeck->m_Deck, point);
memcpy(lpDeck->m_Deck, tmp.m_Deck, DECK_SIZE - 1);
}
static void SolSwapOutsideJoker(PDECK lpDeck) {
int j1 = -1;
int j2 = -1;
DECK tmp;
for (int i = 0; i < DECK_SIZE; i++) {
if (lpDeck->m_Deck[i] == JOKER_A || lpDeck->m_Deck[i] == JOKER_B) {
if (j1 == -1) {
j1 = i;
} else {
j2 = i;
}
}
}
if (0 < DECK_SIZE - j2 - 1) memcpy(tmp.m_Deck, &lpDeck->m_Deck[j2 + 1], DECK_SIZE - j2 - 1);
tmp.m_Deck[DECK_SIZE - j2 - 1] = lpDeck->m_Deck[j1];
if (0 < j2 - j1 - 1) memcpy(&tmp.m_Deck[DECK_SIZE - j2], &lpDeck->m_Deck[j1 + 1], j2 - j1 - 1);
tmp.m_Deck[DECK_SIZE - j1 - 1] = lpDeck->m_Deck[j2];
if (0 < j1) memcpy(&tmp.m_Deck[DECK_SIZE - j1], lpDeck->m_Deck, j1);
memcpy(lpDeck->m_Deck, tmp.m_Deck, DECK_SIZE);
}
static void SolCutByBottomCard(PDECK lpDeck) {
char p = lpDeck->m_Deck[DECK_SIZE - 1];
if (p == JOKER_B) p = JOKER_A;
SolCutDeck(lpDeck, p);
}
static char SolGetTopCardNum(PDECK lpDeck) {
char p = lpDeck->m_Deck[0];
if (p == JOKER_B) p = JOKER_A;
return lpDeck->m_Deck[(size_t)p];
}
static void SolDeckHash(PDECK lpDeck) {
char p;
do {
SolMoveCard(lpDeck, JOKER_A);
SolMoveCard(lpDeck, JOKER_B);
SolMoveCard(lpDeck, JOKER_B);
SolSwapOutsideJoker(lpDeck);
SolCutByBottomCard(lpDeck);
p = SolGetTopCardNum(lpDeck);
} while (p == JOKER_A || p == JOKER_B);
}
static void SolCreateDeck(PDECK lpDeck, const char *key) {
memcpy_s(lpDeck, sizeof *lpDeck, &SOL_INIT_DECK, sizeof SOL_INIT_DECK);
int p = 0;
while (key[p] != '\0') {
SolDeckHash(lpDeck);
char c = char2num(key[p]);
SolCutDeck(lpDeck, c);
p++;
}
}
void SolitaireCipherEncode(const char *szKey, const char *szSrc, char *szDst) {
DECK deck;
SolCreateDeck(&deck, szKey);
int i = 0;
while (szSrc[i] != '\0') {
SolDeckHash(&deck);
char p = SolGetTopCardNum(&deck);
szDst[i] = num2char(char2num(szSrc[i]) + p);
i++;
}
szDst[i] = '\0';
}
void SolitaireCipherDecode(const char *szKey, const char *szSrc, char *szDst) {
DECK deck;
SolCreateDeck(&deck, szKey);
int i = 0;
while (szSrc[i] != '\0') {
SolDeckHash(&deck);
char p = SolGetTopCardNum(&deck);
szDst[i] = num2char(char2num(szSrc[i]) - p);
i++;
}
szDst[i] = '\0';
}
void SolitaireCipher(int nMode, const char *szKey, const char *szSrc, char *szDst) {
if (nMode == 0)
SolitaireCipherEncode(szKey, szSrc, szDst);
else if (nMode == 1)
SolitaireCipherDecode(szKey, szSrc, szDst);
}

3
iccard/solitaire.h Normal file
View File

@ -0,0 +1,3 @@
void SolitaireCipherDecode(const char *szKey, const char *szSrc, char *szDst);
void SolitaireCipherEncode(const char *szKey, const char *szSrc, char *szDst);
void SolitaireCipher(int mode, const char *key, const char *src_str, char *dest_str);