- AWID26 command context added as 'lf awid' containing realtime demodulation as well as cloning/simulation based on tag numbers (Craig Young)
- Added 'hw status'. This command makes the ARM print out some runtime information. (holiman)
- Added 'hw ping'. This command just sends a usb packets and checks if the pm3 is responsive. Can be used to abort certain operations which supports abort over usb. (holiman)
+- Added `data hex2bin` and `data bin2hex` for command line conversion between binary and hexadecimal (holiman)
### Changed
- Revised workflow for StandAloneMode14a (Craig Young)
// measure the USB Speed by sending SpeedTestBufferSize bytes to client and measuring the elapsed time.
// Note: this mimics GetFromBigbuf(), i.e. we have the overhead of the UsbCommand structure included.
-void printUSBSpeed(uint32_t SpeedTestBufferSize)
+void printUSBSpeed(void)
{
Dbprintf("USB Speed:");
- Dbprintf(" Sending %d bytes payload...", SpeedTestBufferSize);
+ Dbprintf(" Sending USB packets to client...");
+ #define USB_SPEED_TEST_MIN_TIME 1500 // in milliseconds
uint8_t *test_data = BigBuf_get_addr();
+ uint32_t end_time;
- uint32_t start_time = GetTickCount();
+ uint32_t start_time = end_time = GetTickCount();
+ uint32_t bytes_transferred = 0;
LED_B_ON();
- for(size_t i=0; i < SpeedTestBufferSize; i += USB_CMD_DATA_SIZE) {
- size_t len = MIN((SpeedTestBufferSize - i), USB_CMD_DATA_SIZE);
- cmd_send(CMD_DOWNLOADED_RAW_ADC_SAMPLES_125K,0,len,0,test_data,len);
+ while(end_time < start_time + USB_SPEED_TEST_MIN_TIME) {
+ cmd_send(CMD_DOWNLOADED_RAW_ADC_SAMPLES_125K, 0, USB_CMD_DATA_SIZE, 0, test_data, USB_CMD_DATA_SIZE);
+ end_time = GetTickCount();
+ bytes_transferred += USB_CMD_DATA_SIZE;
}
LED_B_OFF();
- uint32_t end_time = GetTickCount();
-
- Dbprintf(" Time elapsed: %dms, USB Transfer Speed PM3 -> Client = %d Bytes/s",
- end_time - start_time,
- 1000* SpeedTestBufferSize / (end_time - start_time));
+ Dbprintf(" Time elapsed: %dms", end_time - start_time);
+ Dbprintf(" Bytes transferred: %d", bytes_transferred);
+ Dbprintf(" USB Transfer Speed PM3 -> Client = %d Bytes/s",
+ 1000 * bytes_transferred / (end_time - start_time));
}
/**
* Prints runtime information about the PM3.
**/
-void SendStatus(uint32_t SpeedTestBufferSize)
+void SendStatus(void)
{
BigBuf_print_status();
Fpga_print_status();
printConfig(); //LF Sampling config
- printUSBSpeed(SpeedTestBufferSize);
+ printUSBSpeed();
Dbprintf("Various");
Dbprintf(" MF_DBGLEVEL........%d", MF_DBGLEVEL);
Dbprintf(" ToSendMax..........%d", ToSendMax);
case CMD_AWID_DEMOD_FSK: // Set realtime AWID demodulation
CmdAWIDdemodFSK(c->arg[0], 0, 0, 1);
break;
+ case CMD_VIKING_CLONE_TAG:
+ CopyViKingtoT55x7(c->arg[0],c->arg[1]);
+ break;
+
+
#endif
#ifdef WITH_HITAG
LED_B_ON();
uint8_t *BigBuf = BigBuf_get_addr();
+ size_t len = 0;
for(size_t i=0; i<c->arg[1]; i += USB_CMD_DATA_SIZE) {
- size_t len = MIN((c->arg[1] - i),USB_CMD_DATA_SIZE);
+ len = MIN((c->arg[1] - i),USB_CMD_DATA_SIZE);
cmd_send(CMD_DOWNLOADED_RAW_ADC_SAMPLES_125K,i,len,BigBuf_get_traceLen(),BigBuf+c->arg[0]+i,len);
}
// Trigger a finish downloading signal with an ACK frame
SendVersion();
break;
case CMD_STATUS:
- SendStatus(c->arg[0]);
+ SendStatus();
break;
case CMD_PING:
cmd_send(CMD_ACK,0,0,0,0,0);
void ReaderIClass_Replay(uint8_t arg0,uint8_t *MAC);
void IClass_iso14443A_GetPublic(uint8_t arg0);
+void CopyViKingtoT55x7(uint32_t block1,uint32_t block2);
// hitag2.h
void SnoopHitag(uint32_t type);
void SimulateHitagTag(bool tag_mem_supplied, byte_t* data);
response3a[0] = sak & 0xFB;
ComputeCrc14443(CRC_14443_A, response3a, 1, &response3a[1], &response3a[2]);
- uint8_t response5[] = { 0x01, 0x01, 0x01, 0x01 }; // Very random tag nonce
+ uint8_t response5[] = { 0x00, 0x00, 0x00, 0x00 }; // Very random tag nonce
uint8_t response6[] = { 0x04, 0x58, 0x80, 0x02, 0x00, 0x00 }; // dummy ATS (pseudo-ATR), answer to RATS:
// Format byte = 0x58: FSCI=0x08 (FSC=256), TA(1) and TC(1) present,
// TA(1) = 0x80: different divisors not supported, DR = 1, DS = 1
} else if(receivedCmd[0] == 0x30) { // Received a (plain) READ
uint8_t block = receivedCmd[1];
if ( tagType == 7 ) {
- uint8_t start = 4 * block;
+ uint16_t start = 4 * block;
- if ( block < 4 ) {
+ /*if ( block < 4 ) {
//NTAG 215
uint8_t blockdata[50] = {
data[0],data[1],data[2], 0x88 ^ data[0] ^ data[1] ^ data[2],
0x00,0x00};
AppendCrc14443a(blockdata+start, 16);
EmSendCmdEx( blockdata+start, MAX_MIFARE_FRAME_SIZE, false);
- } else {
+ } else {*/
uint8_t emdata[MAX_MIFARE_FRAME_SIZE];
emlGetMemBt( emdata, start, 16);
AppendCrc14443a(emdata, 16);
EmSendCmdEx(emdata, sizeof(emdata), false);
- }
+ //}
p_response = NULL;
} else {
BigBuf_free_keep_EM();
LED_A_OFF();
+ if (MF_DBGLEVEL >= 4){
Dbprintf("-[ Wake ups after halt [%d]", happened);
Dbprintf("-[ Messages after halt [%d]", happened2);
Dbprintf("-[ Num of received cmd [%d]", cmdsRecvd);
+ }
}
nttmp1 = nt1;
nttmp2 = nt2;
- for (i = 1; i < 32768; i++) {
+ for (i = 1; i < 0xFFFF; i++) {
nttmp1 = prng_successor(nttmp1, 1);
if (nttmp1 == nt2) return i;
nttmp2 = prng_successor(nttmp2, 1);
return(-99999); // either nt1 or nt2 are invalid nonces
}
+int32_t dist_nt_ex32(uint32_t nt1, uint32_t nt2, bool *result) {
+
+ uint16_t i;
+ uint32_t nttmp1, nttmp2;
+
+ if (nt1 == nt2) return 0;
+
+ nttmp1 = nt1;
+ nttmp2 = nt2;
+
+ *result = true;
+ for (i = 1; i < 0xFFFFFFFF; i++) {
+ nttmp1 = prng_successor(nttmp1, 1);
+ if (nttmp1 == nt2) return i;
+
+ nttmp2 = prng_successor(nttmp2, 1);
+ if (nttmp2 == nt1) return -i;
+ }
+
+ *result = false;
+ return(-99999); // either nt1 or nt2 are invalid nonces
+}
//-----------------------------------------------------------------------------
// Recover several bits of the cypher stream. This implements (first stages of)
byte_t par_list[8] = {0x00};
byte_t ks_list[8] = {0x00};
+ #define PRNG_SEQUENCE_LENGTH (1 << 16);
static uint32_t sync_time = 0;
static uint32_t sync_cycles = 0;
int catch_up_cycles = 0;
if (first_try) {
mf_nr_ar3 = 0;
sync_time = GetCountSspClk() & 0xfffffff8;
- sync_cycles = 65536; // theory: Mifare Classic's random generator repeats every 2^16 cycles (and so do the nonces).
+ sync_cycles = PRNG_SEQUENCE_LENGTH; //65536; //0x10000 // theory: Mifare Classic's random generator repeats every 2^16 cycles (and so do the nonces).
nt_attacked = 0;
nt = 0;
par[0] = 0;
LED_C_OFF();
- #define DARKSIDE_MAX_TRIES 32 // number of tries to sync on PRNG cycle. Then give up.
- uint16_t unsuccessfull_tries = 0;
+ #define MAX_UNEXPECTED_RANDOM 5 // maximum number of unexpected (i.e. real) random numbers when trying to sync. Then give up.
+ #define MAX_SYNC_TRIES 16
+ uint16_t unexpected_random = 0;
+ uint16_t sync_tries = 0;
+ int16_t debug_info_nr = -1;
+ uint32_t debug_info[MAX_SYNC_TRIES];
for(uint16_t i = 0; TRUE; i++) {
continue;
}
- sync_time = (sync_time & 0xfffffff8) + sync_cycles + catch_up_cycles;
- catch_up_cycles = 0;
+ if (debug_info_nr == -1) {
+ sync_time = (sync_time & 0xfffffff8) + sync_cycles + catch_up_cycles;
+ catch_up_cycles = 0;
- // if we missed the sync time already, advance to the next nonce repeat
- while(GetCountSspClk() > sync_time) {
- sync_time = (sync_time & 0xfffffff8) + sync_cycles;
- }
+ // if we missed the sync time already, advance to the next nonce repeat
+ while(GetCountSspClk() > sync_time) {
+ sync_time = (sync_time & 0xfffffff8) + sync_cycles;
+ }
- // Transmit MIFARE_CLASSIC_AUTH at synctime. Should result in returning the same tag nonce (== nt_attacked)
- ReaderTransmit(mf_auth, sizeof(mf_auth), &sync_time);
+ // Transmit MIFARE_CLASSIC_AUTH at synctime. Should result in returning the same tag nonce (== nt_attacked)
+ ReaderTransmit(mf_auth, sizeof(mf_auth), &sync_time);
+ } else {
+ ReaderTransmit(mf_auth, sizeof(mf_auth), NULL);
+ }
// Receive the (4 Byte) "random" nonce
if (!ReaderReceive(receivedAnswer, receivedAnswerPar)) {
int nt_distance = dist_nt(previous_nt, nt);
if (nt_distance == 0) {
nt_attacked = nt;
- }
- else {
+ } else {
if (nt_distance == -99999) { // invalid nonce received
- unsuccessfull_tries++;
- if (!nt_attacked && unsuccessfull_tries > DARKSIDE_MAX_TRIES) {
+ unexpected_random++;
+ if (!nt_attacked && unexpected_random > MAX_UNEXPECTED_RANDOM) {
isOK = -3; // Card has an unpredictable PRNG. Give up
break;
} else {
continue; // continue trying...
}
}
+ if (++sync_tries > MAX_SYNC_TRIES) {
+ if (sync_tries > 2 * MAX_SYNC_TRIES) {
+ isOK = -4; // Card's PRNG runs at an unexpected frequency or resets unexpectedly
+ break;
+ } else { // continue for a while, just to collect some debug info
+ debug_info[++debug_info_nr] = nt_distance;
+ continue;
+ }
+ }
sync_cycles = (sync_cycles - nt_distance);
- if (MF_DBGLEVEL >= 3) Dbprintf("calibrating in cycle %d. nt_distance=%d, Sync_cycles: %d\n", i, nt_distance, sync_cycles);
+ if (sync_cycles <= 0) {
+ sync_cycles += PRNG_SEQUENCE_LENGTH;
+ }
+ if (MF_DBGLEVEL >= 3) {
+ Dbprintf("calibrating in cycle %d. nt_distance=%d, Sync_cycles: %d\n", i, nt_distance, sync_cycles);
+ }
continue;
}
}
mf_nr_ar[3] &= 0x1F;
- byte_t buf[28] = {0x00};
+ if (isOK == -4) {
+ if (MF_DBGLEVEL >= 3) {
+ for(uint16_t i = 0; i < MAX_SYNC_TRIES; i++) {
+ Dbprintf("collected debug info[%d] = %d\n", i, debug_info[i]);
+ }
+ }
+ }
+ byte_t buf[28];
memcpy(buf + 0, uid, 4);
num_to_bytes(nt, 4, buf + 4);
memcpy(buf + 8, par_list, 8);
set_tracing(FALSE);
}
-
- /*
+/**
*MIFARE 1K simulate.
*
*@param flags :
// when we read a TI tag we sample the zerocross line at 2Mhz
// TI tags modulate a 1 as 16 cycles of 123.2Khz
// TI tags modulate a 0 as 16 cycles of 134.2Khz
- #define FSAMPLE 2000000
- #define FREQLO 123200
- #define FREQHI 134200
+ #define FSAMPLE 2000000
+ #define FREQLO 123200
+ #define FREQHI 134200
signed char *dest = (signed char *)BigBuf_get_addr();
uint16_t n = BigBuf_max_traceLen();
*/
/* T55x7 configuration register definitions */
-#define T55x7_POR_DELAY 0x00000001
-#define T55x7_ST_TERMINATOR 0x00000008
-#define T55x7_PWD 0x00000010
+#define T55x7_POR_DELAY 0x00000001
+#define T55x7_ST_TERMINATOR 0x00000008
+#define T55x7_PWD 0x00000010
#define T55x7_MAXBLOCK_SHIFT 5
-#define T55x7_AOR 0x00000200
-#define T55x7_PSKCF_RF_2 0
-#define T55x7_PSKCF_RF_4 0x00000400
-#define T55x7_PSKCF_RF_8 0x00000800
+#define T55x7_AOR 0x00000200
+#define T55x7_PSKCF_RF_2 0
+#define T55x7_PSKCF_RF_4 0x00000400
+#define T55x7_PSKCF_RF_8 0x00000800
#define T55x7_MODULATION_DIRECT 0
#define T55x7_MODULATION_PSK1 0x00001000
#define T55x7_MODULATION_PSK2 0x00002000
#define T55x7_MODULATION_FSK2a 0x00007000
#define T55x7_MODULATION_MANCHESTER 0x00008000
#define T55x7_MODULATION_BIPHASE 0x00010000
-#define T55x7_BITRATE_RF_8 0
-#define T55x7_BITRATE_RF_16 0x00040000
-#define T55x7_BITRATE_RF_32 0x00080000
-#define T55x7_BITRATE_RF_40 0x000C0000
-#define T55x7_BITRATE_RF_50 0x00100000
-#define T55x7_BITRATE_RF_64 0x00140000
+//#define T55x7_MODULATION_BIPHASE57 0x00011000
+#define T55x7_BITRATE_RF_8 0
+#define T55x7_BITRATE_RF_16 0x00040000
+#define T55x7_BITRATE_RF_32 0x00080000
+#define T55x7_BITRATE_RF_40 0x000C0000
+#define T55x7_BITRATE_RF_50 0x00100000
+#define T55x7_BITRATE_RF_64 0x00140000
#define T55x7_BITRATE_RF_100 0x00180000
#define T55x7_BITRATE_RF_128 0x001C0000
/* T5555 (Q5) configuration register definitions */
-#define T5555_ST_TERMINATOR 0x00000001
+#define T5555_ST_TERMINATOR 0x00000001
#define T5555_MAXBLOCK_SHIFT 0x00000001
#define T5555_MODULATION_MANCHESTER 0
#define T5555_MODULATION_PSK1 0x00000010
#define T5555_MODULATION_FSK2 0x00000050
#define T5555_MODULATION_BIPHASE 0x00000060
#define T5555_MODULATION_DIRECT 0x00000070
-#define T5555_INVERT_OUTPUT 0x00000080
-#define T5555_PSK_RF_2 0
-#define T5555_PSK_RF_4 0x00000100
-#define T5555_PSK_RF_8 0x00000200
-#define T5555_USE_PWD 0x00000400
-#define T5555_USE_AOR 0x00000800
-#define T5555_BITRATE_SHIFT 12
-#define T5555_FAST_WRITE 0x00004000
-#define T5555_PAGE_SELECT 0x00008000
+#define T5555_INVERT_OUTPUT 0x00000080
+#define T5555_PSK_RF_2 0
+#define T5555_PSK_RF_4 0x00000100
+#define T5555_PSK_RF_8 0x00000200
+#define T5555_USE_PWD 0x00000400
+#define T5555_USE_AOR 0x00000800
+#define T5555_BITRATE_SHIFT 12
+#define T5555_FAST_WRITE 0x00004000
+#define T5555_PAGE_SELECT 0x00008000
/*
* Relevant times in microsecond
* To compensate antenna falling times shorten the write times
* and enlarge the gap ones.
*/
-#define START_GAP 31*8 // was 250 // SPEC: 1*8 to 50*8 - typ 15*8 (or 15fc)
+
+#define START_GAP 50*8 // was 250 // SPEC: 1*8 to 50*8 - typ 15*8 (or 15fc)
#define WRITE_GAP 20*8 // was 160 // SPEC: 1*8 to 20*8 - typ 10*8 (or 10fc)
#define WRITE_0 18*8 // was 144 // SPEC: 16*8 to 32*8 - typ 24*8 (or 24fc)
#define WRITE_1 50*8 // was 400 // SPEC: 48*8 to 64*8 - typ 56*8 (or 56fc) 432 for T55x7; 448 for E5550
// Write one bit to card
void T55xxWriteBit(int bit)
{
- FpgaDownloadAndGo(FPGA_BITSTREAM_LF);
+ //FpgaDownloadAndGo(FPGA_BITSTREAM_LF);
FpgaSendCommand(FPGA_CMD_SET_DIVISOR, 95); //125Khz
FpgaWriteConfWord(FPGA_MAJOR_MODE_LF_ADC | FPGA_LF_ADC_READER_FIELD);
if (!bit)
// Set up FPGA, 125kHz
// Wait for config.. (192+8190xPOW)x8 == 67ms
LFSetupFPGAForADC(0, true);
-
+
// Now start writting
FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF);
SpinDelayUs(START_GAP);
void TurnReadLFOn(){
FpgaWriteConfWord(FPGA_MAJOR_MODE_LF_ADC | FPGA_LF_ADC_READER_FIELD);
// Give it a bit of time for the resonant antenna to settle.
- SpinDelayUs(8*150);
+ SpinDelayUs(300);
}
// Set up FPGA, 125kHz
// Wait for config.. (192+8190xPOW)x8 == 67ms
- LFSetupFPGAForADC(0, true);
+ //LFSetupFPGAForADC(0, true);
+ FpgaDownloadAndGo(FPGA_BITSTREAM_LF);
+ FpgaSendCommand(FPGA_CMD_SET_DIVISOR, 95); //125Khz
+ FpgaWriteConfWord(FPGA_MAJOR_MODE_LF_ADC | FPGA_LF_ADC_READER_FIELD);
+
+ // Connect the A/D to the peak-detected low-frequency path.
+ SetAdcMuxFor(GPIO_MUXSEL_LOPKD);
+
+ // Now set up the SSC to get the ADC samples that are now streaming at us.
+ FpgaSetupSsc();
+
+ // Give it a bit of time for the resonant antenna to settle.
+ //SpinDelayUs(8*200); //192FC
+ SpinDelay(50);
+
FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF);
SpinDelayUs(START_GAP);
FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF); // field off
LED_D_OFF();
}
+void CopyViKingtoT55x7(uint32_t block1,uint32_t block2)
+{
+ LED_D_ON();
+ T55xxWriteBlock(block1,1,0,0);
+ T55xxWriteBlock(block2,2,0,0);
+
+ T55xxWriteBlock(T55x7_MODULATION_MANCHESTER | T55x7_BITRATE_RF_32 | 2 << T5555_MAXBLOCK_SHIFT,0,0,1);
+ LED_D_OFF();
+ DbpString("DONE!");
+}
+
\r
void MifareEMemSet(uint32_t arg0, uint32_t arg1, uint32_t arg2, uint8_t *datain){\r
FpgaDownloadAndGo(FPGA_BITSTREAM_HF);\r
- emlSetMem(datain, arg0, arg1); // data, block num, blocks count\r
+ //emlSetMem(datain, arg0, arg1); // data, block num, blocks count \r
+ emlSetMem_xt(datain, arg0, arg1, arg2); // data, block num, blocks count, block byte width\r
}\r
\r
void MifareEMemGet(uint32_t arg0, uint32_t arg1, uint32_t arg2, uint8_t *datain){\r
if (MF_DBGLEVEL >= MF_DBG_EXTENDED)\r
Dbprintf("EV1 Auth : %02x%02x%02x%02x", key[0], key[1], key[2], key[3]);\r
len = mifare_sendcmd(0x1B, key, sizeof(key), resp, respPar, NULL);\r
- //len = mifare_sendcmd_short_mfuev1auth(NULL, 0, 0x1B, key, resp, respPar, NULL);\r
+\r
if (len != 4) {\r
if (MF_DBGLEVEL >= MF_DBG_ERROR) Dbprintf("Cmd Error: %02x %u", resp[0], len);\r
return 0;\r
\r
// work with emulator memory\r
void emlSetMem(uint8_t *data, int blockNum, int blocksCount) {\r
+ emlSetMem_xt(data, blockNum, blocksCount, 16);\r
+}\r
+\r
+void emlSetMem_xt(uint8_t *data, int blockNum, int blocksCount, int blockBtWidth) {\r
uint8_t* emCARD = BigBuf_get_EM_addr();\r
- memcpy(emCARD + blockNum * 16, data, blocksCount * 16);\r
+ memcpy(emCARD + blockNum * blockBtWidth, data, blocksCount * blockBtWidth);\r
}\r
\r
void emlGetMem(uint8_t *data, int blockNum, int blocksCount) {\r
// emulator functions\r
void emlClearMem(void);\r
void emlSetMem(uint8_t *data, int blockNum, int blocksCount);\r
+void emlSetMem_xt(uint8_t *data, int blockNum, int blocksCount, int blockBtWidth);\r
void emlGetMem(uint8_t *data, int blockNum, int blocksCount);\r
void emlGetMemBt(uint8_t *data, int bytePtr, int byteCount);\r
uint64_t emlGetKey(int sectorNum, int keyType);\r
}
uint32_t RAMFUNC GetCountUS(){
- return (AT91C_BASE_TC1->TC_CV * 0x8000) + ((AT91C_BASE_TC0->TC_CV / 15) * 10);
+ //return (AT91C_BASE_TC1->TC_CV * 0x8000) + ((AT91C_BASE_TC0->TC_CV / 15) * 10);
+ // By suggestion from PwPiwi, http://www.proxmark.org/forum/viewtopic.php?pid=17548#p17548
+ return (AT91C_BASE_TC1->TC_CV * 0x8000) + ((AT91C_BASE_TC0->TC_CV * 2) / 3);
}
static uint32_t GlobalUsCounter = 0;
# DO NOT use thumb mode in the phase 1 bootloader since that generates a section with glue code
ARMSRC =
-THUMBSRC = cmd.c usb_cdc.c bootrom.c
+THUMBSRC = cmd.c \
+ usb_cdc.c \
+ bootrom.c
ASMSRC = ram-reset.s flash-reset.s
## There is a strange bug with the linker: Sometimes it will not emit the glue to call
cmdlfem4x.c \
cmdlfhitag.c \
cmdlfti.c \
+ cmdlfviking.c\
cmdparser.c \
cmdmain.c \
cmdlft55xx.c \
aes.c\
protocols.c\
sha1.c\
+ sha256.c\
cmdcrc.c\
reveng/reveng.c\
reveng/cli.c\
#include "usb_cmd.h"
#include "crc.h"
#include "crc16.h"
+#include "loclass/cipherutils.h"
uint8_t DemodBuffer[MAX_DEMOD_BUF_LEN];
uint8_t g_debugMode=0;
return ans;
}
+int AmVikingDecode(const uint8_t *id){
+ // searching the buffer for the id
+ //uint8_t id_bits[32];
+ // convert 4 bytes of id to 32 bits present in 32 bytes data;
+ //bytes_to_bits(id,4,id_bits,sizeof(id_bits));
+
+ //print_arraybinary(id_bits,sizeof(id_bits));
+ PrintAndLog(" binary: %s", printBits(4, id) );
+
+ //size_t idx = 0;
+ size_t BitLen = DemodBufferLen;
+ uint8_t BitStream[MAX_GRAPH_TRACE_LEN]={0};
+ memcpy(BitStream, DemodBuffer, BitLen);
+
+ // if (VikingDecode(BitStream,BitLen,&idx,id_bits,sizeof(id_bits)) == 1)
+ // {
+ // setDemodBuf(BitStream,64, idx);
+ // PrintAndLog("Found Viking tag\n");
+ // CmdPrintDemodBuff("x");
+ // }
+ // else
+ // {
+ // PrintAndLog("Not found Viking tag\n");
+ // }
+ return 0;
+}
+int AMVikingDemod(const uint8_t *id){
+ // demod am clock 32 fail
+ if (!ASKDemod("32",g_debugMode,false,1))
+ return 0;
+ // search for the card id from bitstream.
+ return AmVikingDecode(id);
+}
+//by Gusto
+// takes 1 argument <8 bytes of Hex number on the card
+// print binary found and saves in grapbuffer for further commands
+int CmdAMVikingDemod(const char *Cmd){
+ uint8_t id[4];
+ if (param_gethex(Cmd,0,id,8) == 1)
+ {
+ PrintAndLog("Usage: data vikingdemod CardID 8 bytes of hex number");
+ return 0;
+ }
+ PrintAndLog("Card ID : %02X%02X%02X%02X\n",id[0],id[1],id[2],id[3]);
+ // try to demod AMViking
+ return AMVikingDemod(id);
+}
+
int CmdGrid(const char *Cmd)
{
sscanf(Cmd, "%i %i", &PlotGridX, &PlotGridY);
RepaintGraphWindow();
return 0;
}
-typedef struct {
- uint8_t * buffer;
- uint32_t numbits;
- uint32_t position;
-} BitstreamOut;
bool _headBit( BitstreamOut *stream)
{
return 0;
}
+int usage_data_bin2hex(){
+ PrintAndLog("Usage: data bin2hex <binary_digits>");
+ PrintAndLog(" This function will ignore all characters not 1 or 0 (but stop reading on whitespace)");
+ return 0;
+}
+
+/**
+ * @brief Utility for conversion via cmdline.
+ * @param Cmd
+ * @return
+ */
+int Cmdbin2hex(const char *Cmd)
+{
+ int bg =0, en =0;
+ if(param_getptr(Cmd, &bg, &en, 0))
+ {
+ return usage_data_bin2hex();
+ }
+ //Number of digits supplied as argument
+ size_t length = en - bg +1;
+ size_t bytelen = (length+7) / 8;
+ uint8_t* arr = (uint8_t *) malloc(bytelen);
+ memset(arr, 0, bytelen);
+ BitstreamOut bout = { arr, 0, 0 };
+
+ for(; bg <= en ;bg++)
+ {
+ char c = Cmd[bg];
+ if( c == '1') pushBit(&bout, 1);
+ else if( c == '0') pushBit(&bout, 0);
+ else PrintAndLog("Ignoring '%c'", c);
+ }
+
+ if(bout.numbits % 8 != 0)
+ {
+ printf("[padded with %d zeroes]\n", 8-(bout.numbits % 8));
+ }
+
+ //Uses printf instead of PrintAndLog since the latter
+ // adds linebreaks to each printout - this way was more convenient since we don't have to
+ // allocate a string and write to that first...
+ for(size_t x = 0; x < bytelen ; x++)
+ {
+ printf("%02X", arr[x]);
+ }
+ printf("\n");
+ free(arr);
+ return 0;
+}
+
+int usage_data_hex2bin(){
+
+ PrintAndLog("Usage: data bin2hex <binary_digits>");
+ PrintAndLog(" This function will ignore all non-hexadecimal characters (but stop reading on whitespace)");
+ return 0;
+
+}
+
+int Cmdhex2bin(const char *Cmd)
+{
+ int bg =0, en =0;
+ if(param_getptr(Cmd, &bg, &en, 0))
+ {
+ return usage_data_hex2bin();
+ }
+
+
+ while(bg <= en )
+ {
+ char x = Cmd[bg++];
+ // capitalize
+ if (x >= 'a' && x <= 'f')
+ x -= 32;
+ // convert to numeric value
+ if (x >= '0' && x <= '9')
+ x -= '0';
+ else if (x >= 'A' && x <= 'F')
+ x -= 'A' - 10;
+ else
+ continue;
+
+ //Uses printf instead of PrintAndLog since the latter
+ // adds linebreaks to each printout - this way was more convenient since we don't have to
+ // allocate a string and write to that first...
+
+ for(int i= 0 ; i < 4 ; ++i)
+ printf("%d",(x >> (3 - i)) & 1);
+ }
+ printf("\n");
+
+ return 0;
+}
+
static command_t CommandTable[] =
{
{"help", CmdHelp, 1, "This help"},
{"askgproxiidemod", CmdG_Prox_II_Demod, 1, "Demodulate a G Prox II tag from GraphBuffer"},
{"autocorr", CmdAutoCorr, 1, "[window length] [g] -- Autocorrelation over window - g to save back to GraphBuffer (overwrite)"},
{"biphaserawdecode",CmdBiphaseDecodeRaw,1, "[offset] [invert<0|1>] [maxErr] -- Biphase decode bin stream in DemodBuffer (offset = 0|1 bits to shift the decode start)"},
+ {"bin2hex", Cmdbin2hex, 1, "bin2hex <digits> -- Converts binary to hexadecimal"},
{"bitsamples", CmdBitsamples, 0, "Get raw samples as bitstring"},
{"buffclear", CmdBuffClear, 1, "Clear sample buffer and graph window"},
{"dec", CmdDec, 1, "Decimate samples"},
{"detectclock", CmdDetectClockRate, 1, "[modulation] Detect clock rate of wave in GraphBuffer (options: 'a','f','n','p' for ask, fsk, nrz, psk respectively)"},
{"fdxbdemod", CmdFDXBdemodBI , 1, "Demodulate a FDX-B ISO11784/85 Biphase tag from GraphBuffer"},
{"fskawiddemod", CmdFSKdemodAWID, 1, "Demodulate an AWID FSK tag from GraphBuffer"},
+ {"vikingdemod", CmdAMVikingDemod, 1, "Demodulate a Viking AM tag from GraphBuffer"},
//{"fskfcdetect", CmdFSKfcDetect, 1, "Try to detect the Field Clock of an FSK wave"},
{"fskhiddemod", CmdFSKdemodHID, 1, "Demodulate a HID FSK tag from GraphBuffer"},
{"fskiodemod", CmdFSKdemodIO, 1, "Demodulate an IO Prox FSK tag from GraphBuffer"},
{"getbitstream", CmdGetBitStream, 1, "Convert GraphBuffer's >=1 values to 1 and <1 to 0"},
{"grid", CmdGrid, 1, "<x> <y> -- overlay grid on graph window, use zero value to turn off either"},
{"hexsamples", CmdHexsamples, 0, "<bytes> [<offset>] -- Dump big buffer as hex bytes"},
+ {"hex2bin", Cmdhex2bin, 1, "hex2bin <hexadecimal> -- Converts hexadecimal to binary"},
{"hide", CmdHide, 1, "Hide graph window"},
{"hpf", CmdHpf, 1, "Remove DC offset from trace"},
{"load", CmdLoad, 1, "<filename> -- Load trace (to graph window"},
int NRZrawDemod(const char *Cmd, bool verbose);
void printEM410x(uint32_t hi, uint64_t id);
int getSamples(const char *Cmd, bool silent);
-
+int AMVikingDemod(const uint8_t *cardid);
+int CmdAMVikingDemod(const char *cmd);
#define MAX_DEMOD_BUF_LEN (1024*128)
extern uint8_t DemodBuffer[MAX_DEMOD_BUF_LEN];
oddparity ^= (((frame[j] & 0xFF) >> k) & 0x01);
}
uint8_t parityBits = parityBytes[j>>3];
- if (protocol != ISO_14443B && isResponse && (oddparity != ((parityBits >> (7-(j&0x0007))) & 0x01))) {
+ if (protocol != ISO_14443B && (isResponse || protocol == ISO_14443A) && (oddparity != ((parityBits >> (7-(j&0x0007))) & 0x01))) {
snprintf(line[j/16]+(( j % 16) * 4),110, "%02x! ", frame[j]);
} else {
SendCommand(&c);\r
\r
//flush queue\r
- while (ukbhit()) getchar();\r
+ while (ukbhit()) getchar();\r
\r
// wait cycle\r
while (true) {\r
case -1 : PrintAndLog("Button pressed. Aborted.\n"); break;\r
case -2 : PrintAndLog("Card is not vulnerable to Darkside attack (doesn't send NACK on authentication requests).\n"); break;\r
case -3 : PrintAndLog("Card is not vulnerable to Darkside attack (its random number generator is not predictable).\n"); break;\r
+ case -4 : PrintAndLog("The card's random number generator is vulnerable but behaves somewhat weird (Mifare clone?). This needs to be fixed.\n"); break;\r
default: ;\r
}\r
break;\r
} else {\r
isOK = 0;\r
printf("------------------------------------------------------------------\n");\r
- PrintAndLog("Found valid key:%012"llx" \n", r_key);\r
+ PrintAndLog("Found valid key: %012"llx" \n", r_key);\r
}\r
\r
PrintAndLog("");\r
uint8_t buf8[64] = {0x00};\r
int i, len, blockNum, numBlocks;\r
int nameParamNo = 1;\r
- \r
+ uint8_t blockWidth = 32;\r
char ctmp = param_getchar(Cmd, 0);\r
\r
if ( ctmp == 'h' || ctmp == 0x00) {\r
PrintAndLog("It loads emul dump from the file `filename.eml`");\r
PrintAndLog("Usage: hf mf eload [card memory] <file name w/o `.eml`>");\r
- PrintAndLog(" [card memory]: 0 = 320 bytes (Mifare Mini), 1 = 1K (default), 2 = 2K, 4 = 4K");\r
+ PrintAndLog(" [card memory]: 0 = 320 bytes (Mifare Mini), 1 = 1K (default), 2 = 2K, 4 = 4K, u = UL");\r
PrintAndLog("");\r
PrintAndLog(" sample: hf mf eload filename");\r
PrintAndLog(" hf mf eload 4 filename");\r
case '\0': numBlocks = 16*4; break;\r
case '2' : numBlocks = 32*4; break;\r
case '4' : numBlocks = 256; break;\r
+ case 'U' : // fall through\r
+ case 'u' : numBlocks = 255; blockWidth = 8; break;\r
default: {\r
numBlocks = 16*4;\r
nameParamNo = 0;\r
return 2;\r
}\r
\r
- if (strlen(buf) < 32){\r
+ if (strlen(buf) < blockWidth){\r
if(strlen(buf) && feof(f))\r
break;\r
- PrintAndLog("File content error. Block data must include 32 HEX symbols");\r
+ PrintAndLog("File content error. Block data must include %d HEX symbols", blockWidth);\r
fclose(f);\r
return 2;\r
}\r
\r
- for (i = 0; i < 32; i += 2) {\r
+ for (i = 0; i < blockWidth; i += 2) {\r
sscanf(&buf[i], "%02x", (unsigned int *)&buf8[i / 2]);\r
}\r
- \r
- if (mfEmlSetMem(buf8, blockNum, 1)) {\r
+ if (mfEmlSetMem_xt(buf8, blockNum, 1, blockWidth/2)) {\r
PrintAndLog("Cant set emul block: %3d", blockNum);\r
fclose(f);\r
return 3;\r
};
#define MAX_UL_TYPES 18
-uint32_t UL_TYPES_ARRAY[MAX_UL_TYPES] = {UNKNOWN, UL, UL_C, UL_EV1_48, UL_EV1_128, NTAG, NTAG_203,
- NTAG_210, NTAG_212, NTAG_213, NTAG_215, NTAG_216, MY_D, MY_D_NFC, MY_D_MOVE, MY_D_MOVE_NFC, MY_D_MOVE_LEAN, FUDAN_UL};
-
-uint8_t UL_MEMORY_ARRAY[MAX_UL_TYPES] = {MAX_UL_BLOCKS, MAX_UL_BLOCKS, MAX_ULC_BLOCKS, MAX_ULEV1a_BLOCKS,
- MAX_ULEV1b_BLOCKS, MAX_NTAG_203, MAX_NTAG_203, MAX_NTAG_210, MAX_NTAG_212, MAX_NTAG_213,
- MAX_NTAG_215, MAX_NTAG_216, MAX_UL_BLOCKS, MAX_MY_D_NFC, MAX_MY_D_MOVE, MAX_MY_D_MOVE, MAX_MY_D_MOVE_LEAN, MAX_UL_BLOCKS};
+uint32_t UL_TYPES_ARRAY[MAX_UL_TYPES] = {
+ UNKNOWN, UL, UL_C,
+ UL_EV1_48, UL_EV1_128, NTAG,
+ NTAG_203, NTAG_210, NTAG_212,
+ NTAG_213, NTAG_215, NTAG_216,
+ MY_D, MY_D_NFC, MY_D_MOVE,
+ MY_D_MOVE_NFC, MY_D_MOVE_LEAN, FUDAN_UL};
+
+uint8_t UL_MEMORY_ARRAY[MAX_UL_TYPES] = {
+ MAX_UL_BLOCKS, MAX_UL_BLOCKS, MAX_ULC_BLOCKS,
+ MAX_ULEV1a_BLOCKS, MAX_ULEV1b_BLOCKS, MAX_NTAG_203,
+ MAX_NTAG_203, MAX_NTAG_210, MAX_NTAG_212,
+ MAX_NTAG_213, MAX_NTAG_215, MAX_NTAG_216,
+ MAX_UL_BLOCKS, MAX_MY_D_NFC, MAX_MY_D_MOVE,
+ MAX_MY_D_MOVE, MAX_MY_D_MOVE_LEAN, MAX_UL_BLOCKS};
static int CmdHelp(const char *Cmd);
}
}
+ // Read signature
if ((tagtype & (UL_EV1_48 | UL_EV1_128 | NTAG_213 | NTAG_215 | NTAG_216 | NTAG_I2C_1K | NTAG_I2C_2K ))) {
uint8_t ulev1_signature[32] = {0x00};
status = ulev1_readSignature( ulev1_signature, sizeof(ulev1_signature));
}
}
+ // Get Version
if ((tagtype & (UL_EV1_48 | UL_EV1_128 | NTAG_210 | NTAG_212 | NTAG_213 | NTAG_215 | NTAG_216 | NTAG_I2C_1K | NTAG_I2C_2K))) {
uint8_t version[10] = {0x00};
status = ulev1_getVersion(version, sizeof(version));
int CmdVersion(const char *Cmd)
{
+
clearCommandBuffer();
UsbCommand c = {CMD_VERSION};
static UsbCommand resp = {0, {0, 0, 0}};
{
uint8_t speed_test_buffer[USB_CMD_DATA_SIZE];
sample_buf = speed_test_buffer;
- #define USB_SPEED_TEST_SIZE (100*USB_CMD_DATA_SIZE)
clearCommandBuffer();
- UsbCommand c = {CMD_STATUS, {USB_SPEED_TEST_SIZE}};
+ UsbCommand c = {CMD_STATUS};
SendCommand(&c);
- UsbCommand resp;
- if (!WaitForResponseTimeout(CMD_ACK, &resp, 2500)) {
+ if (!WaitForResponseTimeout(CMD_ACK,&c,1900)) {
PrintAndLog("Status command failed. USB Speed Test timed out");
}
return 0;
UsbCommand resp;
UsbCommand c = {CMD_PING};
SendCommand(&c);
- if (WaitForResponseTimeout(CMD_ACK,&resp,1000)) {
+ if (WaitForResponseTimeout(CMD_ACK,&resp,1000))
PrintAndLog("Ping successfull");
- }else{
- PrintAndLog("Ping failed");
- }
- return 0;
+ else
+ PrintAndLog("Ping failed");
+ return 0;
}
static command_t CommandTable[] =
{
- {"help", CmdHelp, 1, "This help"},
- {"detectreader", CmdDetectReader,0, "['l'|'h'] -- Detect external reader field (option 'l' or 'h' to limit to LF or HF)"},
- {"fpgaoff", CmdFPGAOff, 0, "Set FPGA off"},
- {"lcd", CmdLCD, 0, "<HEX command> <count> -- Send command/data to LCD"},
- {"lcdreset", CmdLCDReset, 0, "Hardware reset LCD"},
- {"readmem", CmdReadmem, 0, "[address] -- Read memory at decimal address from flash"},
- {"reset", CmdReset, 0, "Reset the Proxmark3"},
- {"setlfdivisor", CmdSetDivisor, 0, "<19 - 255> -- Drive LF antenna at 12Mhz/(divisor+1)"},
- {"setmux", CmdSetMux, 0, "<loraw|hiraw|lopkd|hipkd> -- Set the ADC mux to a specific value"},
- {"tune", CmdTune, 0, "Measure antenna tuning"},
- {"version", CmdVersion, 0, "Show version information about the connected Proxmark"},
+ {"help", CmdHelp, 1, "This help"},
+ {"detectreader", CmdDetectReader,0, "['l'|'h'] -- Detect external reader field (option 'l' or 'h' to limit to LF or HF)"},
+ {"fpgaoff", CmdFPGAOff, 0, "Set FPGA off"},
+ {"lcd", CmdLCD, 0, "<HEX command> <count> -- Send command/data to LCD"},
+ {"lcdreset", CmdLCDReset, 0, "Hardware reset LCD"},
+ {"readmem", CmdReadmem, 0, "[address] -- Read memory at decimal address from flash"},
+ {"reset", CmdReset, 0, "Reset the Proxmark3"},
+ {"setlfdivisor", CmdSetDivisor, 0, "<19 - 255> -- Drive LF antenna at 12Mhz/(divisor+1)"},
+ {"setmux", CmdSetMux, 0, "<loraw|hiraw|lopkd|hipkd> -- Set the ADC mux to a specific value"},
+ {"tune", CmdTune, 0, "Measure antenna tuning"},
+ {"version", CmdVersion, 0, "Show version information about the connected Proxmark"},
{"status", CmdStatus, 0, "Show runtime status information about the connected Proxmark"},
{"ping", CmdPing, 0, "Test if the pm3 is responsive"},
- {NULL, NULL, 0, NULL}
+ {NULL, NULL, 0, NULL}
};
int CmdHW(const char *Cmd)
{
- CmdsParse(CommandTable, Cmd);
- return 0;
+ CmdsParse(CommandTable, Cmd);
+ return 0;
}
int CmdHelp(const char *Cmd)
{
- CmdsHelp(CommandTable);
- return 0;
+ CmdsHelp(CommandTable);
+ return 0;
}
#include "cmdlfpcf7931.h"
#include "cmdlfio.h"
#include "lfdemod.h"
-
+#include "cmdlfviking.h"
static int CmdHelp(const char *Cmd);
+
+int usage_lf_cmdread()
+{
+ PrintAndLog("Usage: lf cmdread <delay off> <zero> <one> <cmdbytes> [H] ");
+ PrintAndLog("Options: ");
+ PrintAndLog(" h This help");
+ PrintAndLog(" L Low frequency (125 KHz)");
+ PrintAndLog(" H High frequency (134 KHz)");
+ PrintAndLog(" H delay OFF");
+ PrintAndLog(" H time period ZERO");
+ PrintAndLog(" H time period ONE");
+ PrintAndLog("Examples:");
+ PrintAndLog(" lf cmdread 80 100 200 11000");
+ PrintAndLog(" lf cmdread 80 100 100 11000 H");
+ return 0;
+}
+
/* send a command before reading */
int CmdLFCommandRead(const char *Cmd)
{
- static char dummy[3];
+ static char dummy[3] = {0x20,0x00,0x00};
+ bool errors = FALSE;
+ uint8_t divisor = 0; //125khz
+ uint8_t cmdp =0;
+ while(param_getchar(Cmd, cmdp) != 0x00)
+ {
+ switch(param_getchar(Cmd, cmdp))
+ {
+ case 'h':
+ return usage_lf_cmdread();
+ case 'H':
+ divisor = 88;
+ cmdp++;
+ break;
+ case 'a':
+ //param_getchar(Cmd, cmdp+1) == '1';
+ cmdp+=2;
+ break;
+ default:
+ PrintAndLog("Unknown parameter '%c'", param_getchar(Cmd, cmdp));
+ errors = 1;
+ break;
+ }
+ if(errors) break;
+ }
+ // No args
+ if(cmdp == 0) errors = 1;
- dummy[0]= ' ';
+ //Validations
+ if(errors) return usage_lf_cmdread();
+
+ UsbCommand c = {CMD_MOD_THEN_ACQUIRE_RAW_ADC_SAMPLES_125K};
+ sscanf(Cmd, "%"lli" %"lli" %"lli" %s %s", &c.arg[0], &c.arg[1], &c.arg[2],(char*)(&c.d.asBytes),(char*)(&dummy+1));
+ // in case they specified 'h'
+ strcpy((char *)&c.d.asBytes + strlen((char *)c.d.asBytes), dummy);
- UsbCommand c = {CMD_MOD_THEN_ACQUIRE_RAW_ADC_SAMPLES_125K};
- sscanf(Cmd, "%"lli" %"lli" %"lli" %s %s", &c.arg[0], &c.arg[1], &c.arg[2],(char*)(&c.d.asBytes),(char*)(&dummy+1));
- // in case they specified 'h'
- strcpy((char *)&c.d.asBytes + strlen((char *)c.d.asBytes), dummy);
- SendCommand(&c);
- return 0;
+ PrintAndLog("ICE: %d %s -- %s", strlen((char *)c.d.asBytes) ,dummy, c.d.asBytes);
+ clearCommandBuffer();
+ SendCommand(&c);
+ return 0;
}
int CmdFlexdemod(const char *Cmd)
ans=CmdG_Prox_II_Demod("");
if (ans>0) {
- PrintAndLog("\nValid G Prox II ID Found!");
+ PrintAndLog("\nValid Guardall G-Prox II ID Found!");
return 1;
}
{"pcf7931", CmdLFPCF7931, 1, "{ PCF7931 RFIDs... }"},
{"ti", CmdLFTI, 1, "{ TI RFIDs... }"},
{"t55xx", CmdLFT55XX, 1, "{ T55X7 RFIDs... }"},
-
+{"viking", CmdLFViking, 1, "{ Viking RFIDs... }"},
{"config", CmdLFSetConfig, 0, "Set config for LF sampling, bit/sample, decimation, frequency"},
{"cmdread", CmdLFCommandRead, 0, "<off period> <'0' period> <'1' period> <command> ['h' 134] \n\t\t-- Modulate LF reader field to send command before read (all periods in microseconds)"},
}\r
} else {\r
clk = GetAskClock("", FALSE, FALSE);\r
+ \r
if (clk>0) {\r
sprintf(cmdStr,"%d", clk/2);\r
CmdLtrim(cmdStr);\r
#ifndef CMDLFT55XX_H__\r
#define CMDLFT55XX_H__\r
\r
+// config blocks\r
+#define T55X7_DEFAULT_CONFIG_BLOCK 0x000880E8 // compat mode, data rate 32, manchester, ST, 7 data blocks\r
+#define T55X7_RAW_CONFIG_BLOCK 0x000880E0 // compat mode, data rate 32, manchester, 7 data blocks\r
+\r
+#define T55X7_EM_UNIQUE_CONFIG_BLOCK 0x00148040 // emulate em4x02/unique - compat mode, manchester, data rate 64, 2 data blocks\r
+\r
+\r
+// FDXB requires data inversion and BiPhase 57 is simply BipHase 50 inverted, so we can either do it using the modulation scheme or the inversion flag\r
+// we've done both below to prove that it works either way, and the modulation value for BiPhase 50 in the Atmel data sheet of binary "10001" (17) is a typo,\r
+// and it should actually be "10000" (16)\r
+// #define T55X7_FDXB_CONFIG_BLOCK 903F8080 // emulate fdx-b - xtended mode, BiPhase ('57), data rate 32, 4 data blocks\r
+#define T55X7_FDXB_CONFIG_BLOCK 0x903F0082 // emulate fdx-b - xtended mode, BiPhase ('50), invert data, data rate 32, 4 data blocks\r
+#define T55X7_HID_26_CONFIG_BLOCK 0x00107060 // hid 26 bit - compat mode, FSK2a, data rate 50, 3 data blocks\r
+#define T55X7_INDALA_64_CONFIG_BLOCK 0x00081040 // emulate indala 64 bit - compat mode, PSK1, psk carrier FC * 2, data rate 32, maxblock 2\r
+#define T55X7_INDALA_224_CONFIG_BLOCK 0x000810E0 // emulate indala 224 bit - compat mode, PSK1, psk carrier FC * 2, data rate 32, maxblock 7\r
+#define T55X7_GUARDPROXII_CONFIG_BLOCK 0x00150060 // bitrate 64pcb, Direct modulation, Biphase, 3 data blocks\r
+#define T55X7_VIKING_CONFIG_BLOCK 0x00088040 // compat mode, data rate 32, Manchester, 2 data blocks\r
+#define T55X7_bin 0b0010\r
+\r
+\r
typedef struct {\r
enum {\r
DEMOD_NRZ = 0x00, \r
--- /dev/null
+#include <stdio.h>
+#include <string.h>
+#include <inttypes.h>
+#include "proxmark3.h"
+#include "ui.h"
+#include "util.h"
+#include "graph.h"
+#include "cmdparser.h"
+#include "cmddata.h"
+#include "cmdmain.h"
+#include "cmdlf.h"
+#include "cmdlfviking.h"
+#include "lfdemod.h"
+static int CmdHelp(const char *Cmd);
+int CmdVikingDemod(const char *Cmd)
+{
+ uint8_t id[4];
+ if (param_gethex(Cmd,0,id,8) == 1)
+ {
+ PrintAndLog("Usage: lf viking demod <CardID 8 bytes of hex number>");
+ return 0;
+ }
+ UsbCommand c = {CMD_ACQUIRE_RAW_ADC_SAMPLES_125K, {false,0,0}};
+ SendCommand(&c);
+ WaitForResponse(CMD_ACK,NULL);
+ getSamples("40000",true);
+ // try to demod AMViking
+ return AMVikingDemod(id);
+}
+int CmdVikingClone(const char *Cmd)
+{
+ uint32_t b1,b2;
+ // get the tag number 64 bits (8 bytes) in hex
+ uint8_t id[8];
+ if (param_gethex(Cmd,0,id,16) == 1)
+ {
+ PrintAndLog("Usage: lf viking clone <Card ID 16 bytes of hex number>");
+ return 0;
+ }
+ b1 = bytes_to_num(id,sizeof(uint32_t));
+ b2 = bytes_to_num(id + sizeof(uint32_t),sizeof(uint32_t));
+ UsbCommand c = {CMD_VIKING_CLONE_TAG,{b1,b2}};
+ SendCommand(&c);
+ return 0;
+}
+
+static command_t CommandTable[] =
+{
+ {"help", CmdHelp, 1, "This help"},
+ {"demod",CmdVikingDemod ,1, "<8 digits tag id> -- Extract tag data"},
+ {"clone", CmdVikingClone, 1, "<16 digits card data> clone viking tag"},
+ {NULL, NULL, 0, NULL}
+};
+
+int CmdLFViking(const char *Cmd)
+{
+ CmdsParse(CommandTable, Cmd);
+ return 0;
+}
+
+int CmdHelp(const char *Cmd)
+{
+ CmdsHelp(CommandTable);
+ return 0;
+}
--- /dev/null
+#ifndef CMDLFVIKING_H__
+#define CMDLFVIKING_H__
+int CmdLFViking(const char *Cmd);
+int CmdVikingDemod(const char *Cmd);
+int CmdVikingClone(const char *Cmd);
+#endif
+
static int CmdLS(const char *Cmd);
//For storing command that are received from the device
+#define CMD_BUFFER_SIZE 50
static UsbCommand cmdBuffer[CMD_BUFFER_SIZE];
//Points to the next empty position to write to
static int cmd_head;//Starts as 0
response = &resp;
// Wait until the command is received
- for(size_t dm_seconds=0; dm_seconds < ms_timeout/10; dm_seconds++) {
+ for ( size_t dm_seconds = 0; dm_seconds < ms_timeout/10; dm_seconds++ ) {
- while(getCommand(response)) {
+ while( getCommand(response) ) {
if(response->cmd == cmd){
return true;
}
}
bool WaitForResponse(uint32_t cmd, UsbCommand* response) {
- return WaitForResponseTimeout(cmd,response,-1);
+ return WaitForResponseTimeout(cmd, response, -1);
}
//-----------------------------------------------------------------------------
return;
} break;
- default: break;
- }
+ default:
storeCommand(UC);
+ break;
+ }
+
}
#define CMD_ASK_SIM_TAG 0x021F
#define CMD_PSK_SIM_TAG 0x0220
#define CMD_AWID_DEMOD_FSK 0x0221
+#define CMD_VIKING_CLONE_TAG 0x0222
/* CMD_SET_ADC_MUX: ext1 is 0 for lopkd, 1 for loraw, 2 for hipkd, 3 for hiraw */
CMD_ASK_SIM_TAG = 0x021F,
CMD_PSK_SIM_TAG = 0x0220,
CMD_AWID_DEMOD_FSK = 0x0221,
-
+ CMD_VIKING_CLONE_TAG = 0x0222,
+
--/* CMD_SET_ADC_MUX: ext1 is 0 for lopkd, 1 for loraw, 2 for hipkd, 3 for hiraw */
--// For the 13.56 MHz tags
return o
end,
parse = function(packet)
- local count, cmd, arg1, arg2, arg3, data = bin.unpack('LLLLH512', packet)
+ local count, cmd, arg1, arg2, arg3, data = bin.unpack('LLLLH511', packet)
return Command:new{cmd = cmd, arg1 = arg1, arg2 = arg2, arg3 = arg3, data = data}
end
return resp.arg[0]; // error during nested\r
}\r
\r
- memcpy(&uid, resp.d.asBytes, 4);\r
+ memcpy(&uid, resp.d.asBytes, 4);\r
PrintAndLog("uid:%08x trgbl=%d trgkey=%x", uid, (uint16_t)resp.arg[2] & 0xff, (uint16_t)resp.arg[2] >> 8);\r
\r
- for (i = 0; i < 2; i++) {\r
- statelists[i].blockNo = resp.arg[2] & 0xff;\r
- statelists[i].keyType = (resp.arg[2] >> 8) & 0xff;\r
- statelists[i].uid = uid;\r
- memcpy(&statelists[i].nt, (void *)(resp.d.asBytes + 4 + i * 8 + 0), 4);\r
- memcpy(&statelists[i].ks1, (void *)(resp.d.asBytes + 4 + i * 8 + 4), 4);\r
- }\r
+ for (i = 0; i < 2; i++) {\r
+ statelists[i].blockNo = resp.arg[2] & 0xff;\r
+ statelists[i].keyType = (resp.arg[2] >> 8) & 0xff;\r
+ statelists[i].uid = uid;\r
+ memcpy(&statelists[i].nt, (void *)(resp.d.asBytes + 4 + i * 8 + 0), 4);\r
+ memcpy(&statelists[i].ks1, (void *)(resp.d.asBytes + 4 + i * 8 + 4), 4);\r
+ }\r
\r
// calc keys\r
\r
}\r
\r
free(statelists[0].head.slhead);\r
- free(statelists[1].head.slhead);\r
- \r
+ free(statelists[1].head.slhead); \r
return 0;\r
}\r
\r
\r
UsbCommand c = {CMD_MIFARE_CHKKEYS, {((blockNo & 0xff) | ((keyType&0xff)<<8)), clear_trace, keycnt}};\r
memcpy(c.d.asBytes, keyBlock, 6 * keycnt);\r
+ \r
+ clearCommandBuffer();\r
SendCommand(&c);\r
-\r
UsbCommand resp;\r
if (!WaitForResponseTimeout(CMD_ACK,&resp,3000)) return 1;\r
if ((resp.arg[0] & 0xff) != 0x01) return 2;\r
\r
int mfEmlGetMem(uint8_t *data, int blockNum, int blocksCount) {\r
UsbCommand c = {CMD_MIFARE_EML_MEMGET, {blockNum, blocksCount, 0}};\r
+ clearCommandBuffer();\r
SendCommand(&c);\r
-\r
UsbCommand resp;\r
if (!WaitForResponseTimeout(CMD_ACK,&resp,1500)) return 1;\r
memcpy(data, resp.d.asBytes, blocksCount * 16);\r
}\r
\r
int mfEmlSetMem(uint8_t *data, int blockNum, int blocksCount) {\r
- UsbCommand c = {CMD_MIFARE_EML_MEMSET, {blockNum, blocksCount, 0}};\r
- memcpy(c.d.asBytes, data, blocksCount * 16); \r
+ return mfEmlSetMem_xt(data, blockNum, blocksCount, 16);\r
+}\r
+\r
+int mfEmlSetMem_xt(uint8_t *data, int blockNum, int blocksCount, int blockBtWidth) {\r
+ UsbCommand c = {CMD_MIFARE_EML_MEMSET, {blockNum, blocksCount, blockBtWidth}};\r
+ memcpy(c.d.asBytes, data, blocksCount * blockBtWidth); \r
+\r
+ clearCommandBuffer();\r
SendCommand(&c);\r
return 0;\r
}\r
uint8_t isOK = 0;\r
UsbCommand c = {CMD_MIFARE_CSETBLOCK, {wantWipe, params & (0xFE | (uid == NULL ? 0:1)), blockNo}};\r
memcpy(c.d.asBytes, data, 16); \r
- SendCommand(&c);\r
\r
+ clearCommandBuffer();\r
+ SendCommand(&c);\r
UsbCommand resp;\r
if (WaitForResponseTimeout(CMD_ACK,&resp,1500)) {\r
isOK = resp.arg[0] & 0xff;\r
uint8_t isOK = 0;\r
\r
UsbCommand c = {CMD_MIFARE_CGETBLOCK, {params, 0, blockNo}};\r
+ \r
+ clearCommandBuffer();\r
SendCommand(&c);\r
-\r
- UsbCommand resp;\r
+ UsbCommand resp;\r
if (WaitForResponseTimeout(CMD_ACK,&resp,1500)) {\r
isOK = resp.arg[0] & 0xff;\r
memcpy(data, resp.d.asBytes, 16);\r
\r
int mfEmlGetMem(uint8_t *data, int blockNum, int blocksCount);\r
int mfEmlSetMem(uint8_t *data, int blockNum, int blocksCount);\r
+int mfEmlSetMem_xt(uint8_t *data, int blockNum, int blocksCount, int blockBtWidth);\r
\r
int mfCSetUID(uint8_t *uid, uint8_t *atqa, uint8_t *sak, uint8_t *oldUID, bool wantWipe);\r
int mfCSetBlock(uint8_t blockNo, uint8_t *data, uint8_t *uid, bool wantWipe, uint8_t params);\r
}
int nonce2key(uint32_t uid, uint32_t nt, uint32_t nr, uint64_t par_info, uint64_t ks_info, uint64_t * key) {
- struct Crypto1State *state;
- uint32_t i, pos, rr, nr_diff, key_count;//, ks1, ks2;
- byte_t bt, ks3x[8], par[8][8];
- uint64_t key_recovered;
- int64_t *state_s;
- static uint32_t last_uid;
- static int64_t *last_keylist;
- rr = 0;
+ struct Crypto1State *state;
+ uint32_t i, pos, rr, nr_diff, key_count;//, ks1, ks2;
+ byte_t bt, ks3x[8], par[8][8];
+ uint64_t key_recovered;
+ int64_t *state_s;
+ static uint32_t last_uid;
+ static int64_t *last_keylist;
+ rr = 0;
- if (last_uid != uid && last_keylist != NULL)
- {
- free(last_keylist);
- last_keylist = NULL;
- }
- last_uid = uid;
+ if (last_uid != uid && last_keylist != NULL) {
+ free(last_keylist);
+ last_keylist = NULL;
+ }
+ last_uid = uid;
- // Reset the last three significant bits of the reader nonce
- nr &= 0xffffff1f;
+ // Reset the last three significant bits of the reader nonce
+ nr &= 0xffffff1f;
- PrintAndLog("\nuid(%08x) nt(%08x) par(%016"llx") ks(%016"llx") nr(%08"llx")\n\n",uid,nt,par_info,ks_info,nr);
+ PrintAndLog("\nuid(%08x) nt(%08x) par(%016"llx") ks(%016"llx") nr(%08"llx")\n\n", uid, nt, par_info, ks_info, nr);
+
+ for (pos=0; pos<8; pos++) {
+ ks3x[7-pos] = (ks_info >> (pos*8)) & 0x0f;
+ bt = (par_info >> (pos*8)) & 0xff;
+ for (i=0; i<8; i++) {
+ par[7-pos][i] = (bt >> i) & 0x01;
+ }
+ }
- for (pos=0; pos<8; pos++)
- {
- ks3x[7-pos] = (ks_info >> (pos*8)) & 0x0f;
- bt = (par_info >> (pos*8)) & 0xff;
- for (i=0; i<8; i++)
- {
- par[7-pos][i] = (bt >> i) & 0x01;
- }
- }
+ printf("|diff|{nr} |ks3|ks3^5|parity |\n");
+ printf("+----+--------+---+-----+---------------+\n");
+ for (i=0; i<8; i++) {
+ nr_diff = nr | i << 5;
+ printf("| %02x |%08x|", i << 5, nr_diff);
+ printf(" %01x | %01x |", ks3x[i], ks3x[i]^5);
+ for (pos=0; pos<7; pos++)
+ printf("%01x,", par[i][pos]);
+ printf("%01x|\n", par[i][7]);
+ }
+ printf("+----+--------+---+-----+---------------+\n");
- printf("|diff|{nr} |ks3|ks3^5|parity |\n");
- printf("+----+--------+---+-----+---------------+\n");
- for (i=0; i<8; i++)
- {
- nr_diff = nr | i << 5;
- printf("| %02x |%08x|",i << 5, nr_diff);
- printf(" %01x | %01x |",ks3x[i], ks3x[i]^5);
- for (pos=0; pos<7; pos++) printf("%01x,", par[i][pos]);
- printf("%01x|\n", par[i][7]);
- }
-
- if (par_info==0)
- PrintAndLog("parity is all zero,try special attack!just wait for few more seconds...");
+ if ( par_info == 0 )
+ PrintAndLog("Parity is all zero, try special attack! Wait for few more seconds...");
state = lfsr_common_prefix(nr, rr, ks3x, par, par_info==0);
state_s = (int64_t*)state;
*(state_s + i) = -1;
//Create the intersection:
- if (par_info == 0 )
- if ( last_keylist != NULL)
- {
+ if (par_info == 0 ) {
+ if ( last_keylist != NULL) {
int64_t *p1, *p2, *p3;
p1 = p3 = last_keylist;
p2 = state_s;
while ( *p1 != -1 && *p2 != -1 ) {
if (compar_state(p1, p2) == 0) {
- printf("p1:%"llx" p2:%"llx" p3:%"llx" key:%012"llx"\n",(uint64_t)(p1-last_keylist),(uint64_t)(p2-state_s),(uint64_t)(p3-last_keylist),*p1);
+ printf("p1:%"llx" p2:%"llx" p3:%"llx" key:%012"llx"\n",
+ (uint64_t)(p1-last_keylist),
+ (uint64_t)(p2-state_s),
+ (uint64_t)(p3-last_keylist),
+ *p1);
*p3++ = *p1++;
p2++;
- }
- else {
+ } else {
while (compar_state(p1, p2) == -1) ++p1;
while (compar_state(p1, p2) == 1) ++p2;
}
}
- key_count = p3 - last_keylist;;
- }
- else
+ key_count = p3 - last_keylist;
+ } else {
key_count = 0;
- else
- {
+ }
+ } else {
last_keylist = state_s;
key_count = i;
}
- printf("key_count:%d\n", key_count);
+ printf("key candidates count: %d\n", key_count);
// The list may still contain several key candidates. Test each of them with mfCheckKeys
+ int res;
+ uint8_t keyBlock[6];
+ uint64_t key64;
for (i = 0; i < key_count; i++) {
- uint8_t keyBlock[6];
- uint64_t key64;
+
key64 = *(last_keylist + i);
num_to_bytes(key64, 6, keyBlock);
key64 = 0;
- if (!mfCheckKeys(0, 0, false, 1, keyBlock, &key64)) {
+ res = mfCheckKeys(0, 0, false, 1, keyBlock, &key64);
+ if (!res) {
*key = key64;
free(last_keylist);
last_keylist = NULL;
- if (par_info ==0)
+ if (par_info == 0)
free(state);
return 0;
}
}
-
free(last_keylist);
last_keylist = state_s;
-
return 1;
}
return isSuccess;
}
-
int tryMfk64(uint64_t myuid, uint8_t *data, uint8_t *outputkey ){
struct Crypto1State *revstate;
--- /dev/null
+-- The getopt-functionality is loaded from pm3/getopt.lua
+-- Have a look there for further details
+getopt = require('getopt')
+bin = require('bin')
+
+example = "script run dumptoemul -i dumpdata-foobar.bin"
+author = "Martin Holst Swende"
+usage = "script run dumptoemul [-i <file>] [-o <file>]"
+desc =[[
+This script takes a dumpfile from 'hf mf dump' and converts it to a format that can be used
+by the emulator
+
+Arguments:
+ -h This help
+ -i <file> Specifies the dump-file (input). If omitted, 'dumpdata.bin' is used
+ -o <filename> Specifies the output file. If omitted, <uid>.eml is used.
+
+]]
+
+-------------------------------
+-- Some utilities
+-------------------------------
+
+---
+-- A debug printout-function
+function dbg(args)
+ if DEBUG then
+ print("###", args)
+ end
+end
+---
+-- This is only meant to be used when errors occur
+function oops(err)
+ print("ERROR: ",err)
+end
+
+
+---
+-- Usage help
+function help()
+ print(desc)
+ print("Example usage")
+ print(example)
+end
+
+local function convert_to_ascii(hexdata)
+ if string.len(hexdata) % 8 ~= 0 then
+ return oops(("Bad data, length should be a multiple of 8 (was %d)"):format(string.len(hexdata)))
+ end
+
+ local js,i = "[";
+ for i = 1, string.len(hexdata),8 do
+ js = js .."'" ..string.sub(hexdata,i,i+7).."',\n"
+ end
+ js = js .. "]"
+ return js
+end
+
+local function readdump(infile)
+ t = infile:read("*all")
+ --print(string.len(t))
+ len = string.len(t)
+ local len,hex = bin.unpack(("H%d"):format(len),t)
+ --print(len,hex)
+ return hex
+end
+
+local function convert_to_emulform(hexdata)
+ if string.len(hexdata) % 8 ~= 0 then
+ return oops(("Bad data, length should be a multiple of 8 (was %d)"):format(string.len(hexdata)))
+ end
+ local ascii,i = "";
+ for i = 1, string.len(hexdata),8 do
+ ascii = ascii ..string.sub(hexdata,i,i+7).."\n"
+ end
+
+ return string.sub(ascii,1,-1)
+end
+
+local function main(args)
+
+ local input = "dumpdata.bin"
+ local output
+
+ for o, a in getopt.getopt(args, 'i:o:h') do
+ if o == "h" then return help() end
+ if o == "i" then input = a end
+ if o == "o" then output = a end
+ end
+ -- Validate the parameters
+
+ local infile = io.open(input, "rb")
+ if infile == nil then
+ return oops("Could not read file ", input)
+ end
+ local dumpdata = readdump(infile)
+ -- The hex-data is now in ascii-format,
+
+ -- But first, check the uid
+ local uid = string.sub(dumpdata,1,8)
+ output = output or (uid .. ".eml")
+
+ -- Format some linebreaks
+ dumpdata = convert_to_emulform(dumpdata)
+
+ local outfile = io.open(output, "w")
+ if outfile == nil then
+ return oops("Could not write to file ", output)
+ end
+
+ outfile:write(dumpdata:lower())
+ io.close(outfile)
+ print(("Wrote an emulator-dump to the file %s"):format(output))
+end
+
+
+--[[
+In the future, we may implement so that scripts are invoked directly
+into a 'main' function, instead of being executed blindly. For future
+compatibility, I have done so, but I invoke my main from here.
+--]]
+main(args)
return nil, "Card is not vulnerable to Darkside attack (doesn't send NACK on authentication requests). You can try 'script run mfkeys' or 'hf mf chk' to test various known keys."
elseif isOK == 0xFFFFFFFD then
return nil, "Card is not vulnerable to Darkside attack (its random number generator is not predictable). You can try 'script run mfkeys' or 'hf mf chk' to test various known keys."
+ elseif isOK == 0xFFFFFFFC then
+ return nil, "The card's random number generator is vulnerable but behaves somewhat weird (Mifare clone?). You can try 'script run mfkeys' or 'hf mf chk' to test various known keys."
elseif isOK ~= 1 then
return nil, "Error occurred"
end
uint8_t *SwapEndian64(const uint8_t *src, const size_t len, const uint8_t blockSize);
char param_getchar(const char *line, int paramnum);
+int param_getptr(const char *line, int *bg, int *en, int paramnum);
uint8_t param_get8(const char *line, int paramnum);
uint8_t param_get8ex(const char *line, int paramnum, int deflt, int base);
uint32_t param_get32ex(const char *line, int paramnum, int deflt, int base);
}\r
\r
bool cmd_send(uint32_t cmd, uint32_t arg0, uint32_t arg1, uint32_t arg2, void* data, size_t len) {\r
- UsbCommand txcmd;\r
\r
- for (size_t i=0; i<sizeof(UsbCommand); i++) {\r
- ((byte_t*)&txcmd)[i] = 0x00;\r
- }\r
- \r
- // Compose the outgoing command frame\r
- txcmd.cmd = cmd;\r
- txcmd.arg[0] = arg0;\r
- txcmd.arg[1] = arg1; \r
- txcmd.arg[2] = arg2;\r
+ UsbCommand txcmd;\r
\r
- // Add the (optional) content to the frame, with a maximum size of USB_CMD_DATA_SIZE\r
- if (data && len) {\r
- len = MIN(len,USB_CMD_DATA_SIZE);\r
- for (size_t i=0; i<len; i++) {\r
- txcmd.d.asBytes[i] = ((byte_t*)data)[i];\r
- }\r
- }\r
- \r
- // Send frame and make sure all bytes are transmitted\r
- if (usb_write((byte_t*)&txcmd,sizeof(UsbCommand)) != 0) return false;\r
- \r
- return true;\r
+ // 0x00 the whole command.\r
+ for (size_t i=0; i < sizeof(UsbCommand); i++)\r
+ ((byte_t*)&txcmd)[i] = 0x00;\r
+\r
+ // Compose the outgoing command frame\r
+ txcmd.cmd = cmd;\r
+ txcmd.arg[0] = arg0;\r
+ txcmd.arg[1] = arg1; \r
+ txcmd.arg[2] = arg2;\r
+\r
+ // Add the (optional) content to the frame, with a maximum size of USB_CMD_DATA_SIZE\r
+ if (data && len) {\r
+ len = MIN(len, USB_CMD_DATA_SIZE);\r
+ for (size_t i=0; i<len; i++) {\r
+ txcmd.d.asBytes[i] = ((byte_t*)data)[i];\r
+ }\r
+ }\r
+\r
+ // Send frame and make sure all bytes are transmitted\r
+ if ( usb_write( (byte_t*)&txcmd, sizeof(UsbCommand)) != 0)\r
+ return false;\r
+\r
+ return true;\r
}\r
\r
\r
--- /dev/null
+/*
+ * HMAC_DRBG implementation (NIST SP 800-90)
+ *
+ * Copyright (C) 2014, ARM Limited, All Rights Reserved
+ *
+ * This file is part of mbed TLS (https://tls.mbed.org)
+ *
+ * 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.
+ */
+
+/*
+ * The NIST SP 800-90A DRBGs are described in the following publication.
+ * http://csrc.nist.gov/publications/nistpubs/800-90A/SP800-90A.pdf
+ * References below are based on rev. 1 (January 2012).
+ */
+
+#if !defined(MBEDTLS_CONFIG_FILE)
+#include "mbedtls/config.h"
+#else
+#include MBEDTLS_CONFIG_FILE
+#endif
+
+#if defined(MBEDTLS_HMAC_DRBG_C)
+
+#include "mbedtls/hmac_drbg.h"
+
+#include <string.h>
+
+#if defined(MBEDTLS_FS_IO)
+#include <stdio.h>
+#endif
+
+#if defined(MBEDTLS_SELF_TEST)
+#if defined(MBEDTLS_PLATFORM_C)
+#include "mbedtls/platform.h"
+#else
+#include <stdio.h>
+#define mbedtls_printf printf
+#endif /* MBEDTLS_SELF_TEST */
+#endif /* MBEDTLS_PLATFORM_C */
+
+/* Implementation that should never be optimized out by the compiler */
+static void mbedtls_zeroize( void *v, size_t n ) {
+ volatile unsigned char *p = v; while( n-- ) *p++ = 0;
+}
+
+/*
+ * HMAC_DRBG context initialization
+ */
+void mbedtls_hmac_drbg_init( mbedtls_hmac_drbg_context *ctx )
+{
+ memset( ctx, 0, sizeof( mbedtls_hmac_drbg_context ) );
+
+#if defined(MBEDTLS_THREADING_C)
+ mbedtls_mutex_init( &ctx->mutex );
+#endif
+}
+
+/*
+ * HMAC_DRBG update, using optional additional data (10.1.2.2)
+ */
+void mbedtls_hmac_drbg_update( mbedtls_hmac_drbg_context *ctx,
+ const unsigned char *additional, size_t add_len )
+{
+ size_t md_len = mbedtls_md_get_size( ctx->md_ctx.md_info );
+ unsigned char rounds = ( additional != NULL && add_len != 0 ) ? 2 : 1;
+ unsigned char sep[1];
+ unsigned char K[MBEDTLS_MD_MAX_SIZE];
+
+ for( sep[0] = 0; sep[0] < rounds; sep[0]++ )
+ {
+ /* Step 1 or 4 */
+ mbedtls_md_hmac_reset( &ctx->md_ctx );
+ mbedtls_md_hmac_update( &ctx->md_ctx, ctx->V, md_len );
+ mbedtls_md_hmac_update( &ctx->md_ctx, sep, 1 );
+ if( rounds == 2 )
+ mbedtls_md_hmac_update( &ctx->md_ctx, additional, add_len );
+ mbedtls_md_hmac_finish( &ctx->md_ctx, K );
+
+ /* Step 2 or 5 */
+ mbedtls_md_hmac_starts( &ctx->md_ctx, K, md_len );
+ mbedtls_md_hmac_update( &ctx->md_ctx, ctx->V, md_len );
+ mbedtls_md_hmac_finish( &ctx->md_ctx, ctx->V );
+ }
+}
+
+/*
+ * Simplified HMAC_DRBG initialisation (for use with deterministic ECDSA)
+ */
+int mbedtls_hmac_drbg_seed_buf( mbedtls_hmac_drbg_context *ctx,
+ const mbedtls_md_info_t * md_info,
+ const unsigned char *data, size_t data_len )
+{
+ int ret;
+
+ if( ( ret = mbedtls_md_setup( &ctx->md_ctx, md_info, 1 ) ) != 0 )
+ return( ret );
+
+ /*
+ * Set initial working state.
+ * Use the V memory location, which is currently all 0, to initialize the
+ * MD context with an all-zero key. Then set V to its initial value.
+ */
+ mbedtls_md_hmac_starts( &ctx->md_ctx, ctx->V, mbedtls_md_get_size( md_info ) );
+ memset( ctx->V, 0x01, mbedtls_md_get_size( md_info ) );
+
+ mbedtls_hmac_drbg_update( ctx, data, data_len );
+
+ return( 0 );
+}
+
+/*
+ * HMAC_DRBG reseeding: 10.1.2.4 (arabic) + 9.2 (Roman)
+ */
+int mbedtls_hmac_drbg_reseed( mbedtls_hmac_drbg_context *ctx,
+ const unsigned char *additional, size_t len )
+{
+ unsigned char seed[MBEDTLS_HMAC_DRBG_MAX_SEED_INPUT];
+ size_t seedlen;
+
+ /* III. Check input length */
+ if( len > MBEDTLS_HMAC_DRBG_MAX_INPUT ||
+ ctx->entropy_len + len > MBEDTLS_HMAC_DRBG_MAX_SEED_INPUT )
+ {
+ return( MBEDTLS_ERR_HMAC_DRBG_INPUT_TOO_BIG );
+ }
+
+ memset( seed, 0, MBEDTLS_HMAC_DRBG_MAX_SEED_INPUT );
+
+ /* IV. Gather entropy_len bytes of entropy for the seed */
+ if( ctx->f_entropy( ctx->p_entropy, seed, ctx->entropy_len ) != 0 )
+ return( MBEDTLS_ERR_HMAC_DRBG_ENTROPY_SOURCE_FAILED );
+
+ seedlen = ctx->entropy_len;
+
+ /* 1. Concatenate entropy and additional data if any */
+ if( additional != NULL && len != 0 )
+ {
+ memcpy( seed + seedlen, additional, len );
+ seedlen += len;
+ }
+
+ /* 2. Update state */
+ mbedtls_hmac_drbg_update( ctx, seed, seedlen );
+
+ /* 3. Reset reseed_counter */
+ ctx->reseed_counter = 1;
+
+ /* 4. Done */
+ return( 0 );
+}
+
+/*
+ * HMAC_DRBG initialisation (10.1.2.3 + 9.1)
+ */
+int mbedtls_hmac_drbg_seed( mbedtls_hmac_drbg_context *ctx,
+ const mbedtls_md_info_t * md_info,
+ int (*f_entropy)(void *, unsigned char *, size_t),
+ void *p_entropy,
+ const unsigned char *custom,
+ size_t len )
+{
+ int ret;
+ size_t entropy_len, md_size;
+
+ if( ( ret = mbedtls_md_setup( &ctx->md_ctx, md_info, 1 ) ) != 0 )
+ return( ret );
+
+ md_size = mbedtls_md_get_size( md_info );
+
+ /*
+ * Set initial working state.
+ * Use the V memory location, which is currently all 0, to initialize the
+ * MD context with an all-zero key. Then set V to its initial value.
+ */
+ mbedtls_md_hmac_starts( &ctx->md_ctx, ctx->V, md_size );
+ memset( ctx->V, 0x01, md_size );
+
+ ctx->f_entropy = f_entropy;
+ ctx->p_entropy = p_entropy;
+
+ ctx->reseed_interval = MBEDTLS_HMAC_DRBG_RESEED_INTERVAL;
+
+ /*
+ * See SP800-57 5.6.1 (p. 65-66) for the security strength provided by
+ * each hash function, then according to SP800-90A rev1 10.1 table 2,
+ * min_entropy_len (in bits) is security_strength.
+ *
+ * (This also matches the sizes used in the NIST test vectors.)
+ */
+ entropy_len = md_size <= 20 ? 16 : /* 160-bits hash -> 128 bits */
+ md_size <= 28 ? 24 : /* 224-bits hash -> 192 bits */
+ 32; /* better (256+) -> 256 bits */
+
+ /*
+ * For initialisation, use more entropy to emulate a nonce
+ * (Again, matches test vectors.)
+ */
+ ctx->entropy_len = entropy_len * 3 / 2;
+
+ if( ( ret = mbedtls_hmac_drbg_reseed( ctx, custom, len ) ) != 0 )
+ return( ret );
+
+ ctx->entropy_len = entropy_len;
+
+ return( 0 );
+}
+
+/*
+ * Set prediction resistance
+ */
+void mbedtls_hmac_drbg_set_prediction_resistance( mbedtls_hmac_drbg_context *ctx,
+ int resistance )
+{
+ ctx->prediction_resistance = resistance;
+}
+
+/*
+ * Set entropy length grabbed for reseeds
+ */
+void mbedtls_hmac_drbg_set_entropy_len( mbedtls_hmac_drbg_context *ctx, size_t len )
+{
+ ctx->entropy_len = len;
+}
+
+/*
+ * Set reseed interval
+ */
+void mbedtls_hmac_drbg_set_reseed_interval( mbedtls_hmac_drbg_context *ctx, int interval )
+{
+ ctx->reseed_interval = interval;
+}
+
+/*
+ * HMAC_DRBG random function with optional additional data:
+ * 10.1.2.5 (arabic) + 9.3 (Roman)
+ */
+int mbedtls_hmac_drbg_random_with_add( void *p_rng,
+ unsigned char *output, size_t out_len,
+ const unsigned char *additional, size_t add_len )
+{
+ int ret;
+ mbedtls_hmac_drbg_context *ctx = (mbedtls_hmac_drbg_context *) p_rng;
+ size_t md_len = mbedtls_md_get_size( ctx->md_ctx.md_info );
+ size_t left = out_len;
+ unsigned char *out = output;
+
+ /* II. Check request length */
+ if( out_len > MBEDTLS_HMAC_DRBG_MAX_REQUEST )
+ return( MBEDTLS_ERR_HMAC_DRBG_REQUEST_TOO_BIG );
+
+ /* III. Check input length */
+ if( add_len > MBEDTLS_HMAC_DRBG_MAX_INPUT )
+ return( MBEDTLS_ERR_HMAC_DRBG_INPUT_TOO_BIG );
+
+ /* 1. (aka VII and IX) Check reseed counter and PR */
+ if( ctx->f_entropy != NULL && /* For no-reseeding instances */
+ ( ctx->prediction_resistance == MBEDTLS_HMAC_DRBG_PR_ON ||
+ ctx->reseed_counter > ctx->reseed_interval ) )
+ {
+ if( ( ret = mbedtls_hmac_drbg_reseed( ctx, additional, add_len ) ) != 0 )
+ return( ret );
+
+ add_len = 0; /* VII.4 */
+ }
+
+ /* 2. Use additional data if any */
+ if( additional != NULL && add_len != 0 )
+ mbedtls_hmac_drbg_update( ctx, additional, add_len );
+
+ /* 3, 4, 5. Generate bytes */
+ while( left != 0 )
+ {
+ size_t use_len = left > md_len ? md_len : left;
+
+ mbedtls_md_hmac_reset( &ctx->md_ctx );
+ mbedtls_md_hmac_update( &ctx->md_ctx, ctx->V, md_len );
+ mbedtls_md_hmac_finish( &ctx->md_ctx, ctx->V );
+
+ memcpy( out, ctx->V, use_len );
+ out += use_len;
+ left -= use_len;
+ }
+
+ /* 6. Update */
+ mbedtls_hmac_drbg_update( ctx, additional, add_len );
+
+ /* 7. Update reseed counter */
+ ctx->reseed_counter++;
+
+ /* 8. Done */
+ return( 0 );
+}
+
+/*
+ * HMAC_DRBG random function
+ */
+int mbedtls_hmac_drbg_random( void *p_rng, unsigned char *output, size_t out_len )
+{
+ int ret;
+ mbedtls_hmac_drbg_context *ctx = (mbedtls_hmac_drbg_context *) p_rng;
+
+#if defined(MBEDTLS_THREADING_C)
+ if( ( ret = mbedtls_mutex_lock( &ctx->mutex ) ) != 0 )
+ return( ret );
+#endif
+
+ ret = mbedtls_hmac_drbg_random_with_add( ctx, output, out_len, NULL, 0 );
+
+#if defined(MBEDTLS_THREADING_C)
+ if( mbedtls_mutex_unlock( &ctx->mutex ) != 0 )
+ return( MBEDTLS_ERR_THREADING_MUTEX_ERROR );
+#endif
+
+ return( ret );
+}
+
+/*
+ * Free an HMAC_DRBG context
+ */
+void mbedtls_hmac_drbg_free( mbedtls_hmac_drbg_context *ctx )
+{
+ if( ctx == NULL )
+ return;
+
+#if defined(MBEDTLS_THREADING_C)
+ mbedtls_mutex_free( &ctx->mutex );
+#endif
+ mbedtls_md_free( &ctx->md_ctx );
+ mbedtls_zeroize( ctx, sizeof( mbedtls_hmac_drbg_context ) );
+}
+
+#if defined(MBEDTLS_FS_IO)
+int mbedtls_hmac_drbg_write_seed_file( mbedtls_hmac_drbg_context *ctx, const char *path )
+{
+ int ret;
+ FILE *f;
+ unsigned char buf[ MBEDTLS_HMAC_DRBG_MAX_INPUT ];
+
+ if( ( f = fopen( path, "wb" ) ) == NULL )
+ return( MBEDTLS_ERR_HMAC_DRBG_FILE_IO_ERROR );
+
+ if( ( ret = mbedtls_hmac_drbg_random( ctx, buf, sizeof( buf ) ) ) != 0 )
+ goto exit;
+
+ if( fwrite( buf, 1, sizeof( buf ), f ) != sizeof( buf ) )
+ {
+ ret = MBEDTLS_ERR_HMAC_DRBG_FILE_IO_ERROR;
+ goto exit;
+ }
+
+ ret = 0;
+
+exit:
+ fclose( f );
+ return( ret );
+}
+
+int mbedtls_hmac_drbg_update_seed_file( mbedtls_hmac_drbg_context *ctx, const char *path )
+{
+ FILE *f;
+ size_t n;
+ unsigned char buf[ MBEDTLS_HMAC_DRBG_MAX_INPUT ];
+
+ if( ( f = fopen( path, "rb" ) ) == NULL )
+ return( MBEDTLS_ERR_HMAC_DRBG_FILE_IO_ERROR );
+
+ fseek( f, 0, SEEK_END );
+ n = (size_t) ftell( f );
+ fseek( f, 0, SEEK_SET );
+
+ if( n > MBEDTLS_HMAC_DRBG_MAX_INPUT )
+ {
+ fclose( f );
+ return( MBEDTLS_ERR_HMAC_DRBG_INPUT_TOO_BIG );
+ }
+
+ if( fread( buf, 1, n, f ) != n )
+ {
+ fclose( f );
+ return( MBEDTLS_ERR_HMAC_DRBG_FILE_IO_ERROR );
+ }
+
+ fclose( f );
+
+ mbedtls_hmac_drbg_update( ctx, buf, n );
+
+ return( mbedtls_hmac_drbg_write_seed_file( ctx, path ) );
+}
+#endif /* MBEDTLS_FS_IO */
+
+
+#if defined(MBEDTLS_SELF_TEST)
+
+#if !defined(MBEDTLS_SHA1_C)
+/* Dummy checkup routine */
+int mbedtls_hmac_drbg_self_test( int verbose )
+{
+
+ if( verbose != 0 )
+ mbedtls_printf( "\n" );
+
+ return( 0 );
+}
+#else
+
+#define OUTPUT_LEN 80
+
+/* From a NIST PR=true test vector */
+static const unsigned char entropy_pr[] = {
+ 0xa0, 0xc9, 0xab, 0x58, 0xf1, 0xe2, 0xe5, 0xa4, 0xde, 0x3e, 0xbd, 0x4f,
+ 0xf7, 0x3e, 0x9c, 0x5b, 0x64, 0xef, 0xd8, 0xca, 0x02, 0x8c, 0xf8, 0x11,
+ 0x48, 0xa5, 0x84, 0xfe, 0x69, 0xab, 0x5a, 0xee, 0x42, 0xaa, 0x4d, 0x42,
+ 0x17, 0x60, 0x99, 0xd4, 0x5e, 0x13, 0x97, 0xdc, 0x40, 0x4d, 0x86, 0xa3,
+ 0x7b, 0xf5, 0x59, 0x54, 0x75, 0x69, 0x51, 0xe4 };
+static const unsigned char result_pr[OUTPUT_LEN] = {
+ 0x9a, 0x00, 0xa2, 0xd0, 0x0e, 0xd5, 0x9b, 0xfe, 0x31, 0xec, 0xb1, 0x39,
+ 0x9b, 0x60, 0x81, 0x48, 0xd1, 0x96, 0x9d, 0x25, 0x0d, 0x3c, 0x1e, 0x94,
+ 0x10, 0x10, 0x98, 0x12, 0x93, 0x25, 0xca, 0xb8, 0xfc, 0xcc, 0x2d, 0x54,
+ 0x73, 0x19, 0x70, 0xc0, 0x10, 0x7a, 0xa4, 0x89, 0x25, 0x19, 0x95, 0x5e,
+ 0x4b, 0xc6, 0x00, 0x1d, 0x7f, 0x4e, 0x6a, 0x2b, 0xf8, 0xa3, 0x01, 0xab,
+ 0x46, 0x05, 0x5c, 0x09, 0xa6, 0x71, 0x88, 0xf1, 0xa7, 0x40, 0xee, 0xf3,
+ 0xe1, 0x5c, 0x02, 0x9b, 0x44, 0xaf, 0x03, 0x44 };
+
+/* From a NIST PR=false test vector */
+static const unsigned char entropy_nopr[] = {
+ 0x79, 0x34, 0x9b, 0xbf, 0x7c, 0xdd, 0xa5, 0x79, 0x95, 0x57, 0x86, 0x66,
+ 0x21, 0xc9, 0x13, 0x83, 0x11, 0x46, 0x73, 0x3a, 0xbf, 0x8c, 0x35, 0xc8,
+ 0xc7, 0x21, 0x5b, 0x5b, 0x96, 0xc4, 0x8e, 0x9b, 0x33, 0x8c, 0x74, 0xe3,
+ 0xe9, 0x9d, 0xfe, 0xdf };
+static const unsigned char result_nopr[OUTPUT_LEN] = {
+ 0xc6, 0xa1, 0x6a, 0xb8, 0xd4, 0x20, 0x70, 0x6f, 0x0f, 0x34, 0xab, 0x7f,
+ 0xec, 0x5a, 0xdc, 0xa9, 0xd8, 0xca, 0x3a, 0x13, 0x3e, 0x15, 0x9c, 0xa6,
+ 0xac, 0x43, 0xc6, 0xf8, 0xa2, 0xbe, 0x22, 0x83, 0x4a, 0x4c, 0x0a, 0x0a,
+ 0xff, 0xb1, 0x0d, 0x71, 0x94, 0xf1, 0xc1, 0xa5, 0xcf, 0x73, 0x22, 0xec,
+ 0x1a, 0xe0, 0x96, 0x4e, 0xd4, 0xbf, 0x12, 0x27, 0x46, 0xe0, 0x87, 0xfd,
+ 0xb5, 0xb3, 0xe9, 0x1b, 0x34, 0x93, 0xd5, 0xbb, 0x98, 0xfa, 0xed, 0x49,
+ 0xe8, 0x5f, 0x13, 0x0f, 0xc8, 0xa4, 0x59, 0xb7 };
+
+/* "Entropy" from buffer */
+static size_t test_offset;
+static int hmac_drbg_self_test_entropy( void *data,
+ unsigned char *buf, size_t len )
+{
+ const unsigned char *p = data;
+ memcpy( buf, p + test_offset, len );
+ test_offset += len;
+ return( 0 );
+}
+
+#define CHK( c ) if( (c) != 0 ) \
+ { \
+ if( verbose != 0 ) \
+ mbedtls_printf( "failed\n" ); \
+ return( 1 ); \
+ }
+
+/*
+ * Checkup routine for HMAC_DRBG with SHA-1
+ */
+int mbedtls_hmac_drbg_self_test( int verbose )
+{
+ mbedtls_hmac_drbg_context ctx;
+ unsigned char buf[OUTPUT_LEN];
+ const mbedtls_md_info_t *md_info = mbedtls_md_info_from_type( MBEDTLS_MD_SHA1 );
+
+ mbedtls_hmac_drbg_init( &ctx );
+
+ /*
+ * PR = True
+ */
+ if( verbose != 0 )
+ mbedtls_printf( " HMAC_DRBG (PR = True) : " );
+
+ test_offset = 0;
+ CHK( mbedtls_hmac_drbg_seed( &ctx, md_info,
+ hmac_drbg_self_test_entropy, (void *) entropy_pr,
+ NULL, 0 ) );
+ mbedtls_hmac_drbg_set_prediction_resistance( &ctx, MBEDTLS_HMAC_DRBG_PR_ON );
+ CHK( mbedtls_hmac_drbg_random( &ctx, buf, OUTPUT_LEN ) );
+ CHK( mbedtls_hmac_drbg_random( &ctx, buf, OUTPUT_LEN ) );
+ CHK( memcmp( buf, result_pr, OUTPUT_LEN ) );
+ mbedtls_hmac_drbg_free( &ctx );
+
+ mbedtls_hmac_drbg_free( &ctx );
+
+ if( verbose != 0 )
+ mbedtls_printf( "passed\n" );
+
+ /*
+ * PR = False
+ */
+ if( verbose != 0 )
+ mbedtls_printf( " HMAC_DRBG (PR = False) : " );
+
+ mbedtls_hmac_drbg_init( &ctx );
+
+ test_offset = 0;
+ CHK( mbedtls_hmac_drbg_seed( &ctx, md_info,
+ hmac_drbg_self_test_entropy, (void *) entropy_nopr,
+ NULL, 0 ) );
+ CHK( mbedtls_hmac_drbg_reseed( &ctx, NULL, 0 ) );
+ CHK( mbedtls_hmac_drbg_random( &ctx, buf, OUTPUT_LEN ) );
+ CHK( mbedtls_hmac_drbg_random( &ctx, buf, OUTPUT_LEN ) );
+ CHK( memcmp( buf, result_nopr, OUTPUT_LEN ) );
+ mbedtls_hmac_drbg_free( &ctx );
+
+ mbedtls_hmac_drbg_free( &ctx );
+
+ if( verbose != 0 )
+ mbedtls_printf( "passed\n" );
+
+ if( verbose != 0 )
+ mbedtls_printf( "\n" );
+
+ return( 0 );
+}
+#endif /* MBEDTLS_SHA1_C */
+#endif /* MBEDTLS_SELF_TEST */
+
+#endif /* MBEDTLS_HMAC_DRBG_C */
--- /dev/null
+/**
+ * \file hmac_drbg.h
+ *
+ * \brief HMAC_DRBG (NIST SP 800-90A)
+ *
+ * Copyright (C) 2014, ARM Limited, All Rights Reserved
+ *
+ * This file is part of mbed TLS (https://tls.mbed.org)
+ *
+ * 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.
+ */
+#ifndef MBEDTLS_HMAC_DRBG_H
+#define MBEDTLS_HMAC_DRBG_H
+
+#include "md.h"
+
+#if defined(MBEDTLS_THREADING_C)
+#include "mbedtls/threading.h"
+#endif
+
+/*
+ * Error codes
+ */
+#define MBEDTLS_ERR_HMAC_DRBG_REQUEST_TOO_BIG -0x0003 /**< Too many random requested in single call. */
+#define MBEDTLS_ERR_HMAC_DRBG_INPUT_TOO_BIG -0x0005 /**< Input too large (Entropy + additional). */
+#define MBEDTLS_ERR_HMAC_DRBG_FILE_IO_ERROR -0x0007 /**< Read/write error in file. */
+#define MBEDTLS_ERR_HMAC_DRBG_ENTROPY_SOURCE_FAILED -0x0009 /**< The entropy source failed. */
+
+/**
+ * \name SECTION: Module settings
+ *
+ * The configuration options you can set for this module are in this section.
+ * Either change them in config.h or define them on the compiler command line.
+ * \{
+ */
+
+#if !defined(MBEDTLS_HMAC_DRBG_RESEED_INTERVAL)
+#define MBEDTLS_HMAC_DRBG_RESEED_INTERVAL 10000 /**< Interval before reseed is performed by default */
+#endif
+
+#if !defined(MBEDTLS_HMAC_DRBG_MAX_INPUT)
+#define MBEDTLS_HMAC_DRBG_MAX_INPUT 256 /**< Maximum number of additional input bytes */
+#endif
+
+#if !defined(MBEDTLS_HMAC_DRBG_MAX_REQUEST)
+#define MBEDTLS_HMAC_DRBG_MAX_REQUEST 1024 /**< Maximum number of requested bytes per call */
+#endif
+
+#if !defined(MBEDTLS_HMAC_DRBG_MAX_SEED_INPUT)
+#define MBEDTLS_HMAC_DRBG_MAX_SEED_INPUT 384 /**< Maximum size of (re)seed buffer */
+#endif
+
+/* \} name SECTION: Module settings */
+
+#define MBEDTLS_HMAC_DRBG_PR_OFF 0 /**< No prediction resistance */
+#define MBEDTLS_HMAC_DRBG_PR_ON 1 /**< Prediction resistance enabled */
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**
+ * HMAC_DRBG context.
+ */
+typedef struct
+{
+ /* Working state: the key K is not stored explicitely,
+ * but is implied by the HMAC context */
+ mbedtls_md_context_t md_ctx; /*!< HMAC context (inc. K) */
+ unsigned char V[MBEDTLS_MD_MAX_SIZE]; /*!< V in the spec */
+ int reseed_counter; /*!< reseed counter */
+
+ /* Administrative state */
+ size_t entropy_len; /*!< entropy bytes grabbed on each (re)seed */
+ int prediction_resistance; /*!< enable prediction resistance (Automatic
+ reseed before every random generation) */
+ int reseed_interval; /*!< reseed interval */
+
+ /* Callbacks */
+ int (*f_entropy)(void *, unsigned char *, size_t); /*!< entropy function */
+ void *p_entropy; /*!< context for the entropy function */
+
+#if defined(MBEDTLS_THREADING_C)
+ mbedtls_threading_mutex_t mutex;
+#endif
+} mbedtls_hmac_drbg_context;
+
+/**
+ * \brief HMAC_DRBG context initialization
+ * Makes the context ready for mbetls_hmac_drbg_seed(),
+ * mbedtls_hmac_drbg_seed_buf() or
+ * mbedtls_hmac_drbg_free().
+ *
+ * \param ctx HMAC_DRBG context to be initialized
+ */
+void mbedtls_hmac_drbg_init( mbedtls_hmac_drbg_context *ctx );
+
+/**
+ * \brief HMAC_DRBG initial seeding
+ * Seed and setup entropy source for future reseeds.
+ *
+ * \param ctx HMAC_DRBG context to be seeded
+ * \param md_info MD algorithm to use for HMAC_DRBG
+ * \param f_entropy Entropy callback (p_entropy, buffer to fill, buffer
+ * length)
+ * \param p_entropy Entropy context
+ * \param custom Personalization data (Device specific identifiers)
+ * (Can be NULL)
+ * \param len Length of personalization data
+ *
+ * \note The "security strength" as defined by NIST is set to:
+ * 128 bits if md_alg is SHA-1,
+ * 192 bits if md_alg is SHA-224,
+ * 256 bits if md_alg is SHA-256 or higher.
+ * Note that SHA-256 is just as efficient as SHA-224.
+ *
+ * \return 0 if successful, or
+ * MBEDTLS_ERR_MD_BAD_INPUT_DATA, or
+ * MBEDTLS_ERR_MD_ALLOC_FAILED, or
+ * MBEDTLS_ERR_HMAC_DRBG_ENTROPY_SOURCE_FAILED.
+ */
+int mbedtls_hmac_drbg_seed( mbedtls_hmac_drbg_context *ctx,
+ const mbedtls_md_info_t * md_info,
+ int (*f_entropy)(void *, unsigned char *, size_t),
+ void *p_entropy,
+ const unsigned char *custom,
+ size_t len );
+
+/**
+ * \brief Initilisation of simpified HMAC_DRBG (never reseeds).
+ * (For use with deterministic ECDSA.)
+ *
+ * \param ctx HMAC_DRBG context to be initialised
+ * \param md_info MD algorithm to use for HMAC_DRBG
+ * \param data Concatenation of entropy string and additional data
+ * \param data_len Length of data in bytes
+ *
+ * \return 0 if successful, or
+ * MBEDTLS_ERR_MD_BAD_INPUT_DATA, or
+ * MBEDTLS_ERR_MD_ALLOC_FAILED.
+ */
+int mbedtls_hmac_drbg_seed_buf( mbedtls_hmac_drbg_context *ctx,
+ const mbedtls_md_info_t * md_info,
+ const unsigned char *data, size_t data_len );
+
+/**
+ * \brief Enable / disable prediction resistance (Default: Off)
+ *
+ * Note: If enabled, entropy is used for ctx->entropy_len before each call!
+ * Only use this if you have ample supply of good entropy!
+ *
+ * \param ctx HMAC_DRBG context
+ * \param resistance MBEDTLS_HMAC_DRBG_PR_ON or MBEDTLS_HMAC_DRBG_PR_OFF
+ */
+void mbedtls_hmac_drbg_set_prediction_resistance( mbedtls_hmac_drbg_context *ctx,
+ int resistance );
+
+/**
+ * \brief Set the amount of entropy grabbed on each reseed
+ * (Default: given by the security strength, which
+ * depends on the hash used, see \c mbedtls_hmac_drbg_init() )
+ *
+ * \param ctx HMAC_DRBG context
+ * \param len Amount of entropy to grab, in bytes
+ */
+void mbedtls_hmac_drbg_set_entropy_len( mbedtls_hmac_drbg_context *ctx,
+ size_t len );
+
+/**
+ * \brief Set the reseed interval
+ * (Default: MBEDTLS_HMAC_DRBG_RESEED_INTERVAL)
+ *
+ * \param ctx HMAC_DRBG context
+ * \param interval Reseed interval
+ */
+void mbedtls_hmac_drbg_set_reseed_interval( mbedtls_hmac_drbg_context *ctx,
+ int interval );
+
+/**
+ * \brief HMAC_DRBG update state
+ *
+ * \param ctx HMAC_DRBG context
+ * \param additional Additional data to update state with, or NULL
+ * \param add_len Length of additional data, or 0
+ *
+ * \note Additional data is optional, pass NULL and 0 as second
+ * third argument if no additional data is being used.
+ */
+void mbedtls_hmac_drbg_update( mbedtls_hmac_drbg_context *ctx,
+ const unsigned char *additional, size_t add_len );
+
+/**
+ * \brief HMAC_DRBG reseeding (extracts data from entropy source)
+ *
+ * \param ctx HMAC_DRBG context
+ * \param additional Additional data to add to state (Can be NULL)
+ * \param len Length of additional data
+ *
+ * \return 0 if successful, or
+ * MBEDTLS_ERR_HMAC_DRBG_ENTROPY_SOURCE_FAILED
+ */
+int mbedtls_hmac_drbg_reseed( mbedtls_hmac_drbg_context *ctx,
+ const unsigned char *additional, size_t len );
+
+/**
+ * \brief HMAC_DRBG generate random with additional update input
+ *
+ * Note: Automatically reseeds if reseed_counter is reached or PR is enabled.
+ *
+ * \param p_rng HMAC_DRBG context
+ * \param output Buffer to fill
+ * \param output_len Length of the buffer
+ * \param additional Additional data to update with (can be NULL)
+ * \param add_len Length of additional data (can be 0)
+ *
+ * \return 0 if successful, or
+ * MBEDTLS_ERR_HMAC_DRBG_ENTROPY_SOURCE_FAILED, or
+ * MBEDTLS_ERR_HMAC_DRBG_REQUEST_TOO_BIG, or
+ * MBEDTLS_ERR_HMAC_DRBG_INPUT_TOO_BIG.
+ */
+int mbedtls_hmac_drbg_random_with_add( void *p_rng,
+ unsigned char *output, size_t output_len,
+ const unsigned char *additional,
+ size_t add_len );
+
+/**
+ * \brief HMAC_DRBG generate random
+ *
+ * Note: Automatically reseeds if reseed_counter is reached or PR is enabled.
+ *
+ * \param p_rng HMAC_DRBG context
+ * \param output Buffer to fill
+ * \param out_len Length of the buffer
+ *
+ * \return 0 if successful, or
+ * MBEDTLS_ERR_HMAC_DRBG_ENTROPY_SOURCE_FAILED, or
+ * MBEDTLS_ERR_HMAC_DRBG_REQUEST_TOO_BIG
+ */
+int mbedtls_hmac_drbg_random( void *p_rng, unsigned char *output, size_t out_len );
+
+/**
+ * \brief Free an HMAC_DRBG context
+ *
+ * \param ctx HMAC_DRBG context to free.
+ */
+void mbedtls_hmac_drbg_free( mbedtls_hmac_drbg_context *ctx );
+
+#if defined(MBEDTLS_FS_IO)
+/**
+ * \brief Write a seed file
+ *
+ * \param ctx HMAC_DRBG context
+ * \param path Name of the file
+ *
+ * \return 0 if successful, 1 on file error, or
+ * MBEDTLS_ERR_HMAC_DRBG_ENTROPY_SOURCE_FAILED
+ */
+int mbedtls_hmac_drbg_write_seed_file( mbedtls_hmac_drbg_context *ctx, const char *path );
+
+/**
+ * \brief Read and update a seed file. Seed is added to this
+ * instance
+ *
+ * \param ctx HMAC_DRBG context
+ * \param path Name of the file
+ *
+ * \return 0 if successful, 1 on file error,
+ * MBEDTLS_ERR_HMAC_DRBG_ENTROPY_SOURCE_FAILED or
+ * MBEDTLS_ERR_HMAC_DRBG_INPUT_TOO_BIG
+ */
+int mbedtls_hmac_drbg_update_seed_file( mbedtls_hmac_drbg_context *ctx, const char *path );
+#endif /* MBEDTLS_FS_IO */
+
+
+#if defined(MBEDTLS_SELF_TEST)
+/**
+ * \brief Checkup routine
+ *
+ * \return 0 if successful, or 1 if the test failed
+ */
+int mbedtls_hmac_drbg_self_test( int verbose );
+#endif
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* hmac_drbg.h */
*size = numBits;
return errCnt;
}
+// on successful return 1 otherwise return 0
+int VikingDecode(uint8_t *BitStream,
+ size_t size,
+ size_t *startIdx,
+ uint8_t *id_bits,
+ size_t id_bits_size)
+{
+ //no arguments needed - built this way in case we want this to be a direct call from "data " cmds in the future
+ // otherwise could be a void with no arguments
+ //set defaults
+ uint32_t i = 0;
+ uint32_t lastcheckindex = size - (id_bits_size * 2);
+ int found = 0;
+ while (i < lastcheckindex)
+ {
+ if (memcmp(BitStream + i,id_bits,id_bits_size) == 0)
+ {
+ *startIdx = i;
+ found = 1;
+ break;
+ }
+ i++;
+ }
+ return found;
+}
+
+
int indala26decode(uint8_t *bitStream, size_t *size, uint8_t *invert);
int PyramiddemodFSK(uint8_t *dest, size_t *size);
int ParadoxdemodFSK(uint8_t *dest, size_t *size, uint32_t *hi2, uint32_t *hi, uint32_t *lo);
+int VikingDecode(uint8_t *BitStream, size_t size, size_t *startIdx,uint8_t *id_bit,size_t id_bits_size);
#endif
--- /dev/null
+/*
+ * FIPS-180-2 compliant SHA-256 implementation
+ *
+ * Copyright (C) 2006-2014, ARM Limited, All Rights Reserved
+ *
+ * This file is part of mbed TLS (https://tls.mbed.org)
+ *
+ * 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.
+ */
+/*
+ * The SHA-256 Secure Hash Standard was published by NIST in 2002.
+ *
+ * http://csrc.nist.gov/publications/fips/fips180-2/fips180-2.pdf
+ */
+
+#if !defined(MBEDTLS_CONFIG_FILE)
+//#include "mbedtls/config.h"
+#else
+#include MBEDTLS_CONFIG_FILE
+#endif
+
+#if defined(MBEDTLS_SHA256_C)
+
+#include "mbedtls/sha256.h"
+
+#include <string.h>
+
+#if defined(MBEDTLS_SELF_TEST)
+#if defined(MBEDTLS_PLATFORM_C)
+#include "mbedtls/platform.h"
+#else
+#include <stdio.h>
+#define mbedtls_printf printf
+#endif /* MBEDTLS_PLATFORM_C */
+#endif /* MBEDTLS_SELF_TEST */
+
+/* Implementation that should never be optimized out by the compiler */
+static void mbedtls_zeroize( void *v, size_t n ) {
+ volatile unsigned char *p = v; while( n-- ) *p++ = 0;
+}
+
+#if !defined(MBEDTLS_SHA256_ALT)
+
+/*
+ * 32-bit integer manipulation macros (big endian)
+ */
+#ifndef GET_UINT32_BE
+#define GET_UINT32_BE(n,b,i) \
+do { \
+ (n) = ( (uint32_t) (b)[(i) ] << 24 ) \
+ | ( (uint32_t) (b)[(i) + 1] << 16 ) \
+ | ( (uint32_t) (b)[(i) + 2] << 8 ) \
+ | ( (uint32_t) (b)[(i) + 3] ); \
+} while( 0 )
+#endif
+
+#ifndef PUT_UINT32_BE
+#define PUT_UINT32_BE(n,b,i) \
+do { \
+ (b)[(i) ] = (unsigned char) ( (n) >> 24 ); \
+ (b)[(i) + 1] = (unsigned char) ( (n) >> 16 ); \
+ (b)[(i) + 2] = (unsigned char) ( (n) >> 8 ); \
+ (b)[(i) + 3] = (unsigned char) ( (n) ); \
+} while( 0 )
+#endif
+
+void mbedtls_sha256_init( mbedtls_sha256_context *ctx )
+{
+ memset( ctx, 0, sizeof( mbedtls_sha256_context ) );
+}
+
+void mbedtls_sha256_free( mbedtls_sha256_context *ctx )
+{
+ if( ctx == NULL )
+ return;
+
+ mbedtls_zeroize( ctx, sizeof( mbedtls_sha256_context ) );
+}
+
+void mbedtls_sha256_clone( mbedtls_sha256_context *dst,
+ const mbedtls_sha256_context *src )
+{
+ *dst = *src;
+}
+
+/*
+ * SHA-256 context setup
+ */
+void mbedtls_sha256_starts( mbedtls_sha256_context *ctx, int is224 )
+{
+ ctx->total[0] = 0;
+ ctx->total[1] = 0;
+
+ if( is224 == 0 )
+ {
+ /* SHA-256 */
+ ctx->state[0] = 0x6A09E667;
+ ctx->state[1] = 0xBB67AE85;
+ ctx->state[2] = 0x3C6EF372;
+ ctx->state[3] = 0xA54FF53A;
+ ctx->state[4] = 0x510E527F;
+ ctx->state[5] = 0x9B05688C;
+ ctx->state[6] = 0x1F83D9AB;
+ ctx->state[7] = 0x5BE0CD19;
+ }
+ else
+ {
+ /* SHA-224 */
+ ctx->state[0] = 0xC1059ED8;
+ ctx->state[1] = 0x367CD507;
+ ctx->state[2] = 0x3070DD17;
+ ctx->state[3] = 0xF70E5939;
+ ctx->state[4] = 0xFFC00B31;
+ ctx->state[5] = 0x68581511;
+ ctx->state[6] = 0x64F98FA7;
+ ctx->state[7] = 0xBEFA4FA4;
+ }
+
+ ctx->is224 = is224;
+}
+
+#if !defined(MBEDTLS_SHA256_PROCESS_ALT)
+static const uint32_t K[] =
+{
+ 0x428A2F98, 0x71374491, 0xB5C0FBCF, 0xE9B5DBA5,
+ 0x3956C25B, 0x59F111F1, 0x923F82A4, 0xAB1C5ED5,
+ 0xD807AA98, 0x12835B01, 0x243185BE, 0x550C7DC3,
+ 0x72BE5D74, 0x80DEB1FE, 0x9BDC06A7, 0xC19BF174,
+ 0xE49B69C1, 0xEFBE4786, 0x0FC19DC6, 0x240CA1CC,
+ 0x2DE92C6F, 0x4A7484AA, 0x5CB0A9DC, 0x76F988DA,
+ 0x983E5152, 0xA831C66D, 0xB00327C8, 0xBF597FC7,
+ 0xC6E00BF3, 0xD5A79147, 0x06CA6351, 0x14292967,
+ 0x27B70A85, 0x2E1B2138, 0x4D2C6DFC, 0x53380D13,
+ 0x650A7354, 0x766A0ABB, 0x81C2C92E, 0x92722C85,
+ 0xA2BFE8A1, 0xA81A664B, 0xC24B8B70, 0xC76C51A3,
+ 0xD192E819, 0xD6990624, 0xF40E3585, 0x106AA070,
+ 0x19A4C116, 0x1E376C08, 0x2748774C, 0x34B0BCB5,
+ 0x391C0CB3, 0x4ED8AA4A, 0x5B9CCA4F, 0x682E6FF3,
+ 0x748F82EE, 0x78A5636F, 0x84C87814, 0x8CC70208,
+ 0x90BEFFFA, 0xA4506CEB, 0xBEF9A3F7, 0xC67178F2,
+};
+
+#define SHR(x,n) ((x & 0xFFFFFFFF) >> n)
+#define ROTR(x,n) (SHR(x,n) | (x << (32 - n)))
+
+#define S0(x) (ROTR(x, 7) ^ ROTR(x,18) ^ SHR(x, 3))
+#define S1(x) (ROTR(x,17) ^ ROTR(x,19) ^ SHR(x,10))
+
+#define S2(x) (ROTR(x, 2) ^ ROTR(x,13) ^ ROTR(x,22))
+#define S3(x) (ROTR(x, 6) ^ ROTR(x,11) ^ ROTR(x,25))
+
+#define F0(x,y,z) ((x & y) | (z & (x | y)))
+#define F1(x,y,z) (z ^ (x & (y ^ z)))
+
+#define R(t) \
+( \
+ W[t] = S1(W[t - 2]) + W[t - 7] + \
+ S0(W[t - 15]) + W[t - 16] \
+)
+
+#define P(a,b,c,d,e,f,g,h,x,K) \
+{ \
+ temp1 = h + S3(e) + F1(e,f,g) + K + x; \
+ temp2 = S2(a) + F0(a,b,c); \
+ d += temp1; h = temp1 + temp2; \
+}
+
+void mbedtls_sha256_process( mbedtls_sha256_context *ctx, const unsigned char data[64] )
+{
+ uint32_t temp1, temp2, W[64];
+ uint32_t A[8];
+ unsigned int i;
+
+ for( i = 0; i < 8; i++ )
+ A[i] = ctx->state[i];
+
+#if defined(MBEDTLS_SHA256_SMALLER)
+ for( i = 0; i < 64; i++ )
+ {
+ if( i < 16 )
+ GET_UINT32_BE( W[i], data, 4 * i );
+ else
+ R( i );
+
+ P( A[0], A[1], A[2], A[3], A[4], A[5], A[6], A[7], W[i], K[i] );
+
+ temp1 = A[7]; A[7] = A[6]; A[6] = A[5]; A[5] = A[4]; A[4] = A[3];
+ A[3] = A[2]; A[2] = A[1]; A[1] = A[0]; A[0] = temp1;
+ }
+#else /* MBEDTLS_SHA256_SMALLER */
+ for( i = 0; i < 16; i++ )
+ GET_UINT32_BE( W[i], data, 4 * i );
+
+ for( i = 0; i < 16; i += 8 )
+ {
+ P( A[0], A[1], A[2], A[3], A[4], A[5], A[6], A[7], W[i+0], K[i+0] );
+ P( A[7], A[0], A[1], A[2], A[3], A[4], A[5], A[6], W[i+1], K[i+1] );
+ P( A[6], A[7], A[0], A[1], A[2], A[3], A[4], A[5], W[i+2], K[i+2] );
+ P( A[5], A[6], A[7], A[0], A[1], A[2], A[3], A[4], W[i+3], K[i+3] );
+ P( A[4], A[5], A[6], A[7], A[0], A[1], A[2], A[3], W[i+4], K[i+4] );
+ P( A[3], A[4], A[5], A[6], A[7], A[0], A[1], A[2], W[i+5], K[i+5] );
+ P( A[2], A[3], A[4], A[5], A[6], A[7], A[0], A[1], W[i+6], K[i+6] );
+ P( A[1], A[2], A[3], A[4], A[5], A[6], A[7], A[0], W[i+7], K[i+7] );
+ }
+
+ for( i = 16; i < 64; i += 8 )
+ {
+ P( A[0], A[1], A[2], A[3], A[4], A[5], A[6], A[7], R(i+0), K[i+0] );
+ P( A[7], A[0], A[1], A[2], A[3], A[4], A[5], A[6], R(i+1), K[i+1] );
+ P( A[6], A[7], A[0], A[1], A[2], A[3], A[4], A[5], R(i+2), K[i+2] );
+ P( A[5], A[6], A[7], A[0], A[1], A[2], A[3], A[4], R(i+3), K[i+3] );
+ P( A[4], A[5], A[6], A[7], A[0], A[1], A[2], A[3], R(i+4), K[i+4] );
+ P( A[3], A[4], A[5], A[6], A[7], A[0], A[1], A[2], R(i+5), K[i+5] );
+ P( A[2], A[3], A[4], A[5], A[6], A[7], A[0], A[1], R(i+6), K[i+6] );
+ P( A[1], A[2], A[3], A[4], A[5], A[6], A[7], A[0], R(i+7), K[i+7] );
+ }
+#endif /* MBEDTLS_SHA256_SMALLER */
+
+ for( i = 0; i < 8; i++ )
+ ctx->state[i] += A[i];
+}
+#endif /* !MBEDTLS_SHA256_PROCESS_ALT */
+
+/*
+ * SHA-256 process buffer
+ */
+void mbedtls_sha256_update( mbedtls_sha256_context *ctx, const unsigned char *input,
+ size_t ilen )
+{
+ size_t fill;
+ uint32_t left;
+
+ if( ilen == 0 )
+ return;
+
+ left = ctx->total[0] & 0x3F;
+ fill = 64 - left;
+
+ ctx->total[0] += (uint32_t) ilen;
+ ctx->total[0] &= 0xFFFFFFFF;
+
+ if( ctx->total[0] < (uint32_t) ilen )
+ ctx->total[1]++;
+
+ if( left && ilen >= fill )
+ {
+ memcpy( (void *) (ctx->buffer + left), input, fill );
+ mbedtls_sha256_process( ctx, ctx->buffer );
+ input += fill;
+ ilen -= fill;
+ left = 0;
+ }
+
+ while( ilen >= 64 )
+ {
+ mbedtls_sha256_process( ctx, input );
+ input += 64;
+ ilen -= 64;
+ }
+
+ if( ilen > 0 )
+ memcpy( (void *) (ctx->buffer + left), input, ilen );
+}
+
+static const unsigned char sha256_padding[64] =
+{
+ 0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
+};
+
+/*
+ * SHA-256 final digest
+ */
+void mbedtls_sha256_finish( mbedtls_sha256_context *ctx, unsigned char output[32] )
+{
+ uint32_t last, padn;
+ uint32_t high, low;
+ unsigned char msglen[8];
+
+ high = ( ctx->total[0] >> 29 )
+ | ( ctx->total[1] << 3 );
+ low = ( ctx->total[0] << 3 );
+
+ PUT_UINT32_BE( high, msglen, 0 );
+ PUT_UINT32_BE( low, msglen, 4 );
+
+ last = ctx->total[0] & 0x3F;
+ padn = ( last < 56 ) ? ( 56 - last ) : ( 120 - last );
+
+ mbedtls_sha256_update( ctx, sha256_padding, padn );
+ mbedtls_sha256_update( ctx, msglen, 8 );
+
+ PUT_UINT32_BE( ctx->state[0], output, 0 );
+ PUT_UINT32_BE( ctx->state[1], output, 4 );
+ PUT_UINT32_BE( ctx->state[2], output, 8 );
+ PUT_UINT32_BE( ctx->state[3], output, 12 );
+ PUT_UINT32_BE( ctx->state[4], output, 16 );
+ PUT_UINT32_BE( ctx->state[5], output, 20 );
+ PUT_UINT32_BE( ctx->state[6], output, 24 );
+
+ if( ctx->is224 == 0 )
+ PUT_UINT32_BE( ctx->state[7], output, 28 );
+}
+
+#endif /* !MBEDTLS_SHA256_ALT */
+
+/*
+ * output = SHA-256( input buffer )
+ */
+void mbedtls_sha256( const unsigned char *input, size_t ilen,
+ unsigned char output[32], int is224 )
+{
+ mbedtls_sha256_context ctx;
+
+ mbedtls_sha256_init( &ctx );
+ mbedtls_sha256_starts( &ctx, is224 );
+ mbedtls_sha256_update( &ctx, input, ilen );
+ mbedtls_sha256_finish( &ctx, output );
+ mbedtls_sha256_free( &ctx );
+}
+
+#if defined(MBEDTLS_SELF_TEST)
+/*
+ * FIPS-180-2 test vectors
+ */
+static const unsigned char sha256_test_buf[3][57] =
+{
+ { "abc" },
+ { "abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq" },
+ { "" }
+};
+
+static const int sha256_test_buflen[3] =
+{
+ 3, 56, 1000
+};
+
+static const unsigned char sha256_test_sum[6][32] =
+{
+ /*
+ * SHA-224 test vectors
+ */
+ { 0x23, 0x09, 0x7D, 0x22, 0x34, 0x05, 0xD8, 0x22,
+ 0x86, 0x42, 0xA4, 0x77, 0xBD, 0xA2, 0x55, 0xB3,
+ 0x2A, 0xAD, 0xBC, 0xE4, 0xBD, 0xA0, 0xB3, 0xF7,
+ 0xE3, 0x6C, 0x9D, 0xA7 },
+ { 0x75, 0x38, 0x8B, 0x16, 0x51, 0x27, 0x76, 0xCC,
+ 0x5D, 0xBA, 0x5D, 0xA1, 0xFD, 0x89, 0x01, 0x50,
+ 0xB0, 0xC6, 0x45, 0x5C, 0xB4, 0xF5, 0x8B, 0x19,
+ 0x52, 0x52, 0x25, 0x25 },
+ { 0x20, 0x79, 0x46, 0x55, 0x98, 0x0C, 0x91, 0xD8,
+ 0xBB, 0xB4, 0xC1, 0xEA, 0x97, 0x61, 0x8A, 0x4B,
+ 0xF0, 0x3F, 0x42, 0x58, 0x19, 0x48, 0xB2, 0xEE,
+ 0x4E, 0xE7, 0xAD, 0x67 },
+
+ /*
+ * SHA-256 test vectors
+ */
+ { 0xBA, 0x78, 0x16, 0xBF, 0x8F, 0x01, 0xCF, 0xEA,
+ 0x41, 0x41, 0x40, 0xDE, 0x5D, 0xAE, 0x22, 0x23,
+ 0xB0, 0x03, 0x61, 0xA3, 0x96, 0x17, 0x7A, 0x9C,
+ 0xB4, 0x10, 0xFF, 0x61, 0xF2, 0x00, 0x15, 0xAD },
+ { 0x24, 0x8D, 0x6A, 0x61, 0xD2, 0x06, 0x38, 0xB8,
+ 0xE5, 0xC0, 0x26, 0x93, 0x0C, 0x3E, 0x60, 0x39,
+ 0xA3, 0x3C, 0xE4, 0x59, 0x64, 0xFF, 0x21, 0x67,
+ 0xF6, 0xEC, 0xED, 0xD4, 0x19, 0xDB, 0x06, 0xC1 },
+ { 0xCD, 0xC7, 0x6E, 0x5C, 0x99, 0x14, 0xFB, 0x92,
+ 0x81, 0xA1, 0xC7, 0xE2, 0x84, 0xD7, 0x3E, 0x67,
+ 0xF1, 0x80, 0x9A, 0x48, 0xA4, 0x97, 0x20, 0x0E,
+ 0x04, 0x6D, 0x39, 0xCC, 0xC7, 0x11, 0x2C, 0xD0 }
+};
+
+/*
+ * Checkup routine
+ */
+int mbedtls_sha256_self_test( int verbose )
+{
+ int i, j, k, buflen, ret = 0;
+ unsigned char buf[1024];
+ unsigned char sha256sum[32];
+ mbedtls_sha256_context ctx;
+
+ mbedtls_sha256_init( &ctx );
+
+ for( i = 0; i < 6; i++ )
+ {
+ j = i % 3;
+ k = i < 3;
+
+ if( verbose != 0 )
+ mbedtls_printf( " SHA-%d test #%d: ", 256 - k * 32, j + 1 );
+
+ mbedtls_sha256_starts( &ctx, k );
+
+ if( j == 2 )
+ {
+ memset( buf, 'a', buflen = 1000 );
+
+ for( j = 0; j < 1000; j++ )
+ mbedtls_sha256_update( &ctx, buf, buflen );
+ }
+ else
+ mbedtls_sha256_update( &ctx, sha256_test_buf[j],
+ sha256_test_buflen[j] );
+
+ mbedtls_sha256_finish( &ctx, sha256sum );
+
+ if( memcmp( sha256sum, sha256_test_sum[i], 32 - k * 4 ) != 0 )
+ {
+ if( verbose != 0 )
+ mbedtls_printf( "failed\n" );
+
+ ret = 1;
+ goto exit;
+ }
+
+ if( verbose != 0 )
+ mbedtls_printf( "passed\n" );
+ }
+
+ if( verbose != 0 )
+ mbedtls_printf( "\n" );
+
+exit:
+ mbedtls_sha256_free( &ctx );
+
+ return( ret );
+}
+
+#endif /* MBEDTLS_SELF_TEST */
+
+#endif /* MBEDTLS_SHA256_C */
--- /dev/null
+/**
+ * \file mbedtls_sha256.h
+ *
+ * \brief SHA-224 and SHA-256 cryptographic hash function
+ *
+ * Copyright (C) 2006-2014, ARM Limited, All Rights Reserved
+ *
+ * This file is part of mbed TLS (https://tls.mbed.org)
+ *
+ * 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.
+ */
+#ifndef MBEDTLS_SHA256_H
+#define MBEDTLS_SHA256_H
+
+#if !defined(MBEDTLS_CONFIG_FILE)
+#include "config.h"
+#else
+#include MBEDTLS_CONFIG_FILE
+#endif
+
+#include <stddef.h>
+#include <stdint.h>
+
+#if !defined(MBEDTLS_SHA256_ALT)
+// Regular implementation
+//
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**
+ * \brief SHA-256 context structure
+ */
+typedef struct
+{
+ uint32_t total[2]; /*!< number of bytes processed */
+ uint32_t state[8]; /*!< intermediate digest state */
+ unsigned char buffer[64]; /*!< data block being processed */
+ int is224; /*!< 0 => SHA-256, else SHA-224 */
+}
+mbedtls_sha256_context;
+
+/**
+ * \brief Initialize SHA-256 context
+ *
+ * \param ctx SHA-256 context to be initialized
+ */
+void mbedtls_sha256_init( mbedtls_sha256_context *ctx );
+
+/**
+ * \brief Clear SHA-256 context
+ *
+ * \param ctx SHA-256 context to be cleared
+ */
+void mbedtls_sha256_free( mbedtls_sha256_context *ctx );
+
+/**
+ * \brief Clone (the state of) a SHA-256 context
+ *
+ * \param dst The destination context
+ * \param src The context to be cloned
+ */
+void mbedtls_sha256_clone( mbedtls_sha256_context *dst,
+ const mbedtls_sha256_context *src );
+
+/**
+ * \brief SHA-256 context setup
+ *
+ * \param ctx context to be initialized
+ * \param is224 0 = use SHA256, 1 = use SHA224
+ */
+void mbedtls_sha256_starts( mbedtls_sha256_context *ctx, int is224 );
+
+/**
+ * \brief SHA-256 process buffer
+ *
+ * \param ctx SHA-256 context
+ * \param input buffer holding the data
+ * \param ilen length of the input data
+ */
+void mbedtls_sha256_update( mbedtls_sha256_context *ctx, const unsigned char *input,
+ size_t ilen );
+
+/**
+ * \brief SHA-256 final digest
+ *
+ * \param ctx SHA-256 context
+ * \param output SHA-224/256 checksum result
+ */
+void mbedtls_sha256_finish( mbedtls_sha256_context *ctx, unsigned char output[32] );
+
+/* Internal use */
+void mbedtls_sha256_process( mbedtls_sha256_context *ctx, const unsigned char data[64] );
+
+#ifdef __cplusplus
+}
+#endif
+
+#else /* MBEDTLS_SHA256_ALT */
+#include "sha256_alt.h"
+#endif /* MBEDTLS_SHA256_ALT */
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**
+ * \brief Output = SHA-256( input buffer )
+ *
+ * \param input buffer holding the data
+ * \param ilen length of the input data
+ * \param output SHA-224/256 checksum result
+ * \param is224 0 = use SHA256, 1 = use SHA224
+ */
+void mbedtls_sha256( const unsigned char *input, size_t ilen,
+ unsigned char output[32], int is224 );
+
+/**
+ * \brief Checkup routine
+ *
+ * \return 0 if successful, or 1 if the test failed
+ */
+int mbedtls_sha256_self_test( int verbose );
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* mbedtls_sha256.h */
#define CMD_ASK_SIM_TAG 0x021F
#define CMD_PSK_SIM_TAG 0x0220
#define CMD_AWID_DEMOD_FSK 0x0221
+#define CMD_VIKING_CLONE_TAG 0x0222
+
/* CMD_SET_ADC_MUX: ext1 is 0 for lopkd, 1 for loraw, 2 for hipkd, 3 for hiraw */