+int CalculateEncIVCommand(mf4Session *session, uint8_t *iv, bool verbose) {
+ memcpy(&iv[0], session->TI, 4);
+ memcpy(&iv[4], &session->R_Ctr, 2);
+ memcpy(&iv[6], &session->W_Ctr, 2);
+ memcpy(&iv[8], &session->R_Ctr, 2);
+ memcpy(&iv[10], &session->W_Ctr, 2);
+ memcpy(&iv[12], &session->R_Ctr, 2);
+ memcpy(&iv[14], &session->W_Ctr, 2);
+
+ return 0;
+}
+
+int CalculateEncIVResponse(mf4Session *session, uint8_t *iv, bool verbose) {
+ memcpy(&iv[0], &session->R_Ctr, 2);
+ memcpy(&iv[2], &session->W_Ctr, 2);
+ memcpy(&iv[4], &session->R_Ctr, 2);
+ memcpy(&iv[6], &session->W_Ctr, 2);
+ memcpy(&iv[8], &session->R_Ctr, 2);
+ memcpy(&iv[10], &session->W_Ctr, 2);
+ memcpy(&iv[12], session->TI, 4);
+
+ return 0;
+}
+
+
+int CalculateMAC(mf4Session *session, MACType_t mtype, uint8_t blockNum, uint8_t blockCount, uint8_t *data, int datalen, uint8_t *mac, bool verbose) {
+ if (!session || !session->Authenticated || !mac || !data || !datalen || datalen < 1)
+ return 1;
+
+ memset(mac, 0x00, 8);
+
+ uint16_t ctr = session->R_Ctr;
+ switch(mtype) {
+ case mtypWriteCmd:
+ case mtypWriteResp:
+ ctr = session->W_Ctr;
+ break;
+ case mtypReadCmd:
+ case mtypReadResp:
+ break;
+ }
+
+ uint8_t macdata[2049] = {data[0], (ctr & 0xFF), (ctr >> 8), 0};
+ int macdatalen = datalen;
+ memcpy(&macdata[3], session->TI, 4);
+
+ switch(mtype) {
+ case mtypReadCmd:
+ memcpy(&macdata[7], &data[1], datalen - 1);
+ macdatalen = datalen + 6;
+ break;
+ case mtypReadResp:
+ macdata[7] = blockNum;
+ macdata[8] = 0;
+ macdata[9] = blockCount;
+ memcpy(&macdata[10], &data[1], datalen - 1);
+ macdatalen = datalen + 9;
+ break;
+ case mtypWriteCmd:
+ memcpy(&macdata[7], &data[1], datalen - 1);
+ macdatalen = datalen + 6;
+ break;
+ case mtypWriteResp:
+ macdatalen = 1 + 6;
+ break;
+ }
+
+ if (verbose)
+ PrintAndLog("MAC data[%d]: %s", macdatalen, sprint_hex(macdata, macdatalen));
+
+ return aes_cmac8(NULL, session->Kmac, macdata, mac, macdatalen);
+}
+