Merge pull request #1914 from henrygab/serial_from_flash_uniqueid

Use unique USB Serial using flash's uniqueID
This commit is contained in:
Iceman
2023-02-18 21:43:06 +01:00
committed by GitHub
15 changed files with 618 additions and 493 deletions
+1
View File
@@ -3,6 +3,7 @@ All notable changes to this project will be documented in this file.
This project uses the changelog in accordance with [keepchangelog](http://keepachangelog.com/). Please use this to write notable changes, which is not the same as git commit log...
## [unreleased][unreleased]
- Enable unique USB serial numbers when built with `FLASH` -- **_UPDATES BOOTROM ALSO_**
- Changed the readline package to v8.2 in the CMAKE files for the client (@iceman1001)
- Add ICECLASS standalone read/sim mode (@natesales)
- Added verbose flag to `hf iclass encode` (@natesales)
+2
View File
@@ -5,6 +5,8 @@ PLATFORM=PM3RDV4
#PLATFORM=PM3GENERIC
# If you want more than one PLATFORM_EXTRAS option, separate them by spaces:
#PLATFORM_EXTRAS=BTADDON
#PLATFORM_EXTRAS=FLASH
#PLATFORM_EXTRAS=BTADDON FLASH
#STANDALONE=LF_SAMYRUN
# Uncomment the lines below in order to make a 256KB image
+15 -1
View File
@@ -2471,8 +2471,11 @@ static void PacketReceived(PacketCommandNG *packet) {
LED_B_OFF();
break;
}
if (page < 3)
if (page < 3) {
isok = Flash_WipeMemoryPage(page);
// let spiffs check and update its info post flash erase
rdv40_spiffs_check();
}
reply_mix(CMD_ACK, isok, 0, 0, 0, 0);
LED_B_OFF();
@@ -2677,6 +2680,17 @@ void __attribute__((noreturn)) AppMain(void) {
I2C_init(false);
#endif
#ifdef WITH_FLASH
if (FlashInit()) {
uint64_t flash_uniqueID = 0;
if (!Flash_CheckBusy(BUSY_TIMEOUT)) { // OK because firmware was built for devices with flash
Flash_UniqueID((uint8_t *)(&flash_uniqueID));
}
FlashStop();
usb_update_serial(flash_uniqueID);
}
#endif
#ifdef WITH_FPC_USART
usart_init(USART_BAUD_RATE, USART_PARITY);
#endif
+7 -1
View File
@@ -34,11 +34,17 @@ VERSIONSRC = version_pm3.c
# THUMBSRC :=
# stdint.h provided locally until GCC 4.5 becomes C99 compliant
APP_CFLAGS = -I. -ffunction-sections -fdata-sections
APP_CFLAGS = -I. -ffunction-sections -fdata-sections -DAS_BOOTROM
# stack-protect , no-pie reduces size on Gentoo Hardened 8.2 gcc, no-common makes sure uninitialized vars don't end up in COMMON area
APP_CFLAGS += -fno-stack-protector -fno-pie -fno-common
ifneq (,$(findstring WITH_FLASH,$(PLATFORM_DEFS)))
APP_CFLAGS += -DWITH_FLASH
APP_CFLAGS += -I../common_arm
THUMBSRC += flashmem.c ticks.c
endif
# Do not move this inclusion before the definition of {THUMB,ASM,ARM}SRC
include ../common_arm/Makefile.common
+15 -1
View File
@@ -20,6 +20,10 @@
#include "clocks.h"
#include "usb_cdc.h"
#ifdef WITH_FLASH
#include "flashmem.h"
#endif
#include "proxmark3_arm.h"
#define DEBUG 0
@@ -214,8 +218,18 @@ static void flash_mode(void) {
bootrom_unlocked = false;
uint8_t rx[sizeof(PacketCommandOLD)];
g_common_area.command = COMMON_AREA_COMMAND_NONE;
if (!g_common_area.flags.button_pressed && BUTTON_PRESS())
if (!g_common_area.flags.button_pressed && BUTTON_PRESS()) {
g_common_area.flags.button_pressed = 1;
}
#ifdef WITH_FLASH
if (FlashInit()) { // checks for existence of flash also ... OK because bootrom was built for devices with flash
uint64_t flash_uniqueID = 0;
Flash_UniqueID((uint8_t *)&flash_uniqueID);
FlashStop();
usb_update_serial(flash_uniqueID);
}
#endif
usb_enable();
+1
View File
@@ -53,6 +53,7 @@ SECTIONS
*(.rodata.*)
*(.data)
*(.data.*)
*(.ramfunc)
. = ALIGN(4);
} >ram AT>bootphase2 :phase2
+1 -1
View File
@@ -1407,7 +1407,7 @@ static int CmdHFiClassDecrypt(const char *Cmd) {
case DES:
case RFU:
case None:
// Nothing to do for None anyway...
// Nothing to do for None anyway...
default:
continue;
}
+4
View File
@@ -114,6 +114,10 @@ endif
# parsing additional PLATFORM_EXTRAS tokens
PLATFORM_EXTRAS_TMP:=$(PLATFORM_EXTRAS)
ifneq (,$(findstring FLASH,$(PLATFORM_EXTRAS_TMP)))
PLATFORM_DEFS += -DWITH_FLASH
PLATFORM_EXTRAS_TMP := $(strip $(filter-out FLASH,$(PLATFORM_EXTRAS_TMP)))
endif
ifneq (,$(findstring BTADDON,$(PLATFORM_EXTRAS_TMP)))
PLATFORM_DEFS += -DWITH_FPC_USART_HOST
PLATFORM_EXTRAS_TMP := $(strip $(filter-out BTADDON,$(PLATFORM_EXTRAS_TMP)))
File diff suppressed because it is too large Load Diff
+20 -10
View File
@@ -100,17 +100,21 @@
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~//
void FlashmemSetSpiBaudrate(uint32_t baudrate);
bool FlashInit(void);
void FlashSetup(uint32_t baudrate);
void Flash_UniqueID(uint8_t *uid);
void FlashStop(void);
bool Flash_WaitIdle(void);
uint8_t Flash_ReadStat1(void);
uint8_t Flash_ReadStat2(void);
uint16_t FlashSendByte(uint32_t data);
void Flash_TransferAdresse(uint32_t address);
void FlashSetup(uint32_t baudrate);
bool Flash_CheckBusy(uint32_t timeout);
uint8_t Flash_ReadStat1(void);
uint16_t FlashSendByte(uint32_t data);
uint16_t FlashSendLastByte(uint32_t data);
#ifndef AS_BOOTROM
void FlashmemSetSpiBaudrate(uint32_t baudrate);
bool Flash_WaitIdle(void);
void Flash_TransferAdresse(uint32_t address);
void Flash_WriteEnable(void);
bool Flash_WipeMemoryPage(uint8_t page);
@@ -119,8 +123,12 @@ bool Flash_Erase4k(uint8_t block, uint8_t sector);
//bool Flash_Erase32k(uint32_t address);
bool Flash_Erase64k(uint8_t block);
void Flash_UniqueID(uint8_t *uid);
uint8_t Flash_ReadID(void);
typedef struct {
uint8_t manufacturer_id;
uint8_t device_id;
} flash_device_type_90_t; // to differentiate from JDEC ID via cmd 9F
bool Flash_ReadID_90(flash_device_type_90_t *result);
uint16_t Flash_ReadData(uint32_t address, uint8_t *out, uint16_t len);
uint16_t Flash_ReadDataCont(uint32_t address, uint8_t *out, uint16_t len);
uint16_t Flash_Write(uint32_t address, uint8_t *in, uint16_t len);
@@ -128,6 +136,8 @@ uint16_t Flash_WriteData(uint32_t address, uint8_t *in, uint16_t len);
uint16_t Flash_WriteDataCont(uint32_t address, uint8_t *in, uint16_t len);
void Flashmem_print_status(void);
void Flashmem_print_info(void);
uint16_t FlashSendLastByte(uint32_t data);
#endif // #ifndef AS_BOOTROM
#endif
+45 -38
View File
@@ -19,9 +19,13 @@
#include "ticks.h"
#include "proxmark3_arm.h"
#ifndef AS_BOOTROM
#include "dbprint.h"
#endif
#ifndef AS_BOOTROM
// timer counts in 666ns increments (32/48MHz), rounding applies
// WARNING: timer can't measure more than 43ms (666ns * 0xFFFF)
void SpinDelayUsPrecision(int us) {
@@ -117,40 +121,6 @@ uint32_t RAMFUNC GetTickCountDelta(uint32_t start_ticks) {
return (UINT32_MAX - start_ticks) + stop_ticks;
}
// -------------------------------------------------------------------------
// microseconds timer
// -------------------------------------------------------------------------
void StartCountUS(void) {
AT91C_BASE_PMC->PMC_PCER |= (1 << AT91C_ID_TC0) | (1 << AT91C_ID_TC1);
AT91C_BASE_TCB->TCB_BMR = AT91C_TCB_TC0XC0S_NONE | AT91C_TCB_TC1XC1S_TIOA0 | AT91C_TCB_TC2XC2S_NONE;
// fast clock
// tick=1.5mks
AT91C_BASE_TC0->TC_CCR = AT91C_TC_CLKDIS; // timer disable
AT91C_BASE_TC0->TC_CMR = AT91C_TC_CLKS_TIMER_DIV3_CLOCK | // MCK(48MHz) / 32
AT91C_TC_WAVE | AT91C_TC_WAVESEL_UP_AUTO | AT91C_TC_ACPA_CLEAR |
AT91C_TC_ACPC_SET | AT91C_TC_ASWTRG_SET;
AT91C_BASE_TC0->TC_RA = 1;
AT91C_BASE_TC0->TC_RC = 0xBFFF + 1; // 0xC000
AT91C_BASE_TC1->TC_CCR = AT91C_TC_CLKDIS; // timer disable
AT91C_BASE_TC1->TC_CMR = AT91C_TC_CLKS_XC1; // from timer 0
AT91C_BASE_TC0->TC_CCR = AT91C_TC_CLKEN | AT91C_TC_SWTRG;
AT91C_BASE_TC1->TC_CCR = AT91C_TC_CLKEN | AT91C_TC_SWTRG;
// Assert a sync signal. This sets all timers to 0 on next active clock edge
AT91C_BASE_TCB->TCB_BCR = 1;
while (AT91C_BASE_TC1->TC_CV > 0);
}
uint32_t RAMFUNC GetCountUS(void) {
//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 ((uint32_t)AT91C_BASE_TC1->TC_CV) * 0x8000 + (((uint32_t)AT91C_BASE_TC0->TC_CV) * 2) / 3;
}
// -------------------------------------------------------------------------
// Timer for iso14443 commands. Uses ssp_clk from FPGA
// -------------------------------------------------------------------------
@@ -246,6 +216,47 @@ uint32_t RAMFUNC GetCountSspClkDelta(uint32_t start) {
return (UINT32_MAX - start) + stop;
}
void WaitMS(uint32_t ms) {
WaitTicks((ms & 0x1FFFFF) * 1500);
}
#endif // #ifndef AS_BOOTROM
// -------------------------------------------------------------------------
// microseconds timer
// -------------------------------------------------------------------------
void StartCountUS(void) {
AT91C_BASE_PMC->PMC_PCER |= (1 << AT91C_ID_TC0) | (1 << AT91C_ID_TC1);
AT91C_BASE_TCB->TCB_BMR = AT91C_TCB_TC0XC0S_NONE | AT91C_TCB_TC1XC1S_TIOA0 | AT91C_TCB_TC2XC2S_NONE;
// fast clock
// tick=1.5mks
AT91C_BASE_TC0->TC_CCR = AT91C_TC_CLKDIS; // timer disable
AT91C_BASE_TC0->TC_CMR = AT91C_TC_CLKS_TIMER_DIV3_CLOCK | // MCK(48MHz) / 32
AT91C_TC_WAVE | AT91C_TC_WAVESEL_UP_AUTO | AT91C_TC_ACPA_CLEAR |
AT91C_TC_ACPC_SET | AT91C_TC_ASWTRG_SET;
AT91C_BASE_TC0->TC_RA = 1;
AT91C_BASE_TC0->TC_RC = 0xBFFF + 1; // 0xC000
AT91C_BASE_TC1->TC_CCR = AT91C_TC_CLKDIS; // timer disable
AT91C_BASE_TC1->TC_CMR = AT91C_TC_CLKS_XC1; // from timer 0
AT91C_BASE_TC0->TC_CCR = AT91C_TC_CLKEN | AT91C_TC_SWTRG;
AT91C_BASE_TC1->TC_CCR = AT91C_TC_CLKEN | AT91C_TC_SWTRG;
// Assert a sync signal. This sets all timers to 0 on next active clock edge
AT91C_BASE_TCB->TCB_BCR = 1;
while (AT91C_BASE_TC1->TC_CV > 0);
}
uint32_t RAMFUNC GetCountUS(void) {
//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 ((uint32_t)AT91C_BASE_TC1->TC_CV) * 0x8000 + (((uint32_t)AT91C_BASE_TC0->TC_CV) * 2) / 3;
}
// -------------------------------------------------------------------------
// Timer for bitbanging, or LF stuff when you need a very precis timer
// 1us = 1.5ticks
@@ -282,7 +293,6 @@ void StartTicks(void) {
AT91C_BASE_TC0->TC_CCR = AT91C_TC_SWTRG;
while (AT91C_BASE_TC0->TC_CV > 0);
}
uint32_t GetTicks(void) {
uint32_t hi, lo;
@@ -307,9 +317,6 @@ void WaitTicks(uint32_t ticks) {
void WaitUS(uint32_t us) {
WaitTicks((us & 0x3FFFFFFF) * 3 / 2);
}
void WaitMS(uint32_t ms) {
WaitTicks((ms & 0x1FFFFF) * 1500);
}
// stop clock
void StopTicks(void) {
+16 -7
View File
@@ -26,6 +26,19 @@
#define GET_TICKS GetTicks()
#endif
void StartTicks(void);
uint32_t GetTicks(void);
void WaitUS(uint32_t us);
void WaitTicks(uint32_t ticks);
void StartCountUS(void);
uint32_t RAMFUNC GetCountUS(void);
void StopTicks(void);
#ifndef AS_BOOTROM //////////////////////////////////////////////////////////////
// Bootrom does not require these functions.
// Wrap in #ifndef to avoid accidental bloat of bootrom
void SpinDelay(int ms);
void SpinDelayUs(int us);
void SpinDelayUsPrecision(int us); // precision 0.6us , running for 43ms before
@@ -34,8 +47,6 @@ void StartTickCount(void);
uint32_t RAMFUNC GetTickCount(void);
uint32_t RAMFUNC GetTickCountDelta(uint32_t start_ticks);
void StartCountUS(void);
uint32_t RAMFUNC GetCountUS(void);
void ResetUSClock(void);
void SpinDelayCountUs(uint32_t us);
@@ -44,12 +55,10 @@ void ResetSspClk(void);
uint32_t RAMFUNC GetCountSspClk(void);
uint32_t RAMFUNC GetCountSspClkDelta(uint32_t start);
void StartTicks(void);
uint32_t GetTicks(void);
void WaitTicks(uint32_t ticks);
void WaitUS(uint32_t us);
void WaitMS(uint32_t ms);
void StopTicks(void);
#endif // #ifndef AS_BOOTROM
#endif
+49
View File
@@ -366,11 +366,60 @@ static const char StrProduct[] = {
'p', 0, 'r', 0, 'o', 0, 'x', 0, 'm', 0, 'a', 0, 'r', 0, 'k', 0, '3', 0
};
#ifndef WITH_FLASH
static const char StrSerialNumber[] = {
14, // Length
0x03, // Type is string
'i', 0, 'c', 0, 'e', 0, 'm', 0, 'a', 0, 'n', 0
};
#else // WITH_FLASH is defined
// Manually calculated size of descriptor with unique ID:
// offset 0, lengt h 1: total length field
// offset 1, length 1: descriptor type field
// offset 2, length 12: 6x unicode chars (original string)
// offset 14, length 4: 2x unicode chars (underscores) [[ to avoid descriptor being (size % 8) == 0, OS bug workaround ]]
// offset 18, length 32: 16x unicode chars (8-byte serial as hex characters)
// ============================
// total: 50 bytes
#define USB_STRING_DESCRIPTOR_SERIAL_NUMBER_LENGTH 50
char StrSerialNumber[] = {
14, // Length is initially identical to non-unique version ... The length updated at boot, if unique serial is available
0x03, // Type is string
'i', 0, 'c', 0, 'e', 0, 'm', 0, 'a', 0, 'n', 0,
'_', 0, '_', 0,
'x', 0, 'x', 0, 'x', 0, 'x', 0, 'x', 0, 'x', 0, 'x', 0, 'x', 0,
'x', 0, 'x', 0, 'x', 0, 'x', 0, 'x', 0, 'x', 0, 'x', 0, 'x', 0,
};
void usb_update_serial(uint64_t newSerialNumber) {
static bool configured = false; // TODO: enable by setting to false here...
if (configured) {
return;
}
// run this only once per boot... even if it fails to find serial number
configured = true;
// reject serial number if all-zero or all-ones
if ((newSerialNumber == 0x0000000000000000) || (newSerialNumber == 0xFFFFFFFFFFFFFFFF)) {
return;
}
// Descriptor is, effectively, initially identical to non-unique serial
// number because it reports the shorter length in the first byte.
// Convert uniqueID's eight bytes to 16 unicode characters in the
// descriptor and, finally, update the descriptor's length, which
// causes the serial number to become visible.
for (uint8_t i = 0; i < 8; i++) {
// order of nibbles chosen to match display order from `hw status`
uint8_t nibble1 = (newSerialNumber >> ((8 * i) + 4)) & 0xFu; // bitmasks [0xF0, 0xF000, 0xF00000, ... 0xF000000000000000]
uint8_t nibble2 = (newSerialNumber >> ((8 * i) + 0)) & 0xFu; // bitmasks [0x0F, 0x0F00, 0x0F0000, ... 0x0F00000000000000]
char c1 = nibble1 < 10 ? '0' + nibble1 : 'A' + (nibble1 - 10);
char c2 = nibble2 < 10 ? '0' + nibble2 : 'A' + (nibble2 - 10);
StrSerialNumber[18 + (4 * i) + 0] = c1; // [ 18, 22, .., 42, 46 ]
StrSerialNumber[18 + (4 * i) + 2] = c2; // [ 20, 24, .., 44, 48 ]
}
StrSerialNumber[0] = USB_STRING_DESCRIPTOR_SERIAL_NUMBER_LENGTH;
}
#endif
// size includes their own field.
static const char StrMS_OSDescriptor[] = {
+1
View File
@@ -31,6 +31,7 @@ bool usb_poll_validate_length(void);
uint32_t usb_read(uint8_t *data, size_t len);
int usb_write(const uint8_t *data, const size_t len);
uint32_t usb_read_ng(uint8_t *data, size_t len);
void usb_update_serial(uint64_t newSerialNumber);
void SetUSBreconnect(int value);
int GetUSBreconnect(void);
+2 -2
View File
@@ -11507,7 +11507,7 @@
},
"script help": {
"command": "script help",
"description": "This is a feature to run Lua/Cmd scripts. You can place scripts within the luascripts/cmdscripts folders. --------------------------------------------------------------------------------------- script list available offline: yes",
"description": "This is a feature to run Lua/Cmd/Python scripts. You can place scripts within the luascripts/cmdscripts/pyscripts folders. --------------------------------------------------------------------------------------- script list available offline: yes",
"notes": [],
"offline": true,
"options": [],
@@ -11904,6 +11904,6 @@
"metadata": {
"commands_extracted": 749,
"extracted_by": "PM3Help2JSON v1.00",
"extracted_on": "2023-02-11T10:42:29"
"extracted_on": "2023-02-18T20:20:19"
}
}