Skip to content

Instantly share code, notes, and snippets.

@parkerhoyes
Last active February 22, 2017 05:19
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save parkerhoyes/54f8ad30cce1134351ee3ffcb13e69f1 to your computer and use it in GitHub Desktop.
Save parkerhoyes/54f8ad30cce1134351ee3ffcb13e69f1 to your computer and use it in GitHub Desktop.
Demonstration of Bug (Core Fault?) on Nano S
#include <stdbool.h>
#include <stdint.h>
#include "os.h"
#include "os_io_seproxyhal.h"
// BEGIN TEST CODE
static const uint8_t app_test_obj = 42;
static int8_t app_test_int;
static uint8_t app_test_buff[8];
static uint8_t *app_test_buff_ptr;
static void run_test() {
app_test_int = -1;
app_test_buff_ptr = app_test_buff;
const uint8_t *obj_ptr = &app_test_obj;
os_memcpy(app_test_buff_ptr, &obj_ptr, sizeof(obj_ptr));
app_test_buff_ptr += sizeof(uint8_t*);
const uint8_t **obj_ptr_ptr = (const uint8_t**) (app_test_buff_ptr - sizeof(uint8_t*));
const uint8_t *temp = *obj_ptr_ptr; // Core fault on this line?
os_sched_exit(0);
app_test_int = *temp;
}
static void app_event_ticker() {
if (app_test_int == -1)
app_test_int = 0;
}
// END TEST CODE
unsigned char G_io_seproxyhal_spi_buffer[IO_SEPROXYHAL_BUFFER_SIZE_B];
void sample_main() {
volatile unsigned int rx = 0;
volatile unsigned int tx = 0;
volatile unsigned int flags = 0;
while (true) {
volatile unsigned short sw = 0;
BEGIN_TRY {
TRY {
rx = tx;
tx = 0; // Ensure no race in catch_other if io_exchange throws an error
rx = io_exchange(CHANNEL_APDU | flags, rx);
flags = 0;
// No APDU received, well, reset the session, and reset the bootloader configuration
if (rx == 0) {
THROW(0x6982);
}
if (G_io_apdu_buffer[0] != 0x80) {
THROW(0x6E00);
}
// Unauthenticated instruction
switch (G_io_apdu_buffer[1]) {
case 0x00: // Reset
flags |= IO_RESET_AFTER_REPLIED;
THROW(0x9000);
break;
case 0x01: // Case 1
THROW(0x9000);
break;
case 0x02: // Echo
tx = rx;
THROW(0x9000);
break;
case 0xFF: // Return to dashboard
goto return_to_dashboard;
default:
THROW(0x6D00);
break;
}
} CATCH_OTHER(e) {
switch (e & 0xF000) {
case 0x6000:
case 0x9000:
sw = e;
break;
default:
sw = 0x6800 | (e & 0x7FF);
break;
}
// Unexpected exception => report
G_io_apdu_buffer[tx] = sw >> 8;
G_io_apdu_buffer[tx + 1] = sw;
tx += 2;
} FINALLY {}
} END_TRY;
}
return_to_dashboard:
return;
}
unsigned short io_exchange_al(unsigned char channel, unsigned short tx_len) {
switch (channel & ~(IO_FLAGS)) {
case CHANNEL_KEYBOARD:
break;
// Multiplexed io exchange over a SPI channel and TLV encapsulated protocol
case CHANNEL_SPI:
if (tx_len) {
io_seproxyhal_spi_send(G_io_apdu_buffer, tx_len);
if (channel & IO_RESET_AFTER_REPLIED) {
reset();
}
return 0; // Nothing received from the master so far (it's a tx transaction)
} else {
return io_seproxyhal_spi_recv(G_io_apdu_buffer, sizeof(G_io_apdu_buffer), 0);
}
default:
THROW(INVALID_PARAMETER);
}
return 0;
}
unsigned char io_event(unsigned char channel) {
switch (G_io_seproxyhal_spi_buffer[0]) {
case SEPROXYHAL_TAG_TICKER_EVENT:
app_event_ticker();
break;
// Unknown events are acknowledged
default:
break;
}
// Close the event if not done previously (by a display or whatever)
if (!io_seproxyhal_spi_is_status_sent()) {
io_seproxyhal_general_status();
}
// Command has been processed, DO NOT reset the current APDU transport
return 1;
}
__attribute__((section(".boot"))) int main() {
// Exit critical section
__asm volatile("cpsie i");
// Ensure exception will work as planned
os_boot();
BEGIN_TRY {
TRY {
io_seproxyhal_init();
USB_power(0);
USB_power(1);
run_test();
sample_main();
} CATCH_OTHER(e) {} FINALLY {}
} END_TRY;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment