Merge branch 'master' into master

This commit is contained in:
RFID Research Group 2018-11-07 12:12:47 +01:00 committed by GitHub
commit ce30c29f47
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
46 changed files with 2359 additions and 596 deletions

1
.gitignore vendored
View file

@ -32,6 +32,7 @@ luac
fpga_compress
mfkey32
mfkey64
tools/nonce2key/nonce2key
fpga/*
!fpga/tests

View file

@ -79,6 +79,7 @@ This project uses the changelog in accordance with [keepchangelog](http://keepac
- Added to `hf 14a apdu` - apdu and tlv results parser (@merlokk)
- Added 'hf emv' commands (@merlokk)
- lots of bug fixes (many many)
- Changed hf mfp security. Now it works in all the modes. (drHatson)
### Fixed
- Changed driver file proxmark3.inf to support both old and new Product/Vendor IDs (piwi)
- Changed start sequence in Qt mode (fix: short commands hangs main Qt thread) (Merlok)

View file

@ -47,6 +47,9 @@ This fork now compiles just fine on
- Mac OS X / Homebrew
- Docker container
## KALI and ARCHLINUX users
Kali and ArchLinux users usually must kill their modem manager in order for the proxmark3 to enumerate properly.
## Setup and build for UBUNTU
GC made updates to allow this to build easily on Ubuntu 14.04.2 LTS, 15.10 or 16.04
See https://github.com/Proxmark/proxmark3/wiki/Ubuntu%20Linux
@ -57,7 +60,7 @@ I have also added this script to the fork.
https://github.com/RfidResearchGroup/proxmark3/blob/master/install.sh
- Run
`sudo apt-get install p7zip git build-essential libreadline5 libreadline-dev libusb-0.1-4 libusb-dev libqt4-dev perl pkg-config wget libncurses5-dev gcc-arm-none-eabi`
`sudo apt-get install p7zip git build-essential libreadline5 libreadline-dev libusb-0.1-4 libusb-dev libqt4-dev perl pkg-config wget libncurses5-dev gcc-arm-none-eabi libjansson-dev`
- Clone fork
`git clone https://github.com/RfidResearchGroup/proxmark3.git`
@ -82,7 +85,7 @@ https://github.com/RfidResearchGroup/proxmark3/blob/master/install.sh
## Setup and build for ArchLinux
- Run
`sudo pacman -Sy base-devel p7zip libusb readline ncurses arm-none-eabi-newlib --needed`
`sudo pacman -Sy base-devel p7zip libusb readline ncurses libjansson-dev arm-none-eabi-newlib --needed`
`yaourt -S termcap`
- Clone fork
@ -148,8 +151,8 @@ Afterwards just clone the iceman repo or download someone elses.
Read instructions on @Gator96100 repo page. (https://github.com/Gator96100/ProxSpace/)
Links
- https://github.com/Gator96100/ProxSpace/archive/master.zip
- https://github.com/Gator96100/ProxSpace/releases/tag/v2.2 (release v2.2 with gcc v5.3.0 arm-none-eabi-gcc v7.1.0)
- https://github.com/Gator96100/ProxSpace/releases/tag/v3.1 (release v3.1 with gcc v7.3.0 )
- https://github.com/Gator96100/ProxSpace/releases/tag/v2.2 (release v2.2 with gcc v5.3.0 arm-none-eabi-gcc v7.1.0)
### 7. Build and run

View file

@ -66,9 +66,20 @@ clone_script:
Write-Host "[ OK ]" -ForegroundColor Green
Write-Host "Fill msys\etc\fstab file..." -NoNewLine
Write-Host "Fill msys2\etc\fstab file..." -NoNewLine
New-Item c:\ProxSpace\msys\etc\fstab -type file -force -value "#Win32_Path Mount_Point`nc:\ProxSpace\devkitARM /devkitARM`nc:\ProxSpace\Qt\5.6 /qt `nc:\ProxSpace\pm3 /pm3`n"
New-Item c:\ProxSpace\msys2\etc\fstab -type file -force -value "# For a description of the file format, see the Users Guide`n# http://cygwin.com/cygwin-ug-net/using.html#mount-table`nnone / cygdrive binary,posix=0,noacl,user 0 0 `nC:\ProxSpace\pm3 /pm3 ntfs noacl 0 0 `nC:\ProxSpace\gcc-arm-none-eabi /gcc-arm-none-eabi ntfs noacl 0 0 `n"
Write-Host "[ OK ]" -ForegroundColor Green
Write-Host "Update msys2 packages..." -NoNewLine
$env:Path = "C:\ProxSpace\msys2\usr\bin;C:\ProxSpace\msys2\mingw32\bin;C:\ProxSpace\gcc-arm-none-eabi\bin;$env:Path"
C:\ProxSpace\msys2\msys2_shell.cmd -mingw32 -defterm -no-start /dev/null 1> msys1.txt 2>&1
C:\ProxSpace\msys2\msys2_shell.cmd -mingw32 -defterm -no-start /dev/null 1> msys1.txt 2>&1
Write-Host "[ OK ]" -ForegroundColor Green
install:
@ -84,12 +95,25 @@ install:
}
build_script:
- ps: >-
$env:Path = "C:\ProxSpace\msys\bin;$env:Path"
"C:\ProxSpace\msys2\usr\bin;C:\ProxSpace\msys2\mingw32\bin;C:\ProxSpace\gcc-arm-none-eabi\bin;$env:Path"
$env:MINGW_HOME="C:\ProxSpace\msys2\mingw32"
$env:MSYS_HOME="C:\ProxSpace\msys2"
$env:MSYSTEM="MINGW32"
$env:MINGW_PREFIX="/mingw32"
$env:SHELL="/bin/bash"
$env:MSYSTEM_CHOST="i686-w64-mingw32"
#make
bash -lc -i "pwd;make all"
bash -c -i 'pwd;make clean;make all'
#some checks
@ -232,8 +256,8 @@ test_script:
#--- end Job
[bool]$res=$false
# Wait 60 sec timeout for Job
if(Wait-Job $Job -Timeout 60){
# Wait 120 sec timeout for Job
if(Wait-Job $Job -Timeout 150){
$Results = $Job | Receive-Job
if($Results -like "true"){
$res=$true
@ -268,13 +292,20 @@ test_script:
#proxmark logic tests
ExecTest "proxmark help" "proxmark3 -h" {bash -lc 'cd ~/client;proxmark3 -h | grep -q Execute && echo Passed || echo Failed'}
ExecTest "proxmark help" "proxmark3 -h" {bash -lc 'cd ~/client;./proxmark3 -h | grep -q Execute && echo Passed || echo Failed'}
ExecTest "proxmark help hardnested" "proxmark3 -h" {bash -lc 'cd ~/client;proxmark3 -h | grep -q hardnested && echo Passed || echo Failed'}
ExecTest "proxmark help hardnested" "proxmark3 -h" {bash -lc 'cd ~/client;./proxmark3 -h | grep -q hardnested && echo Passed || echo Failed'}
ExecTest "hf mf offline text" "hf mf" {bash -lc "cd ~/client;proxmark3 comx -c 'hf mf'"} "at_enc"
ExecTest "hf mf hardnested" "hf mf hardnested" {bash -lc "cd ~/client;proxmark3 comx -c 'hf mf hardnested t 1 000000000000'"} "found:"
ExecTest "hf mf offline text" "hf mf" {bash -lc "cd ~/client;./proxmark3 comx -c 'hf mf'"} "at_enc"
ExecTest "hf mf hardnested" "hf mf hardnested" {bash -lc "cd ~/client;./proxmark3 comx -c 'hf mf hardnested t 1 000000000000'"} "found:"
#proxmark crypto tests
ExecTest "hf emv test" "hf emv test" {bash -lc "cd ~/client;./proxmark3 comx -c 'hf emv test'"} "Tests ?OK"
if ($global:TestsPassed) {
Write-Host "Tests [ OK ]" -ForegroundColor Green

View file

@ -44,8 +44,7 @@ uint8_t FindOffsetInFlash() {
return 0; // wrap-around
}
void EraseMemory()
{
void EraseMemory() {
if (!FlashInit()){
return;
}
@ -59,10 +58,9 @@ void EraseMemory()
SpinDelay(100);
}
// This is actually copied from SniffIso14443a
void RAMFUNC SniffAndStore(uint8_t param) {
/* This is actually copied from SniffIso14443a */
iso14443a_setup(FPGA_HF_ISO14443A_SNIFFER);
// Allocate memory from BigBuf for some buffers
@ -268,10 +266,7 @@ void RAMFUNC SniffAndStore(uint8_t param) {
// Erase first page of flash mem
EraseMemory();
//for (int i=0; i<memoffset + 4 * auth_attempts; i++)
// if (MF_DBGLEVEL > 1) Dbprintf("[-] total_data[%d] = 0x%02x", i, total_data[i]);
// Write total data to flash mem
uint16_t writelen = Flash_WriteData(0, total_data, memoffset + 4 * auth_attempts);
if (MF_DBGLEVEL > 1) Dbprintf("[!] Wrote %u bytes into flash mem", writelen);
@ -283,18 +278,23 @@ void RAMFUNC SniffAndStore(uint8_t param) {
}
}
void RunMod()
{
Dbprintf("Sniffing started");
void RunMod() {
SpinDelay(200);
Dbprintf(">> Bogiton 14a Sniff UL/UL-EV1/NTAG a.k.a BogitoRun Started <<");
Dbprintf("Starting to sniff");
SpinDown(50);
SpinOff(50);
SpinUp(50);
SpinOff(50);
SpinDown(50);
SpinDelay(500);
// param:
// bit 0 - trigger from first card answer
// bit 1 - trigger from first reader 7-bit request
SniffAndStore(0);
LEDsoff();
SniffAndStore(0);
LEDsoff();
SpinDelay(300);
Dbprintf("- [ End ] -> You can take shell back ...");
}

View file

@ -1,5 +1,5 @@
//-----------------------------------------------------------------------------
// Colin Brigato, 2016,2017
// Colin Brigato, 2016, 2017
// Christian Herrmann, 2017
//
// This code is licensed to you under the terms of the GNU GPL, version 2 or,
@ -21,10 +21,11 @@ int currfline;
int curlline;
// TODO : Implement fast read of KEYS like in RFIdea
// als ohttp://ext.delaat.net/rp/2015-2016/p04/report.pdf
// also http://ext.delaat.net/rp/2015-2016/p04/report.pdf
// Colin's VIGIKPWN sniff/simulate/clone repeat routine for HF Mifare
/*
void cjPrintBigArray(const char *bigar, int len, uint8_t newlines, uint8_t debug)
{
uint32_t chunksize = (USB_CMD_DATA_SIZE / 4);
@ -56,6 +57,7 @@ void cjPrintBigArray(const char *bigar, int len, uint8_t newlines, uint8_t debug
DbprintfEx(FLAG_NOLOG, " ");
}
}
*/
void cjSetCursFRight()
{
@ -85,151 +87,8 @@ void cjPrintKey(uint64_t key, uint8_t *foundKey, uint16_t sectorNo, uint8_t type
DbprintfEx(FLAG_NOLOG, "SEC: %02x | KEY : %s | TYP: %d", sectorNo, tosendkey, type);
}
void SpinOff(uint32_t pause)
void ReadLastTagFromFlash()
{
LED_A_OFF();
LED_B_OFF();
LED_C_OFF();
LED_D_OFF();
SpinDelay(pause);
}
// 0=A, 1=B, 2=C, 3=D
void SpinErr(uint8_t led, uint32_t speed, uint8_t times)
{
SpinOff(speed);
NTIME(times)
{
switch (led)
{
case 0:
LED_A_INV();
break;
case 1:
LED_B_INV();
break;
case 2:
LED_C_INV();
break;
case 3:
LED_D_INV();
break;
}
SpinDelay(speed);
}
}
void SpinDown(uint32_t speed)
{
SpinOff(speed);
LED_D_ON();
SpinDelay(speed);
LED_D_OFF();
LED_C_ON();
SpinDelay(speed);
LED_C_OFF();
LED_B_ON();
SpinDelay(speed);
LED_B_OFF();
LED_A_ON();
SpinDelay(speed);
LED_A_OFF();
}
void SpinUp(uint32_t speed)
{
SpinOff(speed);
LED_A_ON();
SpinDelay(speed);
LED_A_OFF();
LED_B_ON();
SpinDelay(speed);
LED_B_OFF();
LED_C_ON();
SpinDelay(speed);
LED_C_OFF();
LED_D_ON();
SpinDelay(speed);
LED_D_OFF();
}
void TestFlashmemSpeed(size_t buffersize, uint32_t spibaudrate) {
FLASHMEM_SPIBAUDRATE = spibaudrate*1000000;
DbprintfEx(FLAG_NOLOG, "%s---+----[ %s %s[%dKB] %s] (%d)", _GREEN_, _WHITE_, _YELLOW_, buffersize / 1024, _WHITE_, FLASHMEM_SPIBAUDRATE);
uint16_t t = 0;
LED_B_ON();
uint8_t *mem = BigBuf_malloc(buffersize);
bool isok = false;
size_t len = 0;
uint32_t startidx = 0;
uint32_t numofbytes = 0x3FFFF;
if (!FlashInit()) {
return;
}
//Flash_CheckBusy(BUSY_TIMEOUT);
//Flash_ReadStat1();
uint32_t end_time;
uint32_t start_time = end_time = GetTickCount();
for (size_t i = 0; i < numofbytes; i += buffersize)
{
len = MIN((numofbytes - i), buffersize);
//isok = Flash_ReadData(startidx + i, mem, len);
//uint32_t iend_time;
//uint32_t istart_time = iend_time = GetTickCount();
isok = Flash_ReadDataCont(startidx + i, mem, len);
//iend_time = GetTickCount();
//DbprintfEx(FLAG_RAWPRINT, "%s%dms%s>", _YELLOW_, iend_time - istart_time, _WHITE_);
//cjSetCursLeft();
if (!isok)
{
Dbprintf("[FAIL] reading flash memory failed :: | bytes between %d - %d", i, len);
return;
}
//isok = cmd_send(CMD_FLASHMEM_DOWNLOADED, i, len, 0, mem, len);
//if (!isok)
// Dbprintf("transfer to client failed :: | bytes between %d - %d", i, len);
t++;
}
end_time = GetTickCount();
DbprintfEx(FLAG_NOLOG, "%s |--< %s %s%dms%s for FULL_FLASH_READ", _GREEN_, _WHITE_, _YELLOW_, end_time - start_time, _WHITE_);
DbprintfEx(FLAG_NOLOG, "%s `--= %s %d runs of %s~%dms%s each", _GREEN_, _WHITE_, t, _YELLOW_, (end_time - start_time) / t, _WHITE_);
DbprintfEx(FLAG_NOLOG, "");
//cjSetCursLeft();
LED_B_OFF();
FlashStop();
}
void TestFlashmemRoutine()
{
DbprintfEx(FLAG_NOLOG, "%s>>%s Will Now Test dumping Full flash [256Kb] (2Mbits)through Bigbuf buffers\n", _GREEN_, _WHITE_);
MF_DBGLEVEL = MF_DBG_NONE;
//DbprintfEx(FLAG_NOLOG, "---------\n%s[A]%s Using NORMAL Reads @Max (24Mhz=MCK/2)\n--------", _GREEN_, _WHITE_);
TestFlashmemSpeed(32768,24);
TestFlashmemSpeed(16384 + 4096 + 4096,24);
TestFlashmemSpeed(16384,24);
TestFlashmemSpeed(4096,24);
TestFlashmemSpeed(1024,24);
//SpinDelay(1000);
//WDT_HIT();
//DbprintfEx(FLAG_NOLOG, "--------\n%s[B]%s Using FAST Reads @Max (48Mhz=MCK=CPUClock/2=MAXSPI)\n--------", _GREEN_, _WHITE_);
TestFlashmemSpeed(32768,48);
TestFlashmemSpeed(16384 + 4096 + 4096,48);
TestFlashmemSpeed(16384,48);
TestFlashmemSpeed(4096,48);
TestFlashmemSpeed(1024,48);
//SpinDelay(1000);
//WDT_HIT();
return;
}
void ReadLastTagFromFlash() {
SpinOff(0);
LED_A_ON();
LED_B_ON();
@ -250,20 +109,15 @@ void ReadLastTagFromFlash() {
}
Flash_CheckBusy(BUSY_TIMEOUT);
//Flash_ReadStat1();
uint32_t end_time;
uint32_t start_time = end_time = GetTickCount();
for (size_t i = 0; i < len; i += size)
{
len = MIN((len - i), size);
// isok = Flash_FastReadDataCont(startidx + i, mem, len);
isok = Flash_ReadDataCont(startidx + i, mem, len);
if (isok == len)
{
//print_result("Chunk: ", mem, len);
emlSetMem(mem, 0, 64);
}
else
@ -287,7 +141,6 @@ void ReadLastTagFromFlash() {
void WriteTagToFlash(uint8_t index, size_t size)
{
SpinOff(0);
LED_A_ON();
LED_B_ON();
@ -302,7 +155,7 @@ void WriteTagToFlash(uint8_t index, size_t size)
uint8_t data[(size * (16 * 64))/1024];
uint8_t buff[PAGESIZE];
// cnt = 0;
emlGetMem(data, 0, (size * 64)/1024);
if (!FlashInit()){
@ -318,9 +171,8 @@ void WriteTagToFlash(uint8_t index, size_t size)
while (bytes_remaining > 0)
{
Flash_CheckBusy(BUSY_TIMEOUT);
Flash_WriteEnable();
Flash_CheckBusy(BUSY_TIMEOUT);
Flash_WriteEnable();
uint32_t bytes_in_packet = MIN(FLASH_MEM_BLOCK_SIZE, bytes_remaining);
@ -337,7 +189,6 @@ void WriteTagToFlash(uint8_t index, size_t size)
DbprintfEx(FLAG_NOLOG, "FlashMem write FAILEd [offset %u]", bytes_sent);
cjSetCursLeft();
SpinOff(100);
return;
}
@ -352,11 +203,8 @@ void WriteTagToFlash(uint8_t index, size_t size)
cjSetCursLeft();
DbprintfEx(FLAG_NOLOG, "%s[IN]%s %s%dms%s for TAG_FLASH_WRITE", _GREEN_, _WHITE_, _YELLOW_, end_time - start_time, _WHITE_);
cjSetCursLeft();
FlashStop();
SpinOff(0);
return;
}
@ -473,11 +321,12 @@ ACCBITS : 796788[00]+VALUE
{
for (uint16_t sectorNo = 0; sectorNo < sectorsCnt; sectorNo++)
{
// validKey[t][sectorNo] = false;
for (uint16_t i = 0; i < 6; i++)
{
foundKey[t][sectorNo][i] = 0xff;
}
foundKey[t][sectorNo][0] = 0xFF;
foundKey[t][sectorNo][1] = 0xFF;
foundKey[t][sectorNo][2] = 0xFF;
foundKey[t][sectorNo][3] = 0xFF;
foundKey[t][sectorNo][4] = 0xFF;
foundKey[t][sectorNo][5] = 0xFF;
}
}
@ -491,7 +340,6 @@ ACCBITS : 796788[00]+VALUE
// banner:
vtsend_reset(NULL);
DbprintfEx(FLAG_NOLOG, "\r\n%s", clearTerm);
cjPrintBigArray(LOGO, sizeof(LOGO), 0, 0);
DbprintfEx(FLAG_NOLOG, "%s%s%s", _CYAN_, sub_banner, _WHITE_);
DbprintfEx(FLAG_NOLOG, "%s>>%s C.J.B's MifareFastPwn Started\r\n", _RED_, _WHITE_);
@ -506,11 +354,6 @@ ACCBITS : 796788[00]+VALUE
SpinOff(50);
SpinDown(50);
#if 0
TestFlashmemRoutine();
return;
#endif
failtag:
vtsend_cursor_position_save(NULL);
@ -607,7 +450,7 @@ failtag:
for (int sec = 0; sec < sectorsCnt && !err && !trapped; ++sec)
{
key = cjat91_saMifareChkKeys(sec * 4, type, NULL, size, &keyBlock[0], &key64);
// key = saMifareChkKeys(sec * 4, type, NULL, size, &keyBlock[0], &key64);
if (key == -1)
{
err = 1;
@ -932,7 +775,7 @@ failtag:
cjSetCursLeft();
cjSetCursLeft();
WriteTagToFlash(0,1024);
WriteTagToFlash(0, 1024);
readysim:
// SIM ?
@ -966,16 +809,6 @@ readysim:
DbprintfEx(FLAG_NOLOG, "<- We're out of Emulation");
// END SIM
/*for (;;) {
WDT_HIT();
int button_action = BUTTON_HELD(500);
if (button_action == 0) { // No button action, proceed with sim
SpinDelay(100);
WDT_HIT();
} else if (button_action == BUTTON_SINGLE_CLICK) {
*/
cjSetCursLeft();
DbprintfEx(FLAG_NOLOG, "-> Trying a clone !");
@ -987,15 +820,7 @@ readysim:
DbprintfEx(FLAG_NOLOG, "-> End Cloning.");
WDT_HIT();
// break;
/*} else if (button_action == BUTTON_HOLD) {
DbprintfEx(FLAG_RAWPRINT,"Playtime over. Begin cloning...");
iGotoClone = 1;
break;
}*/
// Debunk...
// SpinDelay(300);
cjSetCursLeft();
cjTabulize();
vtsend_set_attribute(NULL, 0);
@ -1020,14 +845,13 @@ void e_MifareECardLoad(uint32_t arg0, uint32_t arg1, uint32_t arg2, uint8_t *dat
uint8_t numSectors = arg0;
uint8_t keyType = arg1;
uint64_t ui64Key = 0;
// uint32_t cuid;
struct Crypto1State mpcs = {0, 0};
struct Crypto1State *pcs;
pcs = &mpcs;
byte_t dataoutbuf[16];
byte_t dataoutbuf2[16];
// uint8_t uid[10];
iso14443a_setup(FPGA_HF_ISO14443A_READER_LISTEN);
@ -1035,7 +859,6 @@ void e_MifareECardLoad(uint32_t arg0, uint32_t arg1, uint32_t arg2, uint8_t *dat
set_tracing(false);
bool isOK = true;
// iso14443a_fast_select_card(cjuid, 0);
if (!iso14443a_select_card(cjuid, NULL, &cjcuid, true, 0, true))
{
@ -1113,22 +936,17 @@ void e_MifareECardLoad(uint32_t arg0, uint32_t arg1, uint32_t arg2, uint8_t *dat
DbpString("EMUL FILL SECTORS FINISHED\n");
}
/* . . . */
/* the chk function is a piwied(tm) check that will try all keys for
a particular sector. also no tracing no dbg */
int cjat91_saMifareChkKeys(uint8_t blockNo, uint8_t keyType, bool clearTrace, uint8_t keyCount, uint8_t *datain, uint64_t *key)
{
MF_DBGLEVEL = MF_DBG_NONE;
iso14443a_setup(FPGA_HF_ISO14443A_READER_LISTEN);
set_tracing(false);
// uint8_t uid[10];
// uint32_t cuid;
struct Crypto1State mpcs = {0, 0};
struct Crypto1State *pcs;
pcs = &mpcs;
// byte_t isOK = 0;
for (int i = 0; i < keyCount; ++i)
{
@ -1241,7 +1059,6 @@ void saMifareMakeTag(void)
//-----------------------------------------------------------------------------
int saMifareCSetBlock(uint32_t arg0, uint32_t arg1, uint32_t arg2, uint8_t *datain)
{
// params
uint8_t needWipe = arg0;
// bit 0 - need get UID
@ -1259,9 +1076,7 @@ int saMifareCSetBlock(uint32_t arg0, uint32_t arg1, uint32_t arg2, uint8_t *data
// variables
byte_t isOK = 0;
// uint8_t uid[10] = {0x00};
uint8_t d_block[18] = {0x00};
// uint32_t cuid;
uint8_t receivedAnswer[MAX_MIFARE_FRAME_SIZE];
uint8_t receivedAnswerPar[MAX_MIFARE_PARITY_SIZE];
@ -1270,7 +1085,6 @@ int saMifareCSetBlock(uint32_t arg0, uint32_t arg1, uint32_t arg2, uint8_t *data
if (workFlags & 0x08)
{
iso14443a_setup(FPGA_HF_ISO14443A_READER_LISTEN);
// clear_trace();
set_tracing(FALSE);
}
@ -1282,19 +1096,15 @@ int saMifareCSetBlock(uint32_t arg0, uint32_t arg1, uint32_t arg2, uint8_t *data
// get UID from chip
if (workFlags & 0x01)
{
// if (!iso14443a_fast_select_card(cjuid, 0)) {
if (!iso14443a_select_card(cjuid, NULL, &cjcuid, true, 0, true))
{
if (MF_DBGLEVEL >= 1)
DbprintfEx(FLAG_NOLOG, "Can't select card");
DbprintfEx(FLAG_NOLOG, "Can't select card");
break;
};
if (mifare_classic_halt(NULL, cjcuid))
{
if (MF_DBGLEVEL >= 1)
DbprintfEx(FLAG_NOLOG, "Halt error");
DbprintfEx(FLAG_NOLOG, "Halt error");
break;
};
};
@ -1305,7 +1115,6 @@ int saMifareCSetBlock(uint32_t arg0, uint32_t arg1, uint32_t arg2, uint8_t *data
ReaderTransmitBitsPar(wupC1, 7, 0, NULL);
if (!ReaderReceive(receivedAnswer, receivedAnswerPar) || (receivedAnswer[0] != 0x0a))
{
// if (MF_DBGLEVEL >= 1)
DbprintfEx(FLAG_NOLOG, "wupC1 error");
break;
};
@ -1313,15 +1122,13 @@ int saMifareCSetBlock(uint32_t arg0, uint32_t arg1, uint32_t arg2, uint8_t *data
ReaderTransmit(wipeC, sizeof(wipeC), NULL);
if (!ReaderReceive(receivedAnswer, receivedAnswerPar) || (receivedAnswer[0] != 0x0a))
{
if (MF_DBGLEVEL >= 1)
DbprintfEx(FLAG_NOLOG, "wipeC error");
DbprintfEx(FLAG_NOLOG, "wipeC error");
break;
};
if (mifare_classic_halt(NULL, cjcuid))
{
if (MF_DBGLEVEL >= 1)
DbprintfEx(FLAG_NOLOG, "Halt error");
DbprintfEx(FLAG_NOLOG, "Halt error");
break;
};
};
@ -1333,7 +1140,6 @@ int saMifareCSetBlock(uint32_t arg0, uint32_t arg1, uint32_t arg2, uint8_t *data
ReaderTransmitBitsPar(wupC1, 7, 0, NULL);
if (!ReaderReceive(receivedAnswer, receivedAnswerPar) || (receivedAnswer[0] != 0x0a))
{
// if (MF_DBGLEVEL >= 1)
DbprintfEx(FLAG_NOLOG, "wupC1 error");
break;
};
@ -1341,7 +1147,6 @@ int saMifareCSetBlock(uint32_t arg0, uint32_t arg1, uint32_t arg2, uint8_t *data
ReaderTransmit(wupC2, sizeof(wupC2), NULL);
if (!ReaderReceive(receivedAnswer, receivedAnswerPar) || (receivedAnswer[0] != 0x0a))
{
// if (MF_DBGLEVEL >= 1)
DbprintfEx(FLAG_NOLOG, "wupC2 errorv");
break;
};
@ -1349,7 +1154,6 @@ int saMifareCSetBlock(uint32_t arg0, uint32_t arg1, uint32_t arg2, uint8_t *data
if ((mifare_sendcmd_short(NULL, 0, 0xA0, blockNo, receivedAnswer, receivedAnswerPar, NULL) != 1) || (receivedAnswer[0] != 0x0a))
{
// if (MF_DBGLEVEL >= 1)
DbprintfEx(FLAG_NOLOG, "write block send command error");
break;
};
@ -1359,7 +1163,6 @@ int saMifareCSetBlock(uint32_t arg0, uint32_t arg1, uint32_t arg2, uint8_t *data
ReaderTransmit(d_block, sizeof(d_block), NULL);
if ((ReaderReceive(receivedAnswer, receivedAnswerPar) != 1) || (receivedAnswer[0] != 0x0a))
{
// if (MF_DBGLEVEL >= 1)
DbprintfEx(FLAG_NOLOG, "write block send data error");
break;
};
@ -1368,7 +1171,6 @@ int saMifareCSetBlock(uint32_t arg0, uint32_t arg1, uint32_t arg2, uint8_t *data
{
if (mifare_classic_halt(NULL, cjcuid))
{
// if (MF_DBGLEVEL >= 1)
cjSetCursFRight();
DbprintfEx(FLAG_NOLOG, "Halt error");

View file

@ -16,18 +16,15 @@
#ifndef __HF_COLIN_H
#define __HF_COLIN_H
#include "proxmark3.h"
#include "mifareutil.h"
#include "iso14443a.h"
//#include "printf.h"
#include "protocols.h"
#include "util.h"
#include "standalone.h" // standalone definitions
#include <stdbool.h> // for bool
#include <stdio.h>
#include <string.h>
//#include <stdio.h>
#include "vtsend.h"
#include "apps.h"
#include "printf.h"
@ -41,23 +38,21 @@
#define _WHITE_ "\x1b[0m"
#define _ORANGE_ _YELLOW_
#define NTIME(n) for (int _index = 0; _index < n; _index++)
int cjat91_saMifareChkKeys(uint8_t blockNo, uint8_t keyType, bool clearTrace, uint8_t keyCount, uint8_t *datain, uint64_t *key);
void e_MifareECardLoad(uint32_t arg0, uint32_t arg1, uint32_t arg2, uint8_t *datain);
void saMifareMakeTag(void);
int saMifareCSetBlock(uint32_t arg0, uint32_t arg1, uint32_t arg2, uint8_t *datain);
void cjPrintBigArray(const char *bigar, int len, uint8_t newlines, uint8_t debug);
void WriteTagToFlash(uint8_t index, size_t size);
const char clearTerm[8] = {0x1b, 0x5b, 0x48, 0x1b, 0x5b, 0x32, 0x4a, '\0'};
void TestFlashmemSpeed(size_t buffersize, uint32_t spibaudrate);
//void cjPrintBigArray(const char *bigar, int len, uint8_t newlines, uint8_t debug);
//void TestFlashmemSpeed(size_t buffersize, uint32_t spibaudrate);
//#define LOGO logo_kigiv
#define LOGO logo_kigiv
const char sub_banner[] = " From Vigik : \"20 years of (un)security without a single update\"";
const char sub_banner[] = " From Vigik : \"20 years of (un)security without a single update\"";
/*
const char logo_kigiv[] = {
0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x1b, 0x5b, 0x33, 0x38, 0x3b, 0x35,
0x3b, 0x39, 0x35, 0x6d, 0x30, 0x1b, 0x5b, 0x33, 0x38, 0x3b, 0x35, 0x3b, 0x31, 0x33, 0x37, 0x6d, 0x30, 0x1b, 0x5b, 0x33, 0x38, 0x3b, 0x35, 0x3b, 0x39, 0x35,
@ -418,6 +413,7 @@ const char logo_kigiv[] = {
0x31, 0x1b, 0x5b, 0x33, 0x38, 0x3b, 0x35, 0x3b, 0x35, 0x39, 0x6d, 0x31, 0x1b, 0x5b, 0x33, 0x38, 0x3b, 0x35, 0x3b, 0x35, 0x39, 0x6d, 0x30, 0x1b, 0x5b, 0x33,
0x38, 0x3b, 0x35, 0x3b, 0x35, 0x39, 0x6d, 0x31, 0x1b, 0x5b, 0x33, 0x38, 0x3b, 0x35, 0x3b, 0x35, 0x39, 0x6d, 0x31, 0x0d, 0x0a};
unsigned int logo_kigiv_len = 9303;
*/
/*const char logo_kigiv_nocolor[] = {
0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x30, 0x30, 0x30, 0x30, 0x20, 0x20,

View file

@ -254,12 +254,7 @@ uint16_t Flash_ReadData(uint32_t address, uint8_t *out, uint16_t len) {
// length should never be zero
if (!len || Flash_CheckBusy(BUSY_TIMEOUT)) return 0;
uint8_t cmd = READDATA;
if(FASTFLASH) {
cmd = FASTREAD;
}
uint8_t cmd = (FASTFLASH) ? FASTREAD : READDATA;
FlashSendByte(cmd);
Flash_TransferAdresse(address);
@ -273,8 +268,6 @@ uint16_t Flash_ReadData(uint32_t address, uint8_t *out, uint16_t len) {
out[i] = FlashSendByte(0xFF);
out[i] = FlashSendLastByte(0xFF);
FlashStop();
return len;
}
@ -291,11 +284,7 @@ uint16_t Flash_ReadDataCont(uint32_t address, uint8_t *out, uint16_t len) {
// length should never be zero
if (!len) return 0;
uint8_t cmd = READDATA;
if(FASTFLASH) {
cmd = FASTREAD;
}
uint8_t cmd = (FASTFLASH) ? FASTREAD : READDATA;
FlashSendByte(cmd);
Flash_TransferAdresse(address);
@ -309,7 +298,6 @@ uint16_t Flash_ReadDataCont(uint32_t address, uint8_t *out, uint16_t len) {
out[i] = FlashSendByte(0xFF);
out[i] = FlashSendLastByte(0xFF);
return len;
}

View file

@ -90,9 +90,9 @@ void setT55xxConfig(uint8_t arg0, t55xx_config *c) {
return;
}
uint8_t *buf = BigBuf_malloc(4096);
uint8_t *buf = BigBuf_malloc(T55XX_CONFIG_LEN);
Flash_CheckBusy(BUSY_TIMEOUT);
uint16_t res = Flash_ReadDataCont(T55XX_CONFIG_OFFSET, buf, 4096);
uint16_t res = Flash_ReadDataCont(T55XX_CONFIG_OFFSET, buf, T55XX_CONFIG_LEN);
if ( res == 0) {
FlashStop();
BigBuf_free();
@ -104,9 +104,9 @@ void setT55xxConfig(uint8_t arg0, t55xx_config *c) {
Flash_CheckBusy(BUSY_TIMEOUT);
Flash_WriteEnable();
Flash_Erase4k(3, 0xD);
res = Flash_Write(T55XX_CONFIG_OFFSET, buf, 4096);
res = Flash_Write(T55XX_CONFIG_OFFSET, buf, T55XX_CONFIG_LEN);
if ( res == 4096 && MF_DBGLEVEL > 1) {
if ( res == T55XX_CONFIG_LEN && MF_DBGLEVEL > 1) {
DbpString("T55XX Config save success");
}
@ -124,10 +124,25 @@ void loadT55xxConfig(void) {
return;
}
uint8_t *buf = BigBuf_malloc(T55XX_CONFIG_LEN);
Flash_CheckBusy(BUSY_TIMEOUT);
uint16_t isok = Flash_ReadDataCont(T55XX_CONFIG_OFFSET, (uint8_t *)&t_config, T55XX_CONFIG_LEN);
uint16_t isok = Flash_ReadDataCont(T55XX_CONFIG_OFFSET, buf, T55XX_CONFIG_LEN);
FlashStop();
// verify read mem is actual data.
uint8_t cntA = T55XX_CONFIG_LEN, cntB = T55XX_CONFIG_LEN;
for (int i=0; i< T55XX_CONFIG_LEN; i++) {
if ( buf[i] == 0xFF) cntA--;
if ( buf[i] == 0x00) cntB--;
}
if ( !cntA || !cntB ) {
BigBuf_free();
return;
}
memcpy((uint8_t *)&t_config, buf, T55XX_CONFIG_LEN);
if ( isok == T55XX_CONFIG_LEN) {
if (MF_DBGLEVEL > 1) DbpString("T55XX Config load success");
}

View file

@ -1425,6 +1425,8 @@ OUT:
void MifareChkKeys(uint16_t arg0, uint8_t arg1, uint8_t arg2, uint8_t *datain) {
FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF);
struct Crypto1State mpcs = {0, 0};
struct Crypto1State *pcs;
pcs = &mpcs;

View file

@ -154,6 +154,70 @@ void LED(int led, int ms) {
LED_D_OFF();
}
void SpinOff(uint32_t pause) {
LED_A_OFF();
LED_B_OFF();
LED_C_OFF();
LED_D_OFF();
SpinDelay(pause);
}
// 0=A, 1=B, 2=C, 3=D
void SpinErr(uint8_t led, uint32_t speed, uint8_t times) {
SpinOff(speed);
NTIME(times)
{
switch (led) {
case 0:
LED_A_INV();
break;
case 1:
LED_B_INV();
break;
case 2:
LED_C_INV();
break;
case 3:
LED_D_INV();
break;
}
SpinDelay(speed);
}
}
void SpinDown(uint32_t speed) {
SpinOff(speed);
LED_D_ON();
SpinDelay(speed);
LED_D_OFF();
LED_C_ON();
SpinDelay(speed);
LED_C_OFF();
LED_B_ON();
SpinDelay(speed);
LED_B_OFF();
LED_A_ON();
SpinDelay(speed);
LED_A_OFF();
}
void SpinUp(uint32_t speed) {
SpinOff(speed);
LED_A_ON();
SpinDelay(speed);
LED_A_OFF();
LED_B_ON();
SpinDelay(speed);
LED_B_OFF();
LED_C_ON();
SpinDelay(speed);
LED_C_OFF();
LED_D_ON();
SpinDelay(speed);
LED_D_OFF();
}
// Determine if a button is double clicked, single clicked,
// not clicked, or held down (for ms || 1sec)
// In general, don't use this function unless you expect a

View file

@ -39,6 +39,10 @@
# define ARRAYLEN(x) (sizeof(x)/sizeof((x)[0]))
#endif
#ifndef NTIME
# define NTIME(n) for (int _index = 0; _index < n; _index++)
#endif
size_t nbytes(size_t nbits);
extern uint32_t reflect(uint32_t v, int b); // used in crc.c ...
@ -53,7 +57,12 @@ int32_t le24toh (uint8_t data[3]);
uint8_t hex2int(char hexchar);
void LED(int led, int ms);
void LEDsoff();
void LEDsoff(void);
void SpinOff(uint32_t pause);
void SpinErr(uint8_t led, uint32_t speed, uint8_t times);
void SpinDown(uint32_t speed);
void SpinUp(uint32_t speed);
int BUTTON_CLICKED(int ms);
int BUTTON_HELD(int ms);
void FormatVersionInformation(char *dst, int len, const char *prefix, void *version_information);

View file

@ -105,11 +105,13 @@ CMDSRCS = crapto1/crapto1.c \
tea.c \
polarssl/des.c \
polarssl/aes.c \
polarssl/aes_cmac128.c \
polarssl/bignum.c \
polarssl/rsa.c \
polarssl/sha1.c \
polarssl/sha256.c \
polarssl/base64.c \
polarssl/libpcrypto.c \
cliparser/argtable3.c\
cliparser/cliparser.c\
loclass/cipher.c \
@ -147,6 +149,7 @@ CMDSRCS = crapto1/crapto1.c \
emv/test/dda_test.c\
emv/test/cda_test.c\
emv/cmdemv.c \
mifare4.c \
cmdanalyse.c \
cmdhf.c \
cmdhflist.c \
@ -158,6 +161,7 @@ CMDSRCS = crapto1/crapto1.c \
cmdhficlass.c \
cmdhfmf.c \
cmdhfmfu.c \
cmdhfmfp.c \
cmdhfmfhard.c \
hardnested/hardnested_bruteforce.c \
cmdhfmfdes.c \

View file

@ -153,23 +153,14 @@ void CLIParserFree() {
// convertors
int CLIParamHexToBuf(struct arg_str *argstr, uint8_t *data, int maxdatalen, int *datalen) {
*datalen = 0;
if (!argstr->count)
return 0;
char buf[256] = {0};
int ibuf = 0;
uint8_t buf[256] = {0};
int res = CLIParamStrToBuf(argstr, buf, maxdatalen * 2, &ibuf); // *2 because here HEX
if (res || !ibuf)
return res;
for (int i = 0; i < argstr->count; i++) {
int len = strlen(argstr->sval[i]);
memcpy(&buf[ibuf], argstr->sval[i], len);
ibuf += len;
}
buf[ibuf] = 0;
if (!ibuf)
return 0;
switch(param_gethex_to_eol(buf, 0, data, maxdatalen, datalen)) {
switch(param_gethex_to_eol((char *)buf, 0, data, maxdatalen, datalen)) {
case 1:
printf("Parameter error: Invalid HEX value.\n");
return 1;
@ -184,5 +175,31 @@ int CLIParamHexToBuf(struct arg_str *argstr, uint8_t *data, int maxdatalen, int
return 0;
}
int CLIParamStrToBuf(struct arg_str *argstr, uint8_t *data, int maxdatalen, int *datalen) {
*datalen = 0;
if (!argstr->count)
return 0;
uint8_t buf[256] = {0};
int ibuf = 0;
for (int i = 0; i < argstr->count; i++) {
int len = strlen(argstr->sval[i]);
memcpy(&buf[ibuf], argstr->sval[i], len);
ibuf += len;
}
buf[ibuf] = 0;
if (!ibuf)
return 0;
if (ibuf > maxdatalen)
return 2;
memcpy(data, buf, ibuf);
*datalen = ibuf;
return 0;
}

View file

@ -17,7 +17,9 @@
#define arg_getsize(a) (sizeof(a) / sizeof(a[0]))
#define arg_get_lit(n)(((struct arg_lit*)argtable[n])->count)
#define arg_get_int_count(n)(((struct arg_int*)argtable[n])->count)
#define arg_get_int(n)(((struct arg_int*)argtable[n])->ival[0])
#define arg_get_int_def(n,def)(arg_get_int_count(n)?(arg_get_int(n)):(def))
#define arg_get_str(n)((struct arg_str*)argtable[n])
#define arg_get_str_len(n)(strlen(((struct arg_str*)argtable[n])->sval[0]))
@ -25,8 +27,9 @@
#define arg_strx0(shortopts, longopts, datatype, glossary) (arg_strn((shortopts), (longopts), (datatype), 0, 250, (glossary)))
#define CLIExecWithReturn(cmd, atbl, ifempty) if (CLIParserParseString(cmd, atbl, arg_getsize(atbl), ifempty)){CLIParserFree();return 0;}
#define CLIGetStrBLessWithReturn(paramnum, data, datalen, delta) if (CLIParamHexToBuf(arg_get_str(paramnum), data, sizeof(data) - (delta), datalen)) {CLIParserFree();return 1;}
#define CLIGetStrWithReturn(paramnum, data, datalen) if (CLIParamHexToBuf(arg_get_str(paramnum), data, sizeof(data), datalen)) {CLIParserFree();return 1;}
#define CLIGetHexBLessWithReturn(paramnum, data, datalen, delta) if (CLIParamHexToBuf(arg_get_str(paramnum), data, sizeof(data) - (delta), datalen)) {CLIParserFree();return 1;}
#define CLIGetHexWithReturn(paramnum, data, datalen) if (CLIParamHexToBuf(arg_get_str(paramnum), data, sizeof(data), datalen)) {CLIParserFree();return 1;}
#define CLIGetStrWithReturn(paramnum, data, datalen) if (CLIParamStrToBuf(arg_get_str(paramnum), data, sizeof(data), datalen)) {CLIParserFree();return 1;}
extern int CLIParserInit(char *vprogramName, char *vprogramHint, char *vprogramHelp);
extern int CLIParserParseString(const char* str, void* argtable[], size_t vargtableLen, bool allowEmptyExec);
@ -35,3 +38,4 @@ extern int CLIParserParseArg(int argc, char **argv, void* argtable[], size_t var
extern void CLIParserFree();
extern int CLIParamHexToBuf(struct arg_str *argstr, uint8_t *data, int maxdatalen, int *datalen);
extern int CLIParamStrToBuf(struct arg_str *argstr, uint8_t *data, int maxdatalen, int *datalen);

View file

@ -117,6 +117,7 @@ static command_t CommandTable[] = {
{"legic", CmdHFLegic, 1, "{ LEGIC RFIDs... }"},
{"iclass", CmdHFiClass, 1, "{ ICLASS RFIDs... }"},
{"mf", CmdHFMF, 1, "{ MIFARE RFIDs... }"},
{"mfp", CmdHFMFP, 1, "{ MIFARE Plus RFIDs... }"},
{"mfu", CmdHFMFUltra, 1, "{ MIFARE Ultralight RFIDs... }"},
{"mfdes", CmdHFMFDes, 1, "{ MIFARE Desfire RFIDs... }"},
{"topaz", CmdHFTopaz, 1, "{ TOPAZ (NFC Type 1) RFIDs... }"},

View file

@ -26,6 +26,7 @@
#include "cmdhficlass.h" // ICLASS
#include "cmdhfmf.h" // CLASSIC
#include "cmdhfmfu.h" // ULTRALIGHT/NTAG etc
#include "cmdhfmfp.h" // Mifare Plus
#include "cmdhfmfdes.h" // DESFIRE
#include "cmdhftopaz.h" // TOPAZ
#include "cmdhffelica.h" // ISO18092 / FeliCa

View file

@ -669,10 +669,12 @@ int CmdHF14ASniff(const char *Cmd) {
}
int ExchangeRAW14a(uint8_t *datain, int datainlen, bool activateField, bool leaveSignalON, uint8_t *dataout, int maxdataoutlen, int *dataoutlen) {
static bool responseNum = false;
uint16_t cmdc = 0;
*dataoutlen = 0;
if (activateField) {
responseNum = false;
UsbCommand resp;
// Anticollision + SELECT card
@ -685,7 +687,7 @@ int ExchangeRAW14a(uint8_t *datain, int datainlen, bool activateField, bool leav
// check result
if (resp.arg[0] == 0) {
PrintAndLogEx(NORMAL, "No card in field.");
PrintAndLogEx(ERR, "No card in field.");
return 1;
}
@ -715,8 +717,11 @@ int ExchangeRAW14a(uint8_t *datain, int datainlen, bool activateField, bool leav
if (leaveSignalON)
cmdc |= ISO14A_NO_DISCONNECT;
UsbCommand c = {CMD_READER_ISO_14443a, {ISO14A_RAW | ISO14A_APPEND_CRC | cmdc, (datainlen & 0xFFFF), 0}};
memcpy(c.d.asBytes, datain, datainlen);
UsbCommand c = {CMD_READER_ISO_14443a, {ISO14A_RAW | ISO14A_APPEND_CRC | cmdc, (datainlen & 0xFFFF) + 2, 0}};
uint8_t header[] = {0x0a | responseNum, 0x00};
responseNum ^= 1;
memcpy(c.d.asBytes, header, 2);
memcpy(&c.d.asBytes[2], datain, datainlen);
SendCommand(&c);
uint8_t *recv;
@ -726,6 +731,11 @@ int ExchangeRAW14a(uint8_t *datain, int datainlen, bool activateField, bool leav
recv = resp.d.asBytes;
int iLen = resp.arg[0];
if(!iLen) {
PrintAndLogEx(ERR, "No card response.");
return 1;
}
*dataoutlen = iLen - 2;
if (*dataoutlen < 0)
*dataoutlen = 0;
@ -735,13 +745,13 @@ int ExchangeRAW14a(uint8_t *datain, int datainlen, bool activateField, bool leav
return 2;
}
memcpy(dataout, recv, *dataoutlen);
if(!iLen) {
PrintAndLogEx(ERR, "No card response.");
return 1;
if (recv[0] != header[0]) {
PrintAndLogEx(ERR, "iso14443-4 framing error. Card send %2x must be %2x", dataout[0], header[0]);
return 2;
}
memcpy(dataout, &recv[2], *dataoutlen);
// CRC Check
if (iLen == -1) {
PrintAndLogEx(ERR, "ISO 14443A CRC error.");

View file

@ -2047,7 +2047,7 @@ int CmdHFiClassCheckKeys(const char *Cmd) {
return 1;
}
PrintPreCalcMac(keyBlock, keycnt, pre);
//PrintPreCalcMac(keyBlock, keycnt, pre);
// max 42 keys inside USB_COMMAND. 512/4 = 103 mac
uint32_t chunksize = keycnt > (USB_CMD_DATA_SIZE/4) ? (USB_CMD_DATA_SIZE/4) : keycnt;

View file

@ -9,6 +9,7 @@
//-----------------------------------------------------------------------------
#include "cmdhfmf.h"
#include "mifare4.h"
#define MIFARE_4K_MAXBLOCK 255
#define MIFARE_2K_MAXBLOCK 128
@ -130,6 +131,13 @@ int usage_hf14_hardnested(void){
PrintAndLogEx(NORMAL, " u <UID> read/write hf-mf-<UID>-nonces.bin instead of default name");
PrintAndLogEx(NORMAL, " f <name> read/write <name> instead of default name");
PrintAndLogEx(NORMAL, " t tests?");
PrintAndLogEx(NORMAL, " i <X> set type of SIMD instructions. Without this flag programs autodetect it.");
PrintAndLogEx(NORMAL, " i 5 = AVX512");
PrintAndLogEx(NORMAL, " i 2 = AVX2");
PrintAndLogEx(NORMAL, " i a = AVX");
PrintAndLogEx(NORMAL, " i s = SSE2");
PrintAndLogEx(NORMAL, " i m = MMX");
PrintAndLogEx(NORMAL, " i n = none (use CPU regular instruction set)");
PrintAndLogEx(NORMAL, "");
PrintAndLogEx(NORMAL, "Examples:");
PrintAndLogEx(NORMAL, " hf mf hardnested 0 A FFFFFFFFFFFF 4 A");
@ -1251,8 +1259,8 @@ int CmdHF14AMfNestedHard(const char *Cmd) {
switch(tolower(param_getchar(Cmd, cmdp))) {
case 'h': return usage_hf14_hardnested();
case 'r':
fptr=GenerateFilename("hf-mf-","-nonces.bin");
if(fptr==NULL)
fptr = GenerateFilename("hf-mf-","-nonces.bin");
if (fptr == NULL)
strncpy(filename,"nonces.bin", FILE_PATH_SIZE);
else
strncpy(filename,fptr, FILE_PATH_SIZE);
@ -1268,10 +1276,10 @@ int CmdHF14AMfNestedHard(const char *Cmd) {
if (!param_gethex(Cmd, cmdp+2, trgkey, 12)) {
know_target_key = true;
}
cmdp+=2;
cmdp += 2;
break;
default:
if(param_getchar(Cmd, cmdp) == 0x00)
if (param_getchar(Cmd, cmdp) == 0x00)
{
PrintAndLogEx(NORMAL, "Block number is missing");
return 1;
@ -1308,7 +1316,7 @@ int CmdHF14AMfNestedHard(const char *Cmd) {
if (ctmp != 'A' && ctmp != 'a') {
trgKeyType = 1;
}
cmdp+=5;
cmdp += 5;
}
if (!param_gethex(Cmd, cmdp, trgkey, 12)) {
know_target_key = true;
@ -1316,14 +1324,13 @@ int CmdHF14AMfNestedHard(const char *Cmd) {
}
while ((ctmp = param_getchar(Cmd, cmdp))) {
switch(tolower(ctmp))
{
switch(tolower(ctmp)) {
case 's':
slow = true;
break;
case 'w':
nonce_file_write = true;
fptr=GenerateFilename("hf-mf-","-nonces.bin");
fptr = GenerateFilename("hf-mf-","-nonces.bin");
if (fptr == NULL)
return 1;
strncpy(filename, fptr, FILE_PATH_SIZE);
@ -1338,6 +1345,34 @@ int CmdHF14AMfNestedHard(const char *Cmd) {
strncpy(filename, szTemp, FILE_PATH_SIZE);
cmdp++;
break;
case 'i':
SetSIMDInstr(SIMD_AUTO);
ctmp = tolower(param_getchar(Cmd, cmdp+1));
switch (ctmp) {
case '5':
SetSIMDInstr(SIMD_AVX512);
break;
case '2':
SetSIMDInstr(SIMD_AVX2);
break;
case 'a':
SetSIMDInstr(SIMD_AVX);
break;
case 's':
SetSIMDInstr(SIMD_SSE2);
break;
case 'm':
SetSIMDInstr(SIMD_MMX);
break;
case 'n':
SetSIMDInstr(SIMD_NONE);
break;
default:
PrintAndLog("Unknown SIMD type. %c", ctmp);
return 1;
}
cmdp += 2;
break;
default:
PrintAndLogEx(WARNING, "Unknown parameter '%c'\n", ctmp);
usage_hf14_hardnested();
@ -3067,50 +3102,12 @@ out:
return 0;
}
int aes_encode(uint8_t *iv, uint8_t *key, uint8_t *input, uint8_t *output, int length){
uint8_t iiv[16] = {0};
if (iv)
memcpy(iiv, iv, 16);
aes_context aes;
aes_init(&aes);
if (aes_setkey_enc(&aes, key, 128))
return 1;
if (aes_crypt_cbc(&aes, AES_ENCRYPT, length, iiv, input, output))
return 2;
aes_free(&aes);
return 0;
}
int aes_decode(uint8_t *iv, uint8_t *key, uint8_t *input, uint8_t *output, int length){
uint8_t iiv[16] = {0};
if (iv)
memcpy(iiv, iv, 16);
aes_context aes;
aes_init(&aes);
if (aes_setkey_dec(&aes, key, 128))
return 1;
if (aes_crypt_cbc(&aes, AES_DECRYPT, length, iiv, input, output))
return 2;
aes_free(&aes);
return 0;
}
int CmdHF14AMfAuth4(const char *cmd) {
uint8_t keyn[20] = {0};
int keynlen = 0;
uint8_t key[16] = {0};
int keylen = 0;
uint8_t data[257] = {0};
int datalen = 0;
uint8_t Rnd1[17] = {0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x00};
uint8_t Rnd2[17] = {0};
CLIParserInit("hf mf auth4",
"Executes AES authentication command in ISO14443-4",
"Usage:\n\thf mf auth4 4000 000102030405060708090a0b0c0d0e0f -> executes authentication\n"
@ -3124,8 +3121,8 @@ int CmdHF14AMfAuth4(const char *cmd) {
};
CLIExecWithReturn(cmd, argtable, true);
CLIGetStrWithReturn(1, keyn, &keynlen);
CLIGetStrWithReturn(2, key, &keylen);
CLIGetHexWithReturn(1, keyn, &keynlen);
CLIGetHexWithReturn(2, key, &keylen);
CLIParserFree();
if (keynlen != 2) {
@ -3138,76 +3135,7 @@ int CmdHF14AMfAuth4(const char *cmd) {
return 1;
}
uint8_t cmd1[] = {0x0a, 0x00, 0x70, keyn[1], keyn[0], 0x00};
int res = ExchangeRAW14a(cmd1, sizeof(cmd1), true, true, data, sizeof(data), &datalen);
if (res) {
PrintAndLog("ERROR exchande raw error: %d", res);
return 2;
}
PrintAndLog("<phase1: %s", sprint_hex(data, datalen));
if (datalen < 3) {
PrintAndLogEx(ERR, "card response length: %d", datalen);
return 3;
}
if (data[0] != 0x0a || data[1] != 0x00) {
PrintAndLogEx(ERR, "Framing error in card response. :%s", sprint_hex(data, 2));
return 3;
}
if (data[2] != 0x90) {
PrintAndLogEx(ERR, "card response error: %02x", data[2]);
return 3;
}
if (datalen != 19) {
PrintAndLogEx(ERR, "card response must be 16 bytes long instead of: %d", datalen);
return 3;
}
aes_decode(NULL, key, &data[3], Rnd2, 16);
Rnd2[16] = Rnd2[0];
PrintAndLog("Rnd2: %s", sprint_hex(Rnd2, 16));
uint8_t cmd2[35] = {0};
cmd2[0] = 0x0b;
cmd2[1] = 0x00;
cmd2[2] = 0x72;
uint8_t raw[32] = {0};
memmove(raw, Rnd1, 16);
memmove(&raw[16], &Rnd2[1], 16);
aes_encode(NULL, key, raw, &cmd2[3], 32);
PrintAndLog(">phase2: %s", sprint_hex(cmd2, 35));
res = ExchangeRAW14a(cmd2, sizeof(cmd2), false, false, data, sizeof(data), &datalen);
if (res) {
PrintAndLogEx(ERR, "exchande raw error: %d", res);
DropField();
return 4;
}
PrintAndLog("<phase2: %s", sprint_hex(data, datalen));
aes_decode(NULL, key, &data[3], raw, 32);
PrintAndLog("res: %s", sprint_hex(raw, 32));
PrintAndLog("Rnd1`: %s", sprint_hex(&raw[4], 16));
if (memcmp(&raw[4], &Rnd1[1], 16)) {
PrintAndLogEx(ERR, "\nAuthentication FAILED. rnd not equal");
PrintAndLog("rnd1 reader: %s", sprint_hex(&Rnd1[1], 16));
PrintAndLog("rnd1 card: %s", sprint_hex(&raw[4], 16));
DropField();
return 5;
}
DropField();
PrintAndLogEx(INFO, "Authentication OK");
return 0;
return MifareAuth4(NULL, keyn, key, true, false, true);
}
static command_t CommandTable[] = {

View file

@ -31,6 +31,7 @@
#include "mifaredefault.h" // mifare default key array
#include "cmdhf14a.h" // dropfield
#include "cliparser/cliparser.h" // argtable
#include "hardnested/hardnested_bf_core.h" // SetSIMDInstr
extern int CmdHFMF(const char *Cmd);

View file

@ -33,6 +33,7 @@
#include "crapto1/crapto1.h"
#include "parity.h"
#include "hardnested/hardnested_bruteforce.h"
#include "hardnested/hardnested_bf_core.h"
#include "hardnested/hardnested_bitarray_core.h"
#include "zlib.h"
@ -72,22 +73,27 @@ static float brute_force_per_second;
static void get_SIMD_instruction_set(char* instruction_set) {
#if defined (__i386__) || defined (__x86_64__)
#if !defined(__APPLE__) || (defined(__APPLE__) && (__clang_major__ > 8 || __clang_major__ == 8 && __clang_minor__ >= 1))
#if (__GNUC__ >= 5) && (__GNUC__ > 5 || __GNUC_MINOR__ > 2)
if (__builtin_cpu_supports("avx512f")) strcpy(instruction_set, "AVX512F");
else if (__builtin_cpu_supports("avx2")) strcpy(instruction_set, "AVX2");
#else
if (__builtin_cpu_supports("avx2")) strcpy(instruction_set, "AVX2");
#endif
else if (__builtin_cpu_supports("avx")) strcpy(instruction_set, "AVX");
else if (__builtin_cpu_supports("sse2")) strcpy(instruction_set, "SSE2");
else if (__builtin_cpu_supports("mmx")) strcpy(instruction_set, "MMX");
else
#endif
#endif
strcpy(instruction_set, "no");
}
switch(GetSIMDInstrAuto()) {
case SIMD_AVX512:
strcpy(instruction_set, "AVX512F");
break;
case SIMD_AVX2:
strcpy(instruction_set, "AVX2");
break;
case SIMD_AVX:
strcpy(instruction_set, "AVX");
break;
case SIMD_SSE2:
strcpy(instruction_set, "SSE2");
break;
case SIMD_MMX:
strcpy(instruction_set, "MMX");
break;
default:
strcpy(instruction_set, "no");
break;
}
}
static void print_progress_header(void) {
@ -267,6 +273,7 @@ static void init_bitflip_bitarrays(void)
if (bytesread != filesize) {
PrintAndLogEx(WARNING, "File read error with %s. Aborting...\n", state_file_name);
fclose(statesfile);
inflateEnd(&compressed_stream);
exit(5);
}
fclose(statesfile);
@ -1743,7 +1750,7 @@ static void add_matching_states(statelist_t *candidates, uint8_t part_sum_a0, ui
PrintAndLogEx(WARNING, "Out of memory error in add_matching_states() - statelist.\n");
exit(4);
}
uint32_t *candidates_bitarray = (uint32_t *)malloc_bitarray(sizeof(uint32_t) * (1<<19));
uint32_t *candidates_bitarray = (uint32_t *)malloc_bitarray(sizeof(uint32_t) * worstcase_size);
if (candidates_bitarray == NULL) {
PrintAndLogEx(WARNING, "Out of memory error in add_matching_states() - bitarray.\n");
free(candidates->states[odd_even]);
@ -2208,6 +2215,10 @@ static void set_test_state(uint8_t byte)
int mfnestedhard(uint8_t blockNo, uint8_t keyType, uint8_t *key, uint8_t trgBlockNo, uint8_t trgKeyType, uint8_t *trgkey, bool nonce_file_read, bool nonce_file_write, bool slow, int tests, uint64_t *foundkey, char *filename)
{
char progress_text[80];
char instr_set[12] = {0};
get_SIMD_instruction_set(instr_set);
PrintAndLog("Using %s SIMD core.", instr_set);
srand((unsigned) time(NULL));
brute_force_per_second = brute_force_benchmark();

759
client/cmdhfmfp.c Normal file
View file

@ -0,0 +1,759 @@
//-----------------------------------------------------------------------------
// Copyright (C) 2018 Merlok
// Copyright (C) 2018 drHatson
//
// This code is licensed to you under the terms of the GNU GPL, version 2 or,
// at your option, any later version. See the LICENSE.txt file for the text of
// the license.
//-----------------------------------------------------------------------------
// High frequency MIFARE Plus commands
//-----------------------------------------------------------------------------
#include "cmdhfmfp.h"
#include <inttypes.h>
#include <string.h>
#include <stdio.h>
#include <stdlib.h>
#include <ctype.h>
#include "comms.h"
#include "cmdmain.h"
#include "util.h"
#include "ui.h"
#include "cmdhf14a.h"
#include "mifare.h"
#include "mifare4.h"
#include "cliparser/cliparser.h"
#include "polarssl/libpcrypto.h"
static const uint8_t DefaultKey[16] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff};
typedef struct {
uint8_t Code;
const char *Description;
} PlusErrorsElm;
static const PlusErrorsElm PlusErrors[] = {
{0xFF, ""},
{0x00, "Transfer cannot be granted within the current authentication."},
{0x06, "Access Conditions not fulfilled. Block does not exist, block is not a value block."},
{0x07, "Too many read or write commands in the session or in the transaction."},
{0x08, "Invalid MAC in command or response"},
{0x09, "Block Number is not valid"},
{0x0a, "Invalid block number, not existing block number"},
{0x0b, "The current command code not available at the current card state."},
{0x0c, "Length error"},
{0x0f, "General Manipulation Error. Failure in the operation of the PICC (cannot write to the data block), etc."},
{0x90, "OK"},
};
int PlusErrorsLen = sizeof(PlusErrors) / sizeof(PlusErrorsElm);
const char * GetErrorDescription(uint8_t errorCode) {
for(int i = 0; i < PlusErrorsLen; i++)
if (errorCode == PlusErrors[i].Code)
return PlusErrors[i].Description;
return PlusErrors[0].Description;
}
static int CmdHelp(const char *Cmd);
static bool VerboseMode = false;
void SetVerboseMode(bool verbose) {
VerboseMode = verbose;
}
int intExchangeRAW14aPlus(uint8_t *datain, int datainlen, bool activateField, bool leaveSignalON, uint8_t *dataout, int maxdataoutlen, int *dataoutlen) {
if(VerboseMode)
PrintAndLogEx(INFO, ">>> %s", sprint_hex(datain, datainlen));
int res = ExchangeRAW14a(datain, datainlen, activateField, leaveSignalON, dataout, maxdataoutlen, dataoutlen);
if(VerboseMode)
PrintAndLogEx(INFO, "<<< %s", sprint_hex(dataout, *dataoutlen));
return res;
}
int MFPWritePerso(uint8_t *keyNum, uint8_t *key, bool activateField, bool leaveSignalON, uint8_t *dataout, int maxdataoutlen, int *dataoutlen) {
uint8_t rcmd[3 + 16] = {0xa8, keyNum[1], keyNum[0], 0x00};
memmove(&rcmd[3], key, 16);
return intExchangeRAW14aPlus(rcmd, sizeof(rcmd), activateField, leaveSignalON, dataout, maxdataoutlen, dataoutlen);
}
int MFPCommitPerso(bool activateField, bool leaveSignalON, uint8_t *dataout, int maxdataoutlen, int *dataoutlen) {
uint8_t rcmd[1] = {0xaa};
return intExchangeRAW14aPlus(rcmd, sizeof(rcmd), activateField, leaveSignalON, dataout, maxdataoutlen, dataoutlen);
}
int MFPReadBlock(mf4Session *session, bool plain, uint8_t blockNum, uint8_t blockCount, bool activateField, bool leaveSignalON, uint8_t *dataout, int maxdataoutlen, int *dataoutlen, uint8_t *mac) {
uint8_t rcmd[4 + 8] = {(plain?(0x37):(0x33)), blockNum, 0x00, blockCount};
if (!plain && session)
CalculateMAC(session, mtypReadCmd, blockNum, blockCount, rcmd, 4, &rcmd[4], VerboseMode);
int res = intExchangeRAW14aPlus(rcmd, plain?4:sizeof(rcmd), activateField, leaveSignalON, dataout, maxdataoutlen, dataoutlen);
if(res)
return res;
if (session)
session->R_Ctr++;
if(session && mac && *dataoutlen > 11)
CalculateMAC(session, mtypReadResp, blockNum, blockCount, dataout, *dataoutlen - 8 - 2, mac, VerboseMode);
return 0;
}
int MFPWriteBlock(mf4Session *session, uint8_t blockNum, uint8_t *data, bool activateField, bool leaveSignalON, uint8_t *dataout, int maxdataoutlen, int *dataoutlen, uint8_t *mac) {
uint8_t rcmd[1 + 2 + 16 + 8] = {0xA3, blockNum, 0x00};
memmove(&rcmd[3], data, 16);
if (session)
CalculateMAC(session, mtypWriteCmd, blockNum, 1, rcmd, 19, &rcmd[19], VerboseMode);
int res = intExchangeRAW14aPlus(rcmd, sizeof(rcmd), activateField, leaveSignalON, dataout, maxdataoutlen, dataoutlen);
if(res)
return res;
if (session)
session->W_Ctr++;
if(session && mac && *dataoutlen > 3)
CalculateMAC(session, mtypWriteResp, blockNum, 1, dataout, *dataoutlen, mac, VerboseMode);
return 0;
}
int CmdHFMFPInfo(const char *cmd) {
if (cmd && strlen(cmd) > 0)
PrintAndLogEx(WARNING, "command don't have any parameters.\n");
// info about 14a part
CmdHF14AInfo("");
// Mifare Plus info
UsbCommand c = {CMD_READER_ISO_14443a, {ISO14A_CONNECT | ISO14A_NO_DISCONNECT, 0, 0}};
SendCommand(&c);
UsbCommand resp;
WaitForResponse(CMD_ACK,&resp);
iso14a_card_select_t card;
memcpy(&card, (iso14a_card_select_t *)resp.d.asBytes, sizeof(iso14a_card_select_t));
uint64_t select_status = resp.arg[0]; // 0: couldn't read, 1: OK, with ATS, 2: OK, no ATS, 3: proprietary Anticollision
if (select_status == 1 || select_status == 2) {
PrintAndLogEx(NORMAL, "----------------------------------------------");
PrintAndLogEx(NORMAL, "Mifare Plus info:");
// MIFARE Type Identification Procedure
// https://www.nxp.com/docs/en/application-note/AN10833.pdf
uint16_t ATQA = card.atqa[0] + (card.atqa[1] << 8);
if (ATQA == 0x0004) PrintAndLogEx(INFO, "ATQA: Mifare Plus 2k 4bUID");
if (ATQA == 0x0002) PrintAndLogEx(INFO, "ATQA: Mifare Plus 4k 4bUID");
if (ATQA == 0x0044) PrintAndLogEx(INFO, "ATQA: Mifare Plus 2k 7bUID");
if (ATQA == 0x0042) PrintAndLogEx(INFO, "ATQA: Mifare Plus 4k 7bUID");
uint8_t SLmode = 0xff;
if (card.sak == 0x08) {
PrintAndLogEx(INFO, "SAK: Mifare Plus 2k 7bUID");
if (select_status == 2) SLmode = 1;
}
if (card.sak == 0x18) {
PrintAndLogEx(INFO, "SAK: Mifare Plus 4k 7bUID");
if (select_status == 2) SLmode = 1;
}
if (card.sak == 0x10) {
PrintAndLogEx(INFO, "SAK: Mifare Plus 2k");
if (select_status == 2) SLmode = 2;
}
if (card.sak == 0x11) {
PrintAndLogEx(INFO, "SAK: Mifare Plus 4k");
if (select_status == 2) SLmode = 2;
}
if (card.sak == 0x20) {
PrintAndLogEx(INFO, "SAK: Mifare Plus SL0/SL3 or Mifare desfire");
if (card.ats_len > 0) {
SLmode = 3;
// check SL0
uint8_t data[250] = {0};
int datalen = 0;
// https://github.com/Proxmark/proxmark3/blob/master/client/scripts/mifarePlus.lua#L161
uint8_t cmd[3 + 16] = {0xa8, 0x90, 0x90, 0x00};
int res = ExchangeRAW14a(cmd, sizeof(cmd), false, false, data, sizeof(data), &datalen);
if (!res && datalen > 1 && data[0] == 0x09) {
SLmode = 0;
}
}
}
if (SLmode != 0xff)
PrintAndLogEx(INFO, "Mifare Plus SL mode: SL%d", SLmode);
else
PrintAndLogEx(WARNING, "Mifare Plus SL mode: unknown(");
} else {
PrintAndLogEx(INFO, "Mifare Plus info not available.");
}
DropField();
return 0;
}
int CmdHFMFPWritePerso(const char *cmd) {
uint8_t keyNum[64] = {0};
int keyNumLen = 0;
uint8_t key[64] = {0};
int keyLen = 0;
CLIParserInit("hf mfp wrp",
"Executes Write Perso command. Can be used in SL0 mode only.",
"Usage:\n\thf mfp wrp 4000 000102030405060708090a0b0c0d0e0f -> write key (00..0f) to key number 4000 \n"
"\thf mfp wrp 4000 -> write default key(0xff..0xff) to key number 4000");
void* argtable[] = {
arg_param_begin,
arg_lit0("vV", "verbose", "show internal data."),
arg_str1(NULL, NULL, "<HEX key number (2b)>", NULL),
arg_strx0(NULL, NULL, "<HEX key (16b)>", NULL),
arg_param_end
};
CLIExecWithReturn(cmd, argtable, true);
bool verbose = arg_get_lit(1);
CLIGetHexWithReturn(2, keyNum, &keyNumLen);
CLIGetHexWithReturn(3, key, &keyLen);
CLIParserFree();
SetVerboseMode(verbose);
if (!keyLen) {
memmove(key, DefaultKey, 16);
keyLen = 16;
}
if (keyNumLen != 2) {
PrintAndLogEx(ERR, "Key number length must be 2 bytes instead of: %d", keyNumLen);
return 1;
}
if (keyLen != 16) {
PrintAndLogEx(ERR, "Key length must be 16 bytes instead of: %d", keyLen);
return 1;
}
uint8_t data[250] = {0};
int datalen = 0;
int res = MFPWritePerso(keyNum, key, true, false, data, sizeof(data), &datalen);
if (res) {
PrintAndLogEx(ERR, "Exchange error: %d", res);
return res;
}
if (datalen != 3) {
PrintAndLogEx(ERR, "Command must return 3 bytes instead of: %d", datalen);
return 1;
}
if (data[0] != 0x90) {
PrintAndLogEx(ERR, "Command error: %02x %s", data[0], GetErrorDescription(data[0]));
return 1;
}
PrintAndLogEx(INFO, "Write OK.");
return 0;
}
uint16_t CardAddresses[] = {0x9000, 0x9001, 0x9002, 0x9003, 0x9004, 0xA000, 0xA001, 0xA080, 0xA081, 0xC000, 0xC001};
int CmdHFMFPInitPerso(const char *cmd) {
int res;
uint8_t key[256] = {0};
int keyLen = 0;
uint8_t keyNum[2] = {0};
uint8_t data[250] = {0};
int datalen = 0;
CLIParserInit("hf mfp initp",
"Executes Write Perso command for all card's keys. Can be used in SL0 mode only.",
"Usage:\n\thf mfp initp 000102030405060708090a0b0c0d0e0f -> fill all the keys with key (00..0f)\n"
"\thf mfp initp -vv -> fill all the keys with default key(0xff..0xff) and show all the data exchange");
void* argtable[] = {
arg_param_begin,
arg_litn("vV", "verbose", 0, 2, "show internal data."),
arg_strx0(NULL, NULL, "<HEX key (16b)>", NULL),
arg_param_end
};
CLIExecWithReturn(cmd, argtable, true);
bool verbose = arg_get_lit(1);
bool verbose2 = arg_get_lit(1) > 1;
CLIGetHexWithReturn(2, key, &keyLen);
CLIParserFree();
if (keyLen && keyLen != 16) {
PrintAndLogEx(ERR, "Key length must be 16 bytes instead of: %d", keyLen);
return 1;
}
if (!keyLen)
memmove(key, DefaultKey, 16);
SetVerboseMode(verbose2);
for (uint16_t sn = 0x4000; sn < 0x4050; sn++) {
keyNum[0] = sn >> 8;
keyNum[1] = sn & 0xff;
res = MFPWritePerso(keyNum, key, (sn == 0x4000), true, data, sizeof(data), &datalen);
if (!res && (datalen == 3) && data[0] == 0x09) {
PrintAndLogEx(INFO, "2k card detected.");
break;
}
if (res || (datalen != 3) || data[0] != 0x90) {
PrintAndLogEx(ERR, "Write error on address %04x", sn);
break;
}
}
SetVerboseMode(verbose);
for (int i = 0; i < sizeof(CardAddresses) / 2; i++) {
keyNum[0] = CardAddresses[i] >> 8;
keyNum[1] = CardAddresses[i] & 0xff;
res = MFPWritePerso(keyNum, key, false, true, data, sizeof(data), &datalen);
if (!res && (datalen == 3) && data[0] == 0x09) {
PrintAndLogEx(WARNING, "Skipped[%04x]...", CardAddresses[i]);
} else {
if (res || (datalen != 3) || data[0] != 0x90) {
PrintAndLogEx(ERR, "Write error on address %04x", CardAddresses[i]);
break;
}
}
}
DropField();
if (res)
return res;
PrintAndLogEx(INFO, "Done.");
return 0;
}
int CmdHFMFPCommitPerso(const char *cmd) {
CLIParserInit("hf mfp commitp",
"Executes Commit Perso command. Can be used in SL0 mode only.",
"Usage:\n\thf mfp commitp -> \n");
void* argtable[] = {
arg_param_begin,
arg_lit0("vV", "verbose", "show internal data."),
arg_int0(NULL, NULL, "SL mode", NULL),
arg_param_end
};
CLIExecWithReturn(cmd, argtable, true);
bool verbose = arg_get_lit(1);
CLIParserFree();
SetVerboseMode(verbose);
uint8_t data[250] = {0};
int datalen = 0;
int res = MFPCommitPerso(true, false, data, sizeof(data), &datalen);
if (res) {
PrintAndLogEx(ERR, "Exchange error: %d", res);
return res;
}
if (datalen != 3) {
PrintAndLogEx(ERR, "Command must return 3 bytes instead of: %d", datalen);
return 1;
}
if (data[0] != 0x90) {
PrintAndLogEx(ERR, "Command error: %02x %s", data[0], GetErrorDescription(data[0]));
return 1;
}
PrintAndLogEx(INFO, "Switch level OK.");
return 0;
}
int CmdHFMFPAuth(const char *cmd) {
uint8_t keyn[250] = {0};
int keynlen = 0;
uint8_t key[250] = {0};
int keylen = 0;
CLIParserInit("hf mfp auth",
"Executes AES authentication command for Mifare Plus card",
"Usage:\n\thf mfp auth 4000 000102030405060708090a0b0c0d0e0f -> executes authentication\n"
"\thf mfp auth 9003 FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF -v -> executes authentication and shows all the system data\n");
void* argtable[] = {
arg_param_begin,
arg_lit0("vV", "verbose", "show internal data."),
arg_str1(NULL, NULL, "<Key Num (HEX 2 bytes)>", NULL),
arg_str1(NULL, NULL, "<Key Value (HEX 16 bytes)>", NULL),
arg_param_end
};
CLIExecWithReturn(cmd, argtable, true);
bool verbose = arg_get_lit(1);
CLIGetHexWithReturn(2, keyn, &keynlen);
CLIGetHexWithReturn(3, key, &keylen);
CLIParserFree();
if (keynlen != 2) {
PrintAndLogEx(ERR, "ERROR: <Key Num> must be 2 bytes long instead of: %d", keynlen);
return 1;
}
if (keylen != 16) {
PrintAndLogEx(ERR, "ERROR: <Key Value> must be 16 bytes long instead of: %d", keylen);
return 1;
}
return MifareAuth4(NULL, keyn, key, true, false, verbose);
}
int CmdHFMFPRdbl(const char *cmd) {
uint8_t keyn[2] = {0};
uint8_t key[250] = {0};
int keylen = 0;
CLIParserInit("hf mfp rdbl",
"Reads several blocks from Mifare Plus card.",
"Usage:\n\thf mfp rdbl 0 000102030405060708090a0b0c0d0e0f -> executes authentication and read block 0 data\n"
"\thf mfp rdbl 1 -v -> executes authentication and shows sector 1 data with default key 0xFF..0xFF and some additional data\n");
void* argtable[] = {
arg_param_begin,
arg_lit0("vV", "verbose", "show internal data."),
arg_int0("nN", "count", "blocks count (by default 1).", NULL),
arg_lit0("bB", "keyb", "use key B (by default keyA)."),
arg_lit0("pP", "plain", "plain communication mode between reader and card."),
arg_int1(NULL, NULL, "<Block Num (0..255)>", NULL),
arg_str0(NULL, NULL, "<Key Value (HEX 16 bytes)>", NULL),
arg_param_end
};
CLIExecWithReturn(cmd, argtable, false);
bool verbose = arg_get_lit(1);
int blocksCount = arg_get_int_def(2, 1);
bool keyB = arg_get_lit(3);
int plain = arg_get_lit(4);
uint32_t blockn = arg_get_int(5);
CLIGetHexWithReturn(6, key, &keylen);
CLIParserFree();
SetVerboseMode(verbose);
if (!keylen) {
memmove(key, DefaultKey, 16);
keylen = 16;
}
if (blockn > 255) {
PrintAndLogEx(ERR, "<Block Num> must be in range [0..255] instead of: %d", blockn);
return 1;
}
if (keylen != 16) {
PrintAndLogEx(ERR, "<Key Value> must be 16 bytes long instead of: %d", keylen);
return 1;
}
// 3 blocks - wo iso14443-4 chaining
if (blocksCount > 3) {
PrintAndLogEx(ERR, "blocks count must be less than 3 instead of: %d", blocksCount);
return 1;
}
if (blocksCount > 1 && mfIsSectorTrailer(blockn)) {
PrintAndLog("WARNING: trailer!");
}
uint8_t sectorNum = mfSectorNum(blockn & 0xff);
uint16_t uKeyNum = 0x4000 + sectorNum * 2 + (keyB ? 1 : 0);
keyn[0] = uKeyNum >> 8;
keyn[1] = uKeyNum & 0xff;
if (verbose)
PrintAndLogEx(INFO, "--block:%d sector[%d]:%02x key:%04x", blockn, mfNumBlocksPerSector(sectorNum), sectorNum, uKeyNum);
mf4Session session;
int res = MifareAuth4(&session, keyn, key, true, true, verbose);
if (res) {
PrintAndLogEx(ERR, "Authentication error: %d", res);
return res;
}
uint8_t data[250] = {0};
int datalen = 0;
uint8_t mac[8] = {0};
res = MFPReadBlock(&session, plain, blockn & 0xff, blocksCount, false, false, data, sizeof(data), &datalen, mac);
if (res) {
PrintAndLogEx(ERR, "Read error: %d", res);
return res;
}
if (datalen && data[0] != 0x90) {
PrintAndLogEx(ERR, "Card read error: %02x %s", data[0], GetErrorDescription(data[0]));
return 6;
}
if (datalen != 1 + blocksCount * 16 + 8 + 2) {
PrintAndLogEx(ERR, "Error return length:%d", datalen);
return 5;
}
int indx = blockn;
for(int i = 0; i < blocksCount; i++) {
PrintAndLogEx(INFO, "data[%03d]: %s", indx, sprint_hex(&data[1 + i * 16], 16));
indx++;
if (mfIsSectorTrailer(indx) && i != blocksCount - 1){
PrintAndLogEx(INFO, "data[%03d]: ------------------- trailer -------------------", indx);
indx++;
}
}
if (memcmp(&data[blocksCount * 16 + 1], mac, 8)) {
PrintAndLogEx(WARNING, "WARNING: mac not equal...");
PrintAndLogEx(WARNING, "MAC card: %s", sprint_hex(&data[blocksCount * 16 + 1], 8));
PrintAndLogEx(WARNING, "MAC reader: %s", sprint_hex(mac, 8));
} else {
if(verbose)
PrintAndLogEx(INFO, "MAC: %s", sprint_hex(&data[blocksCount * 16 + 1], 8));
}
return 0;
}
int CmdHFMFPRdsc(const char *cmd) {
uint8_t keyn[2] = {0};
uint8_t key[250] = {0};
int keylen = 0;
CLIParserInit("hf mfp rdsc",
"Reads one sector from Mifare Plus card.",
"Usage:\n\thf mfp rdsc 0 000102030405060708090a0b0c0d0e0f -> executes authentication and read sector 0 data\n"
"\thf mfp rdsc 1 -v -> executes authentication and shows sector 1 data with default key 0xFF..0xFF and some additional data\n");
void* argtable[] = {
arg_param_begin,
arg_lit0("vV", "verbose", "show internal data."),
arg_lit0("bB", "keyb", "use key B (by default keyA)."),
arg_lit0("pP", "plain", "plain communication mode between reader and card."),
arg_int1(NULL, NULL, "<Sector Num (0..255)>", NULL),
arg_str0(NULL, NULL, "<Key Value (HEX 16 bytes)>", NULL),
arg_param_end
};
CLIExecWithReturn(cmd, argtable, false);
bool verbose = arg_get_lit(1);
bool keyB = arg_get_lit(2);
bool plain = arg_get_lit(3);
uint32_t sectorNum = arg_get_int(4);
CLIGetHexWithReturn(5, key, &keylen);
CLIParserFree();
SetVerboseMode(verbose);
if (!keylen) {
memmove(key, DefaultKey, 16);
keylen = 16;
}
if (sectorNum > 39) {
PrintAndLogEx(ERR, "<Sector Num> must be in range [0..39] instead of: %d", sectorNum);
return 1;
}
if (keylen != 16) {
PrintAndLogEx(ERR, "<Key Value> must be 16 bytes long instead of: %d", keylen);
return 1;
}
uint16_t uKeyNum = 0x4000 + sectorNum * 2 + (keyB ? 1 : 0);
keyn[0] = uKeyNum >> 8;
keyn[1] = uKeyNum & 0xff;
if (verbose)
PrintAndLogEx(INFO, "--sector[%d]:%02x key:%04x", mfNumBlocksPerSector(sectorNum), sectorNum, uKeyNum);
mf4Session session;
int res = MifareAuth4(&session, keyn, key, true, true, verbose);
if (res) {
PrintAndLogEx(ERR, "Authentication error: %d", res);
return res;
}
uint8_t data[250] = {0};
int datalen = 0;
uint8_t mac[8] = {0};
for(int n = mfFirstBlockOfSector(sectorNum); n < mfFirstBlockOfSector(sectorNum) + mfNumBlocksPerSector(sectorNum); n++) {
res = MFPReadBlock(&session, plain, n & 0xff, 1, false, true, data, sizeof(data), &datalen, mac);
if (res) {
PrintAndLogEx(ERR, "Read error: %d", res);
DropField();
return res;
}
if (datalen && data[0] != 0x90) {
PrintAndLogEx(ERR, "Card read error: %02x %s", data[0], GetErrorDescription(data[0]));
DropField();
return 6;
}
if (datalen != 1 + 16 + 8 + 2) {
PrintAndLogEx(ERR, "Error return length:%d", datalen);
DropField();
return 5;
}
PrintAndLogEx(INFO, "data[%03d]: %s", n, sprint_hex(&data[1], 16));
if (memcmp(&data[1 + 16], mac, 8)) {
PrintAndLogEx(WARNING, "WARNING: mac on block %d not equal...", n);
PrintAndLogEx(WARNING, "MAC card: %s", sprint_hex(&data[1 + 16], 8));
PrintAndLogEx(WARNING, "MAC reader: %s", sprint_hex(mac, 8));
} else {
if(verbose)
PrintAndLogEx(INFO, "MAC: %s", sprint_hex(&data[1 + 16], 8));
}
}
DropField();
return 0;
}
int CmdHFMFPWrbl(const char *cmd) {
uint8_t keyn[2] = {0};
uint8_t key[250] = {0};
int keylen = 0;
uint8_t datain[250] = {0};
int datainlen = 0;
CLIParserInit("hf mfp wrbl",
"Writes one block to Mifare Plus card.",
"Usage:\n\thf mfp wrbl 1 ff0000000000000000000000000000ff 000102030405060708090a0b0c0d0e0f -> writes block 1 data\n"
"\thf mfp wrbl 2 ff0000000000000000000000000000ff -v -> writes block 2 data with default key 0xFF..0xFF and some additional data\n");
void* argtable[] = {
arg_param_begin,
arg_lit0("vV", "verbose", "show internal data."),
arg_lit0("bB", "keyb", "use key B (by default keyA)."),
arg_int1(NULL, NULL, "<Block Num (0..255)>", NULL),
arg_str1(NULL, NULL, "<Data (HEX 16 bytes)>", NULL),
arg_str0(NULL, NULL, "<Key (HEX 16 bytes)>", NULL),
arg_param_end
};
CLIExecWithReturn(cmd, argtable, false);
bool verbose = arg_get_lit(1);
bool keyB = arg_get_lit(2);
uint32_t blockNum = arg_get_int(3);
CLIGetHexWithReturn(4, datain, &datainlen);
CLIGetHexWithReturn(5, key, &keylen);
CLIParserFree();
SetVerboseMode(verbose);
if (!keylen) {
memmove(key, DefaultKey, 16);
keylen = 16;
}
if (blockNum > 39) {
PrintAndLogEx(ERR, "<Block Num> must be in range [0..255] instead of: %d", blockNum);
return 1;
}
if (keylen != 16) {
PrintAndLogEx(ERR, "<Key> must be 16 bytes long instead of: %d", keylen);
return 1;
}
if (datainlen != 16) {
PrintAndLogEx(ERR, "<Data> must be 16 bytes long instead of: %d", datainlen);
return 1;
}
uint8_t sectorNum = mfSectorNum(blockNum & 0xff);
uint16_t uKeyNum = 0x4000 + sectorNum * 2 + (keyB ? 1 : 0);
keyn[0] = uKeyNum >> 8;
keyn[1] = uKeyNum & 0xff;
if (verbose)
PrintAndLogEx(INFO, "--block:%d sector[%d]:%02x key:%04x", blockNum & 0xff, mfNumBlocksPerSector(sectorNum), sectorNum, uKeyNum);
mf4Session session;
int res = MifareAuth4(&session, keyn, key, true, true, verbose);
if (res) {
PrintAndLogEx(ERR, "Authentication error: %d", res);
return res;
}
uint8_t data[250] = {0};
int datalen = 0;
uint8_t mac[8] = {0};
res = MFPWriteBlock(&session, blockNum & 0xff, datain, false, false, data, sizeof(data), &datalen, mac);
if (res) {
PrintAndLogEx(ERR, "Write error: %d", res);
DropField();
return res;
}
if (datalen != 3 && (datalen != 3 + 8)) {
PrintAndLogEx(ERR, "Error return length:%d", datalen);
DropField();
return 5;
}
if (datalen && data[0] != 0x90) {
PrintAndLogEx(ERR, "Card write error: %02x %s", data[0], GetErrorDescription(data[0]));
DropField();
return 6;
}
if (memcmp(&data[1], mac, 8)) {
PrintAndLogEx(WARNING, "WARNING: mac not equal...");
PrintAndLogEx(WARNING, "MAC card: %s", sprint_hex(&data[1], 8));
PrintAndLogEx(WARNING, "MAC reader: %s", sprint_hex(mac, 8));
} else {
if(verbose)
PrintAndLogEx(INFO, "MAC: %s", sprint_hex(&data[1], 8));
}
DropField();
PrintAndLogEx(INFO, "Write OK.");
return 0;
}
static command_t CommandTable[] =
{
{"help", CmdHelp, 1, "This help"},
{"info", CmdHFMFPInfo, 0, "Info about Mifare Plus tag"},
{"wrp", CmdHFMFPWritePerso, 0, "Write Perso command"},
{"initp", CmdHFMFPInitPerso, 0, "Fills all the card's keys"},
{"commitp", CmdHFMFPCommitPerso, 0, "Move card to SL1 or SL3 mode"},
{"auth", CmdHFMFPAuth, 0, "Authentication"},
{"rdbl", CmdHFMFPRdbl, 0, "Read blocks"},
{"rdsc", CmdHFMFPRdsc, 0, "Read sectors"},
{"wrbl", CmdHFMFPWrbl, 0, "Write blocks"},
{NULL, NULL, 0, NULL}
};
int CmdHFMFP(const char *Cmd) {
(void)WaitForResponseTimeout(CMD_ACK,NULL,100);
CmdsParse(CommandTable, Cmd);
return 0;
}
int CmdHelp(const char *Cmd) {
CmdsHelp(CommandTable);
return 0;
}

18
client/cmdhfmfp.h Normal file
View file

@ -0,0 +1,18 @@
//-----------------------------------------------------------------------------
// Copyright (C) 2018 Merlok
//
// This code is licensed to you under the terms of the GNU GPL, version 2 or,
// at your option, any later version. See the LICENSE.txt file for the text of
// the license.
//-----------------------------------------------------------------------------
// High frequency MIFARE Plus commands
//-----------------------------------------------------------------------------
#ifndef CMDHFMFP_H__
#define CMDHFMFP_H__
#include "mifaredefault.h"
extern int CmdHFMFP(const char *Cmd);
#endif

View file

@ -21,8 +21,8 @@ int usage_sm_raw(void) {
PrintAndLogEx(NORMAL, " d <bytes> : bytes to send");
PrintAndLogEx(NORMAL, "");
PrintAndLogEx(NORMAL, "Examples:");
PrintAndLogEx(NORMAL, " sc raw d 00a404000e315041592e5359532e444446303100 - “1PAY.SYS.DDF01” PPSE directory");
PrintAndLogEx(NORMAL, " sc raw d 00a404000e325041592e5359532e444446303100 - “2PAY.SYS.DDF01” PPSE directory");
PrintAndLogEx(NORMAL, " sc raw d 00a404000e315041592e5359532e444446303100 - `1PAY.SYS.DDF01` PPSE directory");
PrintAndLogEx(NORMAL, " sc raw d 00a404000e325041592e5359532e444446303100 - `2PAY.SYS.DDF01` PPSE directory");
return 0;
}
int usage_sm_reader(void) {
@ -225,7 +225,6 @@ int CmdSmartRaw(const char *Cmd) {
return 2;
}
// TLV decoder
if (decodeTLV && len > 4)
TLVPrintFromBuffer(buf+1, len-3);
@ -496,7 +495,6 @@ int CmdSmartBruteforceSFI(const char *Cmd) {
char ctmp = tolower(param_getchar(Cmd, 0));
if (ctmp == 'h') return usage_sm_brute();
uint8_t data[5] = {0x00, 0xB2, 0x00, 0x00, 0x00};
PrintAndLogEx(INFO, "Selecting card");

View file

@ -107,7 +107,7 @@ static void storeCommand(UsbCommand *command) {
//If these two are equal, we're about to overwrite in the
// circular buffer.
PrintAndLogEx(FAILED, "WARNING: Command buffer about to overwrite command! This needs to be fixed!");
fflush(NULL);
fflush(stdout);
}
//Store the command at the 'head' location
UsbCommand* destination = &rxBuffer[cmd_head];
@ -185,7 +185,7 @@ static void UsbCommandReceived(UsbCommand* c) {
} else {
PrintAndLogEx(NORMAL, "#db# %s", s);
}
fflush(NULL);
fflush(stdout);
break;
}
case CMD_DEBUG_PRINT_INTEGERS: {
@ -339,7 +339,7 @@ bool OpenProxmark(void *port, bool wait_for_port, int timeout, bool flash_mode)
pthread_create(&USB_communication_thread, NULL, &uart_communication, &conn);
//pthread_create(&FPC_communication_thread, NULL, &uart_communication, &conn);
fflush(NULL);
fflush(stdout);
// create a mutex to avoid interlacing print commands from our different threads
//pthread_mutex_init(&print_lock, NULL);
return true;

View file

@ -173,7 +173,6 @@ B39AE17435DC,
#
# Data from: http://pastebin.com/gQ6nk38G
D39BB83F5297,
A27D3804C259,
85675B200017,
528C9DFFE28C,
C82EC29E3235,
@ -202,15 +201,10 @@ B0C9DD55DD4D,
A0B0C0D0E0F0,
A1B1C1D1E1F1,
#
# Data from: msk three
ae3d65a3dad4,
a73f5dc1d333,
#
# Data from: msk social
2735fc181807,
2aba9519f574,
84fd7f7a12b6,
73068f118c13,
186d8c4b93f9,
3a4bba8adaf0,
8765b17968a2,
@ -223,7 +217,6 @@ a73f5dc1d333,
bf23a53c1f63,
cb9a1f2d7368,
c7c0adb3284f,
2b7f3253fac5,
9f131d8c2057,
67362d90f973,
6202a38f69e2,
@ -335,11 +328,8 @@ a56c2df9a26d,
#
# Data from: https://pastebin.com/vbwast74
#
2031d1e57a3b,
68d3f7307c89,
9189449ea24e,
568c9083f71c,--Smart Rider. Western Australian Public Transport Cards
53c11f90822a,
# Vigik Keys
# Various sources :
# * https://github.com/DumpDos/Vigik
@ -492,10 +482,8 @@ f7a39753d018,
#
# Data from TransPert
2031d1e57a3b,
68d3f7307c89,
53c11f90822a,
9189449ea24e,
568c9083f71c,
#
# data from Github
410b9b40b872,
@ -566,61 +554,157 @@ d58023ba2bdc,-- charlie
2548a443df28,-- charlie
2ed3b15e7c0f,-- charlie
#
# Data from forum
6a1987c40a21
7f33625bc129
60012e9ba3fa,
#
60012e9ba3fa
#
de1fcbec764b
81bfbe8cacba
bff123126c9b
2f47741062a0
b4166b0a27ea
a170d9b59f95
400bc9be8976
d80511fc2ab4
1fcef3005bcf
bb467463acd6
e67c8010502d
ff58ba1b4478
de1fcbec764b,
81bfbe8cacba,
bff123126c9b,
2f47741062a0,
b4166b0a27ea,
a170d9b59f95,
400bc9be8976,
d80511fc2ab4,
1fcef3005bcf,
bb467463acd6,
e67c8010502d,
ff58ba1b4478,
# Data from https://pastebin.com/Kz8xp4ev
2aa05ed1856f
73068f118c13
2b7f3253fac5
eaac88e5dc99
ae3d65a3dad4
a73f5dc1d333
a82607b01c0d
2910989b6880
0f1c63013dba
fbf225dc5d58
fbf225dc5d58,
#
# Data https://pastebin.com/BEm6bdAE
# vingcard.txt
4708111c8604
3d50d902ea48
96a301bce267
6700f10fec09
7a09cc1db70a
560f7cff2d81
66b31e64ca4b
9e53491f685b
3a09911d860c
8a036920ac0c
361f69d2c462
d9bcde7fc489
0c03a720f208
6018522fac02
4708111c8604,
3d50d902ea48,
96a301bce267,
6700f10fec09,
7a09cc1db70a,
560f7cff2d81,
66b31e64ca4b,
9e53491f685b,
3a09911d860c,
8a036920ac0c,
361f69d2c462,
d9bcde7fc489,
0c03a720f208,
6018522fac02,
#
# Data from https://pastebin.com/4t2yFMgt
# Mifare technische Universität Graz TUG
D58660D1ACDE
50A11381502C
C01FC822C6E5
0854BF31111E
D58660D1ACDE,
50A11381502C,
C01FC822C6E5,
0854BF31111E,
# More keys:
8a19d40cf2b5
ae8587108640
8829DA9DAF76,-- Meriton Suites Syd, Aus ;). Not sure where this came from...
8a19d40cf2b5,
ae8587108640,
135b88a94b8b, SafLock standalone door locks.
#
# Russian Troika card
08B386463229,
0E8F64340BA4,
0F1C63013DBA,
2AA05ED1856F,
2B7F3253FAC5,
69A32F1C2F19,
73068F118C13,
9BECDF3D9273,
A73F5DC1D333,
A82607B01C0D,
AE3D65A3DAD4,
CD4C61C26E3D,
D3EAFB5DF46D,
E35173494A81,
FBC2793D540B,
5125974CD391,
ECF751084A80,
7545DF809202,
AB16584C972A,
7A38E3511A38,
C8454C154CB5,
04C297B91308,
EFCB0E689DB3,
07894FFEC1D6,
FBA88F109B32,
2FE3CB83EA43,
B90DE525CEB6,
1CC219E9FEC1,
A74332F74994,
764CD061F1E6,
8F79C4FD8A01,
CD64E567ABCD,
CE26ECB95252,
ABA208516740,
9868925175BA,
16A27AF45407,
372CC880F216,
3EBCE0925B2F,
73E5B9D9D3A4,
0DB520C78C1C,
70D901648CB9,
C11F4597EFB5,
B39D19A280DF,
403D706BA880,
7038CD25C408,
6B02733BB6EC,
EAAC88E5DC99,
4ACEC1205D75,
2910989B6880,
31C7610DE3B0,
5EFBAECEF46B,
F8493407799D,
6B8BD9860763,
D3A297DC2698,
#
# Keys from MifareClassicTool project
044CE1872BC3,
045CECA15535,
0BE5FAC8B06A,
0CE7CD2CC72B,
0EB23CC8110B,
0F01CEFF2742,
0F318130ED18,
114D6BE9440C,
18E3A02B5EFF,
19FC84A3784B,
1B61B2E78C75,
22052B480D11,
3367BFAA91DB,
3A8A139C20B4,
42E9B54E51AB,
46D78E850A7E,
4B609876BBA3,
518DC6EEA089,
6B07877E2C5C,
7259FA0197C6,
72F96BDD3714,
7413B599C4EA,
77DABC9825E1,
7A396F0D633D,
7A86AA203788,
8791B2CCB5C4,
8A8D88151A00,
8C97CD7A0E56,
8E26E45E7D65,
9D993C5D4EF4,
9EA3387A63C1,
A3FAA6DAFF67,
A7141147D430,
AAFB06045877,
ACFFFFFFFFFF,
AFCEF64C9913,
B27ADDFB64B0,
B81F2B0C2F66,
B9F8A7D83978,
BAFF3053B496,
BB52F8CCE07F,
BC2D1791DEC1,
BC4580B7F20B,
C65D4EAA645B,
C76BF71A2509,
D5524F591EED,
E328A1C7156D,
E4821A377B75,
E56AC127DD45,
EA0FD73CB149,
FC0001877BF7,
FD8705E721B0,

View file

@ -2,6 +2,7 @@
# ref. http://www.proxmark.org/forum/viewtopic.php?id=2022
51243648,
000D8787,
19920427,
# ref. http://kazus.ru/forums/showpost.php?p=1045937&postcount=77
05D73B9F,
# ref. http://www.proxmark.org/forum/viewtopic.php?=

58
client/emv/defparams.json Normal file
View file

@ -0,0 +1,58 @@
[
{
"name": "Transaction Date",
"tag": "9A",
"value": "00 00 00",
"length": 3,
"hint": "format: YYMMDD"
},
{
"name": "Transaction Type",
"tag": "9C",
"value": "00",
"length": 1,
"hint": "00: Goods and service, 01: Cash"
},
{
"name": "Amount, authorized",
"tag": "9F 02",
"value": "00 00 00 00 01 00",
"length": 6,
"hint": "amount (numberic) in cents"
},
{
"name": "Transaction Currency Code",
"tag": "5F 2A",
"value": "09 80",
"length": 2,
"hint": "USD 840, EUR 978, RUB 643, RUR 810(old), UAH 980, AZN 031, n/a 999"
},
{
"name": "Terminal Country Code",
"tag": "9F 1A",
"value": "72 75",
"length": 2,
"hint": "ISO3166: de, en (65 6e), uk(75 6b), ru (72 75), us, ua"
},
{
"name": "Terminal Transaction Qualifiers (TTQ)",
"tag": "9F 66",
"value": "26 00 00 00",
"length": 4,
"hint": "qVSDC 26 00 00 00, gen AC from GPO 26 80 00 00, MSD 86 00 00 00, VSDC 46 00 00 00"
},
{
"name": "Unpredictable Number",
"tag": "9F 37",
"value": "01 02 03 04",
"length": 4,
"hint": "4 byte random number"
},
{
"name": "Unpredictable Number (MSD for UDOL)",
"tag": "9F 6A",
"value": "01 02 03 05",
"length": 4,
"hint": "4 byte random number"
}
]

View file

@ -353,15 +353,13 @@ static void emv_tag_dump_dol(const struct tlv *tlv, const struct emv_tag *tag, F
}
}
static void emv_tag_dump_string(const struct tlv *tlv, const struct emv_tag *tag, FILE *f, int level)
{
static void emv_tag_dump_string(const struct tlv *tlv, const struct emv_tag *tag, FILE *f, int level){
fprintf(f, "\tString value '");
fwrite(tlv->value, 1, tlv->len, f);
fprintf(f, "'\n");
}
static unsigned long emv_value_numeric(const struct tlv *tlv, unsigned start, unsigned end)
{
static unsigned long emv_value_numeric(const struct tlv *tlv, unsigned start, unsigned end) {
unsigned long ret = 0;
int i;
@ -391,14 +389,12 @@ static unsigned long emv_value_numeric(const struct tlv *tlv, unsigned start, un
return ret;
}
static void emv_tag_dump_numeric(const struct tlv *tlv, const struct emv_tag *tag, FILE *f, int level)
{
static void emv_tag_dump_numeric(const struct tlv *tlv, const struct emv_tag *tag, FILE *f, int level) {
PRINT_INDENT(level);
fprintf(f, "\tNumeric value %lu\n", emv_value_numeric(tlv, 0, tlv->len * 2));
fprintf(f, "\tNumeric value %" PRIu32 " \n", emv_value_numeric(tlv, 0, tlv->len * 2));
}
static void emv_tag_dump_yymmdd(const struct tlv *tlv, const struct emv_tag *tag, FILE *f, int level)
{
static void emv_tag_dump_yymmdd(const struct tlv *tlv, const struct emv_tag *tag, FILE *f, int level) {
PRINT_INDENT(level);
fprintf(f, "\tDate: 20%02ld.%ld.%ld\n",
emv_value_numeric(tlv, 0, 2),
@ -406,8 +402,7 @@ static void emv_tag_dump_yymmdd(const struct tlv *tlv, const struct emv_tag *tag
emv_value_numeric(tlv, 4, 6));
}
static uint32_t emv_get_binary(const unsigned char *S)
{
static uint32_t emv_get_binary(const unsigned char *S) {
return (S[0] << 24) | (S[1] << 16) | (S[2] << 8) | (S[3] << 0);
}

View file

@ -18,6 +18,7 @@
#include "tlv.h"
#include <stdio.h>
#include <inttypes.h>
// AC
# define EMVAC_AC_MASK 0xC0

View file

@ -14,6 +14,7 @@
#include "bignum.h"
#include "aes.h"
#include "aes_cmac128.h"
#include "des.h"
#include "rsa.h"
#include "sha1.h"
@ -33,6 +34,9 @@ int ExecuteCryptoTests(bool verbose) {
res = aes_self_test(verbose);
if (res) TestFail = true;
res = aes_cmac_self_test(verbose);
if (res) TestFail = true;
res = des_self_test(verbose);
if (res) TestFail = true;

View file

@ -548,44 +548,105 @@ out:
crack_states_bitsliced_t *crack_states_bitsliced_function_p = &crack_states_bitsliced_dispatch;
bitslice_test_nonces_t *bitslice_test_nonces_function_p = &bitslice_test_nonces_dispatch;
// determine the available instruction set at runtime and call the correct function
const uint64_t crack_states_bitsliced_dispatch(uint32_t cuid, uint8_t *best_first_bytes, statelist_t *p, uint32_t *keys_found, uint64_t *num_keys_tested, uint32_t nonces_to_bruteforce, uint8_t *bf_test_nonce_2nd_byte, noncelist_t *nonces) {
static SIMDExecInstr intSIMDInstr = SIMD_AUTO;
void SetSIMDInstr(SIMDExecInstr instr) {
intSIMDInstr = instr;
crack_states_bitsliced_function_p = &crack_states_bitsliced_dispatch;
bitslice_test_nonces_function_p = &bitslice_test_nonces_dispatch;
}
SIMDExecInstr GetSIMDInstr() {
SIMDExecInstr instr = SIMD_NONE;
#if defined (__i386__) || defined (__x86_64__)
#if !defined(__APPLE__) || (defined(__APPLE__) && (__clang_major__ > 8 || __clang_major__ == 8 && __clang_minor__ >= 1))
#if !defined(__APPLE__) || (defined(__APPLE__) && (__clang_major__ > 8 || __clang_major__ == 8 && __clang_minor__ >= 1))
#if (__GNUC__ >= 5) && (__GNUC__ > 5 || __GNUC_MINOR__ > 2)
if (__builtin_cpu_supports("avx512f")) crack_states_bitsliced_function_p = &crack_states_bitsliced_AVX512;
else if (__builtin_cpu_supports("avx2")) crack_states_bitsliced_function_p = &crack_states_bitsliced_AVX2;
if (__builtin_cpu_supports("avx512f")) instr = SIMD_AVX512;
else if (__builtin_cpu_supports("avx2")) instr = SIMD_AVX2;
#else
if (__builtin_cpu_supports("avx2")) crack_states_bitsliced_function_p = &crack_states_bitsliced_AVX2;
if (__builtin_cpu_supports("avx2")) instr = SIMD_AVX2;
#endif
else if (__builtin_cpu_supports("avx")) crack_states_bitsliced_function_p = &crack_states_bitsliced_AVX;
else if (__builtin_cpu_supports("sse2")) crack_states_bitsliced_function_p = &crack_states_bitsliced_SSE2;
else if (__builtin_cpu_supports("mmx")) crack_states_bitsliced_function_p = &crack_states_bitsliced_MMX;
else if (__builtin_cpu_supports("avx")) instr = SIMD_AVX;
else if (__builtin_cpu_supports("sse2")) instr = SIMD_SSE2;
else if (__builtin_cpu_supports("mmx")) instr = SIMD_MMX;
else
#endif
#endif
instr = SIMD_NONE;
return instr;
}
SIMDExecInstr GetSIMDInstrAuto() {
SIMDExecInstr instr = intSIMDInstr;
if (instr == SIMD_AUTO)
return GetSIMDInstr();
return instr;
}
// determine the available instruction set at runtime and call the correct function
const uint64_t crack_states_bitsliced_dispatch(uint32_t cuid, uint8_t *best_first_bytes, statelist_t *p, uint32_t *keys_found, uint64_t *num_keys_tested, uint32_t nonces_to_bruteforce, uint8_t *bf_test_nonce_2nd_byte, noncelist_t *nonces) {
switch(GetSIMDInstrAuto()) {
#if defined (__i386__) || defined (__x86_64__)
#if !defined(__APPLE__) || (defined(__APPLE__) && (__clang_major__ > 8 || __clang_major__ == 8 && __clang_minor__ >= 1))
#if (__GNUC__ >= 5) && (__GNUC__ > 5 || __GNUC_MINOR__ > 2)
case SIMD_AVX512:
crack_states_bitsliced_function_p = &crack_states_bitsliced_AVX512;
break;
#endif
case SIMD_AVX2:
crack_states_bitsliced_function_p = &crack_states_bitsliced_AVX2;
break;
case SIMD_AVX:
crack_states_bitsliced_function_p = &crack_states_bitsliced_AVX;
break;
case SIMD_SSE2:
crack_states_bitsliced_function_p = &crack_states_bitsliced_SSE2;
break;
case SIMD_MMX:
crack_states_bitsliced_function_p = &crack_states_bitsliced_MMX;
break;
#endif
#endif
default:
crack_states_bitsliced_function_p = &crack_states_bitsliced_NOSIMD;
break;
}
// call the most optimized function for this CPU
return (*crack_states_bitsliced_function_p)(cuid, best_first_bytes, p, keys_found, num_keys_tested, nonces_to_bruteforce, bf_test_nonce_2nd_byte, nonces);
}
void bitslice_test_nonces_dispatch(uint32_t nonces_to_bruteforce, uint32_t *bf_test_nonce, uint8_t *bf_test_nonce_par) {
switch(GetSIMDInstrAuto()) {
#if defined (__i386__) || defined (__x86_64__)
#if !defined(__APPLE__) || (defined(__APPLE__) && (__clang_major__ > 8 || __clang_major__ == 8 && __clang_minor__ >= 1))
#if (__GNUC__ >= 5) && (__GNUC__ > 5 || __GNUC_MINOR__ > 2)
if (__builtin_cpu_supports("avx512f")) bitslice_test_nonces_function_p = &bitslice_test_nonces_AVX512;
else if (__builtin_cpu_supports("avx2")) bitslice_test_nonces_function_p = &bitslice_test_nonces_AVX2;
#else
if (__builtin_cpu_supports("avx2")) bitslice_test_nonces_function_p = &bitslice_test_nonces_AVX2;
case SIMD_AVX512:
bitslice_test_nonces_function_p = &bitslice_test_nonces_AVX512;
break;
#endif
else if (__builtin_cpu_supports("avx")) bitslice_test_nonces_function_p = &bitslice_test_nonces_AVX;
else if (__builtin_cpu_supports("sse2")) bitslice_test_nonces_function_p = &bitslice_test_nonces_SSE2;
else if (__builtin_cpu_supports("mmx")) bitslice_test_nonces_function_p = &bitslice_test_nonces_MMX;
else
case SIMD_AVX2:
bitslice_test_nonces_function_p = &bitslice_test_nonces_AVX2;
break;
case SIMD_AVX:
bitslice_test_nonces_function_p = &bitslice_test_nonces_AVX;
break;
case SIMD_SSE2:
bitslice_test_nonces_function_p = &bitslice_test_nonces_SSE2;
break;
case SIMD_MMX:
bitslice_test_nonces_function_p = &bitslice_test_nonces_MMX;
break;
#endif
#endif
default:
bitslice_test_nonces_function_p = &bitslice_test_nonces_NOSIMD;
break;
}
// call the most optimized function for this CPU
(*bitslice_test_nonces_function_p)(nonces_to_bruteforce, bf_test_nonce, bf_test_nonce_par);

View file

@ -52,6 +52,18 @@ THE SOFTWARE.
#include "hardnested_bruteforce.h" // statelist_t
typedef enum {
SIMD_AUTO,
SIMD_AVX512,
SIMD_AVX2,
SIMD_AVX,
SIMD_SSE2,
SIMD_MMX,
SIMD_NONE,
} SIMDExecInstr;
extern void SetSIMDInstr(SIMDExecInstr instr);
extern SIMDExecInstr GetSIMDInstrAuto();
extern const uint64_t crack_states_bitsliced(uint32_t cuid, uint8_t *best_first_bytes, statelist_t *p, uint32_t *keys_found, uint64_t *num_keys_tested, uint32_t nonces_to_bruteforce, uint8_t *bf_test_nonces_2nd_byte, noncelist_t *nonces);
extern void bitslice_test_nonces(uint32_t nonces_to_bruteforce, uint32_t *bf_test_nonces, uint8_t *bf_test_nonce_par);

265
client/mifare4.c Normal file
View file

@ -0,0 +1,265 @@
//-----------------------------------------------------------------------------
// Copyright (C) 2018 Merlok
// Copyright (C) 2018 drHatson
//
// This code is licensed to you under the terms of the GNU GPL, version 2 or,
// at your option, any later version. See the LICENSE.txt file for the text of
// the license.
//-----------------------------------------------------------------------------
// iso14443-4 mifare commands
//-----------------------------------------------------------------------------
#include "mifare4.h"
#include <ctype.h>
#include <string.h>
#include "cmdhf14a.h"
#include "util.h"
#include "ui.h"
#include "polarssl/libpcrypto.h"
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);
}
int MifareAuth4(mf4Session *session, uint8_t *keyn, uint8_t *key, bool activateField, bool leaveSignalON, bool verbose) {
uint8_t data[257] = {0};
int datalen = 0;
uint8_t RndA[17] = {0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x00};
uint8_t RndB[17] = {0};
if (session)
session->Authenticated = false;
uint8_t cmd1[] = {0x70, keyn[1], keyn[0], 0x00};
int res = ExchangeRAW14a(cmd1, sizeof(cmd1), activateField, true, data, sizeof(data), &datalen);
if (res) {
PrintAndLogEx(ERR, "Exchande raw error: %d", res);
DropField();
return 2;
}
if (verbose)
PrintAndLogEx(INFO, "<phase1: %s", sprint_hex(data, datalen));
if (datalen < 1) {
PrintAndLogEx(ERR, "Card response wrong length: %d", datalen);
DropField();
return 3;
}
if (data[0] != 0x90) {
PrintAndLogEx(ERR, "Card response error: %02x", data[2]);
DropField();
return 3;
}
if (datalen != 19) { // code 1b + 16b + crc 2b
PrintAndLogEx(ERR, "Card response must be 19 bytes long instead of: %d", datalen);
DropField();
return 3;
}
aes_decode(NULL, key, &data[1], RndB, 16);
RndB[16] = RndB[0];
if (verbose)
PrintAndLogEx(INFO, "RndB: %s", sprint_hex(RndB, 16));
uint8_t cmd2[33] = {0};
cmd2[0] = 0x72;
uint8_t raw[32] = {0};
memmove(raw, RndA, 16);
memmove(&raw[16], &RndB[1], 16);
aes_encode(NULL, key, raw, &cmd2[1], 32);
if (verbose)
PrintAndLogEx(INFO, ">phase2: %s", sprint_hex(cmd2, 33));
res = ExchangeRAW14a(cmd2, sizeof(cmd2), false, true, data, sizeof(data), &datalen);
if (res) {
PrintAndLogEx(ERR, "Exchande raw error: %d", res);
DropField();
return 4;
}
if (verbose)
PrintAndLogEx(INFO, "<phase2: %s", sprint_hex(data, datalen));
aes_decode(NULL, key, &data[1], raw, 32);
if (verbose) {
PrintAndLogEx(INFO, "res: %s", sprint_hex(raw, 32));
PrintAndLogEx(INFO, "RndA`: %s", sprint_hex(&raw[4], 16));
}
if (memcmp(&raw[4], &RndA[1], 16)) {
PrintAndLogEx(ERR, "\nAuthentication FAILED. rnd not equal");
if (verbose) {
PrintAndLogEx(ERR, "RndA reader: %s", sprint_hex(&RndA[1], 16));
PrintAndLogEx(ERR, "RndA card: %s", sprint_hex(&raw[4], 16));
}
DropField();
return 5;
}
if (verbose) {
PrintAndLogEx(INFO, " TI: %s", sprint_hex(raw, 4));
PrintAndLogEx(INFO, "pic: %s", sprint_hex(&raw[20], 6));
PrintAndLogEx(INFO, "pcd: %s", sprint_hex(&raw[26], 6));
}
uint8_t kenc[16] = {0};
memcpy(&kenc[0], &RndA[11], 5);
memcpy(&kenc[5], &RndB[11], 5);
for(int i = 0; i < 5; i++)
kenc[10 + i] = RndA[4 + i] ^ RndB[4 + i];
kenc[15] = 0x11;
aes_encode(NULL, key, kenc, kenc, 16);
if (verbose) {
PrintAndLogEx(INFO, "kenc: %s", sprint_hex(kenc, 16));
}
uint8_t kmac[16] = {0};
memcpy(&kmac[0], &RndA[7], 5);
memcpy(&kmac[5], &RndB[7], 5);
for(int i = 0; i < 5; i++)
kmac[10 + i] = RndA[0 + i] ^ RndB[0 + i];
kmac[15] = 0x22;
aes_encode(NULL, key, kmac, kmac, 16);
if (verbose) {
PrintAndLogEx(INFO, "kmac: %s", sprint_hex(kmac, 16));
}
if (!leaveSignalON)
DropField();
if (verbose)
PrintAndLog("");
if (session) {
session->Authenticated = true;
session->R_Ctr = 0;
session->W_Ctr = 0;
session->KeyNum = keyn[1] + (keyn[0] << 8);
memmove(session->RndA, RndA, 16);
memmove(session->RndB, RndB, 16);
memmove(session->Key, key, 16);
memmove(session->TI, raw, 4);
memmove(session->PICCap2, &raw[20], 6);
memmove(session->PCDCap2, &raw[26], 6);
memmove(session->Kenc, kenc, 16);
memmove(session->Kmac, kmac, 16);
}
PrintAndLogEx(INFO, "Authentication OK");
return 0;
}
// Mifare Memory Structure: up to 32 Sectors with 4 blocks each (1k and 2k cards),
// plus evtl. 8 sectors with 16 blocks each (4k cards)
uint8_t mfNumBlocksPerSector(uint8_t sectorNo) {
if (sectorNo < 32)
return 4;
else
return 16;
}
uint8_t mfFirstBlockOfSector(uint8_t sectorNo) {
if (sectorNo < 32)
return sectorNo * 4;
else
return 32 * 4 + (sectorNo - 32) * 16;
}
uint8_t mfSectorTrailer(uint8_t blockNo) {
if (blockNo < 32*4) {
return (blockNo | 0x03);
} else {
return (blockNo | 0x0f);
}
}
bool mfIsSectorTrailer(uint8_t blockNo) {
return (blockNo == mfSectorTrailer(blockNo));
}
uint8_t mfSectorNum(uint8_t blockNo) {
if (blockNo < 32 * 4)
return blockNo / 4;
else
return 32 + (blockNo - 32 * 4) / 16;
}

51
client/mifare4.h Normal file
View file

@ -0,0 +1,51 @@
//-----------------------------------------------------------------------------
// Copyright (C) 2018 Merlok
// Copyright (C) 2018 drHatson
//
// This code is licensed to you under the terms of the GNU GPL, version 2 or,
// at your option, any later version. See the LICENSE.txt file for the text of
// the license.
//-----------------------------------------------------------------------------
// iso14443-4 mifare commands
//-----------------------------------------------------------------------------
#ifndef MIFARE4_H
#define MIFARE4_H
#include <stdint.h>
#include <stdbool.h>
#include <stddef.h>
typedef struct {
bool Authenticated;
uint8_t Key[16];
uint16_t KeyNum;
uint8_t RndA[16];
uint8_t RndB[16];
uint8_t TI[4];
uint8_t PICCap2[6];
uint8_t PCDCap2[6];
uint8_t Kenc[16];
uint8_t Kmac[16];
uint16_t R_Ctr;
uint16_t W_Ctr;
}mf4Session;
typedef enum {
mtypReadCmd,
mtypReadResp,
mtypWriteCmd,
mtypWriteResp,
} MACType_t;
extern int CalculateMAC(mf4Session *session, MACType_t mtype, uint8_t blockNum, uint8_t blockCount, uint8_t *data, int datalen, uint8_t *mac, bool verbose);
extern int MifareAuth4(mf4Session *session, uint8_t *keyn, uint8_t *key, bool activateField, bool leaveSignalON, bool verbose);
extern uint8_t mfNumBlocksPerSector(uint8_t sectorNo);
extern uint8_t mfFirstBlockOfSector(uint8_t sectorNo);
extern uint8_t mfSectorTrailer(uint8_t blockNo);
extern bool mfIsSectorTrailer(uint8_t blockNo);
extern uint8_t mfSectorNum(uint8_t blockNo);
#endif // mifare4.h

View file

@ -40,7 +40,7 @@ static void showBanner(void){
printf("\nKeep iceman fork alive with a donation! https://paypal.me/iceman1001/");
printf("\nMONERO: 43mNJLpgBVaTvyZmX9ajcohpvVkaRy1kbZPm8tqAb7itZgfuYecgkRF36rXrKFUkwEGeZedPsASRxgv4HPBHvJwyJdyvQuP");
printf("\n\n\n");
fflush(NULL);
fflush(stdout);
}
#endif
@ -260,6 +260,10 @@ int main(int argc, char* argv[]) {
/* initialize history */
using_history();
#ifdef RL_STATE_READCMD
rl_extend_line_buffer(1024);
#endif
if (argc < 2) {
show_help(true, argv[0]);
@ -282,23 +286,23 @@ int main(int argc, char* argv[]) {
}
// flush output
if(strcmp(argv[i], "-f") == 0 || strcmp(argv[i], "-flush") == 0){
if (strcmp(argv[i], "-f") == 0 || strcmp(argv[i], "-flush") == 0){
SetFlushAfterWrite(true);
PrintAndLogEx(INFO, "Output will be flushed after every print.\n");
}
// wait for comport
if(strcmp(argv[i], "-w") == 0 || strcmp(argv[i], "-wait") == 0){
if (strcmp(argv[i], "-w") == 0 || strcmp(argv[i], "-wait") == 0){
waitCOMPort = true;
}
// execute pm3 command
if(strcmp(argv[i], "-c") == 0 || strcmp(argv[i], "-command") == 0){
if (strcmp(argv[i], "-c") == 0 || strcmp(argv[i], "-command") == 0){
executeCommand = true;
}
// execute lua script
if(strcmp(argv[i], "-l") == 0 || strcmp(argv[i], "-lua") == 0){
if (strcmp(argv[i], "-l") == 0 || strcmp(argv[i], "-lua") == 0){
executeCommand = true;
addLuaExec = true;
}

View file

@ -63,9 +63,10 @@ int scandir (const char *dir,
if (err_no != 0) {
closedir (dirp);
if (nl) {
while (count > 0)
while (count > 0) {
free (nl[--count]);
free (nl);
}
free (nl);
}
return -1;
}

View file

@ -55,20 +55,19 @@ static int l_SendCommand(lua_State *L){
*/
static int l_GetFromBigBuf(lua_State *L){
int len = 0;
int startindex = 0;
int len = 0, startindex = 0;
//Check number of arguments
int n = lua_gettop(L);
if(n == 0) {
if (n == 0) {
//signal error by returning Nil, errorstring
lua_pushnil(L);
lua_pushstring(L,"You need to supply number of len and startindex");
lua_pushstring(L, "You need to supply number of bytes and startindex");
return 2; // two return values
}
if(n >= 2) {
len = luaL_checknumber(L, 1);
startindex = luaL_checknumber(L, 2);
if (n >= 2) {
startindex = luaL_checknumber(L, 1);
len = luaL_checknumber(L, 2);
}
uint8_t *data = calloc(len, sizeof(uint8_t));
@ -78,11 +77,11 @@ static int l_GetFromBigBuf(lua_State *L){
lua_pushstring(L,"Allocating memory failed");
return 2; // two return values
}
if ( !GetFromDevice(BIG_BUF, data, len, startindex, NULL, 2500, false)) {
free(data);
lua_pushnil(L);
lua_pushstring(L,"command execution time out");
lua_pushstring(L, "command execution time out");
return 2;
}
@ -91,6 +90,56 @@ static int l_GetFromBigBuf(lua_State *L){
free(data);
return 1;// return 1 to signal one return value
}
/**
* @brief The following params expected:
* uint8_t *dest
* int bytes
* int start_index
* @param L
* @return
*/
static int l_GetFromFlashMem(lua_State *L){
#ifndef WITH_FLASH
lua_pushnil(L);
lua_pushstring(L, "Not compiled with FLASH MEM support");
return 2;
#else
int len = 0, startindex = 0;
int n = lua_gettop(L);
if (n == 0) {
lua_pushnil(L);
lua_pushstring(L, "You need to supply number of bytes and startindex");
return 2;
}
if (n >= 2) {
startindex = luaL_checknumber(L, 1);
len = luaL_checknumber(L, 2);
}
uint8_t *data = calloc(len, sizeof(uint8_t));
if ( !data ) {
lua_pushnil(L);
lua_pushstring(L, "Allocating memory failed");
return 2;
}
if ( !GetFromDevice(FLASH_MEM, data, len, startindex, NULL, -1, false)) {
free(data);
lua_pushnil(L);
lua_pushstring(L, "command execution time out");
return 2;
}
lua_pushlstring(L,(const char *)data, len);
free(data);
return 1;
#endif
}
/**
* @brief The following params expected:
* uint32_t cmd
@ -655,6 +704,7 @@ int set_pm3_libraries(lua_State *L) {
static const luaL_Reg libs[] = {
{"SendCommand", l_SendCommand},
{"GetFromBigBuf", l_GetFromBigBuf},
{"GetFromFlashMem", l_GetFromFlashMem},
{"WaitForResponseTimeout", l_WaitForResponseTimeout},
{"mfDarkside", l_mfDarkside},
{"foobar", l_foobar},

View file

@ -25,23 +25,20 @@ void PrintAndLogOptions(char *str[][2], size_t size, size_t space) {
char buff[2000] = "Options:\n";
char format[2000] = "";
size_t counts[2] = {0, 0};
for(int i = 0; i < size; i++)
for(int j = 0 ; j < 2 ; j++)
if(counts[j] < strlen(str[i][j]))
{
for (int i = 0; i < size; i++)
for (int j = 0 ; j < 2 ; j++)
if (counts[j] < strlen(str[i][j])) {
counts[j] = strlen(str[i][j]);
}
for(int i = 0; i < size; i++)
{
for(int j = 0; j < 2; j++)
{
if(j == 0)
for (int i = 0; i < size; i++) {
for (int j = 0; j < 2; j++) {
if (j == 0)
snprintf(format, sizeof(format), "%%%zus%%%zus", space, counts[j]);
else
snprintf(format, sizeof(format), "%%%zus%%-%zus", space, counts[j]);
snprintf(buff + strlen(buff), sizeof(buff) - strlen(buff), format, " ", str[i][j]);
}
if(i<size-1)
if (i < size-1)
strncat(buff, "\n", sizeof(buff)-strlen(buff) -1);
}
PrintAndLogEx(NORMAL, buff);
@ -178,7 +175,7 @@ void PrintAndLog(char *fmt, ...) {
va_end(argptr2);
if (flushAfterWrite)
fflush(NULL);
fflush(stdout);
//release lock
pthread_mutex_unlock(&print_lock);

View file

@ -320,14 +320,14 @@ size_t findModStart(uint8_t *src, size_t size, uint8_t expWaveSize) {
size_t i = 0;
size_t waveSizeCnt = 0;
uint8_t thresholdCnt = 0;
bool isAboveThreshold = src[i++] >= FSK_PSK_THRESHOLD;
bool isAboveThreshold = src[i++] >= signalprop.mean; //FSK_PSK_THRESHOLD;
for (; i < size-20; i++ ) {
if(src[i] < FSK_PSK_THRESHOLD && isAboveThreshold) {
if(src[i] < signalprop.mean && isAboveThreshold) {
thresholdCnt++;
if (thresholdCnt > 2 && waveSizeCnt < expWaveSize+1) break;
isAboveThreshold = false;
waveSizeCnt = 0;
} else if (src[i] >= FSK_PSK_THRESHOLD && !isAboveThreshold) {
} else if (src[i] >= signalprop.mean && !isAboveThreshold) {
thresholdCnt++;
if (thresholdCnt > 2 && waveSizeCnt < expWaveSize+1) break;
isAboveThreshold = true;
@ -337,15 +337,24 @@ size_t findModStart(uint8_t *src, size_t size, uint8_t expWaveSize) {
}
if (thresholdCnt > 10) break;
}
if (g_debugMode == 2) prnt("DEBUG: threshold Count reached at %u, count: %u", i, thresholdCnt);
if (g_debugMode == 2) prnt("DEBUG: threshold Count reached at index %u, count: %u", i, thresholdCnt);
return i;
}
// iceman: ranges the old defintion, becomes very forgiving when clock speed increase.
// clocks[i] - (clocks[i]/8) && testclk <= clocks[i]+1 )
// 8 (7-9)
// 16 (14-17)
// 32 (28-33)
// 40 (35-41)
// 50 (46-51)
// 64 (56-65)
// 128 (112-129)
int getClosestClock(int testclk) {
uint8_t clocks[] = {8,16,32,40,50,64,128};
for (uint8_t i = 0; i < 7; i++)
if ( testclk >= clocks[i] - (clocks[i]/8) && testclk <= clocks[i]+1 )
if ( testclk >= clocks[i]-2 && testclk <= clocks[i]+1 )
return clocks[i];
return 0;
@ -474,7 +483,7 @@ int ManchesterEncode(uint8_t *bits, size_t size) {
// by marshmellow
// to detect a wave that has heavily clipped (clean) samples
// loop 512 samples, if 300 of them is deemed maxed out, we assume the wave is clipped.
// loop 512 samples, if 250 of them is deemed maxed out, we assume the wave is clipped.
bool DetectCleanAskWave(uint8_t *dest, size_t size, uint8_t high, uint8_t low) {
bool allArePeaks = true;
uint16_t cntPeaks = 0;
@ -516,8 +525,8 @@ int DetectStrongAskClock(uint8_t *dest, size_t size, int high, int low, int *clo
getNextHigh(dest, size, high, &i);
getNextLow(dest, size, low, &i);
// loop through all samples
while (i < size) {
// loop through all samples (well, we don't want to go out-of-bounds)
while (i < size-512) {
// measure from low to low
startwave = i;
@ -562,36 +571,35 @@ int DetectASKClock(uint8_t *dest, size_t size, int *clock, int maxErr) {
// just noise - no super good detection. good enough
if (signalprop.isnoise) {
if (g_debugMode == 2) prnt("DEBUG DetectASKClock: just noise detected - quitting");
if (g_debugMode == 2) prnt("DEBUG DetectASKClock: just noise detected - aborting");
return -1;
}
//get high and low peak
int peak_hi, peak_low;
//getHiLo(dest, loopCnt, &peak_hi, &peak_low, 75, 75);
getHiLo(&peak_hi, &peak_low, 75, 75);
//test for large clean peaks
if (!clockFnd){
if (DetectCleanAskWave(dest, size, peak_hi, peak_low)){
int ans = DetectStrongAskClock(dest, size, peak_hi, peak_low, clock);
if (g_debugMode == 2) prnt("DEBUG ASK: detectaskclk Clean Ask Wave Detected: clk %i, ShortestWave: %i", *clock ,ans);
if (ans > 0){
return ans; //return shortest wave start position
}
int idx = DetectStrongAskClock(dest, size, peak_hi, peak_low, clock);
if (g_debugMode == 2)
prnt("DEBUG ASK: detectaskclk Clean Ask Wave Detected: clk %i, Best Starting Position: %i", *clock, idx);
if (idx > 0)
return idx; //return shortest wave start position
}
}
// test clock if given as cmd parameter
if ( *clock > 0 )
clk[0] = *clock;
uint16_t ii;
uint8_t clkCnt, tol = 0;
size_t j = 0;
uint16_t bestErr[] = {1000,1000,1000,1000,1000,1000,1000,1000,1000};
uint8_t bestStart[] = {0,0,0,0,0,0,0,0,0};
size_t errCnt = 0;
size_t arrLoc, loopEnd;
size_t errCnt = 0, arrLoc, loopEnd;
if (clockFnd > 0) {
clkCnt = clockFnd;
@ -614,14 +622,17 @@ int DetectASKClock(uint8_t *dest, size_t size, int *clock, int maxErr) {
bestErr[clkCnt] = 1000;
//try lining up the peaks by moving starting point (try first few clocks)
for (ii=0; ii < loopCnt; ii++){
if (dest[ii] < peak_hi && dest[ii] > peak_low) continue;
// get to first full low to prime loop and skip incomplete first pulse
getNextHigh(dest, size, peak_hi, &j);
getNextLow(dest, size, peak_low, &j);
for (; j < loopCnt; j++){
errCnt = 0;
// now that we have the first one lined up test rest of wave array
loopEnd = ((size-ii-tol) / clk[clkCnt]) - 1;
loopEnd = ((size-j-tol) / clk[clkCnt]) - 1;
for (i=0; i < loopEnd; ++i){
arrLoc = ii + (i * clk[clkCnt]);
arrLoc = j + (i * clk[clkCnt]);
if (dest[arrLoc] >= peak_hi || dest[arrLoc] <= peak_low){
} else if (dest[arrLoc-tol] >= peak_hi || dest[arrLoc-tol] <= peak_low){
} else if (dest[arrLoc+tol] >= peak_hi || dest[arrLoc+tol] <= peak_low){
@ -631,21 +642,22 @@ int DetectASKClock(uint8_t *dest, size_t size, int *clock, int maxErr) {
}
//if we found no errors then we can stop here and a low clock (common clocks)
// this is correct one - return this clock
//if (g_debugMode == 2) prnt("DEBUG ASK: clk %d, err %d, startpos %d, endpos %d", clk[clkCnt], errCnt, ii, i);
//if (g_debugMode == 2) prnt("DEBUG ASK: clk %d, err %d, startpos %d, endpos %d", clk[clkCnt], errCnt, j, i);
if (errCnt == 0 && clkCnt < 7) {
if (!clockFnd)
*clock = clk[clkCnt];
return ii;
return j;
}
//if we found errors see if it is lowest so far and save it as best run
if (errCnt < bestErr[clkCnt]) {
bestErr[clkCnt] = errCnt;
bestStart[clkCnt] = ii;
bestStart[clkCnt] = j;
}
}
}
uint8_t k;
uint8_t best = 0;
uint8_t k, best = 0;
for (k=1; k < clkEnd; ++k){
if (bestErr[k] < bestErr[best]){
if (bestErr[k] == 0) bestErr[k] = 1;
@ -1486,7 +1498,7 @@ int askdemod_ext(uint8_t *bits, size_t *size, int *clk, int *invert, int maxErr,
// just noise - no super good detection. good enough
if (signalprop.isnoise) {
if (g_debugMode == 2) prnt("DEBUG askdemod_ext: just noise detected - quitting");
if (g_debugMode == 2) prnt("DEBUG askdemod_ext: just noise detected - aborting");
return -2;
}
@ -1636,7 +1648,7 @@ size_t fsk_wave_demod(uint8_t *dest, size_t size, uint8_t fchigh, uint8_t fclow,
//find start of modulating data in trace
idx = findModStart(dest, size, fchigh);
// Need to threshold first sample
dest[0] = (dest[idx] < FSK_PSK_THRESHOLD) ? 0 : 1;
dest[0] = (dest[idx] < signalprop.mean) ? 0 : 1;
last_transition = idx;
idx++;
@ -1674,7 +1686,7 @@ size_t fsk_wave_demod(uint8_t *dest, size_t size, uint8_t fchigh, uint8_t fclow,
for(; idx < size-20; idx++) {
// threshold current value
dest[idx] = (dest[idx] < FSK_PSK_THRESHOLD) ? 0 : 1;
dest[idx] = (dest[idx] < signalprop.mean) ? 0 : 1;
// Check for 0->1 transition
if (dest[idx-1] < dest[idx]) {

View file

@ -19,7 +19,7 @@
#include <stdlib.h> // for
#include <stdbool.h> // for bool
#include "parity.h" // for parity test
#include "util.h" // for ARRAYLEN
//generic
typedef struct {
int low;

View file

@ -0,0 +1,322 @@
/*
* AES-CMAC from NIST Special Publication 800-38B Recommendation for block cipher modes of operation: The CMAC mode for authentication.
*
* Copyright (C) 2006-2014, Brainspark B.V.
* Copyright (C) 2014, Anargyros Plemenos
* Tests added Merkok, 2018
*
* This file is part of PolarSSL (http://www.polarssl.org)
* Lead Maintainer: Paul Bakker <polarssl_maintainer at polarssl.org>
*
* All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along
* with this program; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Reference : https://polarssl.org/discussions/generic/authentication-token
* NIST Special Publication 800-38B Recommendation for block cipher modes of operation: The CMAC mode for authentication.
* Tests here:
* https://csrc.nist.gov/CSRC/media/Projects/Cryptographic-Standards-and-Guidelines/documents/examples/AES_CMAC.pdf
*/
#include "polarssl/aes_cmac128.h"
#include <stdio.h>
#define MIN(a,b) ((a)<(b)?(a):(b))
#define _MSB(x) (((x)[0] & 0x80)?1:0)
#if !defined(POLARSSL_CONFIG_FILE)
#include "polarssl_config.h"
#else
#include POLARSSL_CONFIG_FILE
#endif
#if defined(POLARSSL_AES_C)
#include "aes.h"
#endif
#if defined(POLARSSL_PLATFORM_C)
#include "polarssl/platform.h"
#else
#define polarssl_printf printf
#endif
/**
* zero a structure
*/
#define ZERO_STRUCT(x) memset((char *)&(x), 0, sizeof(x))
/**
* zero a structure given a pointer to the structure
*/
#define ZERO_STRUCTP(x) do{ if((x) != NULL) memset((char *)(x), 0, sizeof(*(x)));} while(0)
/* For CMAC Calculation */
static unsigned char const_Rb[16] = {
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x87
};
static unsigned char const_Zero[16] = {
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
};
static inline void aes_cmac_128_left_shift_1(const uint8_t in[16], uint8_t out[16])
{
uint8_t overflow = 0;
int8_t i;
for (i = 15; i >= 0; i--) {
out[i] = in[i] << 1;
out[i] |= overflow;
overflow = _MSB(&in[i]);
}
}
static inline void aes_cmac_128_xor(const uint8_t in1[16], const uint8_t in2[16],
uint8_t out[16])
{
uint8_t i;
for (i = 0; i < 16; i++) {
out[i] = in1[i] ^ in2[i];
}
}
/*
* AES-CMAC-128 context setup
*/
void aes_cmac128_starts(aes_cmac128_context *ctx, const uint8_t K[16])
{
uint8_t L[16];
/* Zero struct of aes_context */
ZERO_STRUCTP(ctx);
/* Initialize aes_context */
aes_setkey_enc(&ctx->aes_key, K, 128);
/* step 1 - generate subkeys k1 and k2 */
aes_crypt_ecb(&ctx->aes_key, AES_ENCRYPT, const_Zero, L);
if (_MSB(L) == 0) {
aes_cmac_128_left_shift_1(L, ctx->K1);
} else {
uint8_t tmp_block[16];
aes_cmac_128_left_shift_1(L, tmp_block);
aes_cmac_128_xor(tmp_block, const_Rb, ctx->K1);
ZERO_STRUCT(tmp_block);
}
if (_MSB(ctx->K1) == 0) {
aes_cmac_128_left_shift_1(ctx->K1, ctx->K2);
} else {
uint8_t tmp_block[16];
aes_cmac_128_left_shift_1(ctx->K1, tmp_block);
aes_cmac_128_xor(tmp_block, const_Rb, ctx->K2);
ZERO_STRUCT(tmp_block);
}
ZERO_STRUCT(L);
}
/*
* AES-CMAC-128 process message
*/
void aes_cmac128_update(aes_cmac128_context *ctx, const uint8_t *_msg, size_t _msg_len)
{
uint8_t tmp_block[16];
uint8_t Y[16];
const uint8_t *msg = _msg;
size_t msg_len = _msg_len;
/*
* copy the remembered last block
*/
ZERO_STRUCT(tmp_block);
if (ctx->last_len) {
memcpy(tmp_block, ctx->last, ctx->last_len);
}
/*
* check if we expand the block
*/
if (ctx->last_len < 16) {
size_t len = MIN(16 - ctx->last_len, msg_len);
memcpy(&tmp_block[ctx->last_len], msg, len);
memcpy(ctx->last, tmp_block, 16);
msg += len;
msg_len -= len;
ctx->last_len += len;
}
if (msg_len == 0) {
/* if it is still the last block, we are done */
ZERO_STRUCT(tmp_block);
return;
}
/*
* It is not the last block anymore
*/
ZERO_STRUCT(ctx->last);
ctx->last_len = 0;
/*
* now checksum everything but the last block
*/
aes_cmac_128_xor(ctx->X, tmp_block, Y);
aes_crypt_ecb(&ctx->aes_key, AES_ENCRYPT, Y, ctx->X);
while (msg_len > 16) {
memcpy(tmp_block, msg, 16);
msg += 16;
msg_len -= 16;
aes_cmac_128_xor(ctx->X, tmp_block, Y);
aes_crypt_ecb(&ctx->aes_key, AES_ENCRYPT, Y, ctx->X);
}
/*
* copy the last block, it will be processed in
* aes_cmac128_final().
*/
memcpy(ctx->last, msg, msg_len);
ctx->last_len = msg_len;
ZERO_STRUCT(tmp_block);
ZERO_STRUCT(Y);
}
/*
* AES-CMAC-128 compute T
*/
void aes_cmac128_final(aes_cmac128_context *ctx, uint8_t T[16])
{
uint8_t tmp_block[16];
uint8_t Y[16];
if (ctx->last_len < 16) {
ctx->last[ctx->last_len] = 0x80;
aes_cmac_128_xor(ctx->last, ctx->K2, tmp_block);
} else {
aes_cmac_128_xor(ctx->last, ctx->K1, tmp_block);
}
aes_cmac_128_xor(tmp_block, ctx->X, Y);
aes_crypt_ecb(&ctx->aes_key, AES_ENCRYPT, Y, T);
ZERO_STRUCT(tmp_block);
ZERO_STRUCT(Y);
ZERO_STRUCTP(ctx);
}
/*
* Checkup routine
*
* https://csrc.nist.gov/projects/cryptographic-standards-and-guidelines/example-values
* https://csrc.nist.gov/CSRC/media/Projects/Cryptographic-Standards-and-Guidelines/documents/examples/AES_CMAC.pdf
*/
int aes_cmac_self_test( int verbose )
{
unsigned char key[16] = {0x2B, 0x7E, 0x15, 0x16, 0x28, 0xAE, 0xD2, 0xA6, 0xAB, 0xF7, 0x15, 0x88, 0x09, 0xCF, 0x4F, 0x3C};
unsigned char mac[16] = {0};
aes_cmac128_context ctx;
int ret;
// check Example1:
if( verbose != 0 )
polarssl_printf( " AES-CMAC-128 zero length data: " );
unsigned char ex1data[16] = {0};
aes_cmac128_starts(&ctx, key);
aes_cmac128_update(&ctx, ex1data, 0);
aes_cmac128_final(&ctx, mac);
unsigned char ex1res[16] = {0xBB, 0x1D, 0x69, 0x29, 0xE9, 0x59, 0x37, 0x28, 0x7F, 0xA3, 0x7D, 0x12, 0x9B, 0x75, 0x67, 0x46};
if(!memcmp(mac, ex1res, 16)) {
if( verbose != 0 )
polarssl_printf( "passed\n" );
} else {
polarssl_printf( "failed\n" );
ret = 1;
goto exit;
}
// check Example2:
if( verbose != 0 )
polarssl_printf( " AES-CMAC-128 one block data : " );
unsigned char ex2data[16] = {0x6B, 0xC1, 0xBE, 0xE2, 0x2E, 0x40, 0x9F, 0x96, 0xE9, 0x3D, 0x7E, 0x11, 0x73, 0x93, 0x17, 0x2A};
aes_cmac128_starts(&ctx, key);
aes_cmac128_update(&ctx, ex2data, sizeof(ex2data));
aes_cmac128_final(&ctx, mac);
unsigned char ex2res[16] = {0x07, 0x0A, 0x16, 0xB4, 0x6B, 0x4D, 0x41, 0x44, 0xF7, 0x9B, 0xDD, 0x9D, 0xD0, 0x4A, 0x28, 0x7C};
if(!memcmp(mac, ex2res, 16)) {
if( verbose != 0 )
polarssl_printf( "passed\n" );
} else {
polarssl_printf( "failed\n" );
ret = 1;
goto exit;
}
// check Example3:
if( verbose != 0 )
polarssl_printf( " AES-CMAC-128 20 bytes of data: " );
unsigned char ex3data[20] = {0x6B, 0xC1, 0xBE, 0xE2, 0x2E, 0x40, 0x9F, 0x96, 0xE9, 0x3D, 0x7E, 0x11, 0x73, 0x93, 0x17, 0x2A,
0xAE, 0x2D, 0x8A, 0x57};
aes_cmac128_starts(&ctx, key);
aes_cmac128_update(&ctx, ex3data, sizeof(ex3data));
aes_cmac128_final(&ctx, mac);
unsigned char ex3res[16] = {0x7D, 0x85, 0x44, 0x9E, 0xA6, 0xEA, 0x19, 0xC8, 0x23, 0xA7, 0xBF, 0x78, 0x83, 0x7D, 0xFA, 0xDE};
if(!memcmp(mac, ex3res, 16)) {
if( verbose != 0 )
polarssl_printf( "passed\n" );
} else {
polarssl_printf( "failed\n" );
ret = 1;
goto exit;
}
// check Example4:
if( verbose != 0 )
polarssl_printf( " AES-CMAC-128 4 blocks of data: " );
unsigned char ex4data[64] = {0x6B, 0xC1, 0xBE, 0xE2, 0x2E, 0x40, 0x9F, 0x96, 0xE9, 0x3D, 0x7E, 0x11, 0x73, 0x93, 0x17, 0x2A,
0xAE, 0x2D, 0x8A, 0x57, 0x1E, 0x03, 0xAC, 0x9C, 0x9E, 0xB7, 0x6F, 0xAC, 0x45, 0xAF, 0x8E, 0x51,
0x30, 0xC8, 0x1C, 0x46, 0xA3, 0x5C, 0xE4, 0x11, 0xE5, 0xFB, 0xC1, 0x19, 0x1A, 0x0A, 0x52, 0xEF,
0xF6, 0x9F, 0x24, 0x45, 0xDF, 0x4F, 0x9B, 0x17, 0xAD, 0x2B, 0x41, 0x7B, 0xE6, 0x6C, 0x37, 0x10};
aes_cmac128_starts(&ctx, key);
aes_cmac128_update(&ctx, ex4data, sizeof(ex4data));
aes_cmac128_final(&ctx, mac);
unsigned char ex4res[16] = {0x51, 0xF0, 0xBE, 0xBF, 0x7E, 0x3B, 0x9D, 0x92, 0xFC, 0x49, 0x74, 0x17, 0x79, 0x36, 0x3C, 0xFE};
if(!memcmp(mac, ex4res, 16)) {
if( verbose != 0 )
polarssl_printf( "passed\n" );
} else {
polarssl_printf( "failed\n" );
ret = 1;
goto exit;
}
if( verbose != 0 )
polarssl_printf( "\n" );
ret = 0;
exit:
return( ret );
}

View file

@ -0,0 +1,81 @@
/*
* AES-CMAC from NIST Special Publication 800-38B Recommendation for block cipher modes of operation: The CMAC mode for authentication.
*
* Copyright (C) 2006-2014, Brainspark B.V.
* Copyright (C) 2014, Anargyros Plemenos
* Tests added Merkok, 2018
*
* This file is part of PolarSSL (http://www.polarssl.org)
* Lead Maintainer: Paul Bakker <polarssl_maintainer at polarssl.org>
*
* All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along
* with this program; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Reference : https://polarssl.org/discussions/generic/authentication-token
* NIST Special Publication 800-38B Recommendation for block cipher modes of operation: The CMAC mode for authentication.
* Tests here:
* https://csrc.nist.gov/CSRC/media/Projects/Cryptographic-Standards-and-Guidelines/documents/examples/AES_CMAC.pdf
*/
#include <stdint.h>
#include <stddef.h>
#include "aes.h"
typedef struct aes_cmac_128_context {
aes_context aes_key;
uint8_t K1[16];
uint8_t K2[16];
uint8_t X[16];
uint8_t last[16];
size_t last_len;
}
aes_cmac128_context;
/*
* \brief AES-CMAC-128 context setup
*
* \param ctx context to be initialized
* \param key secret key for AES-128
*/
void aes_cmac128_starts(aes_cmac128_context *ctx, const uint8_t K[16]);
/*
* \brief AES-CMAC-128 process message
*
* \param ctx context to be initialized
* \param _msg the given message
* \param _msg_len the length of message
*/
void aes_cmac128_update(aes_cmac128_context *ctx, const uint8_t *_msg, size_t _msg_len);
/*
* \brief AES-CMAC-128 compute T
*
* \param ctx context to be initialized
* \param T the generated MAC which is used to validate the message
*/
void aes_cmac128_final(aes_cmac128_context *ctx, uint8_t T[16]);
/**
* \brief Checkup routine
*
* \return 0 if successful, or 1 if the test failed
*/
int aes_cmac_self_test( int verbose );

View file

@ -0,0 +1,78 @@
//-----------------------------------------------------------------------------
// Copyright (C) 2018 Merlok
// Copyright (C) 2018 drHatson
//
// This code is licensed to you under the terms of the GNU GPL, version 2 or,
// at your option, any later version. See the LICENSE.txt file for the text of
// the license.
//-----------------------------------------------------------------------------
// crypto commands
//-----------------------------------------------------------------------------
#include "polarssl/libpcrypto.h"
#include <polarssl/aes.h>
#include <polarssl/aes_cmac128.h>
// NIST Special Publication 800-38A — Recommendation for block cipher modes of operation: methods and techniques, 2001.
int aes_encode(uint8_t *iv, uint8_t *key, uint8_t *input, uint8_t *output, int length){
uint8_t iiv[16] = {0};
if (iv)
memcpy(iiv, iv, 16);
aes_context aes;
aes_init(&aes);
if (aes_setkey_enc(&aes, key, 128))
return 1;
if (aes_crypt_cbc(&aes, AES_ENCRYPT, length, iiv, input, output))
return 2;
aes_free(&aes);
return 0;
}
int aes_decode(uint8_t *iv, uint8_t *key, uint8_t *input, uint8_t *output, int length){
uint8_t iiv[16] = {0};
if (iv)
memcpy(iiv, iv, 16);
aes_context aes;
aes_init(&aes);
if (aes_setkey_dec(&aes, key, 128))
return 1;
if (aes_crypt_cbc(&aes, AES_DECRYPT, length, iiv, input, output))
return 2;
aes_free(&aes);
return 0;
}
// NIST Special Publication 800-38B — Recommendation for block cipher modes of operation: The CMAC mode for authentication.
// https://csrc.nist.gov/CSRC/media/Projects/Cryptographic-Standards-and-Guidelines/documents/examples/AES_CMAC.pdf
int aes_cmac(uint8_t *iv, uint8_t *key, uint8_t *input, uint8_t *mac, int length) {
memset(mac, 0x00, 16);
uint8_t iiv[16] = {0};
if (iv)
memcpy(iiv, iv, 16);
// NIST 800-38B
aes_cmac128_context ctx;
aes_cmac128_starts(&ctx, key);
aes_cmac128_update(&ctx, input, length);
aes_cmac128_final(&ctx, mac);
return 0;
}
int aes_cmac8(uint8_t *iv, uint8_t *key, uint8_t *input, uint8_t *mac, int length) {
uint8_t cmac[16] = {0};
memset(mac, 0x00, 8);
int res = aes_cmac(iv, key, input, cmac, length);
if (res)
return res;
for(int i = 0; i < 8; i++)
mac[i] = cmac[i * 2 + 1];
return 0;
}

View file

@ -0,0 +1,22 @@
//-----------------------------------------------------------------------------
// Copyright (C) 2018 Merlok
//
// This code is licensed to you under the terms of the GNU GPL, version 2 or,
// at your option, any later version. See the LICENSE.txt file for the text of
// the license.
//-----------------------------------------------------------------------------
// crypto commands
//-----------------------------------------------------------------------------
#ifndef LIBPCRYPTO_H
#define LIBPCRYPTO_H
#include <stdint.h>
#include <stddef.h>
extern int aes_encode(uint8_t *iv, uint8_t *key, uint8_t *input, uint8_t *output, int length);
extern int aes_decode(uint8_t *iv, uint8_t *key, uint8_t *input, uint8_t *output, int length);
extern int aes_cmac(uint8_t *iv, uint8_t *key, uint8_t *input, uint8_t *mac, int length);
extern int aes_cmac8(uint8_t *iv, uint8_t *key, uint8_t *input, uint8_t *mac, int length);
#endif /* libpcrypto.h */