From c6f37b32bcc80d63fd4eea1e21fec95c2287bdda Mon Sep 17 00:00:00 2001 From: Matthew Brugman Date: Fri, 17 Jan 2025 13:58:10 -0600 Subject: [PATCH 1/5] fixup datatype in loop counter, rename setup/teardown methods to disambiguate --- src/commands/uart/glitch.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/commands/uart/glitch.c b/src/commands/uart/glitch.c index c699e528..77983e32 100644 --- a/src/commands/uart/glitch.c +++ b/src/commands/uart/glitch.c @@ -345,7 +345,7 @@ static inline uint32_t get_ticks() { * * Enable PIO and get ready to go *******************************************************/ -bool setup_hardware() { +bool setup_uart_glitch_hardware() { PRINT_INFO("glitch::Entering setup_hardware()\r\n"); bio_put(M_UART_RTS, 0); @@ -377,7 +377,7 @@ bool setup_hardware() { /******************************************************** * Deallocate the 2 IO pins and remove the PIO program *******************************************************/ -void teardown_hardware() { +void teardown_uart_glitch_hardware() { PRINT_INFO("glitch::Entering teardown_hardware()\r\n"); bio_put(M_UART_RTS, 1); @@ -411,7 +411,7 @@ void uart_glitch_handler(struct command_result* res) { } // set up and enable the two hardware pins, start the PIO program - if (!setup_hardware()) + if (!setup_uart_glitch_hardware()) { return; } @@ -424,7 +424,7 @@ void uart_glitch_handler(struct command_result* res) { // that's what the goofy last_was_high thing is all about. uint32_t edges = 0; bool last_was_high = false; - for (uint8_t ii = 0; ii < 8; ++ii) { + for (size_t ii = 0; ii < 8; ++ii) { if (uart_glitch_config.glitch_trg & (1U << ii)) { ++edges; if (last_was_high) { @@ -596,5 +596,5 @@ void uart_glitch_handler(struct command_result* res) { } // we're done, release the two hardware pins and PIO program - teardown_hardware(); + teardown_uart_glitch_hardware(); } From 0d6a6a5fae577bcf3bb0c3afc6d8ea0136798035 Mon Sep 17 00:00:00 2001 From: Matthew Brugman Date: Sun, 19 Jan 2025 13:52:11 -0600 Subject: [PATCH 2/5] PIO state machine set to run at 100MHz, 10ns per instruction for finer glitch control --- src/commands/uart/glitch.c | 4 ++-- src/commands/uart/glitch.pio | 10 ++++++---- 2 files changed, 8 insertions(+), 6 deletions(-) diff --git a/src/commands/uart/glitch.c b/src/commands/uart/glitch.c index 77983e32..bec26d2b 100644 --- a/src/commands/uart/glitch.c +++ b/src/commands/uart/glitch.c @@ -490,9 +490,9 @@ void uart_glitch_handler(struct command_result* res) { // third item is the delay before firing the pulse // NOTE - multiplication by 19 is for scaling; future version may allow // fractional microsecond timing - pio_sm_put_blocking(glitch_pio.pio, glitch_pio.sm, uart_glitch_config.glitch_time * 19); + pio_sm_put_blocking(glitch_pio.pio, glitch_pio.sm, uart_glitch_config.glitch_time); pio_sm_put_blocking(glitch_pio.pio, glitch_pio.sm, edges); - pio_sm_put_blocking(glitch_pio.pio, glitch_pio.sm, this_glitch_delay * 19); + pio_sm_put_blocking(glitch_pio.pio, glitch_pio.sm, this_glitch_delay); // serial out the trigger character. The stop bit transition is the // trigger used by PIO to start timing diff --git a/src/commands/uart/glitch.pio b/src/commands/uart/glitch.pio index 8b440824..9664b610 100644 --- a/src/commands/uart/glitch.pio +++ b/src/commands/uart/glitch.pio @@ -1,5 +1,6 @@ ; -; +; PIO State Machine to handle timing and "on" time of a glitching +; device. ; .program uart_glitch @@ -11,10 +12,10 @@ mov y OSR ; store it in Y pull ; get the delay before starting glitch pulse (just hold on for now) -return_loop: +trigger_loop: wait 0 pin 0 ; idle state of TX line is high, wait for it to go low wait 1 pin 0 ; wait for it to go back up - jmp y-- return_loop ; decrement + jmp y-- trigger_loop ; decrement mov y OSR ; now set the delay time to the y register @@ -41,7 +42,8 @@ static inline void uart_glitch_program_init(PIO pio, uint sm, uint offset, uint pio_sm_set_consecutive_pindirs(pio, sm, glitch_pin, 1, true); pio_sm_set_consecutive_pindirs(pio, sm, tx_pin, 1, false); - float div = (float)clock_get_hz(clk_sys) / (2e7); + // 100MHz = 10ns per instruction + float div = (float)clock_get_hz(clk_sys) / (100e6); sm_config_set_clkdiv(&c, div); pio_sm_init(pio, sm, offset, &c); From 34859f950106c5a90b372bf2df2d9d3e59c80850 Mon Sep 17 00:00:00 2001 From: Matthew Brugman Date: Sun, 19 Jan 2025 15:01:21 -0600 Subject: [PATCH 3/5] Glitch control new has resolution of 10 ns instead of 1 us. Changed limits and text to be more clear. --- src/commands/uart/glitch.c | 24 +++++++++++++++--------- src/translation/en-us.h | 14 +++++++------- src/translation/history/en-us.json | 28 ++++++++++++++-------------- 3 files changed, 36 insertions(+), 30 deletions(-) diff --git a/src/commands/uart/glitch.c b/src/commands/uart/glitch.c index bec26d2b..836ae35e 100644 --- a/src/commands/uart/glitch.c +++ b/src/commands/uart/glitch.c @@ -67,8 +67,8 @@ // maximum number of characters to receive in glitch loop #define RX_CHAR_LIMIT 20 -static const char* const usage[] = { "glitch\t[-h(elp)]", - "UART glitch generator", +static const char* const usage[] = { "glitch\t[-h(elp)] [-c(onfig)]", + "UART glitch generator. Note that times are in terms of nanoseconds * 10; therefore, a setting of 3 = 30ns", "Exit: press Bus Pirate button" }; // config struct typedef struct _uart_glitch_config { @@ -88,6 +88,7 @@ static struct _uart_glitch_config uart_glitch_config; static const struct ui_help_options options[] = { { 1, "", T_HELP_UART_GLITCH }, // command help { 0, "-h", T_HELP_FLAG }, // help + { 0, "-c", T_HELP_LOGIC_INFO } // show config }; // LCD display pin text @@ -145,7 +146,7 @@ static const struct ui_prompt uart_menu[] = { [0] = { .description = T_UART_GLIT .menu_items_count = count_of(uart_glitch_dly_menu), .prompt_text = T_UART_GLITCH_DLY_PROMPT, .minval = 1, - .maxval = 5000, + .maxval = 5000000, .defval = 1, .menu_action = 0, .config = &prompt_int_cfg }, @@ -162,8 +163,8 @@ static const struct ui_prompt uart_menu[] = { [0] = { .description = T_UART_GLIT .menu_items = uart_glitch_lng_menu, .menu_items_count = count_of(uart_glitch_lng_menu), .prompt_text = T_UART_GLITCH_LNG_PROMPT, - .minval = 1, - .maxval = 5000, + .minval = 0, + .maxval = 5000000, .defval = 1, .menu_action = 0, .config = &prompt_int_cfg }, @@ -207,9 +208,9 @@ static const struct ui_prompt uart_menu[] = { [0] = { .description = T_UART_GLIT void glitch_settings(void) { ui_prompt_mode_settings_int(GET_T(T_UART_GLITCH_TRG_MENU), uart_glitch_config.glitch_trg, "(ASCII)"); - ui_prompt_mode_settings_int(GET_T(T_UART_GLITCH_DLY_MENU), uart_glitch_config.glitch_delay, "us"); - ui_prompt_mode_settings_int(GET_T(T_UART_GLITCH_VRY_MENU), uart_glitch_config.glitch_wander, "us"); - ui_prompt_mode_settings_int(GET_T(T_UART_GLITCH_LNG_MENU), uart_glitch_config.glitch_time, "us"); + ui_prompt_mode_settings_int(GET_T(T_UART_GLITCH_DLY_MENU), uart_glitch_config.glitch_delay, "us*10"); + ui_prompt_mode_settings_int(GET_T(T_UART_GLITCH_VRY_MENU), uart_glitch_config.glitch_wander, "us*10"); + ui_prompt_mode_settings_int(GET_T(T_UART_GLITCH_LNG_MENU), uart_glitch_config.glitch_time, "us*10"); ui_prompt_mode_settings_int(GET_T(T_UART_GLITCH_CYC_MENU), uart_glitch_config.glitch_recycle, "ms"); ui_prompt_mode_settings_int(GET_T(T_UART_GLITCH_FAIL_MENU), uart_glitch_config.fail_resp, "(ASCII)"); ui_prompt_mode_settings_int(GET_T(T_UART_GLITCH_CNT_MENU), uart_glitch_config.retry_count, 0x00); @@ -400,6 +401,11 @@ void uart_glitch_handler(struct command_result* res) { return; } + if (cmdln_args_find_flag('c')) { + glitch_settings(); + return; + } + // Go get/set up config for glitching if (!uart_glitch_setup()) { printf("%s%s%s\r\n", ui_term_color_error(), GET_T(T_UART_GLITCH_SETUP_ERR), ui_term_color_reset()); @@ -538,7 +544,7 @@ void uart_glitch_handler(struct command_result* res) { busy_wait_us_32(500); } - printf("Attempt %3d at %2dus RX: %s\r\n", tries + 1, this_glitch_delay, resp_string); + printf("Attempt %3d, delay %dus RX: %s\r\n", tries + 1, this_glitch_delay * 10, resp_string); // parse through the response. if our "normal bad password response" // character is present, then we didn't glitch :/ diff --git a/src/translation/en-us.h b/src/translation/en-us.h index 272fbc3c..2cd90884 100644 --- a/src/translation/en-us.h +++ b/src/translation/en-us.h @@ -119,26 +119,26 @@ static char const * const en_us[]={ [T_UART_GLITCH_TRG_MENU_1]="1 - 255", [T_UART_GLITCH_TRG_PROMPT]="ASCII value of trigger character (13)", [T_UART_GLITCH_DLY_MENU]="Glitch trigger delay", - [T_UART_GLITCH_DLY_MENU_1]="1 - 5000", - [T_UART_GLITCH_DLY_PROMPT]="Glitch trigger delay in us (1)", + [T_UART_GLITCH_DLY_MENU_1]="1 - 5000000", + [T_UART_GLITCH_DLY_PROMPT]="Glitch trigger delay in ns * 10 (1)", [T_UART_GLITCH_VRY_MENU]="Glitch vary time", [T_UART_GLITCH_VRY_MENU_1] = "1 - 50", - [T_UART_GLITCH_VRY_PROMPT] = "Glitch vary time in us (3)", + [T_UART_GLITCH_VRY_PROMPT] = "Glitch vary time in ns * 10 (3)", [T_UART_GLITCH_LNG_MENU]="Glitch output on time", - [T_UART_GLITCH_LNG_MENU_1]="1 - 5000", - [T_UART_GLITCH_LNG_PROMPT]="Glitch on time in us (1)", + [T_UART_GLITCH_LNG_MENU_1]="1 - 5000000", + [T_UART_GLITCH_LNG_PROMPT]="Glitch on time in ns * 10 (1)", [T_UART_GLITCH_CYC_MENU]="Glitch cycle delay", [T_UART_GLITCH_CYC_MENU_1]="10-1000", [T_UART_GLITCH_CYC_PROMPT]="Minimum time between glitch cycles in ms (10)", [T_UART_GLITCH_FAIL_MENU]="Normal response character", [T_UART_GLITCH_FAIL_MENU_1]="1 - 255", - [T_UART_GLITCH_FAIL_PROMPT]="ASCII value of first char of normal response (35 - '#')", + [T_UART_GLITCH_FAIL_PROMPT]="ASCII value of a known char of normal response (35 - '#')", [T_UART_GLITCH_CNT_MENU]="Number of glitch attempts", [T_UART_GLITCH_CNT_MENU_1]="1 - 10000", [T_UART_GLITCH_CNT_PROMPT]="Number of glitch attempts before quitting (100)", [T_UART_GLITCH_NORDY_MENU]="Bypass 'READY' input checking", [T_UART_GLITCH_NORDY_MENU_1]="0, 1", - [T_UART_GLITCH_NORDY_PROMPT]="0 to disable, 1 to enable (1)", + [T_UART_GLITCH_NORDY_PROMPT]="0 to disable, 1 to enable (1, do not check input)", [T_UART_GLITCH_NORDY_DISABLED]="Bypass disabled ('READY' check enforced)", [T_UART_GLITCH_NORDY_ENABLED]="Bypass enabled ('READY' check disabled)", [T_UART_GLITCH_GLITCHED]="Target glitch success!", diff --git a/src/translation/history/en-us.json b/src/translation/history/en-us.json index 3751ea57..4b138a99 100644 --- a/src/translation/history/en-us.json +++ b/src/translation/history/en-us.json @@ -690,14 +690,14 @@ "DataTypes": [] }, "T_UART_GLITCH_DLY_MENU_1": { - "Localized": "1 - 5000", - "EN_US": "1 - 5000", + "Localized": "1 - 5000000", + "EN_US": "1 - 5000000", "Comments": "Autogenerated from en-us.h", "DataTypes": [] }, "T_UART_GLITCH_DLY_PROMPT": { - "Localized": "Glitch trigger delay in us (1)", - "EN_US": "Glitch trigger delay in us (1)", + "Localized": "Glitch trigger delay in ns * 10 (1)", + "EN_US": "Glitch trigger delay in ns * 10 (1)", "Comments": "Autogenerated from en-us.h", "DataTypes": [] }, @@ -714,8 +714,8 @@ "DataTypes": [] }, "T_UART_GLITCH_VRY_PROMPT": { - "Localized": "Glitch vary time in us (3)", - "EN_US": "Glitch vary time in us (3)", + "Localized": "Glitch vary time in ns * 10 (3)", + "EN_US": "Glitch vary time in ns * 10 (3)", "Comments": "Autogenerated from en-us.h", "DataTypes": [] }, @@ -726,14 +726,14 @@ "DataTypes": [] }, "T_UART_GLITCH_LNG_MENU_1": { - "Localized": "1 - 5000", - "EN_US": "1 - 5000", + "Localized": "1 - 5000000", + "EN_US": "1 - 5000000", "Comments": "Autogenerated from en-us.h", "DataTypes": [] }, "T_UART_GLITCH_LNG_PROMPT": { - "Localized": "Glitch on time in us (1)", - "EN_US": "Glitch on time in us (1)", + "Localized": "Glitch on time in ns * 10 (1)", + "EN_US": "Glitch on time in ns * 10 (1)", "Comments": "Autogenerated from en-us.h", "DataTypes": [] }, @@ -768,8 +768,8 @@ "DataTypes": [] }, "T_UART_GLITCH_FAIL_PROMPT": { - "Localized": "ASCII value of first char of normal response (35 - '#')", - "EN_US": "ASCII value of first char of normal response (35 - '#')", + "Localized": "ASCII value of a known char of normal response (35 - '#')", + "EN_US": "ASCII value of a known char of normal response (35 - '#')", "Comments": "Autogenerated from en-us.h", "DataTypes": [] }, @@ -804,8 +804,8 @@ "DataTypes": [] }, "T_UART_GLITCH_NORDY_PROMPT": { - "Localized": "0 to disable, 1 to enable (1)", - "EN_US": "0 to disable, 1 to enable (1)", + "Localized": "0 to disable, 1 to enable (1, do not check input)", + "EN_US": "0 to disable, 1 to enable (1, do not check input)", "Comments": "Autogenerated from en-us.h", "DataTypes": [] }, From faaebfd42e1d3b3b3f58808ad5753d4ba2595e9b Mon Sep 17 00:00:00 2001 From: Matthew Brugman Date: Sun, 19 Jan 2025 15:06:24 -0600 Subject: [PATCH 4/5] Ope, fixup a TODO comment and add a little more to the header plate comment --- src/commands/uart/glitch.c | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/src/commands/uart/glitch.c b/src/commands/uart/glitch.c index 836ae35e..6772caaf 100644 --- a/src/commands/uart/glitch.c +++ b/src/commands/uart/glitch.c @@ -32,7 +32,10 @@ * * This module is used to time either of those two attacks. * - * A PIO program handles the actual timing and output control + * A PIO SM handles the actual timing and output control. + * The SM is set to run at 100MHz, so each instruction is 10 + * nanoseconds. There is a bit of error in the actual timing + * in terms of an extra cycle or so. ************************************************************/ #include @@ -494,8 +497,8 @@ void uart_glitch_handler(struct command_result* res) { // first item is the "on" time for the glitch pulse // second item is the number of edges for the trigger character // third item is the delay before firing the pulse - // NOTE - multiplication by 19 is for scaling; future version may allow - // fractional microsecond timing + // Note that timing is in terms of ns * 10 for items 1 and 3; so if value is + // 7, then 70us. pio_sm_put_blocking(glitch_pio.pio, glitch_pio.sm, uart_glitch_config.glitch_time); pio_sm_put_blocking(glitch_pio.pio, glitch_pio.sm, edges); pio_sm_put_blocking(glitch_pio.pio, glitch_pio.sm, this_glitch_delay); From 04d78df4fe92224cfcceb2ceeb95fef298ba62a7 Mon Sep 17 00:00:00 2001 From: Matthew Brugman Date: Sun, 19 Jan 2025 15:10:55 -0600 Subject: [PATCH 5/5] Nanoseconds, not microseconds. Made sure text and comments reflect that. --- src/commands/uart/glitch.c | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/src/commands/uart/glitch.c b/src/commands/uart/glitch.c index 6772caaf..03b9af47 100644 --- a/src/commands/uart/glitch.c +++ b/src/commands/uart/glitch.c @@ -76,9 +76,9 @@ static const char* const usage[] = { "glitch\t[-h(elp)] [-c(onfig)]", // config struct typedef struct _uart_glitch_config { uint32_t glitch_trg; // character sent from BP UART to trigger the glitch - uint32_t glitch_delay; // how long (us) after trigger stop bit to fire trigger - uint32_t glitch_wander; // amount of time (us) to vary glitch timing - uint32_t glitch_time; // amount of time (us) to have output on + uint32_t glitch_delay; // how long (ns*10) after trigger stop bit to fire trigger + uint32_t glitch_wander; // amount of time (ns*10) to vary glitch timing + uint32_t glitch_time; // amount of time (ns*10) to have output on uint32_t glitch_recycle; // minimum time (ms) between one glitch cycle and the next uint32_t fail_resp; // first character response from device on bad password uint32_t retry_count; // number of times to try glitching before quitting @@ -211,9 +211,9 @@ static const struct ui_prompt uart_menu[] = { [0] = { .description = T_UART_GLIT void glitch_settings(void) { ui_prompt_mode_settings_int(GET_T(T_UART_GLITCH_TRG_MENU), uart_glitch_config.glitch_trg, "(ASCII)"); - ui_prompt_mode_settings_int(GET_T(T_UART_GLITCH_DLY_MENU), uart_glitch_config.glitch_delay, "us*10"); - ui_prompt_mode_settings_int(GET_T(T_UART_GLITCH_VRY_MENU), uart_glitch_config.glitch_wander, "us*10"); - ui_prompt_mode_settings_int(GET_T(T_UART_GLITCH_LNG_MENU), uart_glitch_config.glitch_time, "us*10"); + ui_prompt_mode_settings_int(GET_T(T_UART_GLITCH_DLY_MENU), uart_glitch_config.glitch_delay, "ns*10"); + ui_prompt_mode_settings_int(GET_T(T_UART_GLITCH_VRY_MENU), uart_glitch_config.glitch_wander, "ns*10"); + ui_prompt_mode_settings_int(GET_T(T_UART_GLITCH_LNG_MENU), uart_glitch_config.glitch_time, "ns*10"); ui_prompt_mode_settings_int(GET_T(T_UART_GLITCH_CYC_MENU), uart_glitch_config.glitch_recycle, "ms"); ui_prompt_mode_settings_int(GET_T(T_UART_GLITCH_FAIL_MENU), uart_glitch_config.fail_resp, "(ASCII)"); ui_prompt_mode_settings_int(GET_T(T_UART_GLITCH_CNT_MENU), uart_glitch_config.retry_count, 0x00); @@ -498,7 +498,7 @@ void uart_glitch_handler(struct command_result* res) { // second item is the number of edges for the trigger character // third item is the delay before firing the pulse // Note that timing is in terms of ns * 10 for items 1 and 3; so if value is - // 7, then 70us. + // 7, then 70ns. pio_sm_put_blocking(glitch_pio.pio, glitch_pio.sm, uart_glitch_config.glitch_time); pio_sm_put_blocking(glitch_pio.pio, glitch_pio.sm, edges); pio_sm_put_blocking(glitch_pio.pio, glitch_pio.sm, this_glitch_delay); @@ -547,7 +547,7 @@ void uart_glitch_handler(struct command_result* res) { busy_wait_us_32(500); } - printf("Attempt %3d, delay %dus RX: %s\r\n", tries + 1, this_glitch_delay * 10, resp_string); + printf("Attempt %3d, delay %dns RX: %s\r\n", tries + 1, this_glitch_delay * 10, resp_string); // parse through the response. if our "normal bad password response" // character is present, then we didn't glitch :/