option to disable solo bootloader

This commit is contained in:
Conor Patrick 2018-12-05 00:14:28 -05:00
parent b9ebde22e5
commit beedc24839
6 changed files with 101 additions and 23 deletions

View File

@ -24,6 +24,7 @@ typedef enum
BootVersion = 0x44,
BootReboot = 0x45,
BootBootloader = 0x46,
BootDisable = 0x47,
} BootOperation;
@ -46,12 +47,30 @@ static void erase_application()
}
}
#define LAST_ADDR (APPLICATION_END_ADDR-2048 + 8)
#define LAST_PAGE (APPLICATION_END_PAGE-1)
static void disable_bootloader()
{
uint8_t page[PAGE_SIZE];
memmove(page, (uint8_t*)LAST_ADDR, PAGE_SIZE);
memset(page+PAGE_SIZE -4, 0, 4);
flash_erase_page(LAST_PAGE);
flash_write(LAST_ADDR, page, PAGE_SIZE);
}
static void authorize_application()
{
uint32_t zero = 0;
uint32_t * ptr;
ptr = (uint32_t *)AUTH_WORD_ADDR;
flash_write((uint32_t)ptr, (uint8_t *)&zero, 4);
// uint32_t zero = 0;
// uint32_t * ptr;
// ptr = (uint32_t *)AUTH_WORD_ADDR;
// flash_write((uint32_t)ptr, (uint8_t *)&zero, 4);
uint8_t page[PAGE_SIZE];
if (is_authorized_to_boot())
return;
memmove(page, (uint8_t*)LAST_ADDR, PAGE_SIZE);
memset(page+PAGE_SIZE -8, 0, 4);
flash_erase_page(LAST_PAGE);
flash_write(LAST_ADDR, page, PAGE_SIZE);
}
int is_authorized_to_boot()
@ -60,6 +79,12 @@ int is_authorized_to_boot()
return *auth == 0;
}
int is_bootloader_disabled()
{
uint32_t * auth = (uint32_t *)(AUTH_WORD_ADDR+4);
return *auth == 0;
}
int bootloader_bridge(int klen, uint8_t * keyh)
{
static int has_erased = 0;
@ -150,7 +175,22 @@ int bootloader_bridge(int klen, uint8_t * keyh)
break;
case BootReboot:
printf1(TAG_BOOT, "BootReboot.\r\n");
device_reboot();
REBOOT_FLAG = 1;
break;
case BootDisable:
printf1(TAG_BOOT, "BootDisable %08lx.\r\n", *(uint32_t *)(AUTH_WORD_ADDR+4));
if (req->payload[0] == 0xcd && req->payload[1] == 0xde
&& req->payload[2] == 0xba && req->payload[3] == 0xaa)
{
disable_bootloader();
version = 0;
u2f_response_writeback(&version,1);
}
else
{
version = CTAP2_ERR_OPERATION_DENIED;
u2f_response_writeback(&version,1);
}
break;
#ifdef SOLO_HACKER
case BootBootloader:

View File

@ -95,22 +95,26 @@ int main(int argc, char * argv[])
}
}
#ifdef SOLO_HACKER
stboot_time = millis();
if ( RCC->CSR & (1<<29) )// check if there was independent watchdog reset
if (!is_bootloader_disabled())
{
RCC->CSR |= (1<<23); // clear reset flags
goto start_bootloader;
stboot_time = millis();
if ( RCC->CSR & (1<<29) )// check if there was independent watchdog reset
{
RCC->CSR |= (1<<23); // clear reset flags
goto start_bootloader;
}
}
#endif
if (boot && is_authorized_to_boot())
if (is_authorized_to_boot() && (boot || is_bootloader_disabled()))
{
BOOT_boot();
}
else
{
printf1(TAG_RED,"Not authorized to boot\r\n");
printf1(TAG_RED,"Not authorized to boot (%08x == %08lx)\r\n", AUTH_WORD_ADDR, *(uint32_t*)AUTH_WORD_ADDR);
}
start_bootloader:
@ -156,7 +160,7 @@ int main(int argc, char * argv[])
{
stboot_time = millis();
}
if ((millis() - stboot_time) > 2000)
if ((millis() - stboot_time) > 5000)
{
boot_st_bootloader();
}

View File

@ -25,4 +25,9 @@ first[AUTH_WORD_ADDR+1] = 0
first[AUTH_WORD_ADDR+2] = 0
first[AUTH_WORD_ADDR+3] = 0
first[AUTH_WORD_ADDR+4] = 0xff
first[AUTH_WORD_ADDR+5] = 0xff
first[AUTH_WORD_ADDR+6] = 0xff
first[AUTH_WORD_ADDR+7] = 0xff
first.tofile(sys.argv[len(sys.argv)-1], format='hex')

View File

@ -170,7 +170,7 @@ void heartbeat()
{
state = !state;
}
if (but) led_rgb((val*b));
if (but) led_rgb(((val * r)<<8) | ((val*b) << 16) | (val*g));
else
led_rgb(((val * g)<<8) | ((val*r) << 16) | (val*b));
}

View File

@ -20,8 +20,13 @@ static void flash_unlock()
// Locks flash and turns off DFU
void flash_option_bytes_init(int boot_from_dfu)
{
#if DEBUG_LEVEL
#ifndef FLASH_ROP
#define FLASH_ROP 0
#endif
#if FLASH_ROP == 0
uint32_t val = 0xfffff8aa;
#elif FLASH_ROP == 2
uint32_t val = 0xfffff8cc;
#else
uint32_t val = 0xfffff8b9;
#endif

View File

@ -24,6 +24,7 @@ class SoloBootloader:
version = 0x44
reboot = 0x45
st_dfu = 0x46
disable = 0x47
HIDCommandBoot = 0x50
HIDCommandEnterBoot = 0x51
@ -136,21 +137,24 @@ class Programmer():
self.send_data_hid(CTAPHID.INIT, '\x11\x11\x11\x11\x11\x11\x11\x11')
self.send_data_hid(SoloBootloader.HIDCommandEnterBoot, '')
def is_solo_bootloader(self,):
try:
p.version()
return True
except CtapError as e:
if e.code == CtapError.ERR.INVALID_COMMAND:
pass
else:
raise (e)
return False
def enter_st_dfu(self,):
"""
If solo is configured as solo hacker or something similar,
this command will tell the token to boot directly to the st DFU
so it can be reprogrammed. Warning, you could brick your device.
"""
soloboot = False
try:
p.version()
soloboot = True
except CtapError as e:
if e.code == CtapError.ERR.INVALID_COMMAND:
pass
else:
raise (e)
soloboot = self.is_solo_bootloader()
if soloboot or self.exchange == self.exchange_u2f:
req = Programmer.format_request(SoloBootloader.st_dfu)
@ -158,6 +162,21 @@ class Programmer():
else:
self.send_only_hid(SoloBootloader.HIDCommandEnterSTBoot, '')
def disable_solo_bootloader(self,):
"""
Disables the Solo bootloader. Only do this if you want to void the possibility
of any updates.
If you've started from a solo hacker, make you you've programmed a final/production build!
"""
ret = self.exchange(SoloBootloader.disable, 0, b'\xcd\xde\xba\xaa') # magic number
if ret[0] != CtapError.ERR.SUCCESS:
print('Failed to disable bootloader')
return False
time.sleep(0.1)
self.exchange(SoloBootloader.reboot)
return True
def program_file(self,name):
if name.lower().endswith('.json'):
@ -246,6 +265,7 @@ if __name__ == '__main__':
parser.add_argument("--reboot", action="store_true", help = 'Tell bootloader to reboot.')
parser.add_argument("--enter-bootloader", action="store_true", help = 'Don\'t write anything, try to enter bootloader. Typically only supported by Solo Hacker builds.')
parser.add_argument("--st-dfu", action="store_true", help = 'Don\'t write anything, try to enter ST DFU. Warning, you could brick your Solo if you overwrite everything. You should reprogram the option bytes just to be safe (boot to Solo bootloader first, then run this command).')
parser.add_argument("--disable", action="store_true", help = 'Disable the Solo bootloader. Cannot be undone. No future updates can be applied.')
args = parser.parse_args()
print()
@ -271,6 +291,10 @@ if __name__ == '__main__':
p.enter_st_dfu()
sys.exit(0)
if args.disable:
p.disable_solo_bootloader()
sys.exit(0)
try:
print('version is ', p.version())
except CtapError as e: