boot directly st bootlaoder

This commit is contained in:
Conor Patrick 2018-12-04 19:14:11 -05:00
parent 97b715881b
commit 5a636d1ebe
7 changed files with 92 additions and 5 deletions

View File

@ -711,7 +711,12 @@ uint8_t ctaphid_handle_packet(uint8_t * pkt_raw)
ctaphid_write(&wb, NULL, 0); ctaphid_write(&wb, NULL, 0);
is_busy = 0; is_busy = 0;
break; break;
case CTAPHID_ENTERSTBOOT:
printf1(TAG_HID,"CTAPHID_ENTERBOOT\n");
boot_st_bootloader();
break;
#endif #endif
default: default:
printf2(TAG_ERR,"error, unimplemented HID cmd: %02x\r\n", buffer_cmd()); printf2(TAG_ERR,"error, unimplemented HID cmd: %02x\r\n", buffer_cmd());
ctaphid_send_error(cid, CTAP1_ERR_INVALID_COMMAND); ctaphid_send_error(cid, CTAP1_ERR_INVALID_COMMAND);

View File

@ -41,6 +41,7 @@
// Custom commands between 0x40-0x7f // Custom commands between 0x40-0x7f
#define CTAPHID_BOOT (TYPE_INIT | 0x50) #define CTAPHID_BOOT (TYPE_INIT | 0x50)
#define CTAPHID_ENTERBOOT (TYPE_INIT | 0x51) #define CTAPHID_ENTERBOOT (TYPE_INIT | 0x51)
#define CTAPHID_ENTERSTBOOT (TYPE_INIT | 0x52)
#define ERR_INVALID_CMD 0x01 #define ERR_INVALID_CMD 0x01
#define ERR_INVALID_PAR 0x02 #define ERR_INVALID_PAR 0x02

View File

@ -96,7 +96,7 @@ void ctap_overwrite_rk(int index,CTAP_residentKey * rk);
// For Solo hacker // For Solo hacker
void boot_solo_bootloader(); void boot_solo_bootloader();
void boot_st_bootloader();

View File

@ -22,6 +22,8 @@ typedef enum
BootCheck = 0x42, BootCheck = 0x42,
BootErase = 0x43, BootErase = 0x43,
BootVersion = 0x44, BootVersion = 0x44,
BootReboot = 0x45,
BootBootloader = 0x46,
} BootOperation; } BootOperation;
@ -143,6 +145,17 @@ int bootloader_bridge(int klen, uint8_t * keyh)
u2f_response_writeback(&version,1); u2f_response_writeback(&version,1);
return 0; return 0;
break; break;
case BootReboot:
printf1(TAG_BOOT, "BootReboot.\r\n");
device_reboot();
break;
#ifndef SOLO_HACKER
case BootBootloader:
printf1(TAG_BOOT, "BootBootloader.\r\n");
flash_option_bytes_init(1);
boot_st_bootloader();
break;
#endif
default: default:
return CTAP1_ERR_INVALID_COMMAND; return CTAP1_ERR_INVALID_COMMAND;
} }

View File

@ -56,6 +56,7 @@ int main(int argc, char * argv[])
{ {
uint8_t hidmsg[64]; uint8_t hidmsg[64];
uint32_t t1 = 0; uint32_t t1 = 0;
uint32_t stboot_time = 0;
uint32_t boot = 1; uint32_t boot = 1;
set_logging_mask( set_logging_mask(
@ -94,6 +95,7 @@ int main(int argc, char * argv[])
} }
#ifdef SOLO_HACKER #ifdef SOLO_HACKER
stboot_time = millis();
if ( RCC->CSR & (1<<29) )// check if there was independent watchdog reset if ( RCC->CSR & (1<<29) )// check if there was independent watchdog reset
{ {
RCC->CSR |= (1<<23); // clear reset flags RCC->CSR |= (1<<23); // clear reset flags
@ -147,6 +149,17 @@ int main(int argc, char * argv[])
delay(250); delay(250);
device_reboot(); device_reboot();
} }
#ifdef SOLO_HACKER
// Boot ST bootloader if button is held for 2s
if (!device_is_button_pressed())
{
stboot_time = millis();
}
if ((millis() - stboot_time) > 2000)
{
boot_st_bootloader();
}
#endif
} }
// Should never get here // Should never get here

View File

@ -486,6 +486,18 @@ void ctap_overwrite_rk(int index,CTAP_residentKey * rk)
} }
} }
void boot_st_bootloader()
{
__disable_irq();
__set_MSP(*((uint32_t *)0x1fff0000));
((void (*)(void)) (*((uint32_t *)0x1fff0004)))();
while(1)
;
}
void boot_solo_bootloader() void boot_solo_bootloader()
{ {
LL_IWDG_Enable(IWDG); LL_IWDG_Enable(IWDG);

View File

@ -22,9 +22,12 @@ class SoloBootloader:
check = 0x42 check = 0x42
erase = 0x43 erase = 0x43
version = 0x44 version = 0x44
reboot = 0x45
st_dfu = 0x46
HIDCommandBoot = 0x50 HIDCommandBoot = 0x50
HIDCommandEnterBoot = 0x51 HIDCommandEnterBoot = 0x51
HIDCommandEnterSTBoot = 0x52
TAG = b'\x8C\x27\x90\xf6' TAG = b'\x8C\x27\x90\xf6'
@ -45,6 +48,13 @@ class Programmer():
""" option to reboot after programming """ """ option to reboot after programming """
self.reboot = val self.reboot = val
def reboot(self,val):
""" option to reboot after programming """
try:
self.exchange(SoloBootloader.reboot)
except OSError:
pass
def find_device(self,): def find_device(self,):
dev = next(CtapHidDevice.list_devices(), None) dev = next(CtapHidDevice.list_devices(), None)
if not dev: if not dev:
@ -64,6 +74,11 @@ class Programmer():
return cmd + addr[:3] + SoloBootloader.TAG + length + data return cmd + addr[:3] + SoloBootloader.TAG + length + data
def send_only_hid(self, cmd, data):
if type(data) != type(b''):
data = struct.pack('%dB' % len(data), *[ord(x) for x in data])
self.dev._dev.InternalSend(0x80 | cmd, bytearray(data))
def send_data_hid(self, cmd, data): def send_data_hid(self, cmd, data):
if type(data) != type(b''): if type(data) != type(b''):
data = struct.pack('%dB' % len(data), *[ord(x) for x in data]) data = struct.pack('%dB' % len(data), *[ord(x) for x in data])
@ -121,6 +136,18 @@ class Programmer():
self.send_data_hid(CTAPHID.INIT, '\x11\x11\x11\x11\x11\x11\x11\x11') self.send_data_hid(CTAPHID.INIT, '\x11\x11\x11\x11\x11\x11\x11\x11')
self.send_data_hid(SoloBootloader.HIDCommandEnterBoot, '') self.send_data_hid(SoloBootloader.HIDCommandEnterBoot, '')
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.
"""
if self.exchange == self.exchange_hid:
self.send_only_hid(SoloBootloader.HIDCommandEnterSTBoot, '')
else:
req = Programmer.format_request(SoloBootloader.st_dfu)
self.send_only_hid(SoloBootloader.HIDCommandBoot, req)
def program_file(self,name): def program_file(self,name):
if name.lower().endswith('.json'): if name.lower().endswith('.json'):
@ -201,12 +228,14 @@ def attempt_to_boot_bootloader(p):
if __name__ == '__main__': if __name__ == '__main__':
parser = argparse.ArgumentParser() parser = argparse.ArgumentParser()
parser.add_argument("<firmware>", help = 'firmware file. Either a JSON or hex file. JSON file contains signature while hex does not.') parser.add_argument("[firmware]", nargs='?', default='', help = 'firmware file. Either a JSON or hex file. JSON file contains signature while hex does not.')
parser.add_argument("--use-hid", action="store_true", help = 'Programs using custom HID command (default). Quicker than using U2F authenticate which is what a browser has to use.') parser.add_argument("--use-hid", action="store_true", help = 'Programs using custom HID command (default). Quicker than using U2F authenticate which is what a browser has to use.')
parser.add_argument("--use-u2f", action="store_true", help = 'Programs using U2F authenticate. This is what a web application will use.') parser.add_argument("--use-u2f", action="store_true", help = 'Programs using U2F authenticate. This is what a web application will use.')
parser.add_argument("--no-reset", action="store_true", help = 'Don\'t reset after writing firmware. Stay in bootloader mode.') parser.add_argument("--no-reset", action="store_true", help = 'Don\'t reset after writing firmware. Stay in bootloader mode.')
parser.add_argument("--reset-only", action="store_true", help = 'Don\'t write anything, try to boot without a signature.') parser.add_argument("--reset-only", action="store_true", help = 'Don\'t write anything, try to boot without a signature.')
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("--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. Make sure to reprogram the option bytes just to be safe.')
args = parser.parse_args() args = parser.parse_args()
print() print()
@ -223,6 +252,15 @@ if __name__ == '__main__':
attempt_to_boot_bootloader(p) attempt_to_boot_bootloader(p)
sys.exit(0) sys.exit(0)
if args.reboot:
p.reboot()
sys.exit(0)
if args.st_dfu:
print('Sending command to boot into ST DFU...')
p.enter_st_dfu()
sys.exit(0)
try: try:
print('version is ', p.version()) print('version is ', p.version())
except CtapError as e: except CtapError as e:
@ -234,6 +272,11 @@ if __name__ == '__main__':
attempt_to_boot_bootloader(p) attempt_to_boot_bootloader(p)
if not args.reset_only: if not args.reset_only:
p.program_file(args.__dict__['<firmware>']) fw = args.__dict__['[firmware]']
if fw == '':
print('Need to supply firmware filename.')
args.print_help()
sys.exit(1)
p.program_file(fw)
else: else:
p.exchange(SoloBootloader.done,0,b'A'*64) p.exchange(SoloBootloader.done,0,b'A'*64)