diff --git a/.clang-format b/.clang-format index e18df7341..58d4b3b68 100644 --- a/.clang-format +++ b/.clang-format @@ -1,3 +1,2 @@ --- BasedOnStyle: Google -IndentWidth: 4 diff --git a/Makefile b/Makefile index c8f376708..fb945738f 100644 --- a/Makefile +++ b/Makefile @@ -86,10 +86,11 @@ style: ## apply code style on application sources and tests black $(shell find src -name *.py ! -path 'src/trezor/messages/*') cstyle_check: ## run code style check on low-level C code - ./tools/clang-format-check $(shell find embed -type f -name *.[ch]) + ./tools/clang-format-check embed/*/*.{c,h} embed/extmod/modtrezor*/*.{c,h} + cstyle: ## apply code style on low-level C code - clang-format -i $(shell find embed -type f -name *.[ch]) + clang-format -i embed/*/*.{c,h} embed/extmod/modtrezor*/*.{c,h} ## code generation: diff --git a/embed/boardloader/main.c b/embed/boardloader/main.c index 34db7c35b..bdad12c4d 100644 --- a/embed/boardloader/main.c +++ b/embed/boardloader/main.c @@ -21,8 +21,8 @@ #include "common.h" #include "display.h" -#include "image.h" #include "flash.h" +#include "image.h" #include "rng.h" #include "sdcard.h" @@ -45,158 +45,164 @@ static const uint8_t * const BOARDLOADER_KEYS[] = { #endif }; -static uint32_t check_sdcard(void) -{ - if (sectrue != sdcard_power_on()) { - return 0; - } - - uint64_t cap = sdcard_get_capacity_in_bytes(); - if (cap < 1024 * 1024) { - sdcard_power_off(); - return 0; - } +static uint32_t check_sdcard(void) { + if (sectrue != sdcard_power_on()) { + return 0; + } - uint32_t buf[IMAGE_HEADER_SIZE / sizeof(uint32_t)]; + uint64_t cap = sdcard_get_capacity_in_bytes(); + if (cap < 1024 * 1024) { + sdcard_power_off(); + return 0; + } - memzero(buf, sizeof(buf)); + uint32_t buf[IMAGE_HEADER_SIZE / sizeof(uint32_t)]; - const secbool read_status = sdcard_read_blocks(buf, 0, IMAGE_HEADER_SIZE / SDCARD_BLOCK_SIZE); + memzero(buf, sizeof(buf)); - sdcard_power_off(); + const secbool read_status = + sdcard_read_blocks(buf, 0, IMAGE_HEADER_SIZE / SDCARD_BLOCK_SIZE); - image_header hdr; + sdcard_power_off(); - if ((sectrue == read_status) && (sectrue == load_image_header((const uint8_t *)buf, BOOTLOADER_IMAGE_MAGIC, BOOTLOADER_IMAGE_MAXSIZE, BOARDLOADER_KEY_M, BOARDLOADER_KEY_N, BOARDLOADER_KEYS, &hdr))) { - return hdr.codelen; - } else { - return 0; - } -} + image_header hdr; -static void progress_callback(int pos, int len) { - display_printf("."); + if ((sectrue == read_status) && + (sectrue == + load_image_header((const uint8_t *)buf, BOOTLOADER_IMAGE_MAGIC, + BOOTLOADER_IMAGE_MAXSIZE, BOARDLOADER_KEY_M, + BOARDLOADER_KEY_N, BOARDLOADER_KEYS, &hdr))) { + return hdr.codelen; + } else { + return 0; + } } -static secbool copy_sdcard(void) -{ - display_backlight(255); +static void progress_callback(int pos, int len) { display_printf("."); } - display_printf("TREZOR Boardloader\n"); - display_printf("==================\n\n"); +static secbool copy_sdcard(void) { + display_backlight(255); - display_printf("bootloader found on the SD card\n\n"); - display_printf("applying bootloader in 10 seconds\n\n"); - display_printf("unplug now if you want to abort\n\n"); + display_printf("TREZOR Boardloader\n"); + display_printf("==================\n\n"); - uint32_t codelen; + display_printf("bootloader found on the SD card\n\n"); + display_printf("applying bootloader in 10 seconds\n\n"); + display_printf("unplug now if you want to abort\n\n"); - for (int i = 10; i >= 0; i--) { - display_printf("%d ", i); - hal_delay(1000); - codelen = check_sdcard(); - if (0 == codelen) { - display_printf("\n\nno SD card, aborting\n"); - return secfalse; - } - } + uint32_t codelen; - display_printf("\n\nerasing flash:\n\n"); - - // erase all flash (except boardloader) - static const uint8_t sectors[] = { - FLASH_SECTOR_STORAGE_1, - FLASH_SECTOR_STORAGE_2, - 3, - FLASH_SECTOR_BOOTLOADER, - FLASH_SECTOR_FIRMWARE_START, - 7, - 8, - 9, - 10, - FLASH_SECTOR_FIRMWARE_END, - FLASH_SECTOR_UNUSED_START, - 13, - 14, - FLASH_SECTOR_UNUSED_END, - FLASH_SECTOR_FIRMWARE_EXTRA_START, - 18, - 19, - 20, - 21, - 22, - FLASH_SECTOR_FIRMWARE_EXTRA_END, - }; - if (sectrue != flash_erase_sectors(sectors, sizeof(sectors), progress_callback)) { - display_printf(" failed\n"); - return secfalse; + for (int i = 10; i >= 0; i--) { + display_printf("%d ", i); + hal_delay(1000); + codelen = check_sdcard(); + if (0 == codelen) { + display_printf("\n\nno SD card, aborting\n"); + return secfalse; } - display_printf(" done\n\n"); - - ensure(flash_unlock_write(), NULL); - - // copy bootloader from SD card to Flash - display_printf("copying new bootloader from SD card\n\n"); - - ensure(sdcard_power_on(), NULL); - - uint32_t buf[SDCARD_BLOCK_SIZE / sizeof(uint32_t)]; - for (int i = 0; i < (IMAGE_HEADER_SIZE + codelen) / SDCARD_BLOCK_SIZE; i++) { - ensure(sdcard_read_blocks(buf, i, 1), NULL); - for (int j = 0; j < SDCARD_BLOCK_SIZE / sizeof(uint32_t); j++) { - ensure(flash_write_word(FLASH_SECTOR_BOOTLOADER, i * SDCARD_BLOCK_SIZE + j * sizeof(uint32_t), buf[j]), NULL); - } + } + + display_printf("\n\nerasing flash:\n\n"); + + // erase all flash (except boardloader) + static const uint8_t sectors[] = { + FLASH_SECTOR_STORAGE_1, + FLASH_SECTOR_STORAGE_2, + 3, + FLASH_SECTOR_BOOTLOADER, + FLASH_SECTOR_FIRMWARE_START, + 7, + 8, + 9, + 10, + FLASH_SECTOR_FIRMWARE_END, + FLASH_SECTOR_UNUSED_START, + 13, + 14, + FLASH_SECTOR_UNUSED_END, + FLASH_SECTOR_FIRMWARE_EXTRA_START, + 18, + 19, + 20, + 21, + 22, + FLASH_SECTOR_FIRMWARE_EXTRA_END, + }; + if (sectrue != + flash_erase_sectors(sectors, sizeof(sectors), progress_callback)) { + display_printf(" failed\n"); + return secfalse; + } + display_printf(" done\n\n"); + + ensure(flash_unlock_write(), NULL); + + // copy bootloader from SD card to Flash + display_printf("copying new bootloader from SD card\n\n"); + + ensure(sdcard_power_on(), NULL); + + uint32_t buf[SDCARD_BLOCK_SIZE / sizeof(uint32_t)]; + for (int i = 0; i < (IMAGE_HEADER_SIZE + codelen) / SDCARD_BLOCK_SIZE; i++) { + ensure(sdcard_read_blocks(buf, i, 1), NULL); + for (int j = 0; j < SDCARD_BLOCK_SIZE / sizeof(uint32_t); j++) { + ensure(flash_write_word(FLASH_SECTOR_BOOTLOADER, + i * SDCARD_BLOCK_SIZE + j * sizeof(uint32_t), + buf[j]), + NULL); } + } - sdcard_power_off(); - ensure(flash_lock_write(), NULL); + sdcard_power_off(); + ensure(flash_lock_write(), NULL); - display_printf("\ndone\n\n"); - display_printf("Unplug the device and remove the SD card\n"); + display_printf("\ndone\n\n"); + display_printf("Unplug the device and remove the SD card\n"); - return sectrue; + return sectrue; } -int main(void) -{ - if (sectrue != reset_flags_check()) { - return 1; - } +int main(void) { + if (sectrue != reset_flags_check()) { + return 1; + } - // need the systick timer running before many HAL operations. - // want the PVD enabled before flash operations too. - periph_init(); + // need the systick timer running before many HAL operations. + // want the PVD enabled before flash operations too. + periph_init(); - if (sectrue != flash_configure_option_bytes()) { - // display is not initialized so don't call ensure - secbool r = flash_erase_sectors(STORAGE_SECTORS, STORAGE_SECTORS_COUNT, NULL); - (void)r; - return 2; - } + if (sectrue != flash_configure_option_bytes()) { + // display is not initialized so don't call ensure + secbool r = + flash_erase_sectors(STORAGE_SECTORS, STORAGE_SECTORS_COUNT, NULL); + (void)r; + return 2; + } - clear_otg_hs_memory(); + clear_otg_hs_memory(); - display_init(); - sdcard_init(); + display_init(); + sdcard_init(); - if (check_sdcard()) { - return copy_sdcard() == sectrue ? 0 : 3; - } + if (check_sdcard()) { + return copy_sdcard() == sectrue ? 0 : 3; + } - image_header hdr; + image_header hdr; - ensure( - load_image_header((const uint8_t *)BOOTLOADER_START, BOOTLOADER_IMAGE_MAGIC, BOOTLOADER_IMAGE_MAXSIZE, BOARDLOADER_KEY_M, BOARDLOADER_KEY_N, BOARDLOADER_KEYS, &hdr), - "invalid bootloader header"); + ensure(load_image_header((const uint8_t *)BOOTLOADER_START, + BOOTLOADER_IMAGE_MAGIC, BOOTLOADER_IMAGE_MAXSIZE, + BOARDLOADER_KEY_M, BOARDLOADER_KEY_N, + BOARDLOADER_KEYS, &hdr), + "invalid bootloader header"); - const uint8_t sectors[] = { - FLASH_SECTOR_BOOTLOADER, - }; - ensure( - check_image_contents(&hdr, IMAGE_HEADER_SIZE, sectors, 1), - "invalid bootloader hash"); + const uint8_t sectors[] = { + FLASH_SECTOR_BOOTLOADER, + }; + ensure(check_image_contents(&hdr, IMAGE_HEADER_SIZE, sectors, 1), + "invalid bootloader hash"); - jump_to(BOOTLOADER_START + IMAGE_HEADER_SIZE); + jump_to(BOOTLOADER_START + IMAGE_HEADER_SIZE); - return 0; + return 0; } diff --git a/embed/boardloader/version.h b/embed/boardloader/version.h index 5b6f58dc4..ba8991dcd 100644 --- a/embed/boardloader/version.h +++ b/embed/boardloader/version.h @@ -1,4 +1,4 @@ -#define VERSION_MAJOR 2 -#define VERSION_MINOR 0 -#define VERSION_PATCH 2 -#define VERSION_BUILD 0 +#define VERSION_MAJOR 2 +#define VERSION_MINOR 0 +#define VERSION_PATCH 2 +#define VERSION_BUILD 0 diff --git a/embed/bootloader/bootui.c b/embed/bootloader/bootui.c index 05f73c8d9..e5e84b6a6 100644 --- a/embed/bootloader/bootui.c +++ b/embed/bootloader/bootui.c @@ -28,9 +28,9 @@ #include "icon_cancel.h" #include "icon_confirm.h" -#include "icon_info.h" #include "icon_done.h" #include "icon_fail.h" +#include "icon_info.h" #include "icon_install.h" #include "icon_wipe.h" @@ -40,283 +40,319 @@ #define BACKLIGHT_NORMAL 150 -#define COLOR_BL_FAIL RGB16(0xFF, 0x00, 0x00) // red -#define COLOR_BL_DONE RGB16(0x00, 0xAE, 0x0B) // green -#define COLOR_BL_PROCESS RGB16(0x4A, 0x90, 0xE2) // blue -#define COLOR_BL_GRAY RGB16(0x99, 0x99, 0x99) // gray +#define COLOR_BL_FAIL RGB16(0xFF, 0x00, 0x00) // red +#define COLOR_BL_DONE RGB16(0x00, 0xAE, 0x0B) // green +#define COLOR_BL_PROCESS RGB16(0x4A, 0x90, 0xE2) // blue +#define COLOR_BL_GRAY RGB16(0x99, 0x99, 0x99) // gray // common shared functions -static void ui_confirm_cancel_buttons(void) -{ - display_bar_radius(9, 184, 108, 50, COLOR_BL_FAIL, COLOR_WHITE, 4); - display_icon(9 + (108 - 16) / 2, 184 + (50 - 16) / 2, 16, 16, toi_icon_cancel + 12, sizeof(toi_icon_cancel) - 12, COLOR_WHITE, COLOR_BL_FAIL); - display_bar_radius(123, 184, 108, 50, COLOR_BL_DONE, COLOR_WHITE, 4); - display_icon(123 + (108 - 19) / 2, 184 + (50 - 16) / 2, 20, 16, toi_icon_confirm + 12, sizeof(toi_icon_confirm) - 12, COLOR_WHITE, COLOR_BL_DONE); +static void ui_confirm_cancel_buttons(void) { + display_bar_radius(9, 184, 108, 50, COLOR_BL_FAIL, COLOR_WHITE, 4); + display_icon(9 + (108 - 16) / 2, 184 + (50 - 16) / 2, 16, 16, + toi_icon_cancel + 12, sizeof(toi_icon_cancel) - 12, COLOR_WHITE, + COLOR_BL_FAIL); + display_bar_radius(123, 184, 108, 50, COLOR_BL_DONE, COLOR_WHITE, 4); + display_icon(123 + (108 - 19) / 2, 184 + (50 - 16) / 2, 20, 16, + toi_icon_confirm + 12, sizeof(toi_icon_confirm) - 12, + COLOR_WHITE, COLOR_BL_DONE); } -static const char *format_ver(const char *format, uint32_t version) -{ - static char ver_str[64]; - mini_snprintf(ver_str, sizeof(ver_str), format, - (int)(version & 0xFF), - (int)((version >> 8) & 0xFF), - (int)((version >> 16) & 0xFF) - // ignore build field (int)((version >> 24) & 0xFF) - ); - return ver_str; +static const char *format_ver(const char *format, uint32_t version) { + static char ver_str[64]; + mini_snprintf(ver_str, sizeof(ver_str), format, (int)(version & 0xFF), + (int)((version >> 8) & 0xFF), (int)((version >> 16) & 0xFF) + // ignore build field (int)((version >> 24) & 0xFF) + ); + return ver_str; } // boot UI static uint16_t boot_background; -void ui_screen_boot(const vendor_header * const vhdr, const image_header * const hdr) -{ - const int show_string = ((vhdr->vtrust & VTRUST_STRING) == 0); - if ((vhdr->vtrust & VTRUST_RED) == 0) { - boot_background = COLOR_BL_FAIL; - } else { - boot_background = COLOR_BLACK; - } - - const uint8_t *vimg = vhdr->vimg; - const uint32_t fw_version = hdr->version; - - display_bar(0, 0, DISPLAY_RESX, DISPLAY_RESY, boot_background); - - int image_top = show_string ? 30 : (DISPLAY_RESY - 120) / 2; - - // check whether vendor image is 120x120 - if (memcmp(vimg, "TOIf\x78\x00\x78\x00", 4) == 0) { - uint32_t datalen = *(uint32_t *)(vimg + 8); - display_image((DISPLAY_RESX - 120) / 2, image_top, 120, 120, vimg + 12, datalen); - } - - if (show_string) { - display_text_center(DISPLAY_RESX / 2, DISPLAY_RESY - 5 - 50, vhdr->vstr, vhdr->vstr_len, FONT_NORMAL, COLOR_WHITE, boot_background); - const char *ver_str = format_ver("%d.%d.%d", fw_version); - display_text_center(DISPLAY_RESX / 2, DISPLAY_RESY - 5 - 25, ver_str, -1, FONT_NORMAL, COLOR_WHITE, boot_background); - } +void ui_screen_boot(const vendor_header *const vhdr, + const image_header *const hdr) { + const int show_string = ((vhdr->vtrust & VTRUST_STRING) == 0); + if ((vhdr->vtrust & VTRUST_RED) == 0) { + boot_background = COLOR_BL_FAIL; + } else { + boot_background = COLOR_BLACK; + } + + const uint8_t *vimg = vhdr->vimg; + const uint32_t fw_version = hdr->version; + + display_bar(0, 0, DISPLAY_RESX, DISPLAY_RESY, boot_background); + + int image_top = show_string ? 30 : (DISPLAY_RESY - 120) / 2; + + // check whether vendor image is 120x120 + if (memcmp(vimg, "TOIf\x78\x00\x78\x00", 4) == 0) { + uint32_t datalen = *(uint32_t *)(vimg + 8); + display_image((DISPLAY_RESX - 120) / 2, image_top, 120, 120, vimg + 12, + datalen); + } + + if (show_string) { + display_text_center(DISPLAY_RESX / 2, DISPLAY_RESY - 5 - 50, vhdr->vstr, + vhdr->vstr_len, FONT_NORMAL, COLOR_WHITE, + boot_background); + const char *ver_str = format_ver("%d.%d.%d", fw_version); + display_text_center(DISPLAY_RESX / 2, DISPLAY_RESY - 5 - 25, ver_str, -1, + FONT_NORMAL, COLOR_WHITE, boot_background); + } } -void ui_screen_boot_wait(int wait_seconds) -{ - char wait_str[16]; - mini_snprintf(wait_str, sizeof(wait_str), "starting in %d s", wait_seconds); - display_bar(0, DISPLAY_RESY - 5 - 20, DISPLAY_RESX, 5 + 20, boot_background); - display_text_center(DISPLAY_RESX / 2, DISPLAY_RESY - 5, wait_str, -1, FONT_NORMAL, COLOR_WHITE, boot_background); +void ui_screen_boot_wait(int wait_seconds) { + char wait_str[16]; + mini_snprintf(wait_str, sizeof(wait_str), "starting in %d s", wait_seconds); + display_bar(0, DISPLAY_RESY - 5 - 20, DISPLAY_RESX, 5 + 20, boot_background); + display_text_center(DISPLAY_RESX / 2, DISPLAY_RESY - 5, wait_str, -1, + FONT_NORMAL, COLOR_WHITE, boot_background); } void ui_screen_boot_click(void) { - display_bar(0, DISPLAY_RESY - 5 - 20, DISPLAY_RESX, 5 + 20, boot_background); - display_text_center(DISPLAY_RESX / 2, DISPLAY_RESY - 5, "click to continue ...", -1, FONT_NORMAL, COLOR_WHITE, boot_background); + display_bar(0, DISPLAY_RESY - 5 - 20, DISPLAY_RESX, 5 + 20, boot_background); + display_text_center(DISPLAY_RESX / 2, DISPLAY_RESY - 5, + "click to continue ...", -1, FONT_NORMAL, COLOR_WHITE, + boot_background); } // welcome UI -void ui_screen_first(void) -{ - display_icon(0, 0, 240, 240, toi_icon_logo + 12, sizeof(toi_icon_logo) - 12, COLOR_BLACK, COLOR_WHITE); +void ui_screen_first(void) { + display_icon(0, 0, 240, 240, toi_icon_logo + 12, sizeof(toi_icon_logo) - 12, + COLOR_BLACK, COLOR_WHITE); } -void ui_screen_second(void) -{ - display_bar(0, 0, DISPLAY_RESX, DISPLAY_RESY, COLOR_WHITE); - display_icon((DISPLAY_RESX - 200) / 2, (DISPLAY_RESY - 60) / 2, 200, 60, toi_icon_safeplace + 12, sizeof(toi_icon_safeplace) - 12, COLOR_BLACK, COLOR_WHITE); +void ui_screen_second(void) { + display_bar(0, 0, DISPLAY_RESX, DISPLAY_RESY, COLOR_WHITE); + display_icon((DISPLAY_RESX - 200) / 2, (DISPLAY_RESY - 60) / 2, 200, 60, + toi_icon_safeplace + 12, sizeof(toi_icon_safeplace) - 12, + COLOR_BLACK, COLOR_WHITE); } -void ui_screen_third(void) -{ - display_bar(0, 0, DISPLAY_RESX, DISPLAY_RESY, COLOR_WHITE); - display_icon((DISPLAY_RESX - 180) / 2, (DISPLAY_RESY - 30) / 2 - 5, 180, 30, toi_icon_welcome + 12, sizeof(toi_icon_welcome) - 12, COLOR_BLACK, COLOR_WHITE); - display_text_center(120, 220, "Go to trezor.io/start", -1, FONT_NORMAL, COLOR_BLACK, COLOR_WHITE); +void ui_screen_third(void) { + display_bar(0, 0, DISPLAY_RESX, DISPLAY_RESY, COLOR_WHITE); + display_icon((DISPLAY_RESX - 180) / 2, (DISPLAY_RESY - 30) / 2 - 5, 180, 30, + toi_icon_welcome + 12, sizeof(toi_icon_welcome) - 12, + COLOR_BLACK, COLOR_WHITE); + display_text_center(120, 220, "Go to trezor.io/start", -1, FONT_NORMAL, + COLOR_BLACK, COLOR_WHITE); } // info UI -void ui_screen_info(secbool buttons, const vendor_header * const vhdr, const image_header * const hdr) -{ - display_bar(0, 0, DISPLAY_RESX, DISPLAY_RESY, COLOR_WHITE); - const char *ver_str = format_ver("Bootloader %d.%d.%d", VERSION_UINT32); - display_text(16, 32, ver_str, -1, FONT_NORMAL, COLOR_BLACK, COLOR_WHITE); - display_bar(16, 44, DISPLAY_RESX - 14 * 2, 1, COLOR_BLACK); - display_icon(16, 54, 32, 32, toi_icon_info + 12, sizeof(toi_icon_info) - 12, COLOR_BL_GRAY, COLOR_WHITE); - if (vhdr && hdr) { - ver_str = format_ver("Firmware %d.%d.%d", (hdr->version)); - display_text(55, 70, ver_str, -1, FONT_NORMAL, COLOR_BL_GRAY, COLOR_WHITE); - display_text(55, 95, "by", -1, FONT_NORMAL, COLOR_BL_GRAY, COLOR_WHITE); - display_text(55, 120, vhdr->vstr, vhdr->vstr_len, FONT_NORMAL, COLOR_BL_GRAY, COLOR_WHITE); - } else { - display_text(55, 70, "No Firmware", -1, FONT_NORMAL, COLOR_BL_GRAY, COLOR_WHITE); - } - - if (sectrue == buttons) { - display_text_center(120, 170, "Connect to host?", -1, FONT_NORMAL, COLOR_BLACK, COLOR_WHITE); - ui_confirm_cancel_buttons(); - } else { - display_text_center(120, 220, "Go to trezor.io/start", -1, FONT_NORMAL, COLOR_BLACK, COLOR_WHITE); - } +void ui_screen_info(secbool buttons, const vendor_header *const vhdr, + const image_header *const hdr) { + display_bar(0, 0, DISPLAY_RESX, DISPLAY_RESY, COLOR_WHITE); + const char *ver_str = format_ver("Bootloader %d.%d.%d", VERSION_UINT32); + display_text(16, 32, ver_str, -1, FONT_NORMAL, COLOR_BLACK, COLOR_WHITE); + display_bar(16, 44, DISPLAY_RESX - 14 * 2, 1, COLOR_BLACK); + display_icon(16, 54, 32, 32, toi_icon_info + 12, sizeof(toi_icon_info) - 12, + COLOR_BL_GRAY, COLOR_WHITE); + if (vhdr && hdr) { + ver_str = format_ver("Firmware %d.%d.%d", (hdr->version)); + display_text(55, 70, ver_str, -1, FONT_NORMAL, COLOR_BL_GRAY, COLOR_WHITE); + display_text(55, 95, "by", -1, FONT_NORMAL, COLOR_BL_GRAY, COLOR_WHITE); + display_text(55, 120, vhdr->vstr, vhdr->vstr_len, FONT_NORMAL, + COLOR_BL_GRAY, COLOR_WHITE); + } else { + display_text(55, 70, "No Firmware", -1, FONT_NORMAL, COLOR_BL_GRAY, + COLOR_WHITE); + } + + if (sectrue == buttons) { + display_text_center(120, 170, "Connect to host?", -1, FONT_NORMAL, + COLOR_BLACK, COLOR_WHITE); + ui_confirm_cancel_buttons(); + } else { + display_text_center(120, 220, "Go to trezor.io/start", -1, FONT_NORMAL, + COLOR_BLACK, COLOR_WHITE); + } } -void ui_screen_info_fingerprint(const image_header * const hdr) -{ - display_bar(0, 0, DISPLAY_RESX, DISPLAY_RESY, COLOR_WHITE); - display_text(16, 32, "Firmware fingerprint", -1, FONT_NORMAL, COLOR_BLACK, COLOR_WHITE); - display_bar(16, 44, DISPLAY_RESX - 14 * 2, 1, COLOR_BLACK); - - static const char *hexdigits = "0123456789abcdef"; - char fingerprint_str[64]; - for (int i = 0; i < 32; i++) { - fingerprint_str[i * 2 ] = hexdigits[(hdr->fingerprint[i] >> 4) & 0xF]; - fingerprint_str[i * 2 + 1] = hexdigits[hdr->fingerprint[i] & 0xF]; - } - for (int i = 0; i < 4; i++) { - display_text_center(120, 70 + i * 25, fingerprint_str + i * 16, 16, FONT_MONO, COLOR_BLACK, COLOR_WHITE); - } - - display_bar_radius(9, 184, 222, 50, COLOR_BL_DONE, COLOR_WHITE, 4); - display_icon(9 + (222 - 19) / 2, 184 + (50 - 16) / 2, 20, 16, toi_icon_confirm + 12, sizeof(toi_icon_confirm) - 12, COLOR_WHITE, COLOR_BL_DONE); +void ui_screen_info_fingerprint(const image_header *const hdr) { + display_bar(0, 0, DISPLAY_RESX, DISPLAY_RESY, COLOR_WHITE); + display_text(16, 32, "Firmware fingerprint", -1, FONT_NORMAL, COLOR_BLACK, + COLOR_WHITE); + display_bar(16, 44, DISPLAY_RESX - 14 * 2, 1, COLOR_BLACK); + + static const char *hexdigits = "0123456789abcdef"; + char fingerprint_str[64]; + for (int i = 0; i < 32; i++) { + fingerprint_str[i * 2] = hexdigits[(hdr->fingerprint[i] >> 4) & 0xF]; + fingerprint_str[i * 2 + 1] = hexdigits[hdr->fingerprint[i] & 0xF]; + } + for (int i = 0; i < 4; i++) { + display_text_center(120, 70 + i * 25, fingerprint_str + i * 16, 16, + FONT_MONO, COLOR_BLACK, COLOR_WHITE); + } + + display_bar_radius(9, 184, 222, 50, COLOR_BL_DONE, COLOR_WHITE, 4); + display_icon(9 + (222 - 19) / 2, 184 + (50 - 16) / 2, 20, 16, + toi_icon_confirm + 12, sizeof(toi_icon_confirm) - 12, + COLOR_WHITE, COLOR_BL_DONE); } // install UI -void ui_screen_install_confirm_upgrade(const vendor_header * const vhdr, const image_header * const hdr) -{ - display_bar(0, 0, DISPLAY_RESX, DISPLAY_RESY, COLOR_WHITE); - display_text(16, 32, "Firmware update", -1, FONT_NORMAL, COLOR_BLACK, COLOR_WHITE); - display_bar(16, 44, DISPLAY_RESX - 14 * 2, 1, COLOR_BLACK); - display_icon(16, 54, 32, 32, toi_icon_info + 12, sizeof(toi_icon_info) - 12, COLOR_BLACK, COLOR_WHITE); - display_text(55, 70, "Update firmware by", -1, FONT_NORMAL, COLOR_BLACK, COLOR_WHITE); - display_text(55, 95, vhdr->vstr, vhdr->vstr_len, FONT_NORMAL, COLOR_BLACK, COLOR_WHITE); - const char *ver_str = format_ver("to version %d.%d.%d?", hdr->version); - display_text(55, 120, ver_str, -1, FONT_NORMAL, COLOR_BLACK, COLOR_WHITE); - ui_confirm_cancel_buttons(); +void ui_screen_install_confirm_upgrade(const vendor_header *const vhdr, + const image_header *const hdr) { + display_bar(0, 0, DISPLAY_RESX, DISPLAY_RESY, COLOR_WHITE); + display_text(16, 32, "Firmware update", -1, FONT_NORMAL, COLOR_BLACK, + COLOR_WHITE); + display_bar(16, 44, DISPLAY_RESX - 14 * 2, 1, COLOR_BLACK); + display_icon(16, 54, 32, 32, toi_icon_info + 12, sizeof(toi_icon_info) - 12, + COLOR_BLACK, COLOR_WHITE); + display_text(55, 70, "Update firmware by", -1, FONT_NORMAL, COLOR_BLACK, + COLOR_WHITE); + display_text(55, 95, vhdr->vstr, vhdr->vstr_len, FONT_NORMAL, COLOR_BLACK, + COLOR_WHITE); + const char *ver_str = format_ver("to version %d.%d.%d?", hdr->version); + display_text(55, 120, ver_str, -1, FONT_NORMAL, COLOR_BLACK, COLOR_WHITE); + ui_confirm_cancel_buttons(); } -void ui_screen_install_confirm_newvendor(const vendor_header * const vhdr, const image_header * const hdr) -{ - display_bar(0, 0, DISPLAY_RESX, DISPLAY_RESY, COLOR_WHITE); - display_text(16, 32, "Vendor change", -1, FONT_NORMAL, COLOR_BLACK, COLOR_WHITE); - display_bar(16, 44, DISPLAY_RESX - 14 * 2, 1, COLOR_BLACK); - display_icon(16, 54, 32, 32, toi_icon_info + 12, sizeof(toi_icon_info) - 12, COLOR_BLACK, COLOR_WHITE); - display_text(55, 70, "Install firmware by", -1, FONT_NORMAL, COLOR_BLACK, COLOR_WHITE); - display_text(55, 95, vhdr->vstr, vhdr->vstr_len, FONT_NORMAL, COLOR_BLACK, COLOR_WHITE); - const char *ver_str = format_ver("(version %d.%d.%d)?", hdr->version); - display_text(55, 120, ver_str, -1, FONT_NORMAL, COLOR_BLACK, COLOR_WHITE); - display_text_center(120, 170, "Seed will be erased!", -1, FONT_NORMAL, COLOR_BL_FAIL, COLOR_WHITE); - ui_confirm_cancel_buttons(); +void ui_screen_install_confirm_newvendor(const vendor_header *const vhdr, + const image_header *const hdr) { + display_bar(0, 0, DISPLAY_RESX, DISPLAY_RESY, COLOR_WHITE); + display_text(16, 32, "Vendor change", -1, FONT_NORMAL, COLOR_BLACK, + COLOR_WHITE); + display_bar(16, 44, DISPLAY_RESX - 14 * 2, 1, COLOR_BLACK); + display_icon(16, 54, 32, 32, toi_icon_info + 12, sizeof(toi_icon_info) - 12, + COLOR_BLACK, COLOR_WHITE); + display_text(55, 70, "Install firmware by", -1, FONT_NORMAL, COLOR_BLACK, + COLOR_WHITE); + display_text(55, 95, vhdr->vstr, vhdr->vstr_len, FONT_NORMAL, COLOR_BLACK, + COLOR_WHITE); + const char *ver_str = format_ver("(version %d.%d.%d)?", hdr->version); + display_text(55, 120, ver_str, -1, FONT_NORMAL, COLOR_BLACK, COLOR_WHITE); + display_text_center(120, 170, "Seed will be erased!", -1, FONT_NORMAL, + COLOR_BL_FAIL, COLOR_WHITE); + ui_confirm_cancel_buttons(); } -void ui_screen_install(void) -{ - display_bar(0, 0, DISPLAY_RESX, DISPLAY_RESY, COLOR_WHITE); - display_loader(0, -20, COLOR_BL_PROCESS, COLOR_WHITE, toi_icon_install, sizeof(toi_icon_install), COLOR_BLACK); - display_text_center(DISPLAY_RESX / 2, DISPLAY_RESY - 24, "Installing firmware", -1, FONT_NORMAL, COLOR_BLACK, COLOR_WHITE); +void ui_screen_install(void) { + display_bar(0, 0, DISPLAY_RESX, DISPLAY_RESY, COLOR_WHITE); + display_loader(0, -20, COLOR_BL_PROCESS, COLOR_WHITE, toi_icon_install, + sizeof(toi_icon_install), COLOR_BLACK); + display_text_center(DISPLAY_RESX / 2, DISPLAY_RESY - 24, + "Installing firmware", -1, FONT_NORMAL, COLOR_BLACK, + COLOR_WHITE); } -void ui_screen_install_progress_erase(int pos, int len) -{ - display_loader(250 * pos / len, -20, COLOR_BL_PROCESS, COLOR_WHITE, toi_icon_install, sizeof(toi_icon_install), COLOR_BLACK); +void ui_screen_install_progress_erase(int pos, int len) { + display_loader(250 * pos / len, -20, COLOR_BL_PROCESS, COLOR_WHITE, + toi_icon_install, sizeof(toi_icon_install), COLOR_BLACK); } -void ui_screen_install_progress_upload(int pos) -{ - display_loader(pos, -20, COLOR_BL_PROCESS, COLOR_WHITE, toi_icon_install, sizeof(toi_icon_install), COLOR_BLACK); +void ui_screen_install_progress_upload(int pos) { + display_loader(pos, -20, COLOR_BL_PROCESS, COLOR_WHITE, toi_icon_install, + sizeof(toi_icon_install), COLOR_BLACK); } // wipe UI -void ui_screen_wipe_confirm(void) -{ - display_bar(0, 0, DISPLAY_RESX, DISPLAY_RESY, COLOR_WHITE); - display_text(16, 32, "Wipe device", -1, FONT_NORMAL, COLOR_BLACK, COLOR_WHITE); - display_bar(16, 44, DISPLAY_RESX - 14 * 2, 1, COLOR_BLACK); - display_icon(16, 54, 32, 32, toi_icon_info + 12, sizeof(toi_icon_info) - 12, COLOR_BLACK, COLOR_WHITE); - display_text(55, 70, "Do you want to", -1, FONT_NORMAL, COLOR_BLACK, COLOR_WHITE); - display_text(55, 95, "wipe the device?", -1, FONT_NORMAL, COLOR_BLACK, COLOR_WHITE); - - display_text_center(120, 170, "Seed will be erased!", -1, FONT_NORMAL, COLOR_BL_FAIL, COLOR_WHITE); - ui_confirm_cancel_buttons(); +void ui_screen_wipe_confirm(void) { + display_bar(0, 0, DISPLAY_RESX, DISPLAY_RESY, COLOR_WHITE); + display_text(16, 32, "Wipe device", -1, FONT_NORMAL, COLOR_BLACK, + COLOR_WHITE); + display_bar(16, 44, DISPLAY_RESX - 14 * 2, 1, COLOR_BLACK); + display_icon(16, 54, 32, 32, toi_icon_info + 12, sizeof(toi_icon_info) - 12, + COLOR_BLACK, COLOR_WHITE); + display_text(55, 70, "Do you want to", -1, FONT_NORMAL, COLOR_BLACK, + COLOR_WHITE); + display_text(55, 95, "wipe the device?", -1, FONT_NORMAL, COLOR_BLACK, + COLOR_WHITE); + + display_text_center(120, 170, "Seed will be erased!", -1, FONT_NORMAL, + COLOR_BL_FAIL, COLOR_WHITE); + ui_confirm_cancel_buttons(); } -void ui_screen_wipe(void) -{ - display_bar(0, 0, DISPLAY_RESX, DISPLAY_RESY, COLOR_WHITE); - display_loader(0, -20, COLOR_BL_PROCESS, COLOR_WHITE, toi_icon_wipe, sizeof(toi_icon_wipe), COLOR_BLACK); - display_text_center(DISPLAY_RESX / 2, DISPLAY_RESY - 24, "Wiping device", -1, FONT_NORMAL, COLOR_BLACK, COLOR_WHITE); +void ui_screen_wipe(void) { + display_bar(0, 0, DISPLAY_RESX, DISPLAY_RESY, COLOR_WHITE); + display_loader(0, -20, COLOR_BL_PROCESS, COLOR_WHITE, toi_icon_wipe, + sizeof(toi_icon_wipe), COLOR_BLACK); + display_text_center(DISPLAY_RESX / 2, DISPLAY_RESY - 24, "Wiping device", -1, + FONT_NORMAL, COLOR_BLACK, COLOR_WHITE); } -void ui_screen_wipe_progress(int pos, int len) -{ - display_loader(1000 * pos / len, -20, COLOR_BL_PROCESS, COLOR_WHITE, toi_icon_wipe, sizeof(toi_icon_wipe), COLOR_BLACK); +void ui_screen_wipe_progress(int pos, int len) { + display_loader(1000 * pos / len, -20, COLOR_BL_PROCESS, COLOR_WHITE, + toi_icon_wipe, sizeof(toi_icon_wipe), COLOR_BLACK); } // done UI -void ui_screen_done(int restart_seconds, secbool full_redraw) -{ - const char *str; - char count_str[24]; - if (restart_seconds >= 1) { - mini_snprintf(count_str, sizeof(count_str), "Done! Restarting in %d s", restart_seconds); - str = count_str; - } else { - str = "Done! Unplug the device."; - } - if (sectrue == full_redraw) { - display_bar(0, 0, DISPLAY_RESX, DISPLAY_RESY, COLOR_WHITE); - } - display_loader(1000, -20, COLOR_BL_DONE, COLOR_WHITE, toi_icon_done, sizeof(toi_icon_done), COLOR_BLACK); - if (secfalse == full_redraw) { - display_bar(0, DISPLAY_RESY - 24 - 18, 240, 23, COLOR_WHITE); - } - display_text_center(DISPLAY_RESX / 2, DISPLAY_RESY - 24, str, -1, FONT_NORMAL, COLOR_BLACK, COLOR_WHITE); +void ui_screen_done(int restart_seconds, secbool full_redraw) { + const char *str; + char count_str[24]; + if (restart_seconds >= 1) { + mini_snprintf(count_str, sizeof(count_str), "Done! Restarting in %d s", + restart_seconds); + str = count_str; + } else { + str = "Done! Unplug the device."; + } + if (sectrue == full_redraw) { + display_bar(0, 0, DISPLAY_RESX, DISPLAY_RESY, COLOR_WHITE); + } + display_loader(1000, -20, COLOR_BL_DONE, COLOR_WHITE, toi_icon_done, + sizeof(toi_icon_done), COLOR_BLACK); + if (secfalse == full_redraw) { + display_bar(0, DISPLAY_RESY - 24 - 18, 240, 23, COLOR_WHITE); + } + display_text_center(DISPLAY_RESX / 2, DISPLAY_RESY - 24, str, -1, FONT_NORMAL, + COLOR_BLACK, COLOR_WHITE); } // error UI -void ui_screen_fail(void) -{ - display_bar(0, 0, DISPLAY_RESX, DISPLAY_RESY, COLOR_WHITE); - display_loader(1000, -20, COLOR_BL_FAIL, COLOR_WHITE, toi_icon_fail, sizeof(toi_icon_fail), COLOR_BLACK); - display_text_center(DISPLAY_RESX / 2, DISPLAY_RESY - 24, "Failed! Please, reconnect.", -1, FONT_NORMAL, COLOR_BLACK, COLOR_WHITE); +void ui_screen_fail(void) { + display_bar(0, 0, DISPLAY_RESX, DISPLAY_RESY, COLOR_WHITE); + display_loader(1000, -20, COLOR_BL_FAIL, COLOR_WHITE, toi_icon_fail, + sizeof(toi_icon_fail), COLOR_BLACK); + display_text_center(DISPLAY_RESX / 2, DISPLAY_RESY - 24, + "Failed! Please, reconnect.", -1, FONT_NORMAL, + COLOR_BLACK, COLOR_WHITE); } // general functions -void ui_fadein(void) -{ - display_fade(0, BACKLIGHT_NORMAL, 1000); -} +void ui_fadein(void) { display_fade(0, BACKLIGHT_NORMAL, 1000); } -void ui_fadeout(void) -{ - display_fade(BACKLIGHT_NORMAL, 0, 500); - display_clear(); +void ui_fadeout(void) { + display_fade(BACKLIGHT_NORMAL, 0, 500); + display_clear(); } -int ui_user_input(int zones) -{ - for (;;) { - uint32_t evt = touch_click(); - uint16_t x = touch_unpack_x(evt); - uint16_t y = touch_unpack_y(evt); - // clicked on Cancel button - if ((zones & INPUT_CANCEL) && x >= 9 && x < 9 + 108 && y > 184 && y < 184 + 50) { - return INPUT_CANCEL; - } - // clicked on Confirm button - if ((zones & INPUT_CONFIRM) && x >= 123 && x < 123 + 108 && y > 184 && y < 184 + 50) { - return INPUT_CONFIRM; - } - // clicked on Long Confirm button - if ((zones & INPUT_LONG_CONFIRM) && x >= 9 && x < 9 + 222 && y > 184 && y < 184 + 50) { - return INPUT_LONG_CONFIRM; - } - // clicked on Info icon - if ((zones & INPUT_INFO) && x >= 16 && x < 16 + 32 && y > 54 && y < 54 + 32) { - return INPUT_INFO; - } +int ui_user_input(int zones) { + for (;;) { + uint32_t evt = touch_click(); + uint16_t x = touch_unpack_x(evt); + uint16_t y = touch_unpack_y(evt); + // clicked on Cancel button + if ((zones & INPUT_CANCEL) && x >= 9 && x < 9 + 108 && y > 184 && + y < 184 + 50) { + return INPUT_CANCEL; + } + // clicked on Confirm button + if ((zones & INPUT_CONFIRM) && x >= 123 && x < 123 + 108 && y > 184 && + y < 184 + 50) { + return INPUT_CONFIRM; + } + // clicked on Long Confirm button + if ((zones & INPUT_LONG_CONFIRM) && x >= 9 && x < 9 + 222 && y > 184 && + y < 184 + 50) { + return INPUT_LONG_CONFIRM; + } + // clicked on Info icon + if ((zones & INPUT_INFO) && x >= 16 && x < 16 + 32 && y > 54 && + y < 54 + 32) { + return INPUT_INFO; } + } } diff --git a/embed/bootloader/bootui.h b/embed/bootloader/bootui.h index ea669927d..af3fac116 100644 --- a/embed/bootloader/bootui.h +++ b/embed/bootloader/bootui.h @@ -20,10 +20,11 @@ #ifndef __BOOTUI_H__ #define __BOOTUI_H__ -#include "secbool.h" #include "image.h" +#include "secbool.h" -void ui_screen_boot(const vendor_header * const vhdr, const image_header * const hdr); +void ui_screen_boot(const vendor_header* const vhdr, + const image_header* const hdr); void ui_screen_boot_wait(int wait_seconds); void ui_screen_boot_click(void); @@ -31,11 +32,14 @@ void ui_screen_first(void); void ui_screen_second(void); void ui_screen_third(void); -void ui_screen_info(secbool buttons, const vendor_header * const vhdr, const image_header * const hdr); -void ui_screen_info_fingerprint(const image_header * const hdr); +void ui_screen_info(secbool buttons, const vendor_header* const vhdr, + const image_header* const hdr); +void ui_screen_info_fingerprint(const image_header* const hdr); -void ui_screen_install_confirm_upgrade(const vendor_header * const vhdr, const image_header * const hdr); -void ui_screen_install_confirm_newvendor(const vendor_header * const vhdr, const image_header * const hdr); +void ui_screen_install_confirm_upgrade(const vendor_header* const vhdr, + const image_header* const hdr); +void ui_screen_install_confirm_newvendor(const vendor_header* const vhdr, + const image_header* const hdr); void ui_screen_install(void); void ui_screen_install_progress_erase(int pos, int len); void ui_screen_install_progress_upload(int pos); @@ -51,10 +55,10 @@ void ui_screen_fail(void); void ui_fadein(void); void ui_fadeout(void); -#define INPUT_CANCEL 0x01 // Cancel button -#define INPUT_CONFIRM 0x02 // Confirm button -#define INPUT_LONG_CONFIRM 0x04 // Long Confirm button -#define INPUT_INFO 0x08 // Info icon +#define INPUT_CANCEL 0x01 // Cancel button +#define INPUT_CONFIRM 0x02 // Confirm button +#define INPUT_LONG_CONFIRM 0x04 // Long Confirm button +#define INPUT_INFO 0x08 // Info icon int ui_user_input(int zones); #endif diff --git a/embed/bootloader/main.c b/embed/bootloader/main.c index 26e3285a7..f1d225ea5 100644 --- a/embed/bootloader/main.c +++ b/embed/bootloader/main.c @@ -21,11 +21,11 @@ #include #include "common.h" -#include "mpu.h" -#include "image.h" -#include "flash.h" #include "display.h" +#include "flash.h" +#include "image.h" #include "mini_printf.h" +#include "mpu.h" #include "rng.h" #include "secbool.h" #include "touch.h" @@ -48,342 +48,355 @@ static const uint8_t * const BOOTLOADER_KEYS[] = { // (const uint8_t *)"\xee\x93\xa4\xf6\x6f\x8d\x16\xb8\x19\xbb\x9b\xeb\x9f\xfc\xcd\xfc\xdc\x14\x12\xe8\x7f\xee\x6a\x32\x4c\x2a\x99\xa1\xe0\xe6\x71\x48", }; -#define USB_IFACE_NUM 0 +#define USB_IFACE_NUM 0 static void usb_init_all(void) { - - static const usb_dev_info_t dev_info = { - .device_class = 0x00, - .device_subclass = 0x00, - .device_protocol = 0x00, - .vendor_id = 0x1209, - .product_id = 0x53C0, - .release_num = 0x0200, - .manufacturer = "SatoshiLabs", - .product = "TREZOR", - .serial_number = "000000000000000000000000", - .interface = "TREZOR Interface", - .usb21_enabled = sectrue, - .usb21_landing = sectrue, - }; - - static uint8_t rx_buffer[USB_PACKET_SIZE]; - - static const usb_webusb_info_t webusb_info = { - .iface_num = USB_IFACE_NUM, - .ep_in = USB_EP_DIR_IN | 0x01, - .ep_out = USB_EP_DIR_OUT | 0x01, - .subclass = 0, - .protocol = 0, - .max_packet_len = sizeof(rx_buffer), - .rx_buffer = rx_buffer, - .polling_interval = 1, - }; - - usb_init(&dev_info); - - ensure(usb_webusb_add(&webusb_info), NULL); - - usb_start(); + static const usb_dev_info_t dev_info = { + .device_class = 0x00, + .device_subclass = 0x00, + .device_protocol = 0x00, + .vendor_id = 0x1209, + .product_id = 0x53C0, + .release_num = 0x0200, + .manufacturer = "SatoshiLabs", + .product = "TREZOR", + .serial_number = "000000000000000000000000", + .interface = "TREZOR Interface", + .usb21_enabled = sectrue, + .usb21_landing = sectrue, + }; + + static uint8_t rx_buffer[USB_PACKET_SIZE]; + + static const usb_webusb_info_t webusb_info = { + .iface_num = USB_IFACE_NUM, + .ep_in = USB_EP_DIR_IN | 0x01, + .ep_out = USB_EP_DIR_OUT | 0x01, + .subclass = 0, + .protocol = 0, + .max_packet_len = sizeof(rx_buffer), + .rx_buffer = rx_buffer, + .polling_interval = 1, + }; + + usb_init(&dev_info); + + ensure(usb_webusb_add(&webusb_info), NULL); + + usb_start(); } -static secbool bootloader_usb_loop(const vendor_header * const vhdr, const image_header * const hdr) -{ - usb_init_all(); +static secbool bootloader_usb_loop(const vendor_header *const vhdr, + const image_header *const hdr) { + usb_init_all(); - uint8_t buf[USB_PACKET_SIZE]; + uint8_t buf[USB_PACKET_SIZE]; - for (;;) { - int r = usb_webusb_read_blocking(USB_IFACE_NUM, buf, USB_PACKET_SIZE, USB_TIMEOUT); - if (r != USB_PACKET_SIZE) { - continue; + for (;;) { + int r = usb_webusb_read_blocking(USB_IFACE_NUM, buf, USB_PACKET_SIZE, + USB_TIMEOUT); + if (r != USB_PACKET_SIZE) { + continue; + } + uint16_t msg_id; + uint32_t msg_size; + if (sectrue != msg_parse_header(buf, &msg_id, &msg_size)) { + // invalid header -> discard + continue; + } + switch (msg_id) { + case 0: // Initialize + process_msg_Initialize(USB_IFACE_NUM, msg_size, buf, vhdr, hdr); + break; + case 1: // Ping + process_msg_Ping(USB_IFACE_NUM, msg_size, buf); + break; + case 5: // WipeDevice + ui_fadeout(); + ui_screen_wipe_confirm(); + ui_fadein(); + int response = ui_user_input(INPUT_CONFIRM | INPUT_CANCEL); + if (INPUT_CANCEL == response) { + ui_fadeout(); + ui_screen_info(secfalse, vhdr, hdr); + ui_fadein(); + send_user_abort(USB_IFACE_NUM, "Wipe cancelled"); + break; } - uint16_t msg_id; - uint32_t msg_size; - if (sectrue != msg_parse_header(buf, &msg_id, &msg_size)) { - // invalid header -> discard - continue; + ui_fadeout(); + ui_screen_wipe(); + ui_fadein(); + r = process_msg_WipeDevice(USB_IFACE_NUM, msg_size, buf); + if (r < 0) { // error + ui_fadeout(); + ui_screen_fail(); + ui_fadein(); + usb_stop(); + usb_deinit(); + return secfalse; // shutdown + } else { // success + ui_fadeout(); + ui_screen_done(0, sectrue); + ui_fadein(); + usb_stop(); + usb_deinit(); + return secfalse; // shutdown } - switch (msg_id) { - case 0: // Initialize - process_msg_Initialize(USB_IFACE_NUM, msg_size, buf, vhdr, hdr); - break; - case 1: // Ping - process_msg_Ping(USB_IFACE_NUM, msg_size, buf); - break; - case 5: // WipeDevice - ui_fadeout(); - ui_screen_wipe_confirm(); - ui_fadein(); - int response = ui_user_input(INPUT_CONFIRM | INPUT_CANCEL); - if (INPUT_CANCEL == response) { - ui_fadeout(); - ui_screen_info(secfalse, vhdr, hdr); - ui_fadein(); - send_user_abort(USB_IFACE_NUM, "Wipe cancelled"); - break; - } - ui_fadeout(); - ui_screen_wipe(); - ui_fadein(); - r = process_msg_WipeDevice(USB_IFACE_NUM, msg_size, buf); - if (r < 0) { // error - ui_fadeout(); - ui_screen_fail(); - ui_fadein(); - usb_stop(); - usb_deinit(); - return secfalse; // shutdown - } else { // success - ui_fadeout(); - ui_screen_done(0, sectrue); - ui_fadein(); - usb_stop(); - usb_deinit(); - return secfalse; // shutdown - } - break; - case 6: // FirmwareErase - process_msg_FirmwareErase(USB_IFACE_NUM, msg_size, buf); - break; - case 7: // FirmwareUpload - r = process_msg_FirmwareUpload(USB_IFACE_NUM, msg_size, buf); - if (r < 0 && r != -4) { // error, but not user abort (-4) - ui_fadeout(); - ui_screen_fail(); - ui_fadein(); - usb_stop(); - usb_deinit(); - return secfalse; // shutdown - } else - if (r == 0) { // last chunk received - ui_screen_install_progress_upload(1000); - ui_fadeout(); - ui_screen_done(4, sectrue); - ui_fadein(); - ui_screen_done(3, secfalse); - hal_delay(1000); - ui_screen_done(2, secfalse); - hal_delay(1000); - ui_screen_done(1, secfalse); - hal_delay(1000); - usb_stop(); - usb_deinit(); - ui_fadeout(); - return sectrue; // jump to firmware - } - break; - case 55: // GetFeatures - process_msg_GetFeatures(USB_IFACE_NUM, msg_size, buf, vhdr, hdr); - break; - default: - process_msg_unknown(USB_IFACE_NUM, msg_size, buf); - break; + break; + case 6: // FirmwareErase + process_msg_FirmwareErase(USB_IFACE_NUM, msg_size, buf); + break; + case 7: // FirmwareUpload + r = process_msg_FirmwareUpload(USB_IFACE_NUM, msg_size, buf); + if (r < 0 && r != -4) { // error, but not user abort (-4) + ui_fadeout(); + ui_screen_fail(); + ui_fadein(); + usb_stop(); + usb_deinit(); + return secfalse; // shutdown + } else if (r == 0) { // last chunk received + ui_screen_install_progress_upload(1000); + ui_fadeout(); + ui_screen_done(4, sectrue); + ui_fadein(); + ui_screen_done(3, secfalse); + hal_delay(1000); + ui_screen_done(2, secfalse); + hal_delay(1000); + ui_screen_done(1, secfalse); + hal_delay(1000); + usb_stop(); + usb_deinit(); + ui_fadeout(); + return sectrue; // jump to firmware } + break; + case 55: // GetFeatures + process_msg_GetFeatures(USB_IFACE_NUM, msg_size, buf, vhdr, hdr); + break; + default: + process_msg_unknown(USB_IFACE_NUM, msg_size, buf); + break; } + } } -secbool load_vendor_header_keys(const uint8_t * const data, vendor_header * const vhdr) -{ - return load_vendor_header(data, BOOTLOADER_KEY_M, BOOTLOADER_KEY_N, BOOTLOADER_KEYS, vhdr); +secbool load_vendor_header_keys(const uint8_t *const data, + vendor_header *const vhdr) { + return load_vendor_header(data, BOOTLOADER_KEY_M, BOOTLOADER_KEY_N, + BOOTLOADER_KEYS, vhdr); } -static secbool check_vendor_keys_lock(const vendor_header * const vhdr) { - uint8_t lock[FLASH_OTP_BLOCK_SIZE]; - ensure(flash_otp_read(FLASH_OTP_BLOCK_VENDOR_KEYS_LOCK, 0, lock, FLASH_OTP_BLOCK_SIZE), NULL); - if (0 == memcmp(lock, "\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF", FLASH_OTP_BLOCK_SIZE)) { - return sectrue; - } - uint8_t hash[32]; - vendor_keys_hash(vhdr, hash); - return sectrue * (0 == memcmp(lock, hash, 32)); +static secbool check_vendor_keys_lock(const vendor_header *const vhdr) { + uint8_t lock[FLASH_OTP_BLOCK_SIZE]; + ensure(flash_otp_read(FLASH_OTP_BLOCK_VENDOR_KEYS_LOCK, 0, lock, + FLASH_OTP_BLOCK_SIZE), + NULL); + if (0 == + memcmp(lock, + "\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF" + "\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF", + FLASH_OTP_BLOCK_SIZE)) { + return sectrue; + } + uint8_t hash[32]; + vendor_keys_hash(vhdr, hash); + return sectrue * (0 == memcmp(lock, hash, 32)); } // protection against bootloader downgrade #if PRODUCTION -static void check_bootloader_version(void) -{ - uint8_t bits[FLASH_OTP_BLOCK_SIZE]; - for (int i = 0; i < FLASH_OTP_BLOCK_SIZE * 8; i++) { - if (i < VERSION_MONOTONIC) { - bits[i / 8] &= ~(1 << (7 - (i % 8))); - } else { - bits[i / 8] |= (1 << (7 - (i % 8))); - } +static void check_bootloader_version(void) { + uint8_t bits[FLASH_OTP_BLOCK_SIZE]; + for (int i = 0; i < FLASH_OTP_BLOCK_SIZE * 8; i++) { + if (i < VERSION_MONOTONIC) { + bits[i / 8] &= ~(1 << (7 - (i % 8))); + } else { + bits[i / 8] |= (1 << (7 - (i % 8))); } - ensure(flash_otp_write(FLASH_OTP_BLOCK_BOOTLOADER_VERSION, 0, bits, FLASH_OTP_BLOCK_SIZE), NULL); - - uint8_t bits2[FLASH_OTP_BLOCK_SIZE]; - ensure(flash_otp_read(FLASH_OTP_BLOCK_BOOTLOADER_VERSION, 0, bits2, FLASH_OTP_BLOCK_SIZE), NULL); - - ensure(sectrue * (0 == memcmp(bits, bits2, FLASH_OTP_BLOCK_SIZE)), "Bootloader downgraded"); + } + ensure(flash_otp_write(FLASH_OTP_BLOCK_BOOTLOADER_VERSION, 0, bits, + FLASH_OTP_BLOCK_SIZE), + NULL); + + uint8_t bits2[FLASH_OTP_BLOCK_SIZE]; + ensure(flash_otp_read(FLASH_OTP_BLOCK_BOOTLOADER_VERSION, 0, bits2, + FLASH_OTP_BLOCK_SIZE), + NULL); + + ensure(sectrue * (0 == memcmp(bits, bits2, FLASH_OTP_BLOCK_SIZE)), + "Bootloader downgraded"); } #endif -int main(void) -{ - touch_init(); - touch_power_on(); +int main(void) { + touch_init(); + touch_power_on(); - mpu_config_bootloader(); + mpu_config_bootloader(); #if PRODUCTION - check_bootloader_version(); + check_bootloader_version(); #endif main_start: - display_clear(); + display_clear(); - // delay to detect touch - uint32_t touched = 0; - for (int i = 0; i < 100; i++) { - touched = touch_is_detected() | touch_read(); - if (touched) { - break; - } - hal_delay(1); - } - - vendor_header vhdr; - image_header hdr; - secbool firmware_present; - - // detect whether the devices contains a valid firmware - - firmware_present = load_vendor_header_keys((const uint8_t *)FIRMWARE_START, &vhdr); - if (sectrue == firmware_present) { - firmware_present = check_vendor_keys_lock(&vhdr); - } - if (sectrue == firmware_present) { - firmware_present = load_image_header((const uint8_t *)(FIRMWARE_START + vhdr.hdrlen), FIRMWARE_IMAGE_MAGIC, FIRMWARE_IMAGE_MAXSIZE, vhdr.vsig_m, vhdr.vsig_n, vhdr.vpub, &hdr); + // delay to detect touch + uint32_t touched = 0; + for (int i = 0; i < 100; i++) { + touched = touch_is_detected() | touch_read(); + if (touched) { + break; } - if (sectrue == firmware_present) { - firmware_present = check_image_contents(&hdr, IMAGE_HEADER_SIZE + vhdr.hdrlen, FIRMWARE_SECTORS, FIRMWARE_SECTORS_COUNT); + hal_delay(1); + } + + vendor_header vhdr; + image_header hdr; + secbool firmware_present; + + // detect whether the devices contains a valid firmware + + firmware_present = + load_vendor_header_keys((const uint8_t *)FIRMWARE_START, &vhdr); + if (sectrue == firmware_present) { + firmware_present = check_vendor_keys_lock(&vhdr); + } + if (sectrue == firmware_present) { + firmware_present = load_image_header( + (const uint8_t *)(FIRMWARE_START + vhdr.hdrlen), FIRMWARE_IMAGE_MAGIC, + FIRMWARE_IMAGE_MAXSIZE, vhdr.vsig_m, vhdr.vsig_n, vhdr.vpub, &hdr); + } + if (sectrue == firmware_present) { + firmware_present = + check_image_contents(&hdr, IMAGE_HEADER_SIZE + vhdr.hdrlen, + FIRMWARE_SECTORS, FIRMWARE_SECTORS_COUNT); + } + + // start the bootloader if no or broken firmware found ... + if (firmware_present != sectrue) { + // show intro animation + + // no ui_fadeout(); - we already start from black screen + ui_screen_first(); + ui_fadein(); + + hal_delay(1000); + + ui_fadeout(); + ui_screen_second(); + ui_fadein(); + + hal_delay(1000); + + ui_fadeout(); + ui_screen_third(); + ui_fadein(); + + // erase storage + ensure(flash_erase_sectors(STORAGE_SECTORS, STORAGE_SECTORS_COUNT, NULL), + NULL); + + // and start the usb loop + if (bootloader_usb_loop(NULL, NULL) != sectrue) { + return 1; } + } else + // ... or if user touched the screen on start + if (touched) { + // show firmware info with connect buttons - // start the bootloader if no or broken firmware found ... - if (firmware_present != sectrue) { - // show intro animation - - // no ui_fadeout(); - we already start from black screen - ui_screen_first(); - ui_fadein(); - - hal_delay(1000); + // no ui_fadeout(); - we already start from black screen + ui_screen_info(sectrue, &vhdr, &hdr); + ui_fadein(); - ui_fadeout(); - ui_screen_second(); + for (;;) { + int response = ui_user_input(INPUT_CONFIRM | INPUT_CANCEL | INPUT_INFO); + ui_fadeout(); + + // if cancel was pressed -> restart + if (INPUT_CANCEL == response) { + goto main_start; + } + + // if confirm was pressed -> jump out + if (INPUT_CONFIRM == response) { + // show firmware info without connect buttons + ui_screen_info(secfalse, &vhdr, &hdr); ui_fadein(); + break; + } - hal_delay(1000); - - ui_fadeout(); - ui_screen_third(); + // if info icon was pressed -> show fingerprint + if (INPUT_INFO == response) { + // show fingerprint + ui_screen_info_fingerprint(&hdr); ui_fadein(); - - // erase storage - ensure(flash_erase_sectors(STORAGE_SECTORS, STORAGE_SECTORS_COUNT, NULL), NULL); - - // and start the usb loop - if (bootloader_usb_loop(NULL, NULL) != sectrue) { - return 1; + while (INPUT_LONG_CONFIRM != ui_user_input(INPUT_LONG_CONFIRM)) { } - } else - // ... or if user touched the screen on start - if (touched) { - // show firmware info with connect buttons - - // no ui_fadeout(); - we already start from black screen + ui_fadeout(); ui_screen_info(sectrue, &vhdr, &hdr); ui_fadein(); - - for (;;) { - int response = ui_user_input(INPUT_CONFIRM | INPUT_CANCEL | INPUT_INFO); - ui_fadeout(); - - // if cancel was pressed -> restart - if (INPUT_CANCEL == response) { - goto main_start; - } - - // if confirm was pressed -> jump out - if (INPUT_CONFIRM == response) { - // show firmware info without connect buttons - ui_screen_info(secfalse, &vhdr, &hdr); - ui_fadein(); - break; - } - - // if info icon was pressed -> show fingerprint - if (INPUT_INFO == response) { - // show fingerprint - ui_screen_info_fingerprint(&hdr); - ui_fadein(); - while (INPUT_LONG_CONFIRM != ui_user_input(INPUT_LONG_CONFIRM)) { } - ui_fadeout(); - ui_screen_info(sectrue, &vhdr, &hdr); - ui_fadein(); - } - } - - // and start the usb loop - if (bootloader_usb_loop(&vhdr, &hdr) != sectrue) { - return 1; - } + } } - ensure( - load_vendor_header_keys((const uint8_t *)FIRMWARE_START, &vhdr), - "invalid vendor header"); + // and start the usb loop + if (bootloader_usb_loop(&vhdr, &hdr) != sectrue) { + return 1; + } + } - ensure( - check_vendor_keys_lock(&vhdr), - "unauthorized vendor keys"); + ensure(load_vendor_header_keys((const uint8_t *)FIRMWARE_START, &vhdr), + "invalid vendor header"); - ensure( - load_image_header((const uint8_t *)(FIRMWARE_START + vhdr.hdrlen), FIRMWARE_IMAGE_MAGIC, FIRMWARE_IMAGE_MAXSIZE, vhdr.vsig_m, vhdr.vsig_n, vhdr.vpub, &hdr), - "invalid firmware header"); + ensure(check_vendor_keys_lock(&vhdr), "unauthorized vendor keys"); - ensure( - check_image_contents(&hdr, IMAGE_HEADER_SIZE + vhdr.hdrlen, FIRMWARE_SECTORS, FIRMWARE_SECTORS_COUNT), - "invalid firmware hash"); + ensure(load_image_header((const uint8_t *)(FIRMWARE_START + vhdr.hdrlen), + FIRMWARE_IMAGE_MAGIC, FIRMWARE_IMAGE_MAXSIZE, + vhdr.vsig_m, vhdr.vsig_n, vhdr.vpub, &hdr), + "invalid firmware header"); - // if all VTRUST flags are unset = ultimate trust => skip the procedure + ensure(check_image_contents(&hdr, IMAGE_HEADER_SIZE + vhdr.hdrlen, + FIRMWARE_SECTORS, FIRMWARE_SECTORS_COUNT), + "invalid firmware hash"); - if ((vhdr.vtrust & VTRUST_ALL) != VTRUST_ALL) { + // if all VTRUST flags are unset = ultimate trust => skip the procedure - // ui_fadeout(); // no fadeout - we start from black screen - ui_screen_boot(&vhdr, &hdr); - ui_fadein(); + if ((vhdr.vtrust & VTRUST_ALL) != VTRUST_ALL) { + // ui_fadeout(); // no fadeout - we start from black screen + ui_screen_boot(&vhdr, &hdr); + ui_fadein(); - int delay = (vhdr.vtrust & VTRUST_WAIT) ^ VTRUST_WAIT; - if (delay > 1) { - while (delay > 0) { - ui_screen_boot_wait(delay); - hal_delay(1000); - delay--; - } - } else if (delay == 1) { - hal_delay(1000); - } - - if ((vhdr.vtrust & VTRUST_CLICK) == 0) { - ui_screen_boot_click(); - touch_click(); - } + int delay = (vhdr.vtrust & VTRUST_WAIT) ^ VTRUST_WAIT; + if (delay > 1) { + while (delay > 0) { + ui_screen_boot_wait(delay); + hal_delay(1000); + delay--; + } + } else if (delay == 1) { + hal_delay(1000); + } - ui_fadeout(); + if ((vhdr.vtrust & VTRUST_CLICK) == 0) { + ui_screen_boot_click(); + touch_click(); } - // mpu_config_firmware(); - // jump_to_unprivileged(FIRMWARE_START + vhdr.hdrlen + IMAGE_HEADER_SIZE); + ui_fadeout(); + } + + // mpu_config_firmware(); + // jump_to_unprivileged(FIRMWARE_START + vhdr.hdrlen + IMAGE_HEADER_SIZE); - mpu_config_off(); - jump_to(FIRMWARE_START + vhdr.hdrlen + IMAGE_HEADER_SIZE); + mpu_config_off(); + jump_to(FIRMWARE_START + vhdr.hdrlen + IMAGE_HEADER_SIZE); - return 0; + return 0; } diff --git a/embed/bootloader/messages.c b/embed/bootloader/messages.c index faa090281..39b3db401 100644 --- a/embed/bootloader/messages.c +++ b/embed/bootloader/messages.c @@ -39,544 +39,600 @@ #define MSG_HEADER1_LEN 9 #define MSG_HEADER2_LEN 1 -secbool msg_parse_header(const uint8_t *buf, uint16_t *msg_id, uint32_t *msg_size) -{ - if (buf[0] != '?' || buf[1] != '#' || buf[2] != '#') { - return secfalse; - } - *msg_id = (buf[3] << 8) + buf[4]; - *msg_size = (buf[5] << 24) + (buf[6] << 16) + (buf[7] << 8) + buf[8]; - return sectrue; +secbool msg_parse_header(const uint8_t *buf, uint16_t *msg_id, + uint32_t *msg_size) { + if (buf[0] != '?' || buf[1] != '#' || buf[2] != '#') { + return secfalse; + } + *msg_id = (buf[3] << 8) + buf[4]; + *msg_size = (buf[5] << 24) + (buf[6] << 16) + (buf[7] << 8) + buf[8]; + return sectrue; } typedef struct { - uint8_t iface_num; - uint8_t packet_index; - uint8_t packet_pos; - uint8_t buf[USB_PACKET_SIZE]; + uint8_t iface_num; + uint8_t packet_index; + uint8_t packet_pos; + uint8_t buf[USB_PACKET_SIZE]; } usb_write_state; /* we don't use secbool/sectrue/secfalse here as it is a nanopb api */ -static bool _usb_write(pb_ostream_t *stream, const pb_byte_t *buf, size_t count) -{ - usb_write_state *state = (usb_write_state *)(stream->state); - - size_t written = 0; - // while we have data left - while (written < count) { - size_t remaining = count - written; - // if all remaining data fit into our packet - if (state->packet_pos + remaining <= USB_PACKET_SIZE) { - // append data from buf to state->buf - memcpy(state->buf + state->packet_pos, buf + written, remaining); - // advance position - state->packet_pos += remaining; - // and return - return true; - } else { - // append data that fits - memcpy(state->buf + state->packet_pos, buf + written, USB_PACKET_SIZE - state->packet_pos); - written += USB_PACKET_SIZE - state->packet_pos; - // send packet - int r = usb_webusb_write_blocking(state->iface_num, state->buf, USB_PACKET_SIZE, USB_TIMEOUT); - ensure(sectrue * (r == USB_PACKET_SIZE), NULL); - // prepare new packet - state->packet_index++; - memzero(state->buf, USB_PACKET_SIZE); - state->buf[0] = '?'; - state->packet_pos = MSG_HEADER2_LEN; - } +static bool _usb_write(pb_ostream_t *stream, const pb_byte_t *buf, + size_t count) { + usb_write_state *state = (usb_write_state *)(stream->state); + + size_t written = 0; + // while we have data left + while (written < count) { + size_t remaining = count - written; + // if all remaining data fit into our packet + if (state->packet_pos + remaining <= USB_PACKET_SIZE) { + // append data from buf to state->buf + memcpy(state->buf + state->packet_pos, buf + written, remaining); + // advance position + state->packet_pos += remaining; + // and return + return true; + } else { + // append data that fits + memcpy(state->buf + state->packet_pos, buf + written, + USB_PACKET_SIZE - state->packet_pos); + written += USB_PACKET_SIZE - state->packet_pos; + // send packet + int r = usb_webusb_write_blocking(state->iface_num, state->buf, + USB_PACKET_SIZE, USB_TIMEOUT); + ensure(sectrue * (r == USB_PACKET_SIZE), NULL); + // prepare new packet + state->packet_index++; + memzero(state->buf, USB_PACKET_SIZE); + state->buf[0] = '?'; + state->packet_pos = MSG_HEADER2_LEN; } + } - return true; + return true; } -static void _usb_write_flush(usb_write_state *state) -{ - // if packet is not filled up completely - if (state->packet_pos < USB_PACKET_SIZE) { - // pad it with zeroes - memzero(state->buf + state->packet_pos, USB_PACKET_SIZE - state->packet_pos); - } - // send packet - int r = usb_webusb_write_blocking(state->iface_num, state->buf, USB_PACKET_SIZE, USB_TIMEOUT); - ensure(sectrue * (r == USB_PACKET_SIZE), NULL); +static void _usb_write_flush(usb_write_state *state) { + // if packet is not filled up completely + if (state->packet_pos < USB_PACKET_SIZE) { + // pad it with zeroes + memzero(state->buf + state->packet_pos, + USB_PACKET_SIZE - state->packet_pos); + } + // send packet + int r = usb_webusb_write_blocking(state->iface_num, state->buf, + USB_PACKET_SIZE, USB_TIMEOUT); + ensure(sectrue * (r == USB_PACKET_SIZE), NULL); } -static secbool _send_msg(uint8_t iface_num, uint16_t msg_id, const pb_field_t fields[], const void *msg) -{ - // determine message size by serializing it into a dummy stream - pb_ostream_t sizestream = { - .callback = NULL, - .state = NULL, - .max_size = SIZE_MAX, - .bytes_written = 0, - .errmsg = NULL}; - if (false == pb_encode(&sizestream, fields, msg)) { - return secfalse; - } - const uint32_t msg_size = sizestream.bytes_written; - - usb_write_state state = { - .iface_num = iface_num, - .packet_index = 0, - .packet_pos = MSG_HEADER1_LEN, - .buf = { - '?', '#', '#', - (msg_id >> 8) & 0xFF, msg_id & 0xFF, - (msg_size >> 24) & 0xFF, (msg_size >> 16) & 0xFF, (msg_size >> 8) & 0xFF, msg_size & 0xFF, - }, - }; - - pb_ostream_t stream = { - .callback = &_usb_write, - .state = &state, - .max_size = SIZE_MAX, - .bytes_written = 0, - .errmsg = NULL - }; - - if (false == pb_encode(&stream, fields, msg)) { - return secfalse; - } - - _usb_write_flush(&state); - - return sectrue; +static secbool _send_msg(uint8_t iface_num, uint16_t msg_id, + const pb_field_t fields[], const void *msg) { + // determine message size by serializing it into a dummy stream + pb_ostream_t sizestream = {.callback = NULL, + .state = NULL, + .max_size = SIZE_MAX, + .bytes_written = 0, + .errmsg = NULL}; + if (false == pb_encode(&sizestream, fields, msg)) { + return secfalse; + } + const uint32_t msg_size = sizestream.bytes_written; + + usb_write_state state = { + .iface_num = iface_num, + .packet_index = 0, + .packet_pos = MSG_HEADER1_LEN, + .buf = + { + '?', + '#', + '#', + (msg_id >> 8) & 0xFF, + msg_id & 0xFF, + (msg_size >> 24) & 0xFF, + (msg_size >> 16) & 0xFF, + (msg_size >> 8) & 0xFF, + msg_size & 0xFF, + }, + }; + + pb_ostream_t stream = {.callback = &_usb_write, + .state = &state, + .max_size = SIZE_MAX, + .bytes_written = 0, + .errmsg = NULL}; + + if (false == pb_encode(&stream, fields, msg)) { + return secfalse; + } + + _usb_write_flush(&state); + + return sectrue; } #define MSG_SEND_INIT(TYPE) TYPE msg_send = TYPE##_init_default -#define MSG_SEND_ASSIGN_VALUE(FIELD, VALUE) { msg_send.has_##FIELD = true; msg_send.FIELD = VALUE; } -#define MSG_SEND_ASSIGN_STRING(FIELD, VALUE) { msg_send.has_##FIELD = true; memzero(msg_send.FIELD, sizeof(msg_send.FIELD)); strncpy(msg_send.FIELD, VALUE, sizeof(msg_send.FIELD) - 1); } -#define MSG_SEND_ASSIGN_STRING_LEN(FIELD, VALUE, LEN) { msg_send.has_##FIELD = true; memzero(msg_send.FIELD, sizeof(msg_send.FIELD)); strncpy(msg_send.FIELD, VALUE, MIN(LEN, sizeof(msg_send.FIELD) - 1)); } -#define MSG_SEND_ASSIGN_BYTES(FIELD, VALUE, LEN) { msg_send.has_##FIELD = true; memzero(msg_send.FIELD.bytes, sizeof(msg_send.FIELD.bytes)); memcpy(msg_send.FIELD.bytes, VALUE, MIN(LEN, sizeof(msg_send.FIELD.bytes))); msg_send.FIELD.size = MIN(LEN, sizeof(msg_send.FIELD.bytes)); } -#define MSG_SEND(TYPE) _send_msg(iface_num, MessageType_MessageType_##TYPE, TYPE##_fields, &msg_send) +#define MSG_SEND_ASSIGN_VALUE(FIELD, VALUE) \ + { \ + msg_send.has_##FIELD = true; \ + msg_send.FIELD = VALUE; \ + } +#define MSG_SEND_ASSIGN_STRING(FIELD, VALUE) \ + { \ + msg_send.has_##FIELD = true; \ + memzero(msg_send.FIELD, sizeof(msg_send.FIELD)); \ + strncpy(msg_send.FIELD, VALUE, sizeof(msg_send.FIELD) - 1); \ + } +#define MSG_SEND_ASSIGN_STRING_LEN(FIELD, VALUE, LEN) \ + { \ + msg_send.has_##FIELD = true; \ + memzero(msg_send.FIELD, sizeof(msg_send.FIELD)); \ + strncpy(msg_send.FIELD, VALUE, MIN(LEN, sizeof(msg_send.FIELD) - 1)); \ + } +#define MSG_SEND_ASSIGN_BYTES(FIELD, VALUE, LEN) \ + { \ + msg_send.has_##FIELD = true; \ + memzero(msg_send.FIELD.bytes, sizeof(msg_send.FIELD.bytes)); \ + memcpy(msg_send.FIELD.bytes, VALUE, \ + MIN(LEN, sizeof(msg_send.FIELD.bytes))); \ + msg_send.FIELD.size = MIN(LEN, sizeof(msg_send.FIELD.bytes)); \ + } +#define MSG_SEND(TYPE) \ + _send_msg(iface_num, MessageType_MessageType_##TYPE, TYPE##_fields, &msg_send) typedef struct { - uint8_t iface_num; - uint8_t packet_index; - uint8_t packet_pos; - uint8_t *buf; + uint8_t iface_num; + uint8_t packet_index; + uint8_t packet_pos; + uint8_t *buf; } usb_read_state; /* we don't use secbool/sectrue/secfalse here as it is a nanopb api */ -static bool _usb_read(pb_istream_t *stream, uint8_t *buf, size_t count) -{ - usb_read_state *state = (usb_read_state *)(stream->state); - - size_t read = 0; - // while we have data left - while (read < count) { - size_t remaining = count - read; - // if all remaining data fit into our packet - if (state->packet_pos + remaining <= USB_PACKET_SIZE) { - // append data from buf to state->buf - memcpy(buf + read, state->buf + state->packet_pos, remaining); - // advance position - state->packet_pos += remaining; - // and return - return true; - } else { - // append data that fits - memcpy(buf + read, state->buf + state->packet_pos, USB_PACKET_SIZE - state->packet_pos); - read += USB_PACKET_SIZE - state->packet_pos; - // read next packet - int r = usb_webusb_read_blocking(state->iface_num, state->buf, USB_PACKET_SIZE, USB_TIMEOUT); - ensure(sectrue * (r == USB_PACKET_SIZE), NULL); - // prepare next packet - state->packet_index++; - state->packet_pos = MSG_HEADER2_LEN; - } +static bool _usb_read(pb_istream_t *stream, uint8_t *buf, size_t count) { + usb_read_state *state = (usb_read_state *)(stream->state); + + size_t read = 0; + // while we have data left + while (read < count) { + size_t remaining = count - read; + // if all remaining data fit into our packet + if (state->packet_pos + remaining <= USB_PACKET_SIZE) { + // append data from buf to state->buf + memcpy(buf + read, state->buf + state->packet_pos, remaining); + // advance position + state->packet_pos += remaining; + // and return + return true; + } else { + // append data that fits + memcpy(buf + read, state->buf + state->packet_pos, + USB_PACKET_SIZE - state->packet_pos); + read += USB_PACKET_SIZE - state->packet_pos; + // read next packet + int r = usb_webusb_read_blocking(state->iface_num, state->buf, + USB_PACKET_SIZE, USB_TIMEOUT); + ensure(sectrue * (r == USB_PACKET_SIZE), NULL); + // prepare next packet + state->packet_index++; + state->packet_pos = MSG_HEADER2_LEN; } + } - return true; + return true; } -static void _usb_read_flush(usb_read_state *state) -{ - (void)state; -} +static void _usb_read_flush(usb_read_state *state) { (void)state; } -static secbool _recv_msg(uint8_t iface_num, uint32_t msg_size, uint8_t *buf, const pb_field_t fields[], void *msg) -{ - usb_read_state state = { - .iface_num = iface_num, - .packet_index = 0, - .packet_pos = MSG_HEADER1_LEN, - .buf = buf - }; - - pb_istream_t stream = { - .callback = &_usb_read, - .state = &state, - .bytes_left = msg_size, - .errmsg = NULL - }; - - if (false == pb_decode_noinit(&stream, fields, msg)) { - return secfalse; - } +static secbool _recv_msg(uint8_t iface_num, uint32_t msg_size, uint8_t *buf, + const pb_field_t fields[], void *msg) { + usb_read_state state = {.iface_num = iface_num, + .packet_index = 0, + .packet_pos = MSG_HEADER1_LEN, + .buf = buf}; + + pb_istream_t stream = {.callback = &_usb_read, + .state = &state, + .bytes_left = msg_size, + .errmsg = NULL}; - _usb_read_flush(&state); + if (false == pb_decode_noinit(&stream, fields, msg)) { + return secfalse; + } - return sectrue; + _usb_read_flush(&state); + + return sectrue; } #define MSG_RECV_INIT(TYPE) TYPE msg_recv = TYPE##_init_default -#define MSG_RECV_CALLBACK(FIELD, CALLBACK) { msg_recv.FIELD.funcs.decode = &CALLBACK; } -#define MSG_RECV(TYPE) _recv_msg(iface_num, msg_size, buf, TYPE##_fields, &msg_recv) - -void send_user_abort(uint8_t iface_num, const char *msg) -{ - MSG_SEND_INIT(Failure); - MSG_SEND_ASSIGN_VALUE(code, FailureType_Failure_ActionCancelled); - MSG_SEND_ASSIGN_STRING(message, msg); - MSG_SEND(Failure); +#define MSG_RECV_CALLBACK(FIELD, CALLBACK) \ + { msg_recv.FIELD.funcs.decode = &CALLBACK; } +#define MSG_RECV(TYPE) \ + _recv_msg(iface_num, msg_size, buf, TYPE##_fields, &msg_recv) + +void send_user_abort(uint8_t iface_num, const char *msg) { + MSG_SEND_INIT(Failure); + MSG_SEND_ASSIGN_VALUE(code, FailureType_Failure_ActionCancelled); + MSG_SEND_ASSIGN_STRING(message, msg); + MSG_SEND(Failure); } -static void send_msg_features(uint8_t iface_num, const vendor_header * const vhdr, const image_header * const hdr) -{ - MSG_SEND_INIT(Features); - MSG_SEND_ASSIGN_STRING(vendor, "trezor.io"); - MSG_SEND_ASSIGN_VALUE(major_version, VERSION_MAJOR); - MSG_SEND_ASSIGN_VALUE(minor_version, VERSION_MINOR); - MSG_SEND_ASSIGN_VALUE(patch_version, VERSION_PATCH); - MSG_SEND_ASSIGN_VALUE(bootloader_mode, true); - MSG_SEND_ASSIGN_STRING(model, "T"); - if (vhdr && hdr) { - MSG_SEND_ASSIGN_VALUE(firmware_present, true); - MSG_SEND_ASSIGN_VALUE(fw_major, (hdr->version & 0xFF)); - MSG_SEND_ASSIGN_VALUE(fw_minor, ((hdr->version >> 8) & 0xFF)); - MSG_SEND_ASSIGN_VALUE(fw_patch, ((hdr->version >> 16) & 0xFF)); - MSG_SEND_ASSIGN_STRING_LEN(fw_vendor, vhdr->vstr, vhdr->vstr_len); - uint8_t hash[32]; - vendor_keys_hash(vhdr, hash); - MSG_SEND_ASSIGN_BYTES(fw_vendor_keys, hash, 32); - } else { - MSG_SEND_ASSIGN_VALUE(firmware_present, false); - } - MSG_SEND(Features); +static void send_msg_features(uint8_t iface_num, + const vendor_header *const vhdr, + const image_header *const hdr) { + MSG_SEND_INIT(Features); + MSG_SEND_ASSIGN_STRING(vendor, "trezor.io"); + MSG_SEND_ASSIGN_VALUE(major_version, VERSION_MAJOR); + MSG_SEND_ASSIGN_VALUE(minor_version, VERSION_MINOR); + MSG_SEND_ASSIGN_VALUE(patch_version, VERSION_PATCH); + MSG_SEND_ASSIGN_VALUE(bootloader_mode, true); + MSG_SEND_ASSIGN_STRING(model, "T"); + if (vhdr && hdr) { + MSG_SEND_ASSIGN_VALUE(firmware_present, true); + MSG_SEND_ASSIGN_VALUE(fw_major, (hdr->version & 0xFF)); + MSG_SEND_ASSIGN_VALUE(fw_minor, ((hdr->version >> 8) & 0xFF)); + MSG_SEND_ASSIGN_VALUE(fw_patch, ((hdr->version >> 16) & 0xFF)); + MSG_SEND_ASSIGN_STRING_LEN(fw_vendor, vhdr->vstr, vhdr->vstr_len); + uint8_t hash[32]; + vendor_keys_hash(vhdr, hash); + MSG_SEND_ASSIGN_BYTES(fw_vendor_keys, hash, 32); + } else { + MSG_SEND_ASSIGN_VALUE(firmware_present, false); + } + MSG_SEND(Features); } -void process_msg_Initialize(uint8_t iface_num, uint32_t msg_size, uint8_t *buf, const vendor_header * const vhdr, const image_header * const hdr) -{ - MSG_RECV_INIT(Initialize); - MSG_RECV(Initialize); - send_msg_features(iface_num, vhdr, hdr); +void process_msg_Initialize(uint8_t iface_num, uint32_t msg_size, uint8_t *buf, + const vendor_header *const vhdr, + const image_header *const hdr) { + MSG_RECV_INIT(Initialize); + MSG_RECV(Initialize); + send_msg_features(iface_num, vhdr, hdr); } -void process_msg_GetFeatures(uint8_t iface_num, uint32_t msg_size, uint8_t *buf, const vendor_header * const vhdr, const image_header * const hdr) -{ - MSG_RECV_INIT(GetFeatures); - MSG_RECV(GetFeatures); - send_msg_features(iface_num, vhdr, hdr); +void process_msg_GetFeatures(uint8_t iface_num, uint32_t msg_size, uint8_t *buf, + const vendor_header *const vhdr, + const image_header *const hdr) { + MSG_RECV_INIT(GetFeatures); + MSG_RECV(GetFeatures); + send_msg_features(iface_num, vhdr, hdr); } -void process_msg_Ping(uint8_t iface_num, uint32_t msg_size, uint8_t *buf) -{ - MSG_RECV_INIT(Ping); - MSG_RECV(Ping); +void process_msg_Ping(uint8_t iface_num, uint32_t msg_size, uint8_t *buf) { + MSG_RECV_INIT(Ping); + MSG_RECV(Ping); - MSG_SEND_INIT(Success); - MSG_SEND_ASSIGN_STRING(message, msg_recv.message); - MSG_SEND(Success); + MSG_SEND_INIT(Success); + MSG_SEND_ASSIGN_STRING(message, msg_recv.message); + MSG_SEND(Success); } static uint32_t firmware_remaining, firmware_block, chunk_requested; -void process_msg_FirmwareErase(uint8_t iface_num, uint32_t msg_size, uint8_t *buf) -{ - firmware_remaining = 0; - firmware_block = 0; - chunk_requested = 0; - - MSG_RECV_INIT(FirmwareErase); - MSG_RECV(FirmwareErase); - - firmware_remaining = msg_recv.has_length ? msg_recv.length : 0; - if ((firmware_remaining > 0) && ((firmware_remaining % sizeof(uint32_t)) == 0) && (firmware_remaining <= (FIRMWARE_SECTORS_COUNT * IMAGE_CHUNK_SIZE))) { - // request new firmware - chunk_requested = (firmware_remaining > IMAGE_CHUNK_SIZE) ? IMAGE_CHUNK_SIZE : firmware_remaining; - MSG_SEND_INIT(FirmwareRequest); - MSG_SEND_ASSIGN_VALUE(offset, 0); - MSG_SEND_ASSIGN_VALUE(length, chunk_requested); - MSG_SEND(FirmwareRequest); - } else { - // invalid firmware size - MSG_SEND_INIT(Failure); - MSG_SEND_ASSIGN_VALUE(code, FailureType_Failure_DataError); - MSG_SEND_ASSIGN_STRING(message, "Wrong firmware size"); - MSG_SEND(Failure); - } +void process_msg_FirmwareErase(uint8_t iface_num, uint32_t msg_size, + uint8_t *buf) { + firmware_remaining = 0; + firmware_block = 0; + chunk_requested = 0; + + MSG_RECV_INIT(FirmwareErase); + MSG_RECV(FirmwareErase); + + firmware_remaining = msg_recv.has_length ? msg_recv.length : 0; + if ((firmware_remaining > 0) && + ((firmware_remaining % sizeof(uint32_t)) == 0) && + (firmware_remaining <= (FIRMWARE_SECTORS_COUNT * IMAGE_CHUNK_SIZE))) { + // request new firmware + chunk_requested = (firmware_remaining > IMAGE_CHUNK_SIZE) + ? IMAGE_CHUNK_SIZE + : firmware_remaining; + MSG_SEND_INIT(FirmwareRequest); + MSG_SEND_ASSIGN_VALUE(offset, 0); + MSG_SEND_ASSIGN_VALUE(length, chunk_requested); + MSG_SEND(FirmwareRequest); + } else { + // invalid firmware size + MSG_SEND_INIT(Failure); + MSG_SEND_ASSIGN_VALUE(code, FailureType_Failure_DataError); + MSG_SEND_ASSIGN_STRING(message, "Wrong firmware size"); + MSG_SEND(Failure); + } } static uint32_t chunk_size = 0; // SRAM is unused, so we can use it for chunk buffer -uint8_t * const chunk_buffer = (uint8_t * const)0x20000000; +uint8_t *const chunk_buffer = (uint8_t *const)0x20000000; /* we don't use secbool/sectrue/secfalse here as it is a nanopb api */ -static bool _read_payload(pb_istream_t *stream, const pb_field_t *field, void **arg) -{ +static bool _read_payload(pb_istream_t *stream, const pb_field_t *field, + void **arg) { #define BUFSIZE 32768 - if (stream->bytes_left > IMAGE_CHUNK_SIZE) { - chunk_size = 0; - return false; - } + if (stream->bytes_left > IMAGE_CHUNK_SIZE) { + chunk_size = 0; + return false; + } + + // clear chunk buffer + memset(chunk_buffer, 0xFF, IMAGE_CHUNK_SIZE); + + uint32_t chunk_written = 0; + chunk_size = stream->bytes_left; - // clear chunk buffer - memset(chunk_buffer, 0xFF, IMAGE_CHUNK_SIZE); - - uint32_t chunk_written = 0; - chunk_size = stream->bytes_left; - - while (stream->bytes_left) { - // update loader but skip first block - if (firmware_block > 0) { - ui_screen_install_progress_upload(250 + 750 * (firmware_block * IMAGE_CHUNK_SIZE + chunk_written) / (firmware_block * IMAGE_CHUNK_SIZE + firmware_remaining)); - } - // read data - if (!pb_read(stream, (pb_byte_t *)(chunk_buffer + chunk_written), (stream->bytes_left > BUFSIZE) ? BUFSIZE : stream->bytes_left)) { - chunk_size = 0; - return false; - } - chunk_written += BUFSIZE; + while (stream->bytes_left) { + // update loader but skip first block + if (firmware_block > 0) { + ui_screen_install_progress_upload( + 250 + 750 * (firmware_block * IMAGE_CHUNK_SIZE + chunk_written) / + (firmware_block * IMAGE_CHUNK_SIZE + firmware_remaining)); } + // read data + if (!pb_read( + stream, (pb_byte_t *)(chunk_buffer + chunk_written), + (stream->bytes_left > BUFSIZE) ? BUFSIZE : stream->bytes_left)) { + chunk_size = 0; + return false; + } + chunk_written += BUFSIZE; + } - return true; + return true; } -secbool load_vendor_header_keys(const uint8_t * const data, vendor_header * const vhdr); - -static int version_compare(uint32_t vera, uint32_t verb) -{ - int a, b; - a = vera & 0xFF; - b = verb & 0xFF; - if (a != b) return a - b; - a = (vera >> 8) & 0xFF; - b = (verb >> 8) & 0xFF; - if (a != b) return a - b; - a = (vera >> 16) & 0xFF; - b = (verb >> 16) & 0xFF; - if (a != b) return a - b; - a = (vera >> 24) & 0xFF; - b = (verb >> 24) & 0xFF; - return a - b; +secbool load_vendor_header_keys(const uint8_t *const data, + vendor_header *const vhdr); + +static int version_compare(uint32_t vera, uint32_t verb) { + int a, b; + a = vera & 0xFF; + b = verb & 0xFF; + if (a != b) return a - b; + a = (vera >> 8) & 0xFF; + b = (verb >> 8) & 0xFF; + if (a != b) return a - b; + a = (vera >> 16) & 0xFF; + b = (verb >> 16) & 0xFF; + if (a != b) return a - b; + a = (vera >> 24) & 0xFF; + b = (verb >> 24) & 0xFF; + return a - b; } -static void detect_installation(vendor_header *current_vhdr, image_header *current_hdr, const vendor_header * const new_vhdr, const image_header * const new_hdr, secbool *is_new, secbool *is_upgrade) -{ - *is_new = secfalse; - *is_upgrade = secfalse; - if (sectrue != load_vendor_header_keys((const uint8_t *)FIRMWARE_START, current_vhdr)) { - *is_new = sectrue; - return; - } - if (sectrue != load_image_header((const uint8_t *)FIRMWARE_START + current_vhdr->hdrlen, FIRMWARE_IMAGE_MAGIC, FIRMWARE_IMAGE_MAXSIZE, current_vhdr->vsig_m, current_vhdr->vsig_n, current_vhdr->vpub, current_hdr)) { - *is_new = sectrue; - return; - } - uint8_t hash1[32], hash2[32]; - vendor_keys_hash(new_vhdr, hash1); - vendor_keys_hash(current_vhdr, hash2); - if (0 != memcmp(hash1, hash2, 32)) { - return; - } - if (version_compare(new_hdr->version, current_hdr->fix_version) < 0) { - return; - } - *is_upgrade = sectrue; +static void detect_installation(vendor_header *current_vhdr, + image_header *current_hdr, + const vendor_header *const new_vhdr, + const image_header *const new_hdr, + secbool *is_new, secbool *is_upgrade) { + *is_new = secfalse; + *is_upgrade = secfalse; + if (sectrue != + load_vendor_header_keys((const uint8_t *)FIRMWARE_START, current_vhdr)) { + *is_new = sectrue; + return; + } + if (sectrue != + load_image_header((const uint8_t *)FIRMWARE_START + current_vhdr->hdrlen, + FIRMWARE_IMAGE_MAGIC, FIRMWARE_IMAGE_MAXSIZE, + current_vhdr->vsig_m, current_vhdr->vsig_n, + current_vhdr->vpub, current_hdr)) { + *is_new = sectrue; + return; + } + uint8_t hash1[32], hash2[32]; + vendor_keys_hash(new_vhdr, hash1); + vendor_keys_hash(current_vhdr, hash2); + if (0 != memcmp(hash1, hash2, 32)) { + return; + } + if (version_compare(new_hdr->version, current_hdr->fix_version) < 0) { + return; + } + *is_upgrade = sectrue; } static int firmware_upload_chunk_retry = FIRMWARE_UPLOAD_CHUNK_RETRY_COUNT; -int process_msg_FirmwareUpload(uint8_t iface_num, uint32_t msg_size, uint8_t *buf) -{ - MSG_RECV_INIT(FirmwareUpload); - MSG_RECV_CALLBACK(payload, _read_payload); - secbool r = MSG_RECV(FirmwareUpload); - - if (sectrue != r || chunk_size != chunk_requested) { - MSG_SEND_INIT(Failure); - MSG_SEND_ASSIGN_VALUE(code, FailureType_Failure_DataError); - MSG_SEND_ASSIGN_STRING(message, "Invalid chunk size"); - MSG_SEND(Failure); - return -1; - } +int process_msg_FirmwareUpload(uint8_t iface_num, uint32_t msg_size, + uint8_t *buf) { + MSG_RECV_INIT(FirmwareUpload); + MSG_RECV_CALLBACK(payload, _read_payload); + secbool r = MSG_RECV(FirmwareUpload); - static image_header hdr; - - uint32_t firstskip = 0; - if (firmware_block == 0) { - vendor_header vhdr; - if (sectrue != load_vendor_header_keys(chunk_buffer, &vhdr)) { - MSG_SEND_INIT(Failure); - MSG_SEND_ASSIGN_VALUE(code, FailureType_Failure_ProcessError); - MSG_SEND_ASSIGN_STRING(message, "Invalid vendor header"); - MSG_SEND(Failure); - return -2; - } - if (sectrue != load_image_header(chunk_buffer + vhdr.hdrlen, FIRMWARE_IMAGE_MAGIC, FIRMWARE_IMAGE_MAXSIZE, vhdr.vsig_m, vhdr.vsig_n, vhdr.vpub, &hdr)) { - MSG_SEND_INIT(Failure); - MSG_SEND_ASSIGN_VALUE(code, FailureType_Failure_ProcessError); - MSG_SEND_ASSIGN_STRING(message, "Invalid firmware header"); - MSG_SEND(Failure); - return -3; - } - - vendor_header current_vhdr; - image_header current_hdr; - secbool is_new = secfalse, is_upgrade = secfalse; - detect_installation(¤t_vhdr, ¤t_hdr, &vhdr, &hdr, &is_new, &is_upgrade); - - int response = INPUT_CANCEL; - if (sectrue == is_new) { - // new installation - auto confirm - response = INPUT_CONFIRM; - } else - if (sectrue == is_upgrade) { - // firmware upgrade - ui_fadeout(); - ui_screen_install_confirm_upgrade(&vhdr, &hdr); - ui_fadein(); - response = ui_user_input(INPUT_CONFIRM | INPUT_CANCEL); - } else { - // new firmware vendor - ui_fadeout(); - ui_screen_install_confirm_newvendor(&vhdr, &hdr); - ui_fadein(); - response = ui_user_input(INPUT_CONFIRM | INPUT_CANCEL); - } - - if (INPUT_CANCEL == response) { - ui_fadeout(); - ui_screen_info(secfalse, ¤t_vhdr, ¤t_hdr); - ui_fadein(); - send_user_abort(iface_num, "Firmware install cancelled"); - return -4; - } - - ui_fadeout(); - ui_screen_install(); - ui_fadein(); - - // if firmware is not upgrade, erase storage - if (sectrue != is_upgrade) { - ensure(flash_erase_sectors(STORAGE_SECTORS, STORAGE_SECTORS_COUNT, NULL), NULL); - } - ensure(flash_erase_sectors(FIRMWARE_SECTORS, FIRMWARE_SECTORS_COUNT, ui_screen_install_progress_erase), NULL); - - firstskip = IMAGE_HEADER_SIZE + vhdr.hdrlen; + if (sectrue != r || chunk_size != chunk_requested) { + MSG_SEND_INIT(Failure); + MSG_SEND_ASSIGN_VALUE(code, FailureType_Failure_DataError); + MSG_SEND_ASSIGN_STRING(message, "Invalid chunk size"); + MSG_SEND(Failure); + return -1; + } + + static image_header hdr; + + uint32_t firstskip = 0; + if (firmware_block == 0) { + vendor_header vhdr; + if (sectrue != load_vendor_header_keys(chunk_buffer, &vhdr)) { + MSG_SEND_INIT(Failure); + MSG_SEND_ASSIGN_VALUE(code, FailureType_Failure_ProcessError); + MSG_SEND_ASSIGN_STRING(message, "Invalid vendor header"); + MSG_SEND(Failure); + return -2; } - - // should not happen, but double-check - if (firmware_block >= FIRMWARE_SECTORS_COUNT) { - MSG_SEND_INIT(Failure); - MSG_SEND_ASSIGN_VALUE(code, FailureType_Failure_ProcessError); - MSG_SEND_ASSIGN_STRING(message, "Firmware too big"); - MSG_SEND(Failure); - return -5; + if (sectrue != load_image_header(chunk_buffer + vhdr.hdrlen, + FIRMWARE_IMAGE_MAGIC, + FIRMWARE_IMAGE_MAXSIZE, vhdr.vsig_m, + vhdr.vsig_n, vhdr.vpub, &hdr)) { + MSG_SEND_INIT(Failure); + MSG_SEND_ASSIGN_VALUE(code, FailureType_Failure_ProcessError); + MSG_SEND_ASSIGN_STRING(message, "Invalid firmware header"); + MSG_SEND(Failure); + return -3; } - if (sectrue != check_single_hash(hdr.hashes + firmware_block * 32, chunk_buffer + firstskip, chunk_size - firstskip)) { - - if (firmware_upload_chunk_retry > 0) { - --firmware_upload_chunk_retry; - MSG_SEND_INIT(FirmwareRequest); - MSG_SEND_ASSIGN_VALUE(offset, firmware_block * IMAGE_CHUNK_SIZE); - MSG_SEND_ASSIGN_VALUE(length, chunk_requested); - MSG_SEND(FirmwareRequest); - return (int)firmware_remaining; - } - - MSG_SEND_INIT(Failure); - MSG_SEND_ASSIGN_VALUE(code, FailureType_Failure_ProcessError); - MSG_SEND_ASSIGN_STRING(message, "Invalid chunk hash"); - MSG_SEND(Failure); - return -6; + vendor_header current_vhdr; + image_header current_hdr; + secbool is_new = secfalse, is_upgrade = secfalse; + detect_installation(¤t_vhdr, ¤t_hdr, &vhdr, &hdr, &is_new, + &is_upgrade); + + int response = INPUT_CANCEL; + if (sectrue == is_new) { + // new installation - auto confirm + response = INPUT_CONFIRM; + } else if (sectrue == is_upgrade) { + // firmware upgrade + ui_fadeout(); + ui_screen_install_confirm_upgrade(&vhdr, &hdr); + ui_fadein(); + response = ui_user_input(INPUT_CONFIRM | INPUT_CANCEL); + } else { + // new firmware vendor + ui_fadeout(); + ui_screen_install_confirm_newvendor(&vhdr, &hdr); + ui_fadein(); + response = ui_user_input(INPUT_CONFIRM | INPUT_CANCEL); } - ensure(flash_unlock_write(), NULL); - - const uint32_t * const src = (const uint32_t * const)chunk_buffer; - for (int i = 0; i < chunk_size / sizeof(uint32_t); i++) { - ensure(flash_write_word(FIRMWARE_SECTORS[firmware_block], i * sizeof(uint32_t), src[i]), NULL); + if (INPUT_CANCEL == response) { + ui_fadeout(); + ui_screen_info(secfalse, ¤t_vhdr, ¤t_hdr); + ui_fadein(); + send_user_abort(iface_num, "Firmware install cancelled"); + return -4; } - ensure(flash_lock_write(), NULL); + ui_fadeout(); + ui_screen_install(); + ui_fadein(); - firmware_remaining -= chunk_requested; - firmware_block++; - firmware_upload_chunk_retry = FIRMWARE_UPLOAD_CHUNK_RETRY_COUNT; - - if (firmware_remaining > 0) { - chunk_requested = (firmware_remaining > IMAGE_CHUNK_SIZE) ? IMAGE_CHUNK_SIZE : firmware_remaining; - MSG_SEND_INIT(FirmwareRequest); - MSG_SEND_ASSIGN_VALUE(offset, firmware_block * IMAGE_CHUNK_SIZE); - MSG_SEND_ASSIGN_VALUE(length, chunk_requested); - MSG_SEND(FirmwareRequest); - } else { - MSG_SEND_INIT(Success); - MSG_SEND(Success); + // if firmware is not upgrade, erase storage + if (sectrue != is_upgrade) { + ensure(flash_erase_sectors(STORAGE_SECTORS, STORAGE_SECTORS_COUNT, NULL), + NULL); } - return (int)firmware_remaining; -} - -int process_msg_WipeDevice(uint8_t iface_num, uint32_t msg_size, uint8_t *buf) -{ - static const uint8_t sectors[] = { - FLASH_SECTOR_STORAGE_1, - FLASH_SECTOR_STORAGE_2, - // 3, // skip because of MPU protection - FLASH_SECTOR_FIRMWARE_START, - 7, - 8, - 9, - 10, - FLASH_SECTOR_FIRMWARE_END, - FLASH_SECTOR_UNUSED_START, - 13, - 14, - // FLASH_SECTOR_UNUSED_END, // skip because of MPU protection - FLASH_SECTOR_FIRMWARE_EXTRA_START, - 18, - 19, - 20, - 21, - 22, - FLASH_SECTOR_FIRMWARE_EXTRA_END, - }; - if (sectrue != flash_erase_sectors(sectors, sizeof(sectors), ui_screen_wipe_progress)) { - MSG_SEND_INIT(Failure); - MSG_SEND_ASSIGN_VALUE(code, FailureType_Failure_ProcessError); - MSG_SEND_ASSIGN_STRING(message, "Could not erase flash"); - MSG_SEND(Failure); - return -1; - } else { - MSG_SEND_INIT(Success); - MSG_SEND(Success); - return 0; - } -} + ensure(flash_erase_sectors(FIRMWARE_SECTORS, FIRMWARE_SECTORS_COUNT, + ui_screen_install_progress_erase), + NULL); -void process_msg_unknown(uint8_t iface_num, uint32_t msg_size, uint8_t *buf) -{ - // consume remaining message - int remaining_chunks = 0; + firstskip = IMAGE_HEADER_SIZE + vhdr.hdrlen; + } - if (msg_size > (USB_PACKET_SIZE - MSG_HEADER1_LEN)) { - // calculate how many blocks need to be read to drain the message (rounded up to not leave any behind) - remaining_chunks = (msg_size - (USB_PACKET_SIZE - MSG_HEADER1_LEN) + ((USB_PACKET_SIZE - MSG_HEADER2_LEN) - 1)) / (USB_PACKET_SIZE - MSG_HEADER2_LEN); + // should not happen, but double-check + if (firmware_block >= FIRMWARE_SECTORS_COUNT) { + MSG_SEND_INIT(Failure); + MSG_SEND_ASSIGN_VALUE(code, FailureType_Failure_ProcessError); + MSG_SEND_ASSIGN_STRING(message, "Firmware too big"); + MSG_SEND(Failure); + return -5; + } + + if (sectrue != check_single_hash(hdr.hashes + firmware_block * 32, + chunk_buffer + firstskip, + chunk_size - firstskip)) { + if (firmware_upload_chunk_retry > 0) { + --firmware_upload_chunk_retry; + MSG_SEND_INIT(FirmwareRequest); + MSG_SEND_ASSIGN_VALUE(offset, firmware_block * IMAGE_CHUNK_SIZE); + MSG_SEND_ASSIGN_VALUE(length, chunk_requested); + MSG_SEND(FirmwareRequest); + return (int)firmware_remaining; } - for (int i = 0; i < remaining_chunks; i++) { - int r = usb_webusb_read_blocking(iface_num, buf, USB_PACKET_SIZE, USB_TIMEOUT); - ensure(sectrue * (r == USB_PACKET_SIZE), NULL); - } + MSG_SEND_INIT(Failure); + MSG_SEND_ASSIGN_VALUE(code, FailureType_Failure_ProcessError); + MSG_SEND_ASSIGN_STRING(message, "Invalid chunk hash"); + MSG_SEND(Failure); + return -6; + } + + ensure(flash_unlock_write(), NULL); + + const uint32_t *const src = (const uint32_t *const)chunk_buffer; + for (int i = 0; i < chunk_size / sizeof(uint32_t); i++) { + ensure(flash_write_word(FIRMWARE_SECTORS[firmware_block], + i * sizeof(uint32_t), src[i]), + NULL); + } + + ensure(flash_lock_write(), NULL); + + firmware_remaining -= chunk_requested; + firmware_block++; + firmware_upload_chunk_retry = FIRMWARE_UPLOAD_CHUNK_RETRY_COUNT; + + if (firmware_remaining > 0) { + chunk_requested = (firmware_remaining > IMAGE_CHUNK_SIZE) + ? IMAGE_CHUNK_SIZE + : firmware_remaining; + MSG_SEND_INIT(FirmwareRequest); + MSG_SEND_ASSIGN_VALUE(offset, firmware_block * IMAGE_CHUNK_SIZE); + MSG_SEND_ASSIGN_VALUE(length, chunk_requested); + MSG_SEND(FirmwareRequest); + } else { + MSG_SEND_INIT(Success); + MSG_SEND(Success); + } + return (int)firmware_remaining; +} +int process_msg_WipeDevice(uint8_t iface_num, uint32_t msg_size, uint8_t *buf) { + static const uint8_t sectors[] = { + FLASH_SECTOR_STORAGE_1, + FLASH_SECTOR_STORAGE_2, + // 3, // skip because of MPU protection + FLASH_SECTOR_FIRMWARE_START, + 7, + 8, + 9, + 10, + FLASH_SECTOR_FIRMWARE_END, + FLASH_SECTOR_UNUSED_START, + 13, + 14, + // FLASH_SECTOR_UNUSED_END, // skip because of MPU protection + FLASH_SECTOR_FIRMWARE_EXTRA_START, + 18, + 19, + 20, + 21, + 22, + FLASH_SECTOR_FIRMWARE_EXTRA_END, + }; + if (sectrue != + flash_erase_sectors(sectors, sizeof(sectors), ui_screen_wipe_progress)) { MSG_SEND_INIT(Failure); - MSG_SEND_ASSIGN_VALUE(code, FailureType_Failure_UnexpectedMessage); - MSG_SEND_ASSIGN_STRING(message, "Unexpected message"); + MSG_SEND_ASSIGN_VALUE(code, FailureType_Failure_ProcessError); + MSG_SEND_ASSIGN_STRING(message, "Could not erase flash"); MSG_SEND(Failure); + return -1; + } else { + MSG_SEND_INIT(Success); + MSG_SEND(Success); + return 0; + } +} + +void process_msg_unknown(uint8_t iface_num, uint32_t msg_size, uint8_t *buf) { + // consume remaining message + int remaining_chunks = 0; + + if (msg_size > (USB_PACKET_SIZE - MSG_HEADER1_LEN)) { + // calculate how many blocks need to be read to drain the message (rounded + // up to not leave any behind) + remaining_chunks = (msg_size - (USB_PACKET_SIZE - MSG_HEADER1_LEN) + + ((USB_PACKET_SIZE - MSG_HEADER2_LEN) - 1)) / + (USB_PACKET_SIZE - MSG_HEADER2_LEN); + } + + for (int i = 0; i < remaining_chunks; i++) { + int r = + usb_webusb_read_blocking(iface_num, buf, USB_PACKET_SIZE, USB_TIMEOUT); + ensure(sectrue * (r == USB_PACKET_SIZE), NULL); + } + + MSG_SEND_INIT(Failure); + MSG_SEND_ASSIGN_VALUE(code, FailureType_Failure_UnexpectedMessage); + MSG_SEND_ASSIGN_STRING(message, "Unexpected message"); + MSG_SEND(Failure); } diff --git a/embed/bootloader/messages.h b/embed/bootloader/messages.h index d509dd9e1..2a0a6c547 100644 --- a/embed/bootloader/messages.h +++ b/embed/bootloader/messages.h @@ -24,20 +24,27 @@ #include "image.h" #include "secbool.h" -#define USB_TIMEOUT 500 -#define USB_PACKET_SIZE 64 +#define USB_TIMEOUT 500 +#define USB_PACKET_SIZE 64 #define FIRMWARE_UPLOAD_CHUNK_RETRY_COUNT 2 -secbool msg_parse_header(const uint8_t *buf, uint16_t *msg_id, uint32_t *msg_size); +secbool msg_parse_header(const uint8_t *buf, uint16_t *msg_id, + uint32_t *msg_size); void send_user_abort(uint8_t iface_num, const char *msg); -void process_msg_Initialize(uint8_t iface_num, uint32_t msg_size, uint8_t *buf, const vendor_header * const vhdr, const image_header * const hdr); -void process_msg_GetFeatures(uint8_t iface_num, uint32_t msg_size, uint8_t *buf, const vendor_header * const vhdr, const image_header * const hdr); +void process_msg_Initialize(uint8_t iface_num, uint32_t msg_size, uint8_t *buf, + const vendor_header *const vhdr, + const image_header *const hdr); +void process_msg_GetFeatures(uint8_t iface_num, uint32_t msg_size, uint8_t *buf, + const vendor_header *const vhdr, + const image_header *const hdr); void process_msg_Ping(uint8_t iface_num, uint32_t msg_size, uint8_t *buf); -void process_msg_FirmwareErase(uint8_t iface_num, uint32_t msg_size, uint8_t *buf); -int process_msg_FirmwareUpload(uint8_t iface_num, uint32_t msg_size, uint8_t *buf); +void process_msg_FirmwareErase(uint8_t iface_num, uint32_t msg_size, + uint8_t *buf); +int process_msg_FirmwareUpload(uint8_t iface_num, uint32_t msg_size, + uint8_t *buf); int process_msg_WipeDevice(uint8_t iface_num, uint32_t msg_size, uint8_t *buf); void process_msg_unknown(uint8_t iface_num, uint32_t msg_size, uint8_t *buf); diff --git a/embed/bootloader/version.h b/embed/bootloader/version.h index 4a38dd2a3..5cbcb75b5 100644 --- a/embed/bootloader/version.h +++ b/embed/bootloader/version.h @@ -1,12 +1,14 @@ -#define VERSION_MAJOR 2 -#define VERSION_MINOR 0 -#define VERSION_PATCH 3 -#define VERSION_BUILD 0 -#define VERSION_UINT32 (VERSION_MAJOR | (VERSION_MINOR << 8) | (VERSION_PATCH << 16) | (VERSION_BUILD << 24)) +#define VERSION_MAJOR 2 +#define VERSION_MINOR 0 +#define VERSION_PATCH 3 +#define VERSION_BUILD 0 +#define VERSION_UINT32 \ + (VERSION_MAJOR | (VERSION_MINOR << 8) | (VERSION_PATCH << 16) | \ + (VERSION_BUILD << 24)) -#define FIX_VERSION_MAJOR 2 -#define FIX_VERSION_MINOR 0 -#define FIX_VERSION_PATCH 0 -#define FIX_VERSION_BUILD 0 +#define FIX_VERSION_MAJOR 2 +#define FIX_VERSION_MINOR 0 +#define FIX_VERSION_PATCH 0 +#define FIX_VERSION_BUILD 0 -#define VERSION_MONOTONIC 1 +#define VERSION_MONOTONIC 1 diff --git a/embed/extmod/modtrezorconfig/modtrezorconfig.c b/embed/extmod/modtrezorconfig/modtrezorconfig.c index 6dbe13e5a..dcbc0b40b 100644 --- a/embed/extmod/modtrezorconfig/modtrezorconfig.c +++ b/embed/extmod/modtrezorconfig/modtrezorconfig.c @@ -19,31 +19,32 @@ #include -#include "py/runtime.h" #include "py/mphal.h" #include "py/objstr.h" +#include "py/runtime.h" #if MICROPY_PY_TREZORCONFIG #include "embed/extmod/trezorobj.h" -#include "storage.h" #include "common.h" #include "memzero.h" +#include "storage.h" STATIC mp_obj_t ui_wait_callback = mp_const_none; -STATIC secbool wrapped_ui_wait_callback(uint32_t wait, uint32_t progress, const char* message) { - if (mp_obj_is_callable(ui_wait_callback)) { - mp_obj_t args[3]; - args[0] = mp_obj_new_int(wait); - args[1] = mp_obj_new_int(progress); - args[2] = mp_obj_new_str(message, strlen(message)); - if (mp_call_function_n_kw(ui_wait_callback, 3, 0, args) == mp_const_true) { - return sectrue; - } +STATIC secbool wrapped_ui_wait_callback(uint32_t wait, uint32_t progress, + const char *message) { + if (mp_obj_is_callable(ui_wait_callback)) { + mp_obj_t args[3]; + args[0] = mp_obj_new_int(wait); + args[1] = mp_obj_new_int(progress); + args[2] = mp_obj_new_str(message, strlen(message)); + if (mp_call_function_n_kw(ui_wait_callback, 3, 0, args) == mp_const_true) { + return sectrue; } - return secfalse; + } + return secfalse; } /// def init(ui_wait_callback: (int, int -> None)=None) -> None: @@ -52,29 +53,31 @@ STATIC secbool wrapped_ui_wait_callback(uint32_t wait, uint32_t progress, const /// called from this module! /// ''' STATIC mp_obj_t mod_trezorconfig_init(size_t n_args, const mp_obj_t *args) { - if (n_args > 0) { - ui_wait_callback = args[0]; - storage_init(wrapped_ui_wait_callback, HW_ENTROPY_DATA, HW_ENTROPY_LEN); - } else { - storage_init(NULL, HW_ENTROPY_DATA, HW_ENTROPY_LEN); - } - memzero(HW_ENTROPY_DATA, sizeof(HW_ENTROPY_DATA)); - return mp_const_none; + if (n_args > 0) { + ui_wait_callback = args[0]; + storage_init(wrapped_ui_wait_callback, HW_ENTROPY_DATA, HW_ENTROPY_LEN); + } else { + storage_init(NULL, HW_ENTROPY_DATA, HW_ENTROPY_LEN); + } + memzero(HW_ENTROPY_DATA, sizeof(HW_ENTROPY_DATA)); + return mp_const_none; } -STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(mod_trezorconfig_init_obj, 0, 1, mod_trezorconfig_init); +STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(mod_trezorconfig_init_obj, 0, 1, + mod_trezorconfig_init); /// def check_pin(pin: int) -> bool: /// ''' /// Check the given PIN. Returns True on success, False on failure. /// ''' STATIC mp_obj_t mod_trezorconfig_check_pin(mp_obj_t pin) { - uint32_t pin_i = trezor_obj_get_uint(pin); - if (sectrue != storage_unlock(pin_i)) { - return mp_const_false; - } - return mp_const_true; + uint32_t pin_i = trezor_obj_get_uint(pin); + if (sectrue != storage_unlock(pin_i)) { + return mp_const_false; + } + return mp_const_true; } -STATIC MP_DEFINE_CONST_FUN_OBJ_1(mod_trezorconfig_check_pin_obj, mod_trezorconfig_check_pin); +STATIC MP_DEFINE_CONST_FUN_OBJ_1(mod_trezorconfig_check_pin_obj, + mod_trezorconfig_check_pin); /// def unlock(pin: int) -> bool: /// ''' @@ -82,205 +85,227 @@ STATIC MP_DEFINE_CONST_FUN_OBJ_1(mod_trezorconfig_check_pin_obj, mod_trezorconfi /// success, False on failure. /// ''' STATIC mp_obj_t mod_trezorconfig_unlock(mp_obj_t pin) { - uint32_t pin_i = trezor_obj_get_uint(pin); - if (sectrue != storage_unlock(pin_i)) { - return mp_const_false; - } - return mp_const_true; + uint32_t pin_i = trezor_obj_get_uint(pin); + if (sectrue != storage_unlock(pin_i)) { + return mp_const_false; + } + return mp_const_true; } -STATIC MP_DEFINE_CONST_FUN_OBJ_1(mod_trezorconfig_unlock_obj, mod_trezorconfig_unlock); +STATIC MP_DEFINE_CONST_FUN_OBJ_1(mod_trezorconfig_unlock_obj, + mod_trezorconfig_unlock); /// def lock() -> None: /// ''' /// Locks the storage. /// ''' STATIC mp_obj_t mod_trezorconfig_lock(void) { - storage_lock(); - return mp_const_none; + storage_lock(); + return mp_const_none; } -STATIC MP_DEFINE_CONST_FUN_OBJ_0(mod_trezorconfig_lock_obj, mod_trezorconfig_lock); +STATIC MP_DEFINE_CONST_FUN_OBJ_0(mod_trezorconfig_lock_obj, + mod_trezorconfig_lock); /// def has_pin() -> bool: /// ''' /// Returns True if storage has a configured PIN, False otherwise. /// ''' STATIC mp_obj_t mod_trezorconfig_has_pin(void) { - if (sectrue != storage_has_pin()) { - return mp_const_false; - } - return mp_const_true; + if (sectrue != storage_has_pin()) { + return mp_const_false; + } + return mp_const_true; } -STATIC MP_DEFINE_CONST_FUN_OBJ_0(mod_trezorconfig_has_pin_obj, mod_trezorconfig_has_pin); +STATIC MP_DEFINE_CONST_FUN_OBJ_0(mod_trezorconfig_has_pin_obj, + mod_trezorconfig_has_pin); /// def get_pin_rem() -> int: /// ''' /// Returns the number of remaining PIN entry attempts. /// ''' STATIC mp_obj_t mod_trezorconfig_get_pin_rem(void) { - return mp_obj_new_int_from_uint(storage_get_pin_rem()); + return mp_obj_new_int_from_uint(storage_get_pin_rem()); } -STATIC MP_DEFINE_CONST_FUN_OBJ_0(mod_trezorconfig_get_pin_rem_obj, mod_trezorconfig_get_pin_rem); +STATIC MP_DEFINE_CONST_FUN_OBJ_0(mod_trezorconfig_get_pin_rem_obj, + mod_trezorconfig_get_pin_rem); /// def change_pin(pin: int, newpin: int) -> bool: /// ''' /// Change PIN. Returns True on success, False on failure. /// ''' STATIC mp_obj_t mod_trezorconfig_change_pin(mp_obj_t pin, mp_obj_t newpin) { - uint32_t pin_i = trezor_obj_get_uint(pin); - uint32_t newpin_i = trezor_obj_get_uint(newpin); - if (sectrue != storage_change_pin(pin_i, newpin_i)) { - return mp_const_false; - } - return mp_const_true; + uint32_t pin_i = trezor_obj_get_uint(pin); + uint32_t newpin_i = trezor_obj_get_uint(newpin); + if (sectrue != storage_change_pin(pin_i, newpin_i)) { + return mp_const_false; + } + return mp_const_true; } -STATIC MP_DEFINE_CONST_FUN_OBJ_2(mod_trezorconfig_change_pin_obj, mod_trezorconfig_change_pin); +STATIC MP_DEFINE_CONST_FUN_OBJ_2(mod_trezorconfig_change_pin_obj, + mod_trezorconfig_change_pin); /// def get(app: int, key: int, public: bool=False) -> bytes: /// ''' /// Gets the value of the given key for the given app (or None if not set). -/// Raises a RuntimeError if decryption or authentication of the stored value fails. +/// Raises a RuntimeError if decryption or authentication of the stored +/// value fails. /// ''' STATIC mp_obj_t mod_trezorconfig_get(size_t n_args, const mp_obj_t *args) { - uint8_t app = trezor_obj_get_uint8(args[0]) & 0x3F; - uint8_t key = trezor_obj_get_uint8(args[1]); - if (n_args > 2 && args[2] == mp_const_true) { - app |= 0x80; - } - uint16_t appkey = (app << 8) | key; - uint16_t len = 0; - if (sectrue != storage_get(appkey, NULL, 0, &len)) { - return mp_const_none; - } - if (len == 0) { - return mp_const_empty_bytes; - } - vstr_t vstr; - vstr_init_len(&vstr, len); - if (sectrue != storage_get(appkey, vstr.buf, vstr.len, &len)) { - vstr_clear(&vstr); - mp_raise_msg(&mp_type_RuntimeError, "Failed to get value from storage."); - } - return mp_obj_new_str_from_vstr(&mp_type_bytes, &vstr); + uint8_t app = trezor_obj_get_uint8(args[0]) & 0x3F; + uint8_t key = trezor_obj_get_uint8(args[1]); + if (n_args > 2 && args[2] == mp_const_true) { + app |= 0x80; + } + uint16_t appkey = (app << 8) | key; + uint16_t len = 0; + if (sectrue != storage_get(appkey, NULL, 0, &len)) { + return mp_const_none; + } + if (len == 0) { + return mp_const_empty_bytes; + } + vstr_t vstr; + vstr_init_len(&vstr, len); + if (sectrue != storage_get(appkey, vstr.buf, vstr.len, &len)) { + vstr_clear(&vstr); + mp_raise_msg(&mp_type_RuntimeError, "Failed to get value from storage."); + } + return mp_obj_new_str_from_vstr(&mp_type_bytes, &vstr); } -STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(mod_trezorconfig_get_obj, 2, 3, mod_trezorconfig_get); +STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(mod_trezorconfig_get_obj, 2, 3, + mod_trezorconfig_get); /// def set(app: int, key: int, value: bytes, public: bool=False) -> None: /// ''' /// Sets a value of given key for given app. /// ''' STATIC mp_obj_t mod_trezorconfig_set(size_t n_args, const mp_obj_t *args) { - uint8_t app = trezor_obj_get_uint8(args[0]) & 0x3F; - uint8_t key = trezor_obj_get_uint8(args[1]); - if (n_args > 3 && args[3] == mp_const_true) { - app |= 0x80; - } - uint16_t appkey = (app << 8) | key; - mp_buffer_info_t value; - mp_get_buffer_raise(args[2], &value, MP_BUFFER_READ); - if (sectrue != storage_set(appkey, value.buf, value.len)) { - mp_raise_msg(&mp_type_RuntimeError, "Could not save value"); - } - return mp_const_none; + uint8_t app = trezor_obj_get_uint8(args[0]) & 0x3F; + uint8_t key = trezor_obj_get_uint8(args[1]); + if (n_args > 3 && args[3] == mp_const_true) { + app |= 0x80; + } + uint16_t appkey = (app << 8) | key; + mp_buffer_info_t value; + mp_get_buffer_raise(args[2], &value, MP_BUFFER_READ); + if (sectrue != storage_set(appkey, value.buf, value.len)) { + mp_raise_msg(&mp_type_RuntimeError, "Could not save value"); + } + return mp_const_none; } -STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(mod_trezorconfig_set_obj, 3, 4, mod_trezorconfig_set); +STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(mod_trezorconfig_set_obj, 3, 4, + mod_trezorconfig_set); /// def delete(app: int, key: int, public: bool=False) -> bool: /// ''' /// Deletes the given key of the given app. /// ''' STATIC mp_obj_t mod_trezorconfig_delete(size_t n_args, const mp_obj_t *args) { - uint8_t app = trezor_obj_get_uint8(args[0]) & 0x3F; - uint8_t key = trezor_obj_get_uint8(args[1]); - if (n_args > 2 && args[2] == mp_const_true) { - app |= 0x80; - } - uint16_t appkey = (app << 8) | key; - if (sectrue != storage_delete(appkey)) { - return mp_const_false; - } - return mp_const_true; + uint8_t app = trezor_obj_get_uint8(args[0]) & 0x3F; + uint8_t key = trezor_obj_get_uint8(args[1]); + if (n_args > 2 && args[2] == mp_const_true) { + app |= 0x80; + } + uint16_t appkey = (app << 8) | key; + if (sectrue != storage_delete(appkey)) { + return mp_const_false; + } + return mp_const_true; } -STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(mod_trezorconfig_delete_obj, 2, 3, mod_trezorconfig_delete); +STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(mod_trezorconfig_delete_obj, 2, 3, + mod_trezorconfig_delete); -/// def set_counter(app: int, key: int, count: int, writable_locked: bool=False) -> bool: +/// def set_counter(app: int, key: int, count: int, writable_locked: bool=False) +/// -> bool: /// ''' /// Sets the given key of the given app as a counter with the given value. /// ''' -STATIC mp_obj_t mod_trezorconfig_set_counter(size_t n_args, const mp_obj_t *args) { - uint8_t app = trezor_obj_get_uint8(args[0]) & 0x3F; - uint8_t key = trezor_obj_get_uint8(args[1]); - if (n_args > 3 && args[3] == mp_const_true) { - app |= 0xC0; - } else { - app |= 0x80; +STATIC mp_obj_t mod_trezorconfig_set_counter(size_t n_args, + const mp_obj_t *args) { + uint8_t app = trezor_obj_get_uint8(args[0]) & 0x3F; + uint8_t key = trezor_obj_get_uint8(args[1]); + if (n_args > 3 && args[3] == mp_const_true) { + app |= 0xC0; + } else { + app |= 0x80; + } + uint16_t appkey = (app << 8) | key; + if (args[2] == mp_const_none) { + if (sectrue != storage_delete(appkey)) { + return mp_const_false; } - uint16_t appkey = (app << 8) | key; - if (args[2] == mp_const_none) { - if (sectrue != storage_delete(appkey)) { - return mp_const_false; - } - } else { - uint32_t count = trezor_obj_get_uint(args[2]); - if (sectrue != storage_set_counter(appkey, count)) { - return mp_const_false; - } + } else { + uint32_t count = trezor_obj_get_uint(args[2]); + if (sectrue != storage_set_counter(appkey, count)) { + return mp_const_false; } - return mp_const_true; + } + return mp_const_true; } -STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(mod_trezorconfig_set_counter_obj, 3, 4, mod_trezorconfig_set_counter); +STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(mod_trezorconfig_set_counter_obj, 3, + 4, mod_trezorconfig_set_counter); /// def next_counter(app: int, key: int, writable_locked: bool=False) -> bool: /// ''' -/// Increments the counter stored under the given key of the given app and returns the new value. +/// Increments the counter stored under the given key of the given app and +/// returns the new value. /// ''' -STATIC mp_obj_t mod_trezorconfig_next_counter(size_t n_args, const mp_obj_t *args) { - uint8_t app = trezor_obj_get_uint8(args[0]) & 0x3F; - uint8_t key = trezor_obj_get_uint8(args[1]); - if (n_args > 2 && args[2] == mp_const_true) { - app |= 0xC0; - } else { - app |= 0x80; - } - uint16_t appkey = (app << 8) | key; - uint32_t count = 0; - if (sectrue != storage_next_counter(appkey, &count)) { - return mp_const_none; - } - return mp_obj_new_int_from_uint(count); +STATIC mp_obj_t mod_trezorconfig_next_counter(size_t n_args, + const mp_obj_t *args) { + uint8_t app = trezor_obj_get_uint8(args[0]) & 0x3F; + uint8_t key = trezor_obj_get_uint8(args[1]); + if (n_args > 2 && args[2] == mp_const_true) { + app |= 0xC0; + } else { + app |= 0x80; + } + uint16_t appkey = (app << 8) | key; + uint32_t count = 0; + if (sectrue != storage_next_counter(appkey, &count)) { + return mp_const_none; + } + return mp_obj_new_int_from_uint(count); } -STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(mod_trezorconfig_next_counter_obj, 2, 3, mod_trezorconfig_next_counter); +STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(mod_trezorconfig_next_counter_obj, 2, + 3, mod_trezorconfig_next_counter); /// def wipe() -> None: /// ''' /// Erases the whole config. Use with caution! /// ''' STATIC mp_obj_t mod_trezorconfig_wipe(void) { - storage_wipe(); - return mp_const_none; + storage_wipe(); + return mp_const_none; } -STATIC MP_DEFINE_CONST_FUN_OBJ_0(mod_trezorconfig_wipe_obj, mod_trezorconfig_wipe); +STATIC MP_DEFINE_CONST_FUN_OBJ_0(mod_trezorconfig_wipe_obj, + mod_trezorconfig_wipe); STATIC const mp_rom_map_elem_t mp_module_trezorconfig_globals_table[] = { - { MP_ROM_QSTR(MP_QSTR___name__), MP_ROM_QSTR(MP_QSTR_trezorconfig) }, - { MP_ROM_QSTR(MP_QSTR_init), MP_ROM_PTR(&mod_trezorconfig_init_obj) }, - { MP_ROM_QSTR(MP_QSTR_check_pin), MP_ROM_PTR(&mod_trezorconfig_check_pin_obj) }, - { MP_ROM_QSTR(MP_QSTR_unlock), MP_ROM_PTR(&mod_trezorconfig_unlock_obj) }, - { MP_ROM_QSTR(MP_QSTR_lock), MP_ROM_PTR(&mod_trezorconfig_lock_obj) }, - { MP_ROM_QSTR(MP_QSTR_has_pin), MP_ROM_PTR(&mod_trezorconfig_has_pin_obj) }, - { MP_ROM_QSTR(MP_QSTR_get_pin_rem), MP_ROM_PTR(&mod_trezorconfig_get_pin_rem_obj) }, - { MP_ROM_QSTR(MP_QSTR_change_pin), MP_ROM_PTR(&mod_trezorconfig_change_pin_obj) }, - { MP_ROM_QSTR(MP_QSTR_get), MP_ROM_PTR(&mod_trezorconfig_get_obj) }, - { MP_ROM_QSTR(MP_QSTR_set), MP_ROM_PTR(&mod_trezorconfig_set_obj) }, - { MP_ROM_QSTR(MP_QSTR_delete), MP_ROM_PTR(&mod_trezorconfig_delete_obj) }, - { MP_ROM_QSTR(MP_QSTR_set_counter), MP_ROM_PTR(&mod_trezorconfig_set_counter_obj) }, - { MP_ROM_QSTR(MP_QSTR_next_counter), MP_ROM_PTR(&mod_trezorconfig_next_counter_obj) }, - { MP_ROM_QSTR(MP_QSTR_wipe), MP_ROM_PTR(&mod_trezorconfig_wipe_obj) }, + {MP_ROM_QSTR(MP_QSTR___name__), MP_ROM_QSTR(MP_QSTR_trezorconfig)}, + {MP_ROM_QSTR(MP_QSTR_init), MP_ROM_PTR(&mod_trezorconfig_init_obj)}, + {MP_ROM_QSTR(MP_QSTR_check_pin), + MP_ROM_PTR(&mod_trezorconfig_check_pin_obj)}, + {MP_ROM_QSTR(MP_QSTR_unlock), MP_ROM_PTR(&mod_trezorconfig_unlock_obj)}, + {MP_ROM_QSTR(MP_QSTR_lock), MP_ROM_PTR(&mod_trezorconfig_lock_obj)}, + {MP_ROM_QSTR(MP_QSTR_has_pin), MP_ROM_PTR(&mod_trezorconfig_has_pin_obj)}, + {MP_ROM_QSTR(MP_QSTR_get_pin_rem), + MP_ROM_PTR(&mod_trezorconfig_get_pin_rem_obj)}, + {MP_ROM_QSTR(MP_QSTR_change_pin), + MP_ROM_PTR(&mod_trezorconfig_change_pin_obj)}, + {MP_ROM_QSTR(MP_QSTR_get), MP_ROM_PTR(&mod_trezorconfig_get_obj)}, + {MP_ROM_QSTR(MP_QSTR_set), MP_ROM_PTR(&mod_trezorconfig_set_obj)}, + {MP_ROM_QSTR(MP_QSTR_delete), MP_ROM_PTR(&mod_trezorconfig_delete_obj)}, + {MP_ROM_QSTR(MP_QSTR_set_counter), + MP_ROM_PTR(&mod_trezorconfig_set_counter_obj)}, + {MP_ROM_QSTR(MP_QSTR_next_counter), + MP_ROM_PTR(&mod_trezorconfig_next_counter_obj)}, + {MP_ROM_QSTR(MP_QSTR_wipe), MP_ROM_PTR(&mod_trezorconfig_wipe_obj)}, }; -STATIC MP_DEFINE_CONST_DICT(mp_module_trezorconfig_globals, mp_module_trezorconfig_globals_table); +STATIC MP_DEFINE_CONST_DICT(mp_module_trezorconfig_globals, + mp_module_trezorconfig_globals_table); const mp_obj_module_t mp_module_trezorconfig = { - .base = { &mp_type_module }, - .globals = (mp_obj_dict_t*)&mp_module_trezorconfig_globals, + .base = {&mp_type_module}, + .globals = (mp_obj_dict_t *)&mp_module_trezorconfig_globals, }; -#endif // MICROPY_PY_TREZORCONFIG +#endif // MICROPY_PY_TREZORCONFIG diff --git a/embed/extmod/modtrezorconfig/norcow_config.h b/embed/extmod/modtrezorconfig/norcow_config.h index 1faafd79f..ec812647e 100644 --- a/embed/extmod/modtrezorconfig/norcow_config.h +++ b/embed/extmod/modtrezorconfig/norcow_config.h @@ -22,18 +22,20 @@ #include "flash.h" -#define NORCOW_HEADER_LEN 0 -#define NORCOW_SECTOR_COUNT 2 +#define NORCOW_HEADER_LEN 0 +#define NORCOW_SECTOR_COUNT 2 #if TREZOR_MODEL == T -#define NORCOW_SECTOR_SIZE (64*1024) -#define NORCOW_SECTORS {FLASH_SECTOR_STORAGE_1, FLASH_SECTOR_STORAGE_2} +#define NORCOW_SECTOR_SIZE (64 * 1024) +#define NORCOW_SECTORS \ + { FLASH_SECTOR_STORAGE_1, FLASH_SECTOR_STORAGE_2 } #elif TREZOR_MODEL == 1 -#define NORCOW_SECTOR_SIZE (16*1024) -#define NORCOW_SECTORS {2, 3} +#define NORCOW_SECTOR_SIZE (16 * 1024) +#define NORCOW_SECTORS \ + { 2, 3 } #else diff --git a/embed/extmod/modtrezorcrypto/crc.c b/embed/extmod/modtrezorcrypto/crc.c index a4be68b5e..c80efde40 100644 --- a/embed/extmod/modtrezorcrypto/crc.c +++ b/embed/extmod/modtrezorcrypto/crc.c @@ -58,21 +58,18 @@ #include "crc.h" static const uint32_t crc32tab[16] = { - 0x00000000, 0x1db71064, 0x3b6e20c8, 0x26d930ac, 0x76dc4190, - 0x6b6b51f4, 0x4db26158, 0x5005713c, 0xedb88320, 0xf00f9344, - 0xd6d6a3e8, 0xcb61b38c, 0x9b64c2b0, 0x86d3d2d4, 0xa00ae278, - 0xbdbdf21c -}; + 0x00000000, 0x1db71064, 0x3b6e20c8, 0x26d930ac, 0x76dc4190, 0x6b6b51f4, + 0x4db26158, 0x5005713c, 0xedb88320, 0xf00f9344, 0xd6d6a3e8, 0xcb61b38c, + 0x9b64c2b0, 0x86d3d2d4, 0xa00ae278, 0xbdbdf21c}; /* crc is previous value for incremental computation, 0xffffffff initially */ -uint32_t checksum_crc32(const uint8_t *data, uint32_t length, uint32_t crc) -{ - for (uint32_t i = 0; i < length; ++i) { - crc ^= data[i]; - crc = crc32tab[crc & 0x0f] ^ (crc >> 4); - crc = crc32tab[crc & 0x0f] ^ (crc >> 4); - } +uint32_t checksum_crc32(const uint8_t *data, uint32_t length, uint32_t crc) { + for (uint32_t i = 0; i < length; ++i) { + crc ^= data[i]; + crc = crc32tab[crc & 0x0f] ^ (crc >> 4); + crc = crc32tab[crc & 0x0f] ^ (crc >> 4); + } - // return value suitable for passing in next time, for final value invert it - return crc/* ^ 0xffffffff*/; + // return value suitable for passing in next time, for final value invert it + return crc /* ^ 0xffffffff*/; } diff --git a/embed/extmod/modtrezorcrypto/modtrezorcrypto-aes.h b/embed/extmod/modtrezorcrypto/modtrezorcrypto-aes.h index 1bfdaa8f7..bf36c6508 100644 --- a/embed/extmod/modtrezorcrypto/modtrezorcrypto-aes.h +++ b/embed/extmod/modtrezorcrypto/modtrezorcrypto-aes.h @@ -23,11 +23,11 @@ #include "memzero.h" enum AESMode { - ECB = 0x00, - CBC = 0x01, - CFB = 0x02, - OFB = 0x03, - CTR = 0x04, + ECB = 0x00, + CBC = 0x01, + CFB = 0x02, + OFB = 0x03, + CTR = 0x04, }; /// package: trezorcrypto.__init__ @@ -37,102 +37,114 @@ enum AESMode { /// AES context. /// ''' typedef struct _mp_obj_AES_t { - mp_obj_base_t base; - aes_encrypt_ctx encrypt_ctx; - aes_decrypt_ctx decrypt_ctx; - mp_int_t mode; - uint8_t iv[AES_BLOCK_SIZE]; + mp_obj_base_t base; + aes_encrypt_ctx encrypt_ctx; + aes_decrypt_ctx decrypt_ctx; + mp_int_t mode; + uint8_t iv[AES_BLOCK_SIZE]; } mp_obj_AES_t; /// def __init__(self, mode: int, key: bytes, iv: bytes = None) -> None: /// ''' /// Initialize AES context. /// ''' -STATIC mp_obj_t mod_trezorcrypto_AES_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_kw, const mp_obj_t *args) { - mp_arg_check_num(n_args, n_kw, 2, 3, false); - mp_obj_AES_t *o = m_new_obj(mp_obj_AES_t); - o->base.type = type; - o->mode = mp_obj_get_int(args[0]); - if (o->mode < ECB || o->mode > CTR) { - mp_raise_ValueError("Invalid AES mode"); +STATIC mp_obj_t mod_trezorcrypto_AES_make_new(const mp_obj_type_t *type, + size_t n_args, size_t n_kw, + const mp_obj_t *args) { + mp_arg_check_num(n_args, n_kw, 2, 3, false); + mp_obj_AES_t *o = m_new_obj(mp_obj_AES_t); + o->base.type = type; + o->mode = mp_obj_get_int(args[0]); + if (o->mode < ECB || o->mode > CTR) { + mp_raise_ValueError("Invalid AES mode"); + } + mp_buffer_info_t key; + mp_get_buffer_raise(args[1], &key, MP_BUFFER_READ); + if (key.len != 16 && key.len != 24 && key.len != 32) { + mp_raise_ValueError( + "Invalid length of key (has to be 128, 192 or 256 bits)"); + } + if (n_args > 2) { + mp_buffer_info_t iv; + mp_get_buffer_raise(args[2], &iv, MP_BUFFER_READ); + if (iv.len != AES_BLOCK_SIZE) { + mp_raise_ValueError( + "Invalid length of initialization vector (has to be 128 bits)"); } - mp_buffer_info_t key; - mp_get_buffer_raise(args[1], &key, MP_BUFFER_READ); - if (key.len != 16 && key.len != 24 && key.len != 32) { - mp_raise_ValueError("Invalid length of key (has to be 128, 192 or 256 bits)"); - } - if (n_args > 2) { - mp_buffer_info_t iv; - mp_get_buffer_raise(args[2], &iv, MP_BUFFER_READ); - if (iv.len != AES_BLOCK_SIZE) { - mp_raise_ValueError("Invalid length of initialization vector (has to be 128 bits)"); - } - memcpy(o->iv, iv.buf, AES_BLOCK_SIZE); - } else { - memzero(o->iv, AES_BLOCK_SIZE); - } - switch (key.len) { - case 16: - aes_decrypt_key128(key.buf, &(o->decrypt_ctx)); - aes_encrypt_key128(key.buf, &(o->encrypt_ctx)); - break; - case 24: - aes_decrypt_key192(key.buf, &(o->decrypt_ctx)); - aes_encrypt_key192(key.buf, &(o->encrypt_ctx)); - break; - case 32: - aes_decrypt_key256(key.buf, &(o->decrypt_ctx)); - aes_encrypt_key256(key.buf, &(o->encrypt_ctx)); - break; - } - return MP_OBJ_FROM_PTR(o); + memcpy(o->iv, iv.buf, AES_BLOCK_SIZE); + } else { + memzero(o->iv, AES_BLOCK_SIZE); + } + switch (key.len) { + case 16: + aes_decrypt_key128(key.buf, &(o->decrypt_ctx)); + aes_encrypt_key128(key.buf, &(o->encrypt_ctx)); + break; + case 24: + aes_decrypt_key192(key.buf, &(o->decrypt_ctx)); + aes_encrypt_key192(key.buf, &(o->encrypt_ctx)); + break; + case 32: + aes_decrypt_key256(key.buf, &(o->decrypt_ctx)); + aes_encrypt_key256(key.buf, &(o->encrypt_ctx)); + break; + } + return MP_OBJ_FROM_PTR(o); } static mp_obj_t aes_update(mp_obj_t self, mp_obj_t data, bool encrypt) { - mp_buffer_info_t buf; - mp_get_buffer_raise(data, &buf, MP_BUFFER_READ); - if (buf.len == 0) { - return mp_const_empty_bytes; - } - vstr_t vstr; - vstr_init_len(&vstr, buf.len); - mp_obj_AES_t *o = MP_OBJ_TO_PTR(self); - switch (o->mode) { - case ECB: - if (buf.len & (AES_BLOCK_SIZE - 1)) { - mp_raise_ValueError("Invalid data length"); - } - if (encrypt) { - aes_ecb_encrypt(buf.buf, (uint8_t *)vstr.buf, buf.len, &(o->encrypt_ctx)); - } else { - aes_ecb_decrypt(buf.buf, (uint8_t *)vstr.buf, buf.len, &(o->decrypt_ctx)); - } - break; - case CBC: - if (buf.len & (AES_BLOCK_SIZE - 1)) { - mp_raise_ValueError("Invalid data length"); - } - if (encrypt) { - aes_cbc_encrypt(buf.buf, (uint8_t *)vstr.buf, buf.len, o->iv, &(o->encrypt_ctx)); - } else { - aes_cbc_decrypt(buf.buf, (uint8_t *)vstr.buf, buf.len, o->iv, &(o->decrypt_ctx)); - } - break; - case CFB: - if (encrypt) { - aes_cfb_encrypt(buf.buf, (uint8_t *)vstr.buf, buf.len, o->iv, &(o->encrypt_ctx)); - } else { - aes_cfb_decrypt(buf.buf, (uint8_t *)vstr.buf, buf.len, o->iv, &(o->encrypt_ctx)); // decrypt uses encrypt_ctx - } - break; - case OFB: // (encrypt == decrypt) - aes_ofb_crypt(buf.buf, (uint8_t *)vstr.buf, buf.len, o->iv, &(o->encrypt_ctx)); - break; - case CTR: // (encrypt == decrypt) - aes_ctr_crypt(buf.buf, (uint8_t *)vstr.buf, buf.len, o->iv, aes_ctr_cbuf_inc, &(o->encrypt_ctx)); - break; - } - return mp_obj_new_str_from_vstr(&mp_type_bytes, &vstr); + mp_buffer_info_t buf; + mp_get_buffer_raise(data, &buf, MP_BUFFER_READ); + if (buf.len == 0) { + return mp_const_empty_bytes; + } + vstr_t vstr; + vstr_init_len(&vstr, buf.len); + mp_obj_AES_t *o = MP_OBJ_TO_PTR(self); + switch (o->mode) { + case ECB: + if (buf.len & (AES_BLOCK_SIZE - 1)) { + mp_raise_ValueError("Invalid data length"); + } + if (encrypt) { + aes_ecb_encrypt(buf.buf, (uint8_t *)vstr.buf, buf.len, + &(o->encrypt_ctx)); + } else { + aes_ecb_decrypt(buf.buf, (uint8_t *)vstr.buf, buf.len, + &(o->decrypt_ctx)); + } + break; + case CBC: + if (buf.len & (AES_BLOCK_SIZE - 1)) { + mp_raise_ValueError("Invalid data length"); + } + if (encrypt) { + aes_cbc_encrypt(buf.buf, (uint8_t *)vstr.buf, buf.len, o->iv, + &(o->encrypt_ctx)); + } else { + aes_cbc_decrypt(buf.buf, (uint8_t *)vstr.buf, buf.len, o->iv, + &(o->decrypt_ctx)); + } + break; + case CFB: + if (encrypt) { + aes_cfb_encrypt(buf.buf, (uint8_t *)vstr.buf, buf.len, o->iv, + &(o->encrypt_ctx)); + } else { + aes_cfb_decrypt(buf.buf, (uint8_t *)vstr.buf, buf.len, o->iv, + &(o->encrypt_ctx)); // decrypt uses encrypt_ctx + } + break; + case OFB: // (encrypt == decrypt) + aes_ofb_crypt(buf.buf, (uint8_t *)vstr.buf, buf.len, o->iv, + &(o->encrypt_ctx)); + break; + case CTR: // (encrypt == decrypt) + aes_ctr_crypt(buf.buf, (uint8_t *)vstr.buf, buf.len, o->iv, + aes_ctr_cbuf_inc, &(o->encrypt_ctx)); + break; + } + return mp_obj_new_str_from_vstr(&mp_type_bytes, &vstr); } /// def encrypt(self, data: bytes) -> bytes: @@ -140,43 +152,50 @@ static mp_obj_t aes_update(mp_obj_t self, mp_obj_t data, bool encrypt) { /// Encrypt data and update AES context. /// ''' STATIC mp_obj_t mod_trezorcrypto_AES_encrypt(mp_obj_t self, mp_obj_t data) { - return aes_update(self, data, true); + return aes_update(self, data, true); } -STATIC MP_DEFINE_CONST_FUN_OBJ_2(mod_trezorcrypto_AES_encrypt_obj, mod_trezorcrypto_AES_encrypt); +STATIC MP_DEFINE_CONST_FUN_OBJ_2(mod_trezorcrypto_AES_encrypt_obj, + mod_trezorcrypto_AES_encrypt); /// def decrypt(self, data: bytes) -> bytes: /// ''' /// Decrypt data and update AES context. /// ''' STATIC mp_obj_t mod_trezorcrypto_AES_decrypt(mp_obj_t self, mp_obj_t data) { - return aes_update(self, data, false); + return aes_update(self, data, false); } -STATIC MP_DEFINE_CONST_FUN_OBJ_2(mod_trezorcrypto_AES_decrypt_obj, mod_trezorcrypto_AES_decrypt); +STATIC MP_DEFINE_CONST_FUN_OBJ_2(mod_trezorcrypto_AES_decrypt_obj, + mod_trezorcrypto_AES_decrypt); STATIC mp_obj_t mod_trezorcrypto_AES___del__(mp_obj_t self) { - mp_obj_AES_t *o = MP_OBJ_TO_PTR(self); - memzero(&(o->encrypt_ctx), sizeof(aes_encrypt_ctx)); - memzero(&(o->decrypt_ctx), sizeof(aes_decrypt_ctx)); - memzero(o->iv, AES_BLOCK_SIZE); - return mp_const_none; + mp_obj_AES_t *o = MP_OBJ_TO_PTR(self); + memzero(&(o->encrypt_ctx), sizeof(aes_encrypt_ctx)); + memzero(&(o->decrypt_ctx), sizeof(aes_decrypt_ctx)); + memzero(o->iv, AES_BLOCK_SIZE); + return mp_const_none; } -STATIC MP_DEFINE_CONST_FUN_OBJ_1(mod_trezorcrypto_AES___del___obj, mod_trezorcrypto_AES___del__); +STATIC MP_DEFINE_CONST_FUN_OBJ_1(mod_trezorcrypto_AES___del___obj, + mod_trezorcrypto_AES___del__); STATIC const mp_rom_map_elem_t mod_trezorcrypto_AES_locals_dict_table[] = { - { MP_ROM_QSTR(MP_QSTR_encrypt), MP_ROM_PTR(&mod_trezorcrypto_AES_encrypt_obj) }, - { MP_ROM_QSTR(MP_QSTR_decrypt), MP_ROM_PTR(&mod_trezorcrypto_AES_decrypt_obj) }, - { MP_ROM_QSTR(MP_QSTR___del__), MP_ROM_PTR(&mod_trezorcrypto_AES___del___obj) }, - { MP_ROM_QSTR(MP_QSTR_ECB), MP_OBJ_NEW_SMALL_INT(ECB) }, - { MP_ROM_QSTR(MP_QSTR_CBC), MP_OBJ_NEW_SMALL_INT(CBC) }, - { MP_ROM_QSTR(MP_QSTR_CFB), MP_OBJ_NEW_SMALL_INT(CFB) }, - { MP_ROM_QSTR(MP_QSTR_OFB), MP_OBJ_NEW_SMALL_INT(OFB) }, - { MP_ROM_QSTR(MP_QSTR_CTR), MP_OBJ_NEW_SMALL_INT(CTR) }, + {MP_ROM_QSTR(MP_QSTR_encrypt), + MP_ROM_PTR(&mod_trezorcrypto_AES_encrypt_obj)}, + {MP_ROM_QSTR(MP_QSTR_decrypt), + MP_ROM_PTR(&mod_trezorcrypto_AES_decrypt_obj)}, + {MP_ROM_QSTR(MP_QSTR___del__), + MP_ROM_PTR(&mod_trezorcrypto_AES___del___obj)}, + {MP_ROM_QSTR(MP_QSTR_ECB), MP_OBJ_NEW_SMALL_INT(ECB)}, + {MP_ROM_QSTR(MP_QSTR_CBC), MP_OBJ_NEW_SMALL_INT(CBC)}, + {MP_ROM_QSTR(MP_QSTR_CFB), MP_OBJ_NEW_SMALL_INT(CFB)}, + {MP_ROM_QSTR(MP_QSTR_OFB), MP_OBJ_NEW_SMALL_INT(OFB)}, + {MP_ROM_QSTR(MP_QSTR_CTR), MP_OBJ_NEW_SMALL_INT(CTR)}, }; -STATIC MP_DEFINE_CONST_DICT(mod_trezorcrypto_AES_locals_dict, mod_trezorcrypto_AES_locals_dict_table); +STATIC MP_DEFINE_CONST_DICT(mod_trezorcrypto_AES_locals_dict, + mod_trezorcrypto_AES_locals_dict_table); STATIC const mp_obj_type_t mod_trezorcrypto_AES_type = { - { &mp_type_type }, + {&mp_type_type}, .name = MP_QSTR_AES, .make_new = mod_trezorcrypto_AES_make_new, - .locals_dict = (void*)&mod_trezorcrypto_AES_locals_dict, + .locals_dict = (void *)&mod_trezorcrypto_AES_locals_dict, }; diff --git a/embed/extmod/modtrezorcrypto/modtrezorcrypto-bip32.h b/embed/extmod/modtrezorcrypto/modtrezorcrypto-bip32.h index 306f60ea6..bdf30ee5a 100644 --- a/embed/extmod/modtrezorcrypto/modtrezorcrypto-bip32.h +++ b/embed/extmod/modtrezorcrypto/modtrezorcrypto-bip32.h @@ -34,9 +34,9 @@ /// BIP0032 HD node structure. /// ''' typedef struct _mp_obj_HDNode_t { - mp_obj_base_t base; - uint32_t fingerprint; - HDNode hdnode; + mp_obj_base_t base; + uint32_t fingerprint; + HDNode hdnode; } mp_obj_HDNode_t; STATIC const mp_obj_type_t mod_trezorcrypto_HDNode_type; @@ -54,512 +54,612 @@ STATIC const mp_obj_type_t mod_trezorcrypto_HDNode_type; /// curve_name: str = None) -> None: /// ''' /// ''' -STATIC mp_obj_t mod_trezorcrypto_HDNode_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_kw, const mp_obj_t *args) { - - STATIC const mp_arg_t allowed_args[] = { - { MP_QSTR_depth, MP_ARG_REQUIRED | MP_ARG_KW_ONLY | MP_ARG_OBJ, {.u_obj = mp_const_none} }, - { MP_QSTR_fingerprint, MP_ARG_REQUIRED | MP_ARG_KW_ONLY | MP_ARG_OBJ, {.u_obj = mp_const_none} }, - { MP_QSTR_child_num, MP_ARG_REQUIRED | MP_ARG_KW_ONLY | MP_ARG_OBJ, {.u_obj = mp_const_none} }, - { MP_QSTR_chain_code, MP_ARG_REQUIRED | MP_ARG_KW_ONLY | MP_ARG_OBJ, {.u_obj = mp_const_empty_bytes} }, - { MP_QSTR_private_key, MP_ARG_KW_ONLY | MP_ARG_OBJ, {.u_obj = mp_const_empty_bytes} }, - { MP_QSTR_public_key, MP_ARG_KW_ONLY | MP_ARG_OBJ, {.u_obj = mp_const_empty_bytes} }, - { MP_QSTR_curve_name, MP_ARG_KW_ONLY | MP_ARG_OBJ, {.u_obj = mp_const_empty_bytes} }, - }; - mp_arg_val_t vals[MP_ARRAY_SIZE(allowed_args)]; - mp_arg_parse_all_kw_array(n_args, n_kw, args, MP_ARRAY_SIZE(allowed_args), allowed_args, vals); - - mp_buffer_info_t chain_code; - mp_buffer_info_t private_key; - mp_buffer_info_t public_key; - mp_buffer_info_t curve_name; - const uint32_t depth = trezor_obj_get_uint(vals[0].u_obj); - const uint32_t fingerprint = trezor_obj_get_uint(vals[1].u_obj); - const uint32_t child_num = trezor_obj_get_uint(vals[2].u_obj); - mp_get_buffer_raise(vals[3].u_obj, &chain_code, MP_BUFFER_READ); - mp_get_buffer_raise(vals[4].u_obj, &private_key, MP_BUFFER_READ); - mp_get_buffer_raise(vals[5].u_obj, &public_key, MP_BUFFER_READ); - mp_get_buffer_raise(vals[6].u_obj, &curve_name, MP_BUFFER_READ); - - if (32 != chain_code.len) { - mp_raise_ValueError("chain_code is invalid"); - } - if (0 == public_key.len && 0 == private_key.len) { - mp_raise_ValueError("either public_key or private_key is required"); - } - if (0 != private_key.len && 32 != private_key.len) { - mp_raise_ValueError("private_key is invalid"); - } - if (0 != public_key.len && 33 != public_key.len) { - mp_raise_ValueError("public_key is invalid"); - } - - const curve_info *curve = NULL; - if (0 == curve_name.len) { - curve = get_curve_by_name(SECP256K1_NAME); - } else { - curve = get_curve_by_name(curve_name.buf); - } - if (NULL == curve) { - mp_raise_ValueError("curve_name is invalid"); - } - - mp_obj_HDNode_t *o = m_new_obj(mp_obj_HDNode_t); - o->base.type = type; - o->fingerprint = fingerprint; - o->hdnode.depth = depth; - o->hdnode.child_num = child_num; - if (32 == chain_code.len) { - memcpy(o->hdnode.chain_code, chain_code.buf, 32); - } else { - memzero(o->hdnode.chain_code, 32); - } - if (32 == private_key.len) { - memcpy(o->hdnode.private_key, private_key.buf, 32); - } else { - memzero(o->hdnode.private_key, 32); - } - if (33 == public_key.len) { - memcpy(o->hdnode.public_key, public_key.buf, 33); - } else { - memzero(o->hdnode.public_key, 33); - } - o->hdnode.curve = curve; - - return MP_OBJ_FROM_PTR(o); +STATIC mp_obj_t mod_trezorcrypto_HDNode_make_new(const mp_obj_type_t *type, + size_t n_args, size_t n_kw, + const mp_obj_t *args) { + STATIC const mp_arg_t allowed_args[] = { + {MP_QSTR_depth, + MP_ARG_REQUIRED | MP_ARG_KW_ONLY | MP_ARG_OBJ, + {.u_obj = mp_const_none}}, + {MP_QSTR_fingerprint, + MP_ARG_REQUIRED | MP_ARG_KW_ONLY | MP_ARG_OBJ, + {.u_obj = mp_const_none}}, + {MP_QSTR_child_num, + MP_ARG_REQUIRED | MP_ARG_KW_ONLY | MP_ARG_OBJ, + {.u_obj = mp_const_none}}, + {MP_QSTR_chain_code, + MP_ARG_REQUIRED | MP_ARG_KW_ONLY | MP_ARG_OBJ, + {.u_obj = mp_const_empty_bytes}}, + {MP_QSTR_private_key, + MP_ARG_KW_ONLY | MP_ARG_OBJ, + {.u_obj = mp_const_empty_bytes}}, + {MP_QSTR_public_key, + MP_ARG_KW_ONLY | MP_ARG_OBJ, + {.u_obj = mp_const_empty_bytes}}, + {MP_QSTR_curve_name, + MP_ARG_KW_ONLY | MP_ARG_OBJ, + {.u_obj = mp_const_empty_bytes}}, + }; + mp_arg_val_t vals[MP_ARRAY_SIZE(allowed_args)]; + mp_arg_parse_all_kw_array(n_args, n_kw, args, MP_ARRAY_SIZE(allowed_args), + allowed_args, vals); + + mp_buffer_info_t chain_code; + mp_buffer_info_t private_key; + mp_buffer_info_t public_key; + mp_buffer_info_t curve_name; + const uint32_t depth = trezor_obj_get_uint(vals[0].u_obj); + const uint32_t fingerprint = trezor_obj_get_uint(vals[1].u_obj); + const uint32_t child_num = trezor_obj_get_uint(vals[2].u_obj); + mp_get_buffer_raise(vals[3].u_obj, &chain_code, MP_BUFFER_READ); + mp_get_buffer_raise(vals[4].u_obj, &private_key, MP_BUFFER_READ); + mp_get_buffer_raise(vals[5].u_obj, &public_key, MP_BUFFER_READ); + mp_get_buffer_raise(vals[6].u_obj, &curve_name, MP_BUFFER_READ); + + if (32 != chain_code.len) { + mp_raise_ValueError("chain_code is invalid"); + } + if (0 == public_key.len && 0 == private_key.len) { + mp_raise_ValueError("either public_key or private_key is required"); + } + if (0 != private_key.len && 32 != private_key.len) { + mp_raise_ValueError("private_key is invalid"); + } + if (0 != public_key.len && 33 != public_key.len) { + mp_raise_ValueError("public_key is invalid"); + } + + const curve_info *curve = NULL; + if (0 == curve_name.len) { + curve = get_curve_by_name(SECP256K1_NAME); + } else { + curve = get_curve_by_name(curve_name.buf); + } + if (NULL == curve) { + mp_raise_ValueError("curve_name is invalid"); + } + + mp_obj_HDNode_t *o = m_new_obj(mp_obj_HDNode_t); + o->base.type = type; + o->fingerprint = fingerprint; + o->hdnode.depth = depth; + o->hdnode.child_num = child_num; + if (32 == chain_code.len) { + memcpy(o->hdnode.chain_code, chain_code.buf, 32); + } else { + memzero(o->hdnode.chain_code, 32); + } + if (32 == private_key.len) { + memcpy(o->hdnode.private_key, private_key.buf, 32); + } else { + memzero(o->hdnode.private_key, 32); + } + if (33 == public_key.len) { + memcpy(o->hdnode.public_key, public_key.buf, 33); + } else { + memzero(o->hdnode.public_key, 33); + } + o->hdnode.curve = curve; + + return MP_OBJ_FROM_PTR(o); } /// def derive(self, index: int, public: bool=False) -> None: /// ''' /// Derive a BIP0032 child node in place. /// ''' -STATIC mp_obj_t mod_trezorcrypto_HDNode_derive(size_t n_args, const mp_obj_t *args) { - mp_obj_HDNode_t *o = MP_OBJ_TO_PTR(args[0]); - uint32_t i = trezor_obj_get_uint(args[1]); - uint32_t fp = hdnode_fingerprint(&o->hdnode); - bool public = n_args > 2 && args[2] == mp_const_true; - - int res; - if (public) { - res = hdnode_public_ckd(&o->hdnode, i); - } else { - if (0 == memcmp(o->hdnode.private_key, "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00", 32)) { - memzero(&o->hdnode, sizeof(o->hdnode)); - mp_raise_ValueError("Failed to derive, private key not set"); - } - res = hdnode_private_ckd(&o->hdnode, i); +STATIC mp_obj_t mod_trezorcrypto_HDNode_derive(size_t n_args, + const mp_obj_t *args) { + mp_obj_HDNode_t *o = MP_OBJ_TO_PTR(args[0]); + uint32_t i = trezor_obj_get_uint(args[1]); + uint32_t fp = hdnode_fingerprint(&o->hdnode); + bool public = n_args > 2 && args[2] == mp_const_true; + + int res; + if (public) { + res = hdnode_public_ckd(&o->hdnode, i); + } else { + if (0 == + memcmp( + o->hdnode.private_key, + "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00", + 32)) { + memzero(&o->hdnode, sizeof(o->hdnode)); + mp_raise_ValueError("Failed to derive, private key not set"); } - if (!res) { - memzero(&o->hdnode, sizeof(o->hdnode)); - mp_raise_ValueError("Failed to derive"); - } - o->fingerprint = fp; + res = hdnode_private_ckd(&o->hdnode, i); + } + if (!res) { + memzero(&o->hdnode, sizeof(o->hdnode)); + mp_raise_ValueError("Failed to derive"); + } + o->fingerprint = fp; - return mp_const_none; + return mp_const_none; } -STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(mod_trezorcrypto_HDNode_derive_obj, 2, 3, mod_trezorcrypto_HDNode_derive); +STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(mod_trezorcrypto_HDNode_derive_obj, + 2, 3, + mod_trezorcrypto_HDNode_derive); /// def derive_cardano(self, index: int) -> None: /// ''' /// Derive a BIP0032 child node in place using Cardano algorithm. /// ''' -STATIC mp_obj_t mod_trezorcrypto_HDNode_derive_cardano(mp_obj_t self, mp_obj_t index) { - mp_obj_HDNode_t *o = MP_OBJ_TO_PTR(self); - uint32_t i = mp_obj_get_int_truncated(index); - uint32_t fp = hdnode_fingerprint(&o->hdnode); - - int res; - // same as in derive - if (0 == memcmp(o->hdnode.private_key, "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00", 32)) { - memzero(&o->hdnode, sizeof(o->hdnode)); - mp_raise_ValueError("Failed to derive, private key not set"); - } - // special for cardano - res = hdnode_private_ckd_cardano(&o->hdnode, i); - if (!res) { - memzero(&o->hdnode, sizeof(o->hdnode)); - mp_raise_ValueError("Failed to derive"); - } - o->fingerprint = fp; +STATIC mp_obj_t mod_trezorcrypto_HDNode_derive_cardano(mp_obj_t self, + mp_obj_t index) { + mp_obj_HDNode_t *o = MP_OBJ_TO_PTR(self); + uint32_t i = mp_obj_get_int_truncated(index); + uint32_t fp = hdnode_fingerprint(&o->hdnode); + + int res; + // same as in derive + if (0 == + memcmp(o->hdnode.private_key, + "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00", + 32)) { + memzero(&o->hdnode, sizeof(o->hdnode)); + mp_raise_ValueError("Failed to derive, private key not set"); + } + // special for cardano + res = hdnode_private_ckd_cardano(&o->hdnode, i); + if (!res) { + memzero(&o->hdnode, sizeof(o->hdnode)); + mp_raise_ValueError("Failed to derive"); + } + o->fingerprint = fp; - return mp_const_none; + return mp_const_none; } -STATIC MP_DEFINE_CONST_FUN_OBJ_2(mod_trezorcrypto_HDNode_derive_cardano_obj, mod_trezorcrypto_HDNode_derive_cardano); +STATIC MP_DEFINE_CONST_FUN_OBJ_2(mod_trezorcrypto_HDNode_derive_cardano_obj, + mod_trezorcrypto_HDNode_derive_cardano); /// def derive_path(self, path: List[int]) -> None: /// ''' -/// Go through a list of indexes and iteratively derive a child node in place. -/// ''' -STATIC mp_obj_t mod_trezorcrypto_HDNode_derive_path(mp_obj_t self, mp_obj_t path) { - mp_obj_HDNode_t *o = MP_OBJ_TO_PTR(self); - - // get path objects and length - size_t plen; - mp_obj_t *pitems; - mp_obj_get_array(path, &plen, &pitems); - if (plen > 32) { - mp_raise_ValueError("Path cannot be longer than 32 indexes"); - } - - // convert path to int array - uint32_t pi; - uint32_t pints[plen]; - for (pi = 0; pi < plen; pi++) { - pints[pi] = trezor_obj_get_uint(pitems[pi]); - } - - if (!hdnode_private_ckd_cached(&o->hdnode, pints, plen, &o->fingerprint)) { - // derivation failed, reset the state and raise - o->fingerprint = 0; - memzero(&o->hdnode, sizeof(o->hdnode)); - mp_raise_ValueError("Failed to derive path"); - } +/// Go through a list of indexes and iteratively derive a child node in +/// place. +/// ''' +STATIC mp_obj_t mod_trezorcrypto_HDNode_derive_path(mp_obj_t self, + mp_obj_t path) { + mp_obj_HDNode_t *o = MP_OBJ_TO_PTR(self); + + // get path objects and length + size_t plen; + mp_obj_t *pitems; + mp_obj_get_array(path, &plen, &pitems); + if (plen > 32) { + mp_raise_ValueError("Path cannot be longer than 32 indexes"); + } + + // convert path to int array + uint32_t pi; + uint32_t pints[plen]; + for (pi = 0; pi < plen; pi++) { + pints[pi] = trezor_obj_get_uint(pitems[pi]); + } + + if (!hdnode_private_ckd_cached(&o->hdnode, pints, plen, &o->fingerprint)) { + // derivation failed, reset the state and raise + o->fingerprint = 0; + memzero(&o->hdnode, sizeof(o->hdnode)); + mp_raise_ValueError("Failed to derive path"); + } - return mp_const_none; + return mp_const_none; } -STATIC MP_DEFINE_CONST_FUN_OBJ_2(mod_trezorcrypto_HDNode_derive_path_obj, mod_trezorcrypto_HDNode_derive_path); - -STATIC mp_obj_t serialize_public_private(mp_obj_t self, bool use_public, uint32_t version) { - mp_obj_HDNode_t *o = MP_OBJ_TO_PTR(self); - char xpub[XPUB_MAXLEN] = {0}; - int written; - if (use_public) { - hdnode_fill_public_key(&o->hdnode); - written = hdnode_serialize_public(&o->hdnode, o->fingerprint, version, xpub, XPUB_MAXLEN); - } else { - written = hdnode_serialize_private(&o->hdnode, o->fingerprint, version, xpub, XPUB_MAXLEN); - } - if (written <= 0) { - mp_raise_ValueError("Failed to serialize"); - } - return mp_obj_new_str_copy(&mp_type_str, (const uint8_t *)xpub, written - 1); // written includes 0 at the end +STATIC MP_DEFINE_CONST_FUN_OBJ_2(mod_trezorcrypto_HDNode_derive_path_obj, + mod_trezorcrypto_HDNode_derive_path); + +STATIC mp_obj_t serialize_public_private(mp_obj_t self, bool use_public, + uint32_t version) { + mp_obj_HDNode_t *o = MP_OBJ_TO_PTR(self); + char xpub[XPUB_MAXLEN] = {0}; + int written; + if (use_public) { + hdnode_fill_public_key(&o->hdnode); + written = hdnode_serialize_public(&o->hdnode, o->fingerprint, version, xpub, + XPUB_MAXLEN); + } else { + written = hdnode_serialize_private(&o->hdnode, o->fingerprint, version, + xpub, XPUB_MAXLEN); + } + if (written <= 0) { + mp_raise_ValueError("Failed to serialize"); + } + return mp_obj_new_str_copy(&mp_type_str, (const uint8_t *)xpub, + written - 1); // written includes 0 at the end } /// def serialize_public(self, version: int) -> str: /// ''' /// Serialize the public info from HD node to base58 string. /// ''' -STATIC mp_obj_t mod_trezorcrypto_HDNode_serialize_public(mp_obj_t self, mp_obj_t version) { - uint32_t ver = trezor_obj_get_uint(version); - return serialize_public_private(self, true, ver); +STATIC mp_obj_t mod_trezorcrypto_HDNode_serialize_public(mp_obj_t self, + mp_obj_t version) { + uint32_t ver = trezor_obj_get_uint(version); + return serialize_public_private(self, true, ver); } -STATIC MP_DEFINE_CONST_FUN_OBJ_2(mod_trezorcrypto_HDNode_serialize_public_obj, mod_trezorcrypto_HDNode_serialize_public); +STATIC MP_DEFINE_CONST_FUN_OBJ_2(mod_trezorcrypto_HDNode_serialize_public_obj, + mod_trezorcrypto_HDNode_serialize_public); /// def serialize_private(self, version: int) -> str: /// ''' /// Serialize the private info HD node to base58 string. /// ''' -STATIC mp_obj_t mod_trezorcrypto_HDNode_serialize_private(mp_obj_t self, mp_obj_t version) { - uint32_t ver = trezor_obj_get_uint(version); - return serialize_public_private(self, false, ver); +STATIC mp_obj_t mod_trezorcrypto_HDNode_serialize_private(mp_obj_t self, + mp_obj_t version) { + uint32_t ver = trezor_obj_get_uint(version); + return serialize_public_private(self, false, ver); } -STATIC MP_DEFINE_CONST_FUN_OBJ_2(mod_trezorcrypto_HDNode_serialize_private_obj, mod_trezorcrypto_HDNode_serialize_private); +STATIC MP_DEFINE_CONST_FUN_OBJ_2(mod_trezorcrypto_HDNode_serialize_private_obj, + mod_trezorcrypto_HDNode_serialize_private); /// def clone(self) -> HDNode: /// ''' /// Returns a copy of the HD node. /// ''' STATIC mp_obj_t mod_trezorcrypto_HDNode_clone(mp_obj_t self) { - mp_obj_HDNode_t *o = MP_OBJ_TO_PTR(self); - mp_obj_HDNode_t *copy = m_new_obj(mp_obj_HDNode_t); - copy->base.type = &mod_trezorcrypto_HDNode_type; - copy->hdnode = o->hdnode; - copy->fingerprint = o->fingerprint; - return MP_OBJ_FROM_PTR(copy); + mp_obj_HDNode_t *o = MP_OBJ_TO_PTR(self); + mp_obj_HDNode_t *copy = m_new_obj(mp_obj_HDNode_t); + copy->base.type = &mod_trezorcrypto_HDNode_type; + copy->hdnode = o->hdnode; + copy->fingerprint = o->fingerprint; + return MP_OBJ_FROM_PTR(copy); } -STATIC MP_DEFINE_CONST_FUN_OBJ_1(mod_trezorcrypto_HDNode_clone_obj, mod_trezorcrypto_HDNode_clone); +STATIC MP_DEFINE_CONST_FUN_OBJ_1(mod_trezorcrypto_HDNode_clone_obj, + mod_trezorcrypto_HDNode_clone); /// def depth(self) -> int: /// ''' /// Returns a depth of the HD node. /// ''' STATIC mp_obj_t mod_trezorcrypto_HDNode_depth(mp_obj_t self) { - mp_obj_HDNode_t *o = MP_OBJ_TO_PTR(self); - return mp_obj_new_int_from_uint(o->hdnode.depth); + mp_obj_HDNode_t *o = MP_OBJ_TO_PTR(self); + return mp_obj_new_int_from_uint(o->hdnode.depth); } -STATIC MP_DEFINE_CONST_FUN_OBJ_1(mod_trezorcrypto_HDNode_depth_obj, mod_trezorcrypto_HDNode_depth); +STATIC MP_DEFINE_CONST_FUN_OBJ_1(mod_trezorcrypto_HDNode_depth_obj, + mod_trezorcrypto_HDNode_depth); /// def fingerprint(self) -> int: /// ''' /// Returns a fingerprint of the HD node (hash of the parent public key). /// ''' STATIC mp_obj_t mod_trezorcrypto_HDNode_fingerprint(mp_obj_t self) { - mp_obj_HDNode_t *o = MP_OBJ_TO_PTR(self); - return mp_obj_new_int_from_uint(o->fingerprint); + mp_obj_HDNode_t *o = MP_OBJ_TO_PTR(self); + return mp_obj_new_int_from_uint(o->fingerprint); } -STATIC MP_DEFINE_CONST_FUN_OBJ_1(mod_trezorcrypto_HDNode_fingerprint_obj, mod_trezorcrypto_HDNode_fingerprint); +STATIC MP_DEFINE_CONST_FUN_OBJ_1(mod_trezorcrypto_HDNode_fingerprint_obj, + mod_trezorcrypto_HDNode_fingerprint); /// def child_num(self) -> int: /// ''' /// Returns a child index of the HD node. /// ''' STATIC mp_obj_t mod_trezorcrypto_HDNode_child_num(mp_obj_t self) { - mp_obj_HDNode_t *o = MP_OBJ_TO_PTR(self); - return mp_obj_new_int_from_uint(o->hdnode.child_num); + mp_obj_HDNode_t *o = MP_OBJ_TO_PTR(self); + return mp_obj_new_int_from_uint(o->hdnode.child_num); } -STATIC MP_DEFINE_CONST_FUN_OBJ_1(mod_trezorcrypto_HDNode_child_num_obj, mod_trezorcrypto_HDNode_child_num); +STATIC MP_DEFINE_CONST_FUN_OBJ_1(mod_trezorcrypto_HDNode_child_num_obj, + mod_trezorcrypto_HDNode_child_num); /// def chain_code(self) -> bytes: /// ''' /// Returns a chain code of the HD node. /// ''' STATIC mp_obj_t mod_trezorcrypto_HDNode_chain_code(mp_obj_t self) { - mp_obj_HDNode_t *o = MP_OBJ_TO_PTR(self); - return mp_obj_new_bytes(o->hdnode.chain_code, sizeof(o->hdnode.chain_code)); + mp_obj_HDNode_t *o = MP_OBJ_TO_PTR(self); + return mp_obj_new_bytes(o->hdnode.chain_code, sizeof(o->hdnode.chain_code)); } -STATIC MP_DEFINE_CONST_FUN_OBJ_1(mod_trezorcrypto_HDNode_chain_code_obj, mod_trezorcrypto_HDNode_chain_code); +STATIC MP_DEFINE_CONST_FUN_OBJ_1(mod_trezorcrypto_HDNode_chain_code_obj, + mod_trezorcrypto_HDNode_chain_code); /// def private_key(self) -> bytes: /// ''' /// Returns a private key of the HD node. /// ''' STATIC mp_obj_t mod_trezorcrypto_HDNode_private_key(mp_obj_t self) { - mp_obj_HDNode_t *o = MP_OBJ_TO_PTR(self); - return mp_obj_new_bytes(o->hdnode.private_key, sizeof(o->hdnode.private_key)); + mp_obj_HDNode_t *o = MP_OBJ_TO_PTR(self); + return mp_obj_new_bytes(o->hdnode.private_key, sizeof(o->hdnode.private_key)); } -STATIC MP_DEFINE_CONST_FUN_OBJ_1(mod_trezorcrypto_HDNode_private_key_obj, mod_trezorcrypto_HDNode_private_key); +STATIC MP_DEFINE_CONST_FUN_OBJ_1(mod_trezorcrypto_HDNode_private_key_obj, + mod_trezorcrypto_HDNode_private_key); /// def private_key_ext(self) -> bytes: /// ''' /// Returns a private key extension of the HD node. /// ''' STATIC mp_obj_t mod_trezorcrypto_HDNode_private_key_ext(mp_obj_t self) { - mp_obj_HDNode_t *o = MP_OBJ_TO_PTR(self); - return mp_obj_new_bytes(o->hdnode.private_key_extension, sizeof(o->hdnode.private_key_extension)); + mp_obj_HDNode_t *o = MP_OBJ_TO_PTR(self); + return mp_obj_new_bytes(o->hdnode.private_key_extension, + sizeof(o->hdnode.private_key_extension)); } -STATIC MP_DEFINE_CONST_FUN_OBJ_1(mod_trezorcrypto_HDNode_private_key_ext_obj, mod_trezorcrypto_HDNode_private_key_ext); +STATIC MP_DEFINE_CONST_FUN_OBJ_1(mod_trezorcrypto_HDNode_private_key_ext_obj, + mod_trezorcrypto_HDNode_private_key_ext); /// def public_key(self) -> bytes: /// ''' /// Returns a public key of the HD node. /// ''' STATIC mp_obj_t mod_trezorcrypto_HDNode_public_key(mp_obj_t self) { - mp_obj_HDNode_t *o = MP_OBJ_TO_PTR(self); - hdnode_fill_public_key(&o->hdnode); - return mp_obj_new_bytes(o->hdnode.public_key, sizeof(o->hdnode.public_key)); + mp_obj_HDNode_t *o = MP_OBJ_TO_PTR(self); + hdnode_fill_public_key(&o->hdnode); + return mp_obj_new_bytes(o->hdnode.public_key, sizeof(o->hdnode.public_key)); } -STATIC MP_DEFINE_CONST_FUN_OBJ_1(mod_trezorcrypto_HDNode_public_key_obj, mod_trezorcrypto_HDNode_public_key); +STATIC MP_DEFINE_CONST_FUN_OBJ_1(mod_trezorcrypto_HDNode_public_key_obj, + mod_trezorcrypto_HDNode_public_key); /// def address(self, version: int) -> str: /// ''' /// Compute a base58-encoded address string from the HD node. /// ''' -STATIC mp_obj_t mod_trezorcrypto_HDNode_address(mp_obj_t self, mp_obj_t version) { - mp_obj_HDNode_t *o = MP_OBJ_TO_PTR(self); +STATIC mp_obj_t mod_trezorcrypto_HDNode_address(mp_obj_t self, + mp_obj_t version) { + mp_obj_HDNode_t *o = MP_OBJ_TO_PTR(self); - uint32_t v = trezor_obj_get_uint(version); + uint32_t v = trezor_obj_get_uint(version); - char address[ADDRESS_MAXLEN] = {0}; - hdnode_get_address(&o->hdnode, v, address, ADDRESS_MAXLEN); - return mp_obj_new_str_copy(&mp_type_str, (const uint8_t *)address, strlen(address)); + char address[ADDRESS_MAXLEN] = {0}; + hdnode_get_address(&o->hdnode, v, address, ADDRESS_MAXLEN); + return mp_obj_new_str_copy(&mp_type_str, (const uint8_t *)address, + strlen(address)); } -STATIC MP_DEFINE_CONST_FUN_OBJ_2(mod_trezorcrypto_HDNode_address_obj, mod_trezorcrypto_HDNode_address); +STATIC MP_DEFINE_CONST_FUN_OBJ_2(mod_trezorcrypto_HDNode_address_obj, + mod_trezorcrypto_HDNode_address); /// def nem_address(self, network: int) -> str: /// ''' /// Compute a NEM address string from the HD node. /// ''' -STATIC mp_obj_t mod_trezorcrypto_HDNode_nem_address(mp_obj_t self, mp_obj_t network) { - mp_obj_HDNode_t *o = MP_OBJ_TO_PTR(self); +STATIC mp_obj_t mod_trezorcrypto_HDNode_nem_address(mp_obj_t self, + mp_obj_t network) { + mp_obj_HDNode_t *o = MP_OBJ_TO_PTR(self); - uint8_t n = trezor_obj_get_uint8(network); + uint8_t n = trezor_obj_get_uint8(network); - char address[NEM_ADDRESS_SIZE + 1] = {0}; // + 1 for the 0 byte - if (!hdnode_get_nem_address(&o->hdnode, n, address)) { - mp_raise_ValueError("Failed to compute a NEM address"); - } - return mp_obj_new_str_copy(&mp_type_str, (const uint8_t *)address, strlen(address)); + char address[NEM_ADDRESS_SIZE + 1] = {0}; // + 1 for the 0 byte + if (!hdnode_get_nem_address(&o->hdnode, n, address)) { + mp_raise_ValueError("Failed to compute a NEM address"); + } + return mp_obj_new_str_copy(&mp_type_str, (const uint8_t *)address, + strlen(address)); } -STATIC MP_DEFINE_CONST_FUN_OBJ_2(mod_trezorcrypto_HDNode_nem_address_obj, mod_trezorcrypto_HDNode_nem_address); +STATIC MP_DEFINE_CONST_FUN_OBJ_2(mod_trezorcrypto_HDNode_nem_address_obj, + mod_trezorcrypto_HDNode_nem_address); -/// def nem_encrypt(self, transfer_public_key: bytes, iv: bytes, salt: bytes, payload: bytes) -> bytes: +/// def nem_encrypt(self, transfer_public_key: bytes, iv: bytes, salt: bytes, +/// payload: bytes) -> bytes: /// ''' /// Encrypts payload using the transfer's public key /// ''' -STATIC mp_obj_t mod_trezorcrypto_HDNode_nem_encrypt(size_t n_args, const mp_obj_t *args) { - mp_obj_HDNode_t *o = MP_OBJ_TO_PTR(args[0]); - - mp_buffer_info_t transfer_pk; - mp_get_buffer_raise(args[1], &transfer_pk, MP_BUFFER_READ); - if (transfer_pk.len != 32) { - mp_raise_ValueError("transfer_public_key has invalid length"); - } - - mp_buffer_info_t iv; - mp_get_buffer_raise(args[2], &iv, MP_BUFFER_READ); - if (iv.len != 16) { - mp_raise_ValueError("iv has invalid length"); - } - mp_buffer_info_t salt; - mp_get_buffer_raise(args[3], &salt, MP_BUFFER_READ); - if (salt.len != NEM_SALT_SIZE) { - mp_raise_ValueError("salt has invalid length"); - } - mp_buffer_info_t payload; - mp_get_buffer_raise(args[4], &payload, MP_BUFFER_READ); - if (payload.len == 0) { - mp_raise_ValueError("payload is empty"); - } - - vstr_t vstr; - vstr_init_len(&vstr, NEM_ENCRYPTED_SIZE(payload.len)); - if (!hdnode_nem_encrypt(&o->hdnode, *(const ed25519_public_key *)transfer_pk.buf, iv.buf, salt.buf, payload.buf, payload.len, (uint8_t *)vstr.buf)) { - mp_raise_ValueError("HDNode nem encrypt failed"); - } - return mp_obj_new_str_from_vstr(&mp_type_bytes, &vstr); +STATIC mp_obj_t mod_trezorcrypto_HDNode_nem_encrypt(size_t n_args, + const mp_obj_t *args) { + mp_obj_HDNode_t *o = MP_OBJ_TO_PTR(args[0]); + + mp_buffer_info_t transfer_pk; + mp_get_buffer_raise(args[1], &transfer_pk, MP_BUFFER_READ); + if (transfer_pk.len != 32) { + mp_raise_ValueError("transfer_public_key has invalid length"); + } + + mp_buffer_info_t iv; + mp_get_buffer_raise(args[2], &iv, MP_BUFFER_READ); + if (iv.len != 16) { + mp_raise_ValueError("iv has invalid length"); + } + mp_buffer_info_t salt; + mp_get_buffer_raise(args[3], &salt, MP_BUFFER_READ); + if (salt.len != NEM_SALT_SIZE) { + mp_raise_ValueError("salt has invalid length"); + } + mp_buffer_info_t payload; + mp_get_buffer_raise(args[4], &payload, MP_BUFFER_READ); + if (payload.len == 0) { + mp_raise_ValueError("payload is empty"); + } + + vstr_t vstr; + vstr_init_len(&vstr, NEM_ENCRYPTED_SIZE(payload.len)); + if (!hdnode_nem_encrypt( + &o->hdnode, *(const ed25519_public_key *)transfer_pk.buf, iv.buf, + salt.buf, payload.buf, payload.len, (uint8_t *)vstr.buf)) { + mp_raise_ValueError("HDNode nem encrypt failed"); + } + return mp_obj_new_str_from_vstr(&mp_type_bytes, &vstr); } -STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(mod_trezorcrypto_HDNode_nem_encrypt_obj, 5, 5, mod_trezorcrypto_HDNode_nem_encrypt); +STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN( + mod_trezorcrypto_HDNode_nem_encrypt_obj, 5, 5, + mod_trezorcrypto_HDNode_nem_encrypt); /// def ethereum_pubkeyhash(self) -> bytes: /// ''' /// Compute an Ethereum pubkeyhash (aka address) from the HD node. /// ''' STATIC mp_obj_t mod_trezorcrypto_HDNode_ethereum_pubkeyhash(mp_obj_t self) { - mp_obj_HDNode_t *o = MP_OBJ_TO_PTR(self); + mp_obj_HDNode_t *o = MP_OBJ_TO_PTR(self); - uint8_t pkh[20]; - hdnode_get_ethereum_pubkeyhash(&o->hdnode, pkh); - return mp_obj_new_bytes(pkh, sizeof(pkh)); + uint8_t pkh[20]; + hdnode_get_ethereum_pubkeyhash(&o->hdnode, pkh); + return mp_obj_new_bytes(pkh, sizeof(pkh)); } -STATIC MP_DEFINE_CONST_FUN_OBJ_1(mod_trezorcrypto_HDNode_ethereum_pubkeyhash_obj, mod_trezorcrypto_HDNode_ethereum_pubkeyhash); +STATIC MP_DEFINE_CONST_FUN_OBJ_1( + mod_trezorcrypto_HDNode_ethereum_pubkeyhash_obj, + mod_trezorcrypto_HDNode_ethereum_pubkeyhash); STATIC mp_obj_t mod_trezorcrypto_HDNode___del__(mp_obj_t self) { - mp_obj_HDNode_t *o = MP_OBJ_TO_PTR(self); - o->fingerprint = 0; - memzero(&o->hdnode, sizeof(o->hdnode)); - return mp_const_none; + mp_obj_HDNode_t *o = MP_OBJ_TO_PTR(self); + o->fingerprint = 0; + memzero(&o->hdnode, sizeof(o->hdnode)); + return mp_const_none; } -STATIC MP_DEFINE_CONST_FUN_OBJ_1(mod_trezorcrypto_HDNode___del___obj, mod_trezorcrypto_HDNode___del__); +STATIC MP_DEFINE_CONST_FUN_OBJ_1(mod_trezorcrypto_HDNode___del___obj, + mod_trezorcrypto_HDNode___del__); STATIC const mp_rom_map_elem_t mod_trezorcrypto_HDNode_locals_dict_table[] = { - { MP_ROM_QSTR(MP_QSTR___del__), MP_ROM_PTR(&mod_trezorcrypto_HDNode___del___obj) }, - { MP_ROM_QSTR(MP_QSTR_derive), MP_ROM_PTR(&mod_trezorcrypto_HDNode_derive_obj) }, - { MP_ROM_QSTR(MP_QSTR_derive_cardano), MP_ROM_PTR(&mod_trezorcrypto_HDNode_derive_cardano_obj) }, - { MP_ROM_QSTR(MP_QSTR_derive_path), MP_ROM_PTR(&mod_trezorcrypto_HDNode_derive_path_obj) }, - { MP_ROM_QSTR(MP_QSTR_serialize_private), MP_ROM_PTR(&mod_trezorcrypto_HDNode_serialize_private_obj) }, - { MP_ROM_QSTR(MP_QSTR_serialize_public), MP_ROM_PTR(&mod_trezorcrypto_HDNode_serialize_public_obj) }, - - { MP_ROM_QSTR(MP_QSTR_clone), MP_ROM_PTR(&mod_trezorcrypto_HDNode_clone_obj) }, - { MP_ROM_QSTR(MP_QSTR_depth), MP_ROM_PTR(&mod_trezorcrypto_HDNode_depth_obj) }, - { MP_ROM_QSTR(MP_QSTR_fingerprint), MP_ROM_PTR(&mod_trezorcrypto_HDNode_fingerprint_obj) }, - { MP_ROM_QSTR(MP_QSTR_child_num), MP_ROM_PTR(&mod_trezorcrypto_HDNode_child_num_obj) }, - { MP_ROM_QSTR(MP_QSTR_chain_code), MP_ROM_PTR(&mod_trezorcrypto_HDNode_chain_code_obj) }, - { MP_ROM_QSTR(MP_QSTR_private_key), MP_ROM_PTR(&mod_trezorcrypto_HDNode_private_key_obj) }, - { MP_ROM_QSTR(MP_QSTR_private_key_ext), MP_ROM_PTR(&mod_trezorcrypto_HDNode_private_key_ext_obj) }, - { MP_ROM_QSTR(MP_QSTR_public_key), MP_ROM_PTR(&mod_trezorcrypto_HDNode_public_key_obj) }, - { MP_ROM_QSTR(MP_QSTR_address), MP_ROM_PTR(&mod_trezorcrypto_HDNode_address_obj) }, - { MP_ROM_QSTR(MP_QSTR_nem_address), MP_ROM_PTR(&mod_trezorcrypto_HDNode_nem_address_obj) }, - { MP_ROM_QSTR(MP_QSTR_nem_encrypt), MP_ROM_PTR(&mod_trezorcrypto_HDNode_nem_encrypt_obj) }, - { MP_ROM_QSTR(MP_QSTR_ethereum_pubkeyhash), MP_ROM_PTR(&mod_trezorcrypto_HDNode_ethereum_pubkeyhash_obj) }, + {MP_ROM_QSTR(MP_QSTR___del__), + MP_ROM_PTR(&mod_trezorcrypto_HDNode___del___obj)}, + {MP_ROM_QSTR(MP_QSTR_derive), + MP_ROM_PTR(&mod_trezorcrypto_HDNode_derive_obj)}, + {MP_ROM_QSTR(MP_QSTR_derive_cardano), + MP_ROM_PTR(&mod_trezorcrypto_HDNode_derive_cardano_obj)}, + {MP_ROM_QSTR(MP_QSTR_derive_path), + MP_ROM_PTR(&mod_trezorcrypto_HDNode_derive_path_obj)}, + {MP_ROM_QSTR(MP_QSTR_serialize_private), + MP_ROM_PTR(&mod_trezorcrypto_HDNode_serialize_private_obj)}, + {MP_ROM_QSTR(MP_QSTR_serialize_public), + MP_ROM_PTR(&mod_trezorcrypto_HDNode_serialize_public_obj)}, + + {MP_ROM_QSTR(MP_QSTR_clone), + MP_ROM_PTR(&mod_trezorcrypto_HDNode_clone_obj)}, + {MP_ROM_QSTR(MP_QSTR_depth), + MP_ROM_PTR(&mod_trezorcrypto_HDNode_depth_obj)}, + {MP_ROM_QSTR(MP_QSTR_fingerprint), + MP_ROM_PTR(&mod_trezorcrypto_HDNode_fingerprint_obj)}, + {MP_ROM_QSTR(MP_QSTR_child_num), + MP_ROM_PTR(&mod_trezorcrypto_HDNode_child_num_obj)}, + {MP_ROM_QSTR(MP_QSTR_chain_code), + MP_ROM_PTR(&mod_trezorcrypto_HDNode_chain_code_obj)}, + {MP_ROM_QSTR(MP_QSTR_private_key), + MP_ROM_PTR(&mod_trezorcrypto_HDNode_private_key_obj)}, + {MP_ROM_QSTR(MP_QSTR_private_key_ext), + MP_ROM_PTR(&mod_trezorcrypto_HDNode_private_key_ext_obj)}, + {MP_ROM_QSTR(MP_QSTR_public_key), + MP_ROM_PTR(&mod_trezorcrypto_HDNode_public_key_obj)}, + {MP_ROM_QSTR(MP_QSTR_address), + MP_ROM_PTR(&mod_trezorcrypto_HDNode_address_obj)}, + {MP_ROM_QSTR(MP_QSTR_nem_address), + MP_ROM_PTR(&mod_trezorcrypto_HDNode_nem_address_obj)}, + {MP_ROM_QSTR(MP_QSTR_nem_encrypt), + MP_ROM_PTR(&mod_trezorcrypto_HDNode_nem_encrypt_obj)}, + {MP_ROM_QSTR(MP_QSTR_ethereum_pubkeyhash), + MP_ROM_PTR(&mod_trezorcrypto_HDNode_ethereum_pubkeyhash_obj)}, }; -STATIC MP_DEFINE_CONST_DICT(mod_trezorcrypto_HDNode_locals_dict, mod_trezorcrypto_HDNode_locals_dict_table); +STATIC MP_DEFINE_CONST_DICT(mod_trezorcrypto_HDNode_locals_dict, + mod_trezorcrypto_HDNode_locals_dict_table); STATIC const mp_obj_type_t mod_trezorcrypto_HDNode_type = { - { &mp_type_type }, + {&mp_type_type}, .name = MP_QSTR_HDNode, .make_new = mod_trezorcrypto_HDNode_make_new, - .locals_dict = (void*)&mod_trezorcrypto_HDNode_locals_dict, + .locals_dict = (void *)&mod_trezorcrypto_HDNode_locals_dict, }; -/// def deserialize(self, value: str, version_public: int, version_private: int) -> HDNode: +/// def deserialize(self, value: str, version_public: int, version_private: int) +/// -> HDNode: /// ''' /// Construct a BIP0032 HD node from a base58-serialized value. /// ''' -STATIC mp_obj_t mod_trezorcrypto_bip32_deserialize(mp_obj_t value, mp_obj_t version_public, mp_obj_t version_private) { - mp_buffer_info_t valueb; - mp_get_buffer_raise(value, &valueb, MP_BUFFER_READ); - if (valueb.len == 0) { - mp_raise_ValueError("Invalid value"); - } - uint32_t vpub = trezor_obj_get_uint(version_public); - uint32_t vpriv = trezor_obj_get_uint(version_private); - HDNode hdnode; - uint32_t fingerprint; - if (hdnode_deserialize(valueb.buf, vpub, vpriv, SECP256K1_NAME, &hdnode, &fingerprint) < 0) { - mp_raise_ValueError("Failed to deserialize"); - } - - mp_obj_HDNode_t *o = m_new_obj(mp_obj_HDNode_t); - o->base.type = &mod_trezorcrypto_HDNode_type; - o->hdnode = hdnode; - o->fingerprint = fingerprint; - return MP_OBJ_FROM_PTR(o); +STATIC mp_obj_t mod_trezorcrypto_bip32_deserialize(mp_obj_t value, + mp_obj_t version_public, + mp_obj_t version_private) { + mp_buffer_info_t valueb; + mp_get_buffer_raise(value, &valueb, MP_BUFFER_READ); + if (valueb.len == 0) { + mp_raise_ValueError("Invalid value"); + } + uint32_t vpub = trezor_obj_get_uint(version_public); + uint32_t vpriv = trezor_obj_get_uint(version_private); + HDNode hdnode; + uint32_t fingerprint; + if (hdnode_deserialize(valueb.buf, vpub, vpriv, SECP256K1_NAME, &hdnode, + &fingerprint) < 0) { + mp_raise_ValueError("Failed to deserialize"); + } + + mp_obj_HDNode_t *o = m_new_obj(mp_obj_HDNode_t); + o->base.type = &mod_trezorcrypto_HDNode_type; + o->hdnode = hdnode; + o->fingerprint = fingerprint; + return MP_OBJ_FROM_PTR(o); } -STATIC MP_DEFINE_CONST_FUN_OBJ_3(mod_trezorcrypto_bip32_deserialize_obj, mod_trezorcrypto_bip32_deserialize); +STATIC MP_DEFINE_CONST_FUN_OBJ_3(mod_trezorcrypto_bip32_deserialize_obj, + mod_trezorcrypto_bip32_deserialize); /// def from_seed(seed: bytes, curve_name: str) -> HDNode: /// ''' /// Construct a BIP0032 HD node from a BIP0039 seed value. /// ''' -STATIC mp_obj_t mod_trezorcrypto_bip32_from_seed(mp_obj_t seed, mp_obj_t curve_name) { - mp_buffer_info_t seedb; - mp_get_buffer_raise(seed, &seedb, MP_BUFFER_READ); - if (seedb.len == 0) { - mp_raise_ValueError("Invalid seed"); - } - mp_buffer_info_t curveb; - mp_get_buffer_raise(curve_name, &curveb, MP_BUFFER_READ); - if (curveb.len == 0) { - mp_raise_ValueError("Invalid curve name"); - } - HDNode hdnode; - if (!hdnode_from_seed(seedb.buf, seedb.len, curveb.buf, &hdnode)) { - mp_raise_ValueError("Failed to derive the root node"); - } - mp_obj_HDNode_t *o = m_new_obj(mp_obj_HDNode_t); - o->base.type = &mod_trezorcrypto_HDNode_type; - o->hdnode = hdnode; - o->fingerprint = 0; - return MP_OBJ_FROM_PTR(o); +STATIC mp_obj_t mod_trezorcrypto_bip32_from_seed(mp_obj_t seed, + mp_obj_t curve_name) { + mp_buffer_info_t seedb; + mp_get_buffer_raise(seed, &seedb, MP_BUFFER_READ); + if (seedb.len == 0) { + mp_raise_ValueError("Invalid seed"); + } + mp_buffer_info_t curveb; + mp_get_buffer_raise(curve_name, &curveb, MP_BUFFER_READ); + if (curveb.len == 0) { + mp_raise_ValueError("Invalid curve name"); + } + HDNode hdnode; + if (!hdnode_from_seed(seedb.buf, seedb.len, curveb.buf, &hdnode)) { + mp_raise_ValueError("Failed to derive the root node"); + } + mp_obj_HDNode_t *o = m_new_obj(mp_obj_HDNode_t); + o->base.type = &mod_trezorcrypto_HDNode_type; + o->hdnode = hdnode; + o->fingerprint = 0; + return MP_OBJ_FROM_PTR(o); } -STATIC MP_DEFINE_CONST_FUN_OBJ_2(mod_trezorcrypto_bip32_from_seed_obj, mod_trezorcrypto_bip32_from_seed); +STATIC MP_DEFINE_CONST_FUN_OBJ_2(mod_trezorcrypto_bip32_from_seed_obj, + mod_trezorcrypto_bip32_from_seed); /// def from_mnemonic_cardano(mnemonic: str, passphrase: str) -> bytes: /// ''' /// Convert mnemonic to hdnode /// ''' -STATIC mp_obj_t mod_trezorcrypto_bip32_from_mnemonic_cardano(mp_obj_t mnemonic, mp_obj_t passphrase) { - mp_buffer_info_t mnemo, phrase; - mp_get_buffer_raise(mnemonic, &mnemo, MP_BUFFER_READ); - mp_get_buffer_raise(passphrase, &phrase, MP_BUFFER_READ); - HDNode hdnode; - const char *pmnemonic = mnemo.len > 0 ? mnemo.buf : ""; - const char *ppassphrase = phrase.len > 0 ? phrase.buf : ""; - - uint8_t entropy[64]; - int entropy_len = mnemonic_to_entropy(pmnemonic, entropy); - - if (entropy_len == 0) { - mp_raise_ValueError("Invalid mnemonic"); - } - - const int res = hdnode_from_seed_cardano((const uint8_t *)ppassphrase, phrase.len, entropy, entropy_len / 8, &hdnode); - - if (!res) { - mp_raise_ValueError("Secret key generation from mnemonic is looping forever"); - } else - if (res == -1) { - mp_raise_ValueError("Invalid mnemonic"); - } - - mp_obj_HDNode_t *o = m_new_obj(mp_obj_HDNode_t); - o->base.type = &mod_trezorcrypto_HDNode_type; - o->hdnode = hdnode; - o->fingerprint = 0; - return MP_OBJ_FROM_PTR(o); +STATIC mp_obj_t mod_trezorcrypto_bip32_from_mnemonic_cardano( + mp_obj_t mnemonic, mp_obj_t passphrase) { + mp_buffer_info_t mnemo, phrase; + mp_get_buffer_raise(mnemonic, &mnemo, MP_BUFFER_READ); + mp_get_buffer_raise(passphrase, &phrase, MP_BUFFER_READ); + HDNode hdnode; + const char *pmnemonic = mnemo.len > 0 ? mnemo.buf : ""; + const char *ppassphrase = phrase.len > 0 ? phrase.buf : ""; + + uint8_t entropy[64]; + int entropy_len = mnemonic_to_entropy(pmnemonic, entropy); + + if (entropy_len == 0) { + mp_raise_ValueError("Invalid mnemonic"); + } + + const int res = + hdnode_from_seed_cardano((const uint8_t *)ppassphrase, phrase.len, + entropy, entropy_len / 8, &hdnode); + + if (!res) { + mp_raise_ValueError( + "Secret key generation from mnemonic is looping forever"); + } else if (res == -1) { + mp_raise_ValueError("Invalid mnemonic"); + } + + mp_obj_HDNode_t *o = m_new_obj(mp_obj_HDNode_t); + o->base.type = &mod_trezorcrypto_HDNode_type; + o->hdnode = hdnode; + o->fingerprint = 0; + return MP_OBJ_FROM_PTR(o); } -STATIC MP_DEFINE_CONST_FUN_OBJ_2(mod_trezorcrypto_bip32_from_mnemonic_cardano_obj, mod_trezorcrypto_bip32_from_mnemonic_cardano); +STATIC MP_DEFINE_CONST_FUN_OBJ_2( + mod_trezorcrypto_bip32_from_mnemonic_cardano_obj, + mod_trezorcrypto_bip32_from_mnemonic_cardano); STATIC const mp_rom_map_elem_t mod_trezorcrypto_bip32_globals_table[] = { - { MP_ROM_QSTR(MP_QSTR___name__), MP_ROM_QSTR(MP_QSTR_bip32) }, - { MP_ROM_QSTR(MP_QSTR_HDNode), MP_ROM_PTR(&mod_trezorcrypto_HDNode_type) }, - { MP_ROM_QSTR(MP_QSTR_deserialize), MP_ROM_PTR(&mod_trezorcrypto_bip32_deserialize_obj) }, - { MP_ROM_QSTR(MP_QSTR_from_seed), MP_ROM_PTR(&mod_trezorcrypto_bip32_from_seed_obj) }, - { MP_ROM_QSTR(MP_QSTR_from_mnemonic_cardano), MP_ROM_PTR(&mod_trezorcrypto_bip32_from_mnemonic_cardano_obj) }, + {MP_ROM_QSTR(MP_QSTR___name__), MP_ROM_QSTR(MP_QSTR_bip32)}, + {MP_ROM_QSTR(MP_QSTR_HDNode), MP_ROM_PTR(&mod_trezorcrypto_HDNode_type)}, + {MP_ROM_QSTR(MP_QSTR_deserialize), + MP_ROM_PTR(&mod_trezorcrypto_bip32_deserialize_obj)}, + {MP_ROM_QSTR(MP_QSTR_from_seed), + MP_ROM_PTR(&mod_trezorcrypto_bip32_from_seed_obj)}, + {MP_ROM_QSTR(MP_QSTR_from_mnemonic_cardano), + MP_ROM_PTR(&mod_trezorcrypto_bip32_from_mnemonic_cardano_obj)}, }; -STATIC MP_DEFINE_CONST_DICT(mod_trezorcrypto_bip32_globals, mod_trezorcrypto_bip32_globals_table); +STATIC MP_DEFINE_CONST_DICT(mod_trezorcrypto_bip32_globals, + mod_trezorcrypto_bip32_globals_table); STATIC const mp_obj_module_t mod_trezorcrypto_bip32_module = { - .base = { &mp_type_module }, - .globals = (mp_obj_dict_t*)&mod_trezorcrypto_bip32_globals, + .base = {&mp_type_module}, + .globals = (mp_obj_dict_t *)&mod_trezorcrypto_bip32_globals, }; diff --git a/embed/extmod/modtrezorcrypto/modtrezorcrypto-bip39.h b/embed/extmod/modtrezorcrypto/modtrezorcrypto-bip39.h index bde4d4a1b..ffec01d94 100644 --- a/embed/extmod/modtrezorcrypto/modtrezorcrypto-bip39.h +++ b/embed/extmod/modtrezorcrypto/modtrezorcrypto-bip39.h @@ -17,8 +17,8 @@ * along with this program. If not, see . */ -#include "py/runtime.h" #include "py/objstr.h" +#include "py/runtime.h" #include "bip39.h" @@ -28,138 +28,157 @@ /// ''' /// Return the first word from the wordlist starting with prefix. /// ''' -STATIC mp_obj_t mod_trezorcrypto_bip39_find_word(mp_obj_t prefix) -{ - mp_buffer_info_t pfx; - mp_get_buffer_raise(prefix, &pfx, MP_BUFFER_READ); - if (pfx.len == 0) { - return mp_const_none; - } - for (const char * const *w = mnemonic_wordlist(); *w != 0; w++) { - if (strncmp(*w, pfx.buf, pfx.len) == 0) { - return mp_obj_new_str(*w, strlen(*w)); - } - } +STATIC mp_obj_t mod_trezorcrypto_bip39_find_word(mp_obj_t prefix) { + mp_buffer_info_t pfx; + mp_get_buffer_raise(prefix, &pfx, MP_BUFFER_READ); + if (pfx.len == 0) { return mp_const_none; + } + for (const char *const *w = mnemonic_wordlist(); *w != 0; w++) { + if (strncmp(*w, pfx.buf, pfx.len) == 0) { + return mp_obj_new_str(*w, strlen(*w)); + } + } + return mp_const_none; } -STATIC MP_DEFINE_CONST_FUN_OBJ_1(mod_trezorcrypto_bip39_find_word_obj, mod_trezorcrypto_bip39_find_word); +STATIC MP_DEFINE_CONST_FUN_OBJ_1(mod_trezorcrypto_bip39_find_word_obj, + mod_trezorcrypto_bip39_find_word); /// def complete_word(prefix: str) -> int: /// ''' /// Return possible 1-letter suffixes for given word prefix. -/// Result is a bitmask, with 'a' on the lowest bit, 'b' on the second lowest, etc. +/// Result is a bitmask, with 'a' on the lowest bit, 'b' on the second +/// lowest, etc. /// ''' -STATIC mp_obj_t mod_trezorcrypto_bip39_complete_word(mp_obj_t prefix) -{ - mp_buffer_info_t pfx; - mp_get_buffer_raise(prefix, &pfx, MP_BUFFER_READ); - if (pfx.len == 0) { - return mp_obj_new_int(0xFFFFFFFF); // all letters +STATIC mp_obj_t mod_trezorcrypto_bip39_complete_word(mp_obj_t prefix) { + mp_buffer_info_t pfx; + mp_get_buffer_raise(prefix, &pfx, MP_BUFFER_READ); + if (pfx.len == 0) { + return mp_obj_new_int(0xFFFFFFFF); // all letters + } + uint32_t res = 0; + uint8_t bit; + const char *word; + const char *const *wlist; + for (wlist = mnemonic_wordlist(); *wlist != 0; wlist++) { + word = *wlist; + if (strncmp(word, pfx.buf, pfx.len) == 0 && strlen(word) > pfx.len) { + bit = word[pfx.len] - 'a'; + res |= 1 << bit; } - uint32_t res = 0; - uint8_t bit; - const char *word; - const char *const *wlist; - for (wlist = mnemonic_wordlist(); *wlist != 0; wlist++) { - word = *wlist; - if (strncmp(word, pfx.buf, pfx.len) == 0 && strlen(word) > pfx.len) { - bit = word[pfx.len] - 'a'; - res |= 1 << bit; - } - } - return mp_obj_new_int(res); + } + return mp_obj_new_int(res); } -STATIC MP_DEFINE_CONST_FUN_OBJ_1(mod_trezorcrypto_bip39_complete_word_obj, mod_trezorcrypto_bip39_complete_word); +STATIC MP_DEFINE_CONST_FUN_OBJ_1(mod_trezorcrypto_bip39_complete_word_obj, + mod_trezorcrypto_bip39_complete_word); /// def generate(strength: int) -> str: /// ''' /// Generate a mnemonic of given strength (128, 160, 192, 224 and 256 bits). /// ''' STATIC mp_obj_t mod_trezorcrypto_bip39_generate(mp_obj_t strength) { - int bits = mp_obj_get_int(strength); - if (bits % 32 || bits < 128 || bits > 256) { - mp_raise_ValueError("Invalid bit strength (only 128, 160, 192, 224 and 256 values are allowed)"); - } - const char *mnemo = mnemonic_generate(bits); - mp_obj_t res = mp_obj_new_str_copy(&mp_type_str, (const uint8_t *)mnemo, strlen(mnemo)); - mnemonic_clear(); - return res; + int bits = mp_obj_get_int(strength); + if (bits % 32 || bits < 128 || bits > 256) { + mp_raise_ValueError( + "Invalid bit strength (only 128, 160, 192, 224 and 256 values are " + "allowed)"); + } + const char *mnemo = mnemonic_generate(bits); + mp_obj_t res = + mp_obj_new_str_copy(&mp_type_str, (const uint8_t *)mnemo, strlen(mnemo)); + mnemonic_clear(); + return res; } -STATIC MP_DEFINE_CONST_FUN_OBJ_1(mod_trezorcrypto_bip39_generate_obj, mod_trezorcrypto_bip39_generate); +STATIC MP_DEFINE_CONST_FUN_OBJ_1(mod_trezorcrypto_bip39_generate_obj, + mod_trezorcrypto_bip39_generate); /// def from_data(data: bytes) -> str: /// ''' /// Generate a mnemonic from given data (of 16, 20, 24, 28 and 32 bytes). /// ''' STATIC mp_obj_t mod_trezorcrypto_bip39_from_data(mp_obj_t data) { - mp_buffer_info_t bin; - mp_get_buffer_raise(data, &bin, MP_BUFFER_READ); - if (bin.len % 4 || bin.len < 16 || bin.len > 32) { - mp_raise_ValueError("Invalid data length (only 16, 20, 24, 28 and 32 bytes are allowed)"); - } - const char *mnemo = mnemonic_from_data(bin.buf, bin.len); - mp_obj_t res = mp_obj_new_str_copy(&mp_type_str, (const uint8_t *)mnemo, strlen(mnemo)); - mnemonic_clear(); - return res; + mp_buffer_info_t bin; + mp_get_buffer_raise(data, &bin, MP_BUFFER_READ); + if (bin.len % 4 || bin.len < 16 || bin.len > 32) { + mp_raise_ValueError( + "Invalid data length (only 16, 20, 24, 28 and 32 bytes are allowed)"); + } + const char *mnemo = mnemonic_from_data(bin.buf, bin.len); + mp_obj_t res = + mp_obj_new_str_copy(&mp_type_str, (const uint8_t *)mnemo, strlen(mnemo)); + mnemonic_clear(); + return res; } -STATIC MP_DEFINE_CONST_FUN_OBJ_1(mod_trezorcrypto_bip39_from_data_obj, mod_trezorcrypto_bip39_from_data); +STATIC MP_DEFINE_CONST_FUN_OBJ_1(mod_trezorcrypto_bip39_from_data_obj, + mod_trezorcrypto_bip39_from_data); /// def check(mnemonic: str) -> bool: /// ''' /// Check whether given mnemonic is valid. /// ''' STATIC mp_obj_t mod_trezorcrypto_bip39_check(mp_obj_t mnemonic) { - mp_buffer_info_t text; - mp_get_buffer_raise(mnemonic, &text, MP_BUFFER_READ); - return (text.len > 0 && mnemonic_check(text.buf)) ? mp_const_true : mp_const_false; + mp_buffer_info_t text; + mp_get_buffer_raise(mnemonic, &text, MP_BUFFER_READ); + return (text.len > 0 && mnemonic_check(text.buf)) ? mp_const_true + : mp_const_false; } -STATIC MP_DEFINE_CONST_FUN_OBJ_1(mod_trezorcrypto_bip39_check_obj, mod_trezorcrypto_bip39_check); +STATIC MP_DEFINE_CONST_FUN_OBJ_1(mod_trezorcrypto_bip39_check_obj, + mod_trezorcrypto_bip39_check); STATIC mp_obj_t ui_wait_callback = mp_const_none; STATIC void wrapped_ui_wait_callback(uint32_t current, uint32_t total) { - if (mp_obj_is_callable(ui_wait_callback)) { - mp_call_function_2_protected(ui_wait_callback, mp_obj_new_int(current), mp_obj_new_int(total)); - } + if (mp_obj_is_callable(ui_wait_callback)) { + mp_call_function_2_protected(ui_wait_callback, mp_obj_new_int(current), + mp_obj_new_int(total)); + } } -/// def seed(mnemonic: str, passphrase: str, callback: (int, int -> None)=None) -> bytes: +/// def seed(mnemonic: str, passphrase: str, callback: (int, int -> None)=None) +/// -> bytes: /// ''' /// Generate seed from mnemonic and passphrase. /// ''' -STATIC mp_obj_t mod_trezorcrypto_bip39_seed(size_t n_args, const mp_obj_t *args) { - mp_buffer_info_t mnemo; - mp_buffer_info_t phrase; - mp_get_buffer_raise(args[0], &mnemo, MP_BUFFER_READ); - mp_get_buffer_raise(args[1], &phrase, MP_BUFFER_READ); - uint8_t seed[64]; - const char *pmnemonic = mnemo.len > 0 ? mnemo.buf : ""; - const char *ppassphrase = phrase.len > 0 ? phrase.buf : ""; - if (n_args > 2) { - // generate with a progress callback - ui_wait_callback = args[2]; - mnemonic_to_seed(pmnemonic, ppassphrase, seed, wrapped_ui_wait_callback); - ui_wait_callback = mp_const_none; - } else { - // generate without callback - mnemonic_to_seed(pmnemonic, ppassphrase, seed, NULL); - } - return mp_obj_new_bytes(seed, sizeof(seed)); +STATIC mp_obj_t mod_trezorcrypto_bip39_seed(size_t n_args, + const mp_obj_t *args) { + mp_buffer_info_t mnemo; + mp_buffer_info_t phrase; + mp_get_buffer_raise(args[0], &mnemo, MP_BUFFER_READ); + mp_get_buffer_raise(args[1], &phrase, MP_BUFFER_READ); + uint8_t seed[64]; + const char *pmnemonic = mnemo.len > 0 ? mnemo.buf : ""; + const char *ppassphrase = phrase.len > 0 ? phrase.buf : ""; + if (n_args > 2) { + // generate with a progress callback + ui_wait_callback = args[2]; + mnemonic_to_seed(pmnemonic, ppassphrase, seed, wrapped_ui_wait_callback); + ui_wait_callback = mp_const_none; + } else { + // generate without callback + mnemonic_to_seed(pmnemonic, ppassphrase, seed, NULL); + } + return mp_obj_new_bytes(seed, sizeof(seed)); } -STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(mod_trezorcrypto_bip39_seed_obj, 2, 3, mod_trezorcrypto_bip39_seed); +STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(mod_trezorcrypto_bip39_seed_obj, 2, + 3, mod_trezorcrypto_bip39_seed); STATIC const mp_rom_map_elem_t mod_trezorcrypto_bip39_globals_table[] = { - { MP_ROM_QSTR(MP_QSTR___name__), MP_ROM_QSTR(MP_QSTR_bip39) }, - { MP_ROM_QSTR(MP_QSTR_find_word), MP_ROM_PTR(&mod_trezorcrypto_bip39_find_word_obj) }, - { MP_ROM_QSTR(MP_QSTR_complete_word), MP_ROM_PTR(&mod_trezorcrypto_bip39_complete_word_obj) }, - { MP_ROM_QSTR(MP_QSTR_generate), MP_ROM_PTR(&mod_trezorcrypto_bip39_generate_obj) }, - { MP_ROM_QSTR(MP_QSTR_from_data), MP_ROM_PTR(&mod_trezorcrypto_bip39_from_data_obj) }, - { MP_ROM_QSTR(MP_QSTR_check), MP_ROM_PTR(&mod_trezorcrypto_bip39_check_obj) }, - { MP_ROM_QSTR(MP_QSTR_seed), MP_ROM_PTR(&mod_trezorcrypto_bip39_seed_obj) }, + {MP_ROM_QSTR(MP_QSTR___name__), MP_ROM_QSTR(MP_QSTR_bip39)}, + {MP_ROM_QSTR(MP_QSTR_find_word), + MP_ROM_PTR(&mod_trezorcrypto_bip39_find_word_obj)}, + {MP_ROM_QSTR(MP_QSTR_complete_word), + MP_ROM_PTR(&mod_trezorcrypto_bip39_complete_word_obj)}, + {MP_ROM_QSTR(MP_QSTR_generate), + MP_ROM_PTR(&mod_trezorcrypto_bip39_generate_obj)}, + {MP_ROM_QSTR(MP_QSTR_from_data), + MP_ROM_PTR(&mod_trezorcrypto_bip39_from_data_obj)}, + {MP_ROM_QSTR(MP_QSTR_check), MP_ROM_PTR(&mod_trezorcrypto_bip39_check_obj)}, + {MP_ROM_QSTR(MP_QSTR_seed), MP_ROM_PTR(&mod_trezorcrypto_bip39_seed_obj)}, }; -STATIC MP_DEFINE_CONST_DICT(mod_trezorcrypto_bip39_globals, mod_trezorcrypto_bip39_globals_table); +STATIC MP_DEFINE_CONST_DICT(mod_trezorcrypto_bip39_globals, + mod_trezorcrypto_bip39_globals_table); STATIC const mp_obj_module_t mod_trezorcrypto_bip39_module = { - .base = { &mp_type_module }, - .globals = (mp_obj_dict_t*)&mod_trezorcrypto_bip39_globals, + .base = {&mp_type_module}, + .globals = (mp_obj_dict_t *)&mod_trezorcrypto_bip39_globals, }; diff --git a/embed/extmod/modtrezorcrypto/modtrezorcrypto-blake256.h b/embed/extmod/modtrezorcrypto/modtrezorcrypto-blake256.h index 069346246..5bf917bba 100644 --- a/embed/extmod/modtrezorcrypto/modtrezorcrypto-blake256.h +++ b/embed/extmod/modtrezorcrypto/modtrezorcrypto-blake256.h @@ -29,8 +29,8 @@ /// Blake256 context. /// ''' typedef struct _mp_obj_Blake256_t { - mp_obj_base_t base; - BLAKE256_CTX ctx; + mp_obj_base_t base; + BLAKE256_CTX ctx; } mp_obj_Blake256_t; STATIC mp_obj_t mod_trezorcrypto_Blake256_update(mp_obj_t self, mp_obj_t data); @@ -39,16 +39,18 @@ STATIC mp_obj_t mod_trezorcrypto_Blake256_update(mp_obj_t self, mp_obj_t data); /// ''' /// Creates a hash context object. /// ''' -STATIC mp_obj_t mod_trezorcrypto_Blake256_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_kw, const mp_obj_t *args) { - mp_arg_check_num(n_args, n_kw, 0, 1, false); - mp_obj_Blake256_t *o = m_new_obj(mp_obj_Blake256_t); - o->base.type = type; - blake256_Init(&(o->ctx)); - // constructor called with bytes/str as first parameter - if (n_args == 1) { - mod_trezorcrypto_Blake256_update(MP_OBJ_FROM_PTR(o), args[0]); - } - return MP_OBJ_FROM_PTR(o); +STATIC mp_obj_t mod_trezorcrypto_Blake256_make_new(const mp_obj_type_t *type, + size_t n_args, size_t n_kw, + const mp_obj_t *args) { + mp_arg_check_num(n_args, n_kw, 0, 1, false); + mp_obj_Blake256_t *o = m_new_obj(mp_obj_Blake256_t); + o->base.type = type; + blake256_Init(&(o->ctx)); + // constructor called with bytes/str as first parameter + if (n_args == 1) { + mod_trezorcrypto_Blake256_update(MP_OBJ_FROM_PTR(o), args[0]); + } + return MP_OBJ_FROM_PTR(o); } /// def update(self, data: bytes) -> None: @@ -56,50 +58,59 @@ STATIC mp_obj_t mod_trezorcrypto_Blake256_make_new(const mp_obj_type_t *type, si /// Update the hash context with hashed data. /// ''' STATIC mp_obj_t mod_trezorcrypto_Blake256_update(mp_obj_t self, mp_obj_t data) { - mp_obj_Blake256_t *o = MP_OBJ_TO_PTR(self); - mp_buffer_info_t msg; - mp_get_buffer_raise(data, &msg, MP_BUFFER_READ); - if (msg.len > 0) { - blake256_Update(&(o->ctx), msg.buf, msg.len); - } - return mp_const_none; + mp_obj_Blake256_t *o = MP_OBJ_TO_PTR(self); + mp_buffer_info_t msg; + mp_get_buffer_raise(data, &msg, MP_BUFFER_READ); + if (msg.len > 0) { + blake256_Update(&(o->ctx), msg.buf, msg.len); + } + return mp_const_none; } -STATIC MP_DEFINE_CONST_FUN_OBJ_2(mod_trezorcrypto_Blake256_update_obj, mod_trezorcrypto_Blake256_update); +STATIC MP_DEFINE_CONST_FUN_OBJ_2(mod_trezorcrypto_Blake256_update_obj, + mod_trezorcrypto_Blake256_update); /// def digest(self) -> bytes: /// ''' /// Returns the digest of hashed data. /// ''' STATIC mp_obj_t mod_trezorcrypto_Blake256_digest(mp_obj_t self) { - mp_obj_Blake256_t *o = MP_OBJ_TO_PTR(self); - uint8_t hash[BLAKE256_DIGEST_LENGTH]; - BLAKE256_CTX ctx; - memcpy(&ctx, &(o->ctx), sizeof(BLAKE256_CTX)); - blake256_Final(&ctx, hash); - memzero(&ctx, sizeof(BLAKE256_CTX)); - return mp_obj_new_bytes(hash, sizeof(hash)); + mp_obj_Blake256_t *o = MP_OBJ_TO_PTR(self); + uint8_t hash[BLAKE256_DIGEST_LENGTH]; + BLAKE256_CTX ctx; + memcpy(&ctx, &(o->ctx), sizeof(BLAKE256_CTX)); + blake256_Final(&ctx, hash); + memzero(&ctx, sizeof(BLAKE256_CTX)); + return mp_obj_new_bytes(hash, sizeof(hash)); } -STATIC MP_DEFINE_CONST_FUN_OBJ_1(mod_trezorcrypto_Blake256_digest_obj, mod_trezorcrypto_Blake256_digest); +STATIC MP_DEFINE_CONST_FUN_OBJ_1(mod_trezorcrypto_Blake256_digest_obj, + mod_trezorcrypto_Blake256_digest); STATIC mp_obj_t mod_trezorcrypto_Blake256___del__(mp_obj_t self) { - mp_obj_Blake256_t *o = MP_OBJ_TO_PTR(self); - memzero(&(o->ctx), sizeof(BLAKE256_CTX)); - return mp_const_none; + mp_obj_Blake256_t *o = MP_OBJ_TO_PTR(self); + memzero(&(o->ctx), sizeof(BLAKE256_CTX)); + return mp_const_none; } -STATIC MP_DEFINE_CONST_FUN_OBJ_1(mod_trezorcrypto_Blake256___del___obj, mod_trezorcrypto_Blake256___del__); +STATIC MP_DEFINE_CONST_FUN_OBJ_1(mod_trezorcrypto_Blake256___del___obj, + mod_trezorcrypto_Blake256___del__); STATIC const mp_rom_map_elem_t mod_trezorcrypto_Blake256_locals_dict_table[] = { - { MP_ROM_QSTR(MP_QSTR_update), MP_ROM_PTR(&mod_trezorcrypto_Blake256_update_obj) }, - { MP_ROM_QSTR(MP_QSTR_digest), MP_ROM_PTR(&mod_trezorcrypto_Blake256_digest_obj) }, - { MP_ROM_QSTR(MP_QSTR___del__), MP_ROM_PTR(&mod_trezorcrypto_Blake256___del___obj) }, - { MP_ROM_QSTR(MP_QSTR_block_size), MP_OBJ_NEW_SMALL_INT(BLAKE256_BLOCK_LENGTH) }, - { MP_ROM_QSTR(MP_QSTR_digest_size), MP_OBJ_NEW_SMALL_INT(BLAKE256_DIGEST_LENGTH) }, + {MP_ROM_QSTR(MP_QSTR_update), + MP_ROM_PTR(&mod_trezorcrypto_Blake256_update_obj)}, + {MP_ROM_QSTR(MP_QSTR_digest), + MP_ROM_PTR(&mod_trezorcrypto_Blake256_digest_obj)}, + {MP_ROM_QSTR(MP_QSTR___del__), + MP_ROM_PTR(&mod_trezorcrypto_Blake256___del___obj)}, + {MP_ROM_QSTR(MP_QSTR_block_size), + MP_OBJ_NEW_SMALL_INT(BLAKE256_BLOCK_LENGTH)}, + {MP_ROM_QSTR(MP_QSTR_digest_size), + MP_OBJ_NEW_SMALL_INT(BLAKE256_DIGEST_LENGTH)}, }; -STATIC MP_DEFINE_CONST_DICT(mod_trezorcrypto_Blake256_locals_dict, mod_trezorcrypto_Blake256_locals_dict_table); +STATIC MP_DEFINE_CONST_DICT(mod_trezorcrypto_Blake256_locals_dict, + mod_trezorcrypto_Blake256_locals_dict_table); STATIC const mp_obj_type_t mod_trezorcrypto_Blake256_type = { - { &mp_type_type }, + {&mp_type_type}, .name = MP_QSTR_Blake256, .make_new = mod_trezorcrypto_Blake256_make_new, - .locals_dict = (void*)&mod_trezorcrypto_Blake256_locals_dict, + .locals_dict = (void *)&mod_trezorcrypto_Blake256_locals_dict, }; diff --git a/embed/extmod/modtrezorcrypto/modtrezorcrypto-blake2b.h b/embed/extmod/modtrezorcrypto/modtrezorcrypto-blake2b.h index 99e50b40c..99b030df6 100644 --- a/embed/extmod/modtrezorcrypto/modtrezorcrypto-blake2b.h +++ b/embed/extmod/modtrezorcrypto/modtrezorcrypto-blake2b.h @@ -31,61 +31,75 @@ /// Blake2b context. /// ''' typedef struct _mp_obj_Blake2b_t { - mp_obj_base_t base; - BLAKE2B_CTX ctx; + mp_obj_base_t base; + BLAKE2B_CTX ctx; } mp_obj_Blake2b_t; STATIC mp_obj_t mod_trezorcrypto_Blake2b_update(mp_obj_t self, mp_obj_t data); -/// def __init__(self, data: bytes = None, outlen: int = Blake2b.digest_size, personal: bytes = None) -> None: +/// def __init__(self, data: bytes = None, outlen: int = Blake2b.digest_size, +/// personal: bytes = None) -> None: /// ''' /// Creates a hash context object. /// ''' -STATIC mp_obj_t mod_trezorcrypto_Blake2b_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_kw, const mp_obj_t *args) { - - STATIC const mp_arg_t allowed_args[] = { - { MP_QSTR_data, MP_ARG_OBJ, {.u_obj = mp_const_empty_bytes} }, - { MP_QSTR_outlen, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = BLAKE2B_DIGEST_LENGTH} }, - { MP_QSTR_key, MP_ARG_KW_ONLY | MP_ARG_OBJ, {.u_obj = mp_const_empty_bytes} }, - { MP_QSTR_personal, MP_ARG_KW_ONLY | MP_ARG_OBJ, {.u_obj = mp_const_empty_bytes} }, - }; - mp_arg_val_t vals[MP_ARRAY_SIZE(allowed_args)]; - mp_arg_parse_all_kw_array(n_args, n_kw, args, MP_ARRAY_SIZE(allowed_args), allowed_args, vals); - - size_t data_len; - const uint8_t *data = (const uint8_t *)mp_obj_str_get_data(vals[0].u_obj, &data_len); - const mp_int_t outlen = vals[1].u_int; - size_t key_len; - const uint8_t *key = (const uint8_t *)mp_obj_str_get_data(vals[2].u_obj, &key_len); - size_t personal_len; - const uint8_t *personal = (const uint8_t *)mp_obj_str_get_data(vals[3].u_obj, &personal_len); - - if (key_len > 0 && personal_len > 0) { - mp_raise_ValueError("Invalid Blake2b parameters: cannot use key and personal at the same time"); - } - - mp_obj_Blake2b_t *o = m_new_obj(mp_obj_Blake2b_t); - o->base.type = type; - int res = 0; - - if (key_len > 0) { - res = blake2b_InitKey(&(o->ctx), outlen, key, key_len); - } else if (personal_len > 0) { - res = blake2b_InitPersonal(&(o->ctx), outlen, personal, personal_len); - } else { - res = blake2b_Init(&(o->ctx), outlen); - } - - if (res < 0) { - mp_raise_ValueError("Invalid Blake2b parameters"); - } - - // constructor called with data argument set - if (data_len > 0) { - blake2b_Update(&(o->ctx), data, data_len); - } - - return MP_OBJ_FROM_PTR(o); +STATIC mp_obj_t mod_trezorcrypto_Blake2b_make_new(const mp_obj_type_t *type, + size_t n_args, size_t n_kw, + const mp_obj_t *args) { + STATIC const mp_arg_t allowed_args[] = { + {MP_QSTR_data, MP_ARG_OBJ, {.u_obj = mp_const_empty_bytes}}, + {MP_QSTR_outlen, + MP_ARG_KW_ONLY | MP_ARG_INT, + {.u_int = BLAKE2B_DIGEST_LENGTH}}, + {MP_QSTR_key, + MP_ARG_KW_ONLY | MP_ARG_OBJ, + {.u_obj = mp_const_empty_bytes}}, + {MP_QSTR_personal, + MP_ARG_KW_ONLY | MP_ARG_OBJ, + {.u_obj = mp_const_empty_bytes}}, + }; + mp_arg_val_t vals[MP_ARRAY_SIZE(allowed_args)]; + mp_arg_parse_all_kw_array(n_args, n_kw, args, MP_ARRAY_SIZE(allowed_args), + allowed_args, vals); + + size_t data_len; + const uint8_t *data = + (const uint8_t *)mp_obj_str_get_data(vals[0].u_obj, &data_len); + const mp_int_t outlen = vals[1].u_int; + size_t key_len; + const uint8_t *key = + (const uint8_t *)mp_obj_str_get_data(vals[2].u_obj, &key_len); + size_t personal_len; + const uint8_t *personal = + (const uint8_t *)mp_obj_str_get_data(vals[3].u_obj, &personal_len); + + if (key_len > 0 && personal_len > 0) { + mp_raise_ValueError( + "Invalid Blake2b parameters: cannot use key and personal at the same " + "time"); + } + + mp_obj_Blake2b_t *o = m_new_obj(mp_obj_Blake2b_t); + o->base.type = type; + int res = 0; + + if (key_len > 0) { + res = blake2b_InitKey(&(o->ctx), outlen, key, key_len); + } else if (personal_len > 0) { + res = blake2b_InitPersonal(&(o->ctx), outlen, personal, personal_len); + } else { + res = blake2b_Init(&(o->ctx), outlen); + } + + if (res < 0) { + mp_raise_ValueError("Invalid Blake2b parameters"); + } + + // constructor called with data argument set + if (data_len > 0) { + blake2b_Update(&(o->ctx), data, data_len); + } + + return MP_OBJ_FROM_PTR(o); } /// def update(self, data: bytes) -> None: @@ -93,50 +107,59 @@ STATIC mp_obj_t mod_trezorcrypto_Blake2b_make_new(const mp_obj_type_t *type, siz /// Update the hash context with hashed data. /// ''' STATIC mp_obj_t mod_trezorcrypto_Blake2b_update(mp_obj_t self, mp_obj_t data) { - mp_obj_Blake2b_t *o = MP_OBJ_TO_PTR(self); - mp_buffer_info_t msg; - mp_get_buffer_raise(data, &msg, MP_BUFFER_READ); - if (msg.len > 0) { - blake2b_Update(&(o->ctx), msg.buf, msg.len); - } - return mp_const_none; + mp_obj_Blake2b_t *o = MP_OBJ_TO_PTR(self); + mp_buffer_info_t msg; + mp_get_buffer_raise(data, &msg, MP_BUFFER_READ); + if (msg.len > 0) { + blake2b_Update(&(o->ctx), msg.buf, msg.len); + } + return mp_const_none; } -STATIC MP_DEFINE_CONST_FUN_OBJ_2(mod_trezorcrypto_Blake2b_update_obj, mod_trezorcrypto_Blake2b_update); +STATIC MP_DEFINE_CONST_FUN_OBJ_2(mod_trezorcrypto_Blake2b_update_obj, + mod_trezorcrypto_Blake2b_update); /// def digest(self) -> bytes: /// ''' /// Returns the digest of hashed data. /// ''' STATIC mp_obj_t mod_trezorcrypto_Blake2b_digest(mp_obj_t self) { - mp_obj_Blake2b_t *o = MP_OBJ_TO_PTR(self); - uint8_t out[BLAKE2B_DIGEST_LENGTH]; - BLAKE2B_CTX ctx; - memcpy(&ctx, &(o->ctx), sizeof(BLAKE2B_CTX)); - blake2b_Final(&ctx, out, ctx.outlen); - memzero(&ctx, sizeof(BLAKE2B_CTX)); - return mp_obj_new_bytes(out, o->ctx.outlen); + mp_obj_Blake2b_t *o = MP_OBJ_TO_PTR(self); + uint8_t out[BLAKE2B_DIGEST_LENGTH]; + BLAKE2B_CTX ctx; + memcpy(&ctx, &(o->ctx), sizeof(BLAKE2B_CTX)); + blake2b_Final(&ctx, out, ctx.outlen); + memzero(&ctx, sizeof(BLAKE2B_CTX)); + return mp_obj_new_bytes(out, o->ctx.outlen); } -STATIC MP_DEFINE_CONST_FUN_OBJ_1(mod_trezorcrypto_Blake2b_digest_obj, mod_trezorcrypto_Blake2b_digest); +STATIC MP_DEFINE_CONST_FUN_OBJ_1(mod_trezorcrypto_Blake2b_digest_obj, + mod_trezorcrypto_Blake2b_digest); STATIC mp_obj_t mod_trezorcrypto_Blake2b___del__(mp_obj_t self) { - mp_obj_Blake2b_t *o = MP_OBJ_TO_PTR(self); - memzero(&(o->ctx), sizeof(BLAKE2B_CTX)); - return mp_const_none; + mp_obj_Blake2b_t *o = MP_OBJ_TO_PTR(self); + memzero(&(o->ctx), sizeof(BLAKE2B_CTX)); + return mp_const_none; } -STATIC MP_DEFINE_CONST_FUN_OBJ_1(mod_trezorcrypto_Blake2b___del___obj, mod_trezorcrypto_Blake2b___del__); +STATIC MP_DEFINE_CONST_FUN_OBJ_1(mod_trezorcrypto_Blake2b___del___obj, + mod_trezorcrypto_Blake2b___del__); STATIC const mp_rom_map_elem_t mod_trezorcrypto_Blake2b_locals_dict_table[] = { - { MP_ROM_QSTR(MP_QSTR_update), MP_ROM_PTR(&mod_trezorcrypto_Blake2b_update_obj) }, - { MP_ROM_QSTR(MP_QSTR_digest), MP_ROM_PTR(&mod_trezorcrypto_Blake2b_digest_obj) }, - { MP_ROM_QSTR(MP_QSTR___del__), MP_ROM_PTR(&mod_trezorcrypto_Blake2b___del___obj) }, - { MP_ROM_QSTR(MP_QSTR_block_size), MP_OBJ_NEW_SMALL_INT(BLAKE2B_BLOCK_LENGTH) }, - { MP_ROM_QSTR(MP_QSTR_digest_size), MP_OBJ_NEW_SMALL_INT(BLAKE2B_DIGEST_LENGTH) }, + {MP_ROM_QSTR(MP_QSTR_update), + MP_ROM_PTR(&mod_trezorcrypto_Blake2b_update_obj)}, + {MP_ROM_QSTR(MP_QSTR_digest), + MP_ROM_PTR(&mod_trezorcrypto_Blake2b_digest_obj)}, + {MP_ROM_QSTR(MP_QSTR___del__), + MP_ROM_PTR(&mod_trezorcrypto_Blake2b___del___obj)}, + {MP_ROM_QSTR(MP_QSTR_block_size), + MP_OBJ_NEW_SMALL_INT(BLAKE2B_BLOCK_LENGTH)}, + {MP_ROM_QSTR(MP_QSTR_digest_size), + MP_OBJ_NEW_SMALL_INT(BLAKE2B_DIGEST_LENGTH)}, }; -STATIC MP_DEFINE_CONST_DICT(mod_trezorcrypto_Blake2b_locals_dict, mod_trezorcrypto_Blake2b_locals_dict_table); +STATIC MP_DEFINE_CONST_DICT(mod_trezorcrypto_Blake2b_locals_dict, + mod_trezorcrypto_Blake2b_locals_dict_table); STATIC const mp_obj_type_t mod_trezorcrypto_Blake2b_type = { - { &mp_type_type }, + {&mp_type_type}, .name = MP_QSTR_Blake2b, .make_new = mod_trezorcrypto_Blake2b_make_new, - .locals_dict = (void*)&mod_trezorcrypto_Blake2b_locals_dict, + .locals_dict = (void *)&mod_trezorcrypto_Blake2b_locals_dict, }; diff --git a/embed/extmod/modtrezorcrypto/modtrezorcrypto-blake2s.h b/embed/extmod/modtrezorcrypto/modtrezorcrypto-blake2s.h index f450c0ab8..0f289254d 100644 --- a/embed/extmod/modtrezorcrypto/modtrezorcrypto-blake2s.h +++ b/embed/extmod/modtrezorcrypto/modtrezorcrypto-blake2s.h @@ -31,61 +31,75 @@ /// Blake2s context. /// ''' typedef struct _mp_obj_Blake2s_t { - mp_obj_base_t base; - BLAKE2S_CTX ctx; + mp_obj_base_t base; + BLAKE2S_CTX ctx; } mp_obj_Blake2s_t; STATIC mp_obj_t mod_trezorcrypto_Blake2s_update(mp_obj_t self, mp_obj_t data); -/// def __init__(self, data: bytes = None, outlen: int = Blake2s.digest_size, key: bytes = None, personal: bytes = None) -> None: +/// def __init__(self, data: bytes = None, outlen: int = Blake2s.digest_size, +/// key: bytes = None, personal: bytes = None) -> None: /// ''' /// Creates a hash context object. /// ''' -STATIC mp_obj_t mod_trezorcrypto_Blake2s_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_kw, const mp_obj_t *args) { - - STATIC const mp_arg_t allowed_args[] = { - { MP_QSTR_data, MP_ARG_OBJ, {.u_obj = mp_const_empty_bytes} }, - { MP_QSTR_outlen, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = BLAKE2S_DIGEST_LENGTH} }, - { MP_QSTR_key, MP_ARG_KW_ONLY | MP_ARG_OBJ, {.u_obj = mp_const_empty_bytes} }, - { MP_QSTR_personal, MP_ARG_KW_ONLY | MP_ARG_OBJ, {.u_obj = mp_const_empty_bytes} }, - }; - mp_arg_val_t vals[MP_ARRAY_SIZE(allowed_args)]; - mp_arg_parse_all_kw_array(n_args, n_kw, args, MP_ARRAY_SIZE(allowed_args), allowed_args, vals); - - size_t data_len; - const uint8_t *data = (const uint8_t *)mp_obj_str_get_data(vals[0].u_obj, &data_len); - const mp_int_t outlen = vals[1].u_int; - size_t key_len; - const uint8_t *key = (const uint8_t *)mp_obj_str_get_data(vals[2].u_obj, &key_len); - size_t personal_len; - const uint8_t *personal = (const uint8_t *)mp_obj_str_get_data(vals[3].u_obj, &personal_len); - - if (key_len > 0 && personal_len > 0) { - mp_raise_ValueError("Invalid Blake2s parameters: cannot use key and personal at the same time"); - } - - mp_obj_Blake2s_t *o = m_new_obj(mp_obj_Blake2s_t); - o->base.type = type; - int res = 0; - - if (key_len > 0) { - res = blake2s_InitKey(&(o->ctx), outlen, key, key_len); - } else if (personal_len > 0) { - res = blake2s_InitPersonal(&(o->ctx), outlen, personal, personal_len); - } else { - res = blake2s_Init(&(o->ctx), outlen); - } - - if (res < 0) { - mp_raise_ValueError("Invalid Blake2s parameters"); - } - - // constructor called with data argument set - if (data_len > 0) { - blake2s_Update(&(o->ctx), data, data_len); - } - - return MP_OBJ_FROM_PTR(o); +STATIC mp_obj_t mod_trezorcrypto_Blake2s_make_new(const mp_obj_type_t *type, + size_t n_args, size_t n_kw, + const mp_obj_t *args) { + STATIC const mp_arg_t allowed_args[] = { + {MP_QSTR_data, MP_ARG_OBJ, {.u_obj = mp_const_empty_bytes}}, + {MP_QSTR_outlen, + MP_ARG_KW_ONLY | MP_ARG_INT, + {.u_int = BLAKE2S_DIGEST_LENGTH}}, + {MP_QSTR_key, + MP_ARG_KW_ONLY | MP_ARG_OBJ, + {.u_obj = mp_const_empty_bytes}}, + {MP_QSTR_personal, + MP_ARG_KW_ONLY | MP_ARG_OBJ, + {.u_obj = mp_const_empty_bytes}}, + }; + mp_arg_val_t vals[MP_ARRAY_SIZE(allowed_args)]; + mp_arg_parse_all_kw_array(n_args, n_kw, args, MP_ARRAY_SIZE(allowed_args), + allowed_args, vals); + + size_t data_len; + const uint8_t *data = + (const uint8_t *)mp_obj_str_get_data(vals[0].u_obj, &data_len); + const mp_int_t outlen = vals[1].u_int; + size_t key_len; + const uint8_t *key = + (const uint8_t *)mp_obj_str_get_data(vals[2].u_obj, &key_len); + size_t personal_len; + const uint8_t *personal = + (const uint8_t *)mp_obj_str_get_data(vals[3].u_obj, &personal_len); + + if (key_len > 0 && personal_len > 0) { + mp_raise_ValueError( + "Invalid Blake2s parameters: cannot use key and personal at the same " + "time"); + } + + mp_obj_Blake2s_t *o = m_new_obj(mp_obj_Blake2s_t); + o->base.type = type; + int res = 0; + + if (key_len > 0) { + res = blake2s_InitKey(&(o->ctx), outlen, key, key_len); + } else if (personal_len > 0) { + res = blake2s_InitPersonal(&(o->ctx), outlen, personal, personal_len); + } else { + res = blake2s_Init(&(o->ctx), outlen); + } + + if (res < 0) { + mp_raise_ValueError("Invalid Blake2s parameters"); + } + + // constructor called with data argument set + if (data_len > 0) { + blake2s_Update(&(o->ctx), data, data_len); + } + + return MP_OBJ_FROM_PTR(o); } /// def update(self, data: bytes) -> None: @@ -93,50 +107,59 @@ STATIC mp_obj_t mod_trezorcrypto_Blake2s_make_new(const mp_obj_type_t *type, siz /// Update the hash context with hashed data. /// ''' STATIC mp_obj_t mod_trezorcrypto_Blake2s_update(mp_obj_t self, mp_obj_t data) { - mp_obj_Blake2s_t *o = MP_OBJ_TO_PTR(self); - mp_buffer_info_t msg; - mp_get_buffer_raise(data, &msg, MP_BUFFER_READ); - if (msg.len > 0) { - blake2s_Update(&(o->ctx), msg.buf, msg.len); - } - return mp_const_none; + mp_obj_Blake2s_t *o = MP_OBJ_TO_PTR(self); + mp_buffer_info_t msg; + mp_get_buffer_raise(data, &msg, MP_BUFFER_READ); + if (msg.len > 0) { + blake2s_Update(&(o->ctx), msg.buf, msg.len); + } + return mp_const_none; } -STATIC MP_DEFINE_CONST_FUN_OBJ_2(mod_trezorcrypto_Blake2s_update_obj, mod_trezorcrypto_Blake2s_update); +STATIC MP_DEFINE_CONST_FUN_OBJ_2(mod_trezorcrypto_Blake2s_update_obj, + mod_trezorcrypto_Blake2s_update); /// def digest(self) -> bytes: /// ''' /// Returns the digest of hashed data. /// ''' STATIC mp_obj_t mod_trezorcrypto_Blake2s_digest(mp_obj_t self) { - mp_obj_Blake2s_t *o = MP_OBJ_TO_PTR(self); - uint8_t out[BLAKE2S_DIGEST_LENGTH]; - BLAKE2S_CTX ctx; - memcpy(&ctx, &(o->ctx), sizeof(BLAKE2S_CTX)); - blake2s_Final(&ctx, out, ctx.outlen); - memzero(&ctx, sizeof(BLAKE2S_CTX)); - return mp_obj_new_bytes(out, o->ctx.outlen); + mp_obj_Blake2s_t *o = MP_OBJ_TO_PTR(self); + uint8_t out[BLAKE2S_DIGEST_LENGTH]; + BLAKE2S_CTX ctx; + memcpy(&ctx, &(o->ctx), sizeof(BLAKE2S_CTX)); + blake2s_Final(&ctx, out, ctx.outlen); + memzero(&ctx, sizeof(BLAKE2S_CTX)); + return mp_obj_new_bytes(out, o->ctx.outlen); } -STATIC MP_DEFINE_CONST_FUN_OBJ_1(mod_trezorcrypto_Blake2s_digest_obj, mod_trezorcrypto_Blake2s_digest); +STATIC MP_DEFINE_CONST_FUN_OBJ_1(mod_trezorcrypto_Blake2s_digest_obj, + mod_trezorcrypto_Blake2s_digest); STATIC mp_obj_t mod_trezorcrypto_Blake2s___del__(mp_obj_t self) { - mp_obj_Blake2s_t *o = MP_OBJ_TO_PTR(self); - memzero(&(o->ctx), sizeof(BLAKE2S_CTX)); - return mp_const_none; + mp_obj_Blake2s_t *o = MP_OBJ_TO_PTR(self); + memzero(&(o->ctx), sizeof(BLAKE2S_CTX)); + return mp_const_none; } -STATIC MP_DEFINE_CONST_FUN_OBJ_1(mod_trezorcrypto_Blake2s___del___obj, mod_trezorcrypto_Blake2s___del__); +STATIC MP_DEFINE_CONST_FUN_OBJ_1(mod_trezorcrypto_Blake2s___del___obj, + mod_trezorcrypto_Blake2s___del__); STATIC const mp_rom_map_elem_t mod_trezorcrypto_Blake2s_locals_dict_table[] = { - { MP_ROM_QSTR(MP_QSTR_update), MP_ROM_PTR(&mod_trezorcrypto_Blake2s_update_obj) }, - { MP_ROM_QSTR(MP_QSTR_digest), MP_ROM_PTR(&mod_trezorcrypto_Blake2s_digest_obj) }, - { MP_ROM_QSTR(MP_QSTR___del__), MP_ROM_PTR(&mod_trezorcrypto_Blake2s___del___obj) }, - { MP_ROM_QSTR(MP_QSTR_block_size), MP_OBJ_NEW_SMALL_INT(BLAKE2S_BLOCK_LENGTH) }, - { MP_ROM_QSTR(MP_QSTR_digest_size), MP_OBJ_NEW_SMALL_INT(BLAKE2S_DIGEST_LENGTH) }, + {MP_ROM_QSTR(MP_QSTR_update), + MP_ROM_PTR(&mod_trezorcrypto_Blake2s_update_obj)}, + {MP_ROM_QSTR(MP_QSTR_digest), + MP_ROM_PTR(&mod_trezorcrypto_Blake2s_digest_obj)}, + {MP_ROM_QSTR(MP_QSTR___del__), + MP_ROM_PTR(&mod_trezorcrypto_Blake2s___del___obj)}, + {MP_ROM_QSTR(MP_QSTR_block_size), + MP_OBJ_NEW_SMALL_INT(BLAKE2S_BLOCK_LENGTH)}, + {MP_ROM_QSTR(MP_QSTR_digest_size), + MP_OBJ_NEW_SMALL_INT(BLAKE2S_DIGEST_LENGTH)}, }; -STATIC MP_DEFINE_CONST_DICT(mod_trezorcrypto_Blake2s_locals_dict, mod_trezorcrypto_Blake2s_locals_dict_table); +STATIC MP_DEFINE_CONST_DICT(mod_trezorcrypto_Blake2s_locals_dict, + mod_trezorcrypto_Blake2s_locals_dict_table); STATIC const mp_obj_type_t mod_trezorcrypto_Blake2s_type = { - { &mp_type_type }, + {&mp_type_type}, .name = MP_QSTR_Blake2s, .make_new = mod_trezorcrypto_Blake2s_make_new, - .locals_dict = (void*)&mod_trezorcrypto_Blake2s_locals_dict, + .locals_dict = (void *)&mod_trezorcrypto_Blake2s_locals_dict, }; diff --git a/embed/extmod/modtrezorcrypto/modtrezorcrypto-chacha20poly1305.h b/embed/extmod/modtrezorcrypto/modtrezorcrypto-chacha20poly1305.h index 98563f5bc..91717907a 100644 --- a/embed/extmod/modtrezorcrypto/modtrezorcrypto-chacha20poly1305.h +++ b/embed/extmod/modtrezorcrypto/modtrezorcrypto-chacha20poly1305.h @@ -29,9 +29,9 @@ /// ChaCha20Poly1305 context. /// ''' typedef struct _mp_obj_ChaCha20Poly1305_t { - mp_obj_base_t base; - chacha20poly1305_ctx ctx; - int64_t alen, plen; + mp_obj_base_t base; + chacha20poly1305_ctx ctx; + int64_t alen, plen; } mp_obj_ChaCha20Poly1305_t; /// def __init__(self, key: bytes, nonce: bytes) -> None: @@ -39,56 +39,64 @@ typedef struct _mp_obj_ChaCha20Poly1305_t { /// Initialize the ChaCha20 + Poly1305 context for encryption or decryption /// using a 32 byte key and 12 byte nonce as in the RFC 7539 style. /// ''' -STATIC mp_obj_t mod_trezorcrypto_ChaCha20Poly1305_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_kw, const mp_obj_t *args) { - mp_arg_check_num(n_args, n_kw, 2, 2, false); - mp_obj_ChaCha20Poly1305_t *o = m_new_obj(mp_obj_ChaCha20Poly1305_t); - o->base.type = type; - mp_buffer_info_t key, nonce; - mp_get_buffer_raise(args[0], &key, MP_BUFFER_READ); - mp_get_buffer_raise(args[1], &nonce, MP_BUFFER_READ); - if (key.len != 32) { - mp_raise_ValueError("Invalid length of key"); - } - if (nonce.len != 12) { - mp_raise_ValueError("Invalid length of nonce"); - } - rfc7539_init(&(o->ctx), key.buf, nonce.buf); - o->alen = 0; - o->plen = 0; - return MP_OBJ_FROM_PTR(o); +STATIC mp_obj_t mod_trezorcrypto_ChaCha20Poly1305_make_new( + const mp_obj_type_t *type, size_t n_args, size_t n_kw, + const mp_obj_t *args) { + mp_arg_check_num(n_args, n_kw, 2, 2, false); + mp_obj_ChaCha20Poly1305_t *o = m_new_obj(mp_obj_ChaCha20Poly1305_t); + o->base.type = type; + mp_buffer_info_t key, nonce; + mp_get_buffer_raise(args[0], &key, MP_BUFFER_READ); + mp_get_buffer_raise(args[1], &nonce, MP_BUFFER_READ); + if (key.len != 32) { + mp_raise_ValueError("Invalid length of key"); + } + if (nonce.len != 12) { + mp_raise_ValueError("Invalid length of nonce"); + } + rfc7539_init(&(o->ctx), key.buf, nonce.buf); + o->alen = 0; + o->plen = 0; + return MP_OBJ_FROM_PTR(o); } /// def encrypt(self, data: bytes) -> bytes: /// ''' -/// Encrypt data (length of data must be divisible by 64 except for the final value). +/// Encrypt data (length of data must be divisible by 64 except for the +/// final value). /// ''' -STATIC mp_obj_t mod_trezorcrypto_ChaCha20Poly1305_encrypt(mp_obj_t self, mp_obj_t data) { - mp_obj_ChaCha20Poly1305_t *o = MP_OBJ_TO_PTR(self); - mp_buffer_info_t in; - mp_get_buffer_raise(data, &in, MP_BUFFER_READ); - vstr_t vstr; - vstr_init_len(&vstr, in.len); - chacha20poly1305_encrypt(&(o->ctx), in.buf, (uint8_t *)vstr.buf, in.len); - o->plen += in.len; - return mp_obj_new_str_from_vstr(&mp_type_bytes, &vstr); +STATIC mp_obj_t mod_trezorcrypto_ChaCha20Poly1305_encrypt(mp_obj_t self, + mp_obj_t data) { + mp_obj_ChaCha20Poly1305_t *o = MP_OBJ_TO_PTR(self); + mp_buffer_info_t in; + mp_get_buffer_raise(data, &in, MP_BUFFER_READ); + vstr_t vstr; + vstr_init_len(&vstr, in.len); + chacha20poly1305_encrypt(&(o->ctx), in.buf, (uint8_t *)vstr.buf, in.len); + o->plen += in.len; + return mp_obj_new_str_from_vstr(&mp_type_bytes, &vstr); } -STATIC MP_DEFINE_CONST_FUN_OBJ_2(mod_trezorcrypto_ChaCha20Poly1305_encrypt_obj, mod_trezorcrypto_ChaCha20Poly1305_encrypt); +STATIC MP_DEFINE_CONST_FUN_OBJ_2(mod_trezorcrypto_ChaCha20Poly1305_encrypt_obj, + mod_trezorcrypto_ChaCha20Poly1305_encrypt); /// def decrypt(self, data: bytes) -> bytes: /// ''' -/// Decrypt data (length of data must be divisible by 64 except for the final value). +/// Decrypt data (length of data must be divisible by 64 except for the +/// final value). /// ''' -STATIC mp_obj_t mod_trezorcrypto_ChaCha20Poly1305_decrypt(mp_obj_t self, mp_obj_t data) { - mp_obj_ChaCha20Poly1305_t *o = MP_OBJ_TO_PTR(self); - mp_buffer_info_t in; - mp_get_buffer_raise(data, &in, MP_BUFFER_READ); - vstr_t vstr; - vstr_init_len(&vstr, in.len); - chacha20poly1305_decrypt(&(o->ctx), in.buf, (uint8_t *)vstr.buf, in.len); - o->plen += in.len; - return mp_obj_new_str_from_vstr(&mp_type_bytes, &vstr); +STATIC mp_obj_t mod_trezorcrypto_ChaCha20Poly1305_decrypt(mp_obj_t self, + mp_obj_t data) { + mp_obj_ChaCha20Poly1305_t *o = MP_OBJ_TO_PTR(self); + mp_buffer_info_t in; + mp_get_buffer_raise(data, &in, MP_BUFFER_READ); + vstr_t vstr; + vstr_init_len(&vstr, in.len); + chacha20poly1305_decrypt(&(o->ctx), in.buf, (uint8_t *)vstr.buf, in.len); + o->plen += in.len; + return mp_obj_new_str_from_vstr(&mp_type_bytes, &vstr); } -STATIC MP_DEFINE_CONST_FUN_OBJ_2(mod_trezorcrypto_ChaCha20Poly1305_decrypt_obj, mod_trezorcrypto_ChaCha20Poly1305_decrypt); +STATIC MP_DEFINE_CONST_FUN_OBJ_2(mod_trezorcrypto_ChaCha20Poly1305_decrypt_obj, + mod_trezorcrypto_ChaCha20Poly1305_decrypt); /// def auth(self, data: bytes) -> None: /// ''' @@ -96,49 +104,61 @@ STATIC MP_DEFINE_CONST_FUN_OBJ_2(mod_trezorcrypto_ChaCha20Poly1305_decrypt_obj, /// style with 16 byte padding. This must only be called once and prior /// to encryption or decryption. /// ''' -STATIC mp_obj_t mod_trezorcrypto_ChaCha20Poly1305_auth(mp_obj_t self, mp_obj_t data) { - mp_obj_ChaCha20Poly1305_t *o = MP_OBJ_TO_PTR(self); - mp_buffer_info_t in; - mp_get_buffer_raise(data, &in, MP_BUFFER_READ); - rfc7539_auth(&(o->ctx), in.buf, in.len); - o->alen += in.len; - return mp_const_none; +STATIC mp_obj_t mod_trezorcrypto_ChaCha20Poly1305_auth(mp_obj_t self, + mp_obj_t data) { + mp_obj_ChaCha20Poly1305_t *o = MP_OBJ_TO_PTR(self); + mp_buffer_info_t in; + mp_get_buffer_raise(data, &in, MP_BUFFER_READ); + rfc7539_auth(&(o->ctx), in.buf, in.len); + o->alen += in.len; + return mp_const_none; } -STATIC MP_DEFINE_CONST_FUN_OBJ_2(mod_trezorcrypto_ChaCha20Poly1305_auth_obj, mod_trezorcrypto_ChaCha20Poly1305_auth); +STATIC MP_DEFINE_CONST_FUN_OBJ_2(mod_trezorcrypto_ChaCha20Poly1305_auth_obj, + mod_trezorcrypto_ChaCha20Poly1305_auth); /// def finish(self) -> bytes: /// ''' /// Compute RFC 7539-style Poly1305 MAC. /// ''' STATIC mp_obj_t mod_trezorcrypto_ChaCha20Poly1305_finish(mp_obj_t self) { - mp_obj_ChaCha20Poly1305_t *o = MP_OBJ_TO_PTR(self); - uint8_t out[16]; - rfc7539_finish(&(o->ctx), o->alen, o->plen, out); - return mp_obj_new_bytes(out, sizeof(out)); + mp_obj_ChaCha20Poly1305_t *o = MP_OBJ_TO_PTR(self); + uint8_t out[16]; + rfc7539_finish(&(o->ctx), o->alen, o->plen, out); + return mp_obj_new_bytes(out, sizeof(out)); } -STATIC MP_DEFINE_CONST_FUN_OBJ_1(mod_trezorcrypto_ChaCha20Poly1305_finish_obj, mod_trezorcrypto_ChaCha20Poly1305_finish); +STATIC MP_DEFINE_CONST_FUN_OBJ_1(mod_trezorcrypto_ChaCha20Poly1305_finish_obj, + mod_trezorcrypto_ChaCha20Poly1305_finish); STATIC mp_obj_t mod_trezorcrypto_ChaCha20Poly1305___del__(mp_obj_t self) { - mp_obj_ChaCha20Poly1305_t *o = MP_OBJ_TO_PTR(self); - memzero(&(o->ctx), sizeof(chacha20poly1305_ctx)); - o->alen = 0; - o->plen = 0; - return mp_const_none; + mp_obj_ChaCha20Poly1305_t *o = MP_OBJ_TO_PTR(self); + memzero(&(o->ctx), sizeof(chacha20poly1305_ctx)); + o->alen = 0; + o->plen = 0; + return mp_const_none; } -STATIC MP_DEFINE_CONST_FUN_OBJ_1(mod_trezorcrypto_ChaCha20Poly1305___del___obj, mod_trezorcrypto_ChaCha20Poly1305___del__); +STATIC MP_DEFINE_CONST_FUN_OBJ_1(mod_trezorcrypto_ChaCha20Poly1305___del___obj, + mod_trezorcrypto_ChaCha20Poly1305___del__); -STATIC const mp_rom_map_elem_t mod_trezorcrypto_ChaCha20Poly1305_locals_dict_table[] = { - { MP_ROM_QSTR(MP_QSTR_encrypt), MP_ROM_PTR(&mod_trezorcrypto_ChaCha20Poly1305_encrypt_obj) }, - { MP_ROM_QSTR(MP_QSTR_decrypt), MP_ROM_PTR(&mod_trezorcrypto_ChaCha20Poly1305_decrypt_obj) }, - { MP_ROM_QSTR(MP_QSTR_auth), MP_ROM_PTR(&mod_trezorcrypto_ChaCha20Poly1305_auth_obj) }, - { MP_ROM_QSTR(MP_QSTR_finish), MP_ROM_PTR(&mod_trezorcrypto_ChaCha20Poly1305_finish_obj) }, - { MP_ROM_QSTR(MP_QSTR___del__), MP_ROM_PTR(&mod_trezorcrypto_ChaCha20Poly1305___del___obj) }, +STATIC const mp_rom_map_elem_t + mod_trezorcrypto_ChaCha20Poly1305_locals_dict_table[] = { + {MP_ROM_QSTR(MP_QSTR_encrypt), + MP_ROM_PTR(&mod_trezorcrypto_ChaCha20Poly1305_encrypt_obj)}, + {MP_ROM_QSTR(MP_QSTR_decrypt), + MP_ROM_PTR(&mod_trezorcrypto_ChaCha20Poly1305_decrypt_obj)}, + {MP_ROM_QSTR(MP_QSTR_auth), + MP_ROM_PTR(&mod_trezorcrypto_ChaCha20Poly1305_auth_obj)}, + {MP_ROM_QSTR(MP_QSTR_finish), + MP_ROM_PTR(&mod_trezorcrypto_ChaCha20Poly1305_finish_obj)}, + {MP_ROM_QSTR(MP_QSTR___del__), + MP_ROM_PTR(&mod_trezorcrypto_ChaCha20Poly1305___del___obj)}, }; -STATIC MP_DEFINE_CONST_DICT(mod_trezorcrypto_ChaCha20Poly1305_locals_dict, mod_trezorcrypto_ChaCha20Poly1305_locals_dict_table); +STATIC MP_DEFINE_CONST_DICT( + mod_trezorcrypto_ChaCha20Poly1305_locals_dict, + mod_trezorcrypto_ChaCha20Poly1305_locals_dict_table); STATIC const mp_obj_type_t mod_trezorcrypto_ChaCha20Poly1305_type = { - { &mp_type_type }, + {&mp_type_type}, .name = MP_QSTR_ChaCha20Poly1305, .make_new = mod_trezorcrypto_ChaCha20Poly1305_make_new, - .locals_dict = (void*)&mod_trezorcrypto_ChaCha20Poly1305_locals_dict, + .locals_dict = (void *)&mod_trezorcrypto_ChaCha20Poly1305_locals_dict, }; diff --git a/embed/extmod/modtrezorcrypto/modtrezorcrypto-crc.h b/embed/extmod/modtrezorcrypto/modtrezorcrypto-crc.h index a821c7005..42f4baf0a 100644 --- a/embed/extmod/modtrezorcrypto/modtrezorcrypto-crc.h +++ b/embed/extmod/modtrezorcrypto/modtrezorcrypto-crc.h @@ -24,21 +24,23 @@ #include "crc.h" mp_obj_t mod_trezorcrypto_crc_crc32(size_t n_args, const mp_obj_t *args) { - mp_buffer_info_t bufinfo; - mp_get_buffer_raise(args[0], &bufinfo, MP_BUFFER_READ); - uint32_t crc = (n_args > 1) ? trezor_obj_get_uint(args[1]) : 0; - crc = checksum_crc32(bufinfo.buf, bufinfo.len, crc ^ 0xffffffff); - return mp_obj_new_int_from_uint(crc ^ 0xffffffff); + mp_buffer_info_t bufinfo; + mp_get_buffer_raise(args[0], &bufinfo, MP_BUFFER_READ); + uint32_t crc = (n_args > 1) ? trezor_obj_get_uint(args[1]) : 0; + crc = checksum_crc32(bufinfo.buf, bufinfo.len, crc ^ 0xffffffff); + return mp_obj_new_int_from_uint(crc ^ 0xffffffff); } -STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(mod_trezorcrypto_crc_crc32_obj, 1, 2, mod_trezorcrypto_crc_crc32); +STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(mod_trezorcrypto_crc_crc32_obj, 1, 2, + mod_trezorcrypto_crc_crc32); STATIC const mp_rom_map_elem_t mod_trezorcrypto_crc_globals_table[] = { - { MP_ROM_QSTR(MP_QSTR___name__), MP_ROM_QSTR(MP_QSTR_crc) }, - { MP_ROM_QSTR(MP_QSTR_crc32), MP_ROM_PTR(&mod_trezorcrypto_crc_crc32_obj) }, + {MP_ROM_QSTR(MP_QSTR___name__), MP_ROM_QSTR(MP_QSTR_crc)}, + {MP_ROM_QSTR(MP_QSTR_crc32), MP_ROM_PTR(&mod_trezorcrypto_crc_crc32_obj)}, }; -STATIC MP_DEFINE_CONST_DICT(mod_trezorcrypto_crc_globals, mod_trezorcrypto_crc_globals_table); +STATIC MP_DEFINE_CONST_DICT(mod_trezorcrypto_crc_globals, + mod_trezorcrypto_crc_globals_table); STATIC const mp_obj_module_t mod_trezorcrypto_crc_module = { - .base = { &mp_type_module }, - .globals = (mp_obj_dict_t*)&mod_trezorcrypto_crc_globals, + .base = {&mp_type_module}, + .globals = (mp_obj_dict_t *)&mod_trezorcrypto_crc_globals, }; diff --git a/embed/extmod/modtrezorcrypto/modtrezorcrypto-curve25519.h b/embed/extmod/modtrezorcrypto/modtrezorcrypto-curve25519.h index bd24e6fcb..5e7b92c0f 100644 --- a/embed/extmod/modtrezorcrypto/modtrezorcrypto-curve25519.h +++ b/embed/extmod/modtrezorcrypto/modtrezorcrypto-curve25519.h @@ -30,62 +30,71 @@ /// Generate secret key. /// ''' STATIC mp_obj_t mod_trezorcrypto_curve25519_generate_secret() { - uint8_t out[32]; - random_buffer(out, 32); - // taken from https://cr.yp.to/ecdh.html - out[0] &= 248; - out[31] &= 127; - out[31] |= 64; - return mp_obj_new_bytes(out, sizeof(out)); + uint8_t out[32]; + random_buffer(out, 32); + // taken from https://cr.yp.to/ecdh.html + out[0] &= 248; + out[31] &= 127; + out[31] |= 64; + return mp_obj_new_bytes(out, sizeof(out)); } -STATIC MP_DEFINE_CONST_FUN_OBJ_0(mod_trezorcrypto_curve25519_generate_secret_obj, mod_trezorcrypto_curve25519_generate_secret); +STATIC MP_DEFINE_CONST_FUN_OBJ_0( + mod_trezorcrypto_curve25519_generate_secret_obj, + mod_trezorcrypto_curve25519_generate_secret); /// def publickey(secret_key: bytes) -> bytes: /// ''' /// Computes public key from secret key. /// ''' STATIC mp_obj_t mod_trezorcrypto_curve25519_publickey(mp_obj_t secret_key) { - mp_buffer_info_t sk; - mp_get_buffer_raise(secret_key, &sk, MP_BUFFER_READ); - if (sk.len != 32) { - mp_raise_ValueError("Invalid length of secret key"); - } - uint8_t out[32]; - curve25519_scalarmult_basepoint(out, (const uint8_t *)sk.buf); - return mp_obj_new_bytes(out, sizeof(out)); + mp_buffer_info_t sk; + mp_get_buffer_raise(secret_key, &sk, MP_BUFFER_READ); + if (sk.len != 32) { + mp_raise_ValueError("Invalid length of secret key"); + } + uint8_t out[32]; + curve25519_scalarmult_basepoint(out, (const uint8_t *)sk.buf); + return mp_obj_new_bytes(out, sizeof(out)); } -STATIC MP_DEFINE_CONST_FUN_OBJ_1(mod_trezorcrypto_curve25519_publickey_obj, mod_trezorcrypto_curve25519_publickey); +STATIC MP_DEFINE_CONST_FUN_OBJ_1(mod_trezorcrypto_curve25519_publickey_obj, + mod_trezorcrypto_curve25519_publickey); /// def multiply(secret_key: bytes, public_key: bytes) -> bytes: /// ''' -/// Multiplies point defined by public_key with scalar defined by secret_key. -/// Useful for ECDH. +/// Multiplies point defined by public_key with scalar defined by +/// secret_key. Useful for ECDH. /// ''' -STATIC mp_obj_t mod_trezorcrypto_curve25519_multiply(mp_obj_t secret_key, mp_obj_t public_key) { - mp_buffer_info_t sk, pk; - mp_get_buffer_raise(secret_key, &sk, MP_BUFFER_READ); - mp_get_buffer_raise(public_key, &pk, MP_BUFFER_READ); - if (sk.len != 32) { - mp_raise_ValueError("Invalid length of secret key"); - } - if (pk.len != 32) { - mp_raise_ValueError("Invalid length of public key"); - } - uint8_t out[32]; - curve25519_scalarmult(out, (const uint8_t *)sk.buf, (const uint8_t *)pk.buf); - return mp_obj_new_bytes(out, sizeof(out)); +STATIC mp_obj_t mod_trezorcrypto_curve25519_multiply(mp_obj_t secret_key, + mp_obj_t public_key) { + mp_buffer_info_t sk, pk; + mp_get_buffer_raise(secret_key, &sk, MP_BUFFER_READ); + mp_get_buffer_raise(public_key, &pk, MP_BUFFER_READ); + if (sk.len != 32) { + mp_raise_ValueError("Invalid length of secret key"); + } + if (pk.len != 32) { + mp_raise_ValueError("Invalid length of public key"); + } + uint8_t out[32]; + curve25519_scalarmult(out, (const uint8_t *)sk.buf, (const uint8_t *)pk.buf); + return mp_obj_new_bytes(out, sizeof(out)); } -STATIC MP_DEFINE_CONST_FUN_OBJ_2(mod_trezorcrypto_curve25519_multiply_obj, mod_trezorcrypto_curve25519_multiply); +STATIC MP_DEFINE_CONST_FUN_OBJ_2(mod_trezorcrypto_curve25519_multiply_obj, + mod_trezorcrypto_curve25519_multiply); STATIC const mp_rom_map_elem_t mod_trezorcrypto_curve25519_globals_table[] = { - { MP_ROM_QSTR(MP_QSTR___name__), MP_ROM_QSTR(MP_QSTR_curve25519) }, - { MP_ROM_QSTR(MP_QSTR_generate_secret), MP_ROM_PTR(&mod_trezorcrypto_curve25519_generate_secret_obj) }, - { MP_ROM_QSTR(MP_QSTR_publickey), MP_ROM_PTR(&mod_trezorcrypto_curve25519_publickey_obj) }, - { MP_ROM_QSTR(MP_QSTR_multiply), MP_ROM_PTR(&mod_trezorcrypto_curve25519_multiply_obj) }, + {MP_ROM_QSTR(MP_QSTR___name__), MP_ROM_QSTR(MP_QSTR_curve25519)}, + {MP_ROM_QSTR(MP_QSTR_generate_secret), + MP_ROM_PTR(&mod_trezorcrypto_curve25519_generate_secret_obj)}, + {MP_ROM_QSTR(MP_QSTR_publickey), + MP_ROM_PTR(&mod_trezorcrypto_curve25519_publickey_obj)}, + {MP_ROM_QSTR(MP_QSTR_multiply), + MP_ROM_PTR(&mod_trezorcrypto_curve25519_multiply_obj)}, }; -STATIC MP_DEFINE_CONST_DICT(mod_trezorcrypto_curve25519_globals, mod_trezorcrypto_curve25519_globals_table); +STATIC MP_DEFINE_CONST_DICT(mod_trezorcrypto_curve25519_globals, + mod_trezorcrypto_curve25519_globals_table); STATIC const mp_obj_module_t mod_trezorcrypto_curve25519_module = { - .base = { &mp_type_module }, - .globals = (mp_obj_dict_t*)&mod_trezorcrypto_curve25519_globals, + .base = {&mp_type_module}, + .globals = (mp_obj_dict_t *)&mod_trezorcrypto_curve25519_globals, }; diff --git a/embed/extmod/modtrezorcrypto/modtrezorcrypto-ed25519.h b/embed/extmod/modtrezorcrypto/modtrezorcrypto-ed25519.h index 8ed1f5ea6..5ab2b7ba5 100644 --- a/embed/extmod/modtrezorcrypto/modtrezorcrypto-ed25519.h +++ b/embed/extmod/modtrezorcrypto/modtrezorcrypto-ed25519.h @@ -19,8 +19,8 @@ #include "py/objstr.h" -#include "ed25519-donna/ed25519.h" #include "ed25519-donna/ed25519-keccak.h" +#include "ed25519-donna/ed25519.h" #include "rand.h" @@ -31,220 +31,266 @@ /// Generate secret key. /// ''' STATIC mp_obj_t mod_trezorcrypto_ed25519_generate_secret() { - uint8_t out[32]; - random_buffer(out, 32); - // taken from https://cr.yp.to/ecdh.html - out[0] &= 248; - out[31] &= 127; - out[31] |= 64; - return mp_obj_new_bytes(out, sizeof(out)); + uint8_t out[32]; + random_buffer(out, 32); + // taken from https://cr.yp.to/ecdh.html + out[0] &= 248; + out[31] &= 127; + out[31] |= 64; + return mp_obj_new_bytes(out, sizeof(out)); } -STATIC MP_DEFINE_CONST_FUN_OBJ_0(mod_trezorcrypto_ed25519_generate_secret_obj, mod_trezorcrypto_ed25519_generate_secret); +STATIC MP_DEFINE_CONST_FUN_OBJ_0(mod_trezorcrypto_ed25519_generate_secret_obj, + mod_trezorcrypto_ed25519_generate_secret); /// def publickey(secret_key: bytes) -> bytes: /// ''' /// Computes public key from secret key. /// ''' STATIC mp_obj_t mod_trezorcrypto_ed25519_publickey(mp_obj_t secret_key) { - mp_buffer_info_t sk; - mp_get_buffer_raise(secret_key, &sk, MP_BUFFER_READ); - if (sk.len != 32) { - mp_raise_ValueError("Invalid length of secret key"); - } - uint8_t out[32]; - ed25519_publickey(*(const ed25519_secret_key *)sk.buf, *(ed25519_public_key *)out); - return mp_obj_new_bytes(out, sizeof(out)); + mp_buffer_info_t sk; + mp_get_buffer_raise(secret_key, &sk, MP_BUFFER_READ); + if (sk.len != 32) { + mp_raise_ValueError("Invalid length of secret key"); + } + uint8_t out[32]; + ed25519_publickey(*(const ed25519_secret_key *)sk.buf, + *(ed25519_public_key *)out); + return mp_obj_new_bytes(out, sizeof(out)); } -STATIC MP_DEFINE_CONST_FUN_OBJ_1(mod_trezorcrypto_ed25519_publickey_obj, mod_trezorcrypto_ed25519_publickey); +STATIC MP_DEFINE_CONST_FUN_OBJ_1(mod_trezorcrypto_ed25519_publickey_obj, + mod_trezorcrypto_ed25519_publickey); /// def sign(secret_key: bytes, message: bytes, hasher: str='') -> bytes: /// ''' /// Uses secret key to produce the signature of message. /// ''' -STATIC mp_obj_t mod_trezorcrypto_ed25519_sign(size_t n_args, const mp_obj_t *args) { - mp_buffer_info_t sk, msg; - mp_get_buffer_raise(args[0], &sk, MP_BUFFER_READ); - mp_get_buffer_raise(args[1], &msg, MP_BUFFER_READ); - if (sk.len != 32) { - mp_raise_ValueError("Invalid length of secret key"); - } - if (msg.len == 0) { - mp_raise_ValueError("Empty data to sign"); - } - ed25519_public_key pk; - uint8_t out[64]; - mp_buffer_info_t hash_func; - - if (n_args == 3) { - mp_get_buffer_raise(args[2], &hash_func, MP_BUFFER_READ); - // if hash_func == 'keccak': - if (memcmp(hash_func.buf, "keccak", sizeof("keccak")) == 0) { - ed25519_publickey_keccak(*(const ed25519_secret_key *)sk.buf, pk); - ed25519_sign_keccak(msg.buf, msg.len, *(const ed25519_secret_key *)sk.buf, pk, *(ed25519_signature *)out); - } else { - mp_raise_ValueError("Unknown hash function"); - } +STATIC mp_obj_t mod_trezorcrypto_ed25519_sign(size_t n_args, + const mp_obj_t *args) { + mp_buffer_info_t sk, msg; + mp_get_buffer_raise(args[0], &sk, MP_BUFFER_READ); + mp_get_buffer_raise(args[1], &msg, MP_BUFFER_READ); + if (sk.len != 32) { + mp_raise_ValueError("Invalid length of secret key"); + } + if (msg.len == 0) { + mp_raise_ValueError("Empty data to sign"); + } + ed25519_public_key pk; + uint8_t out[64]; + mp_buffer_info_t hash_func; + + if (n_args == 3) { + mp_get_buffer_raise(args[2], &hash_func, MP_BUFFER_READ); + // if hash_func == 'keccak': + if (memcmp(hash_func.buf, "keccak", sizeof("keccak")) == 0) { + ed25519_publickey_keccak(*(const ed25519_secret_key *)sk.buf, pk); + ed25519_sign_keccak(msg.buf, msg.len, *(const ed25519_secret_key *)sk.buf, + pk, *(ed25519_signature *)out); } else { - ed25519_publickey(*(const ed25519_secret_key *)sk.buf, pk); - ed25519_sign(msg.buf, msg.len, *(const ed25519_secret_key *)sk.buf, pk, *(ed25519_signature *)out); + mp_raise_ValueError("Unknown hash function"); } + } else { + ed25519_publickey(*(const ed25519_secret_key *)sk.buf, pk); + ed25519_sign(msg.buf, msg.len, *(const ed25519_secret_key *)sk.buf, pk, + *(ed25519_signature *)out); + } - return mp_obj_new_bytes(out, sizeof(out)); + return mp_obj_new_bytes(out, sizeof(out)); } -STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(mod_trezorcrypto_ed25519_sign_obj, 2, 3, mod_trezorcrypto_ed25519_sign); +STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(mod_trezorcrypto_ed25519_sign_obj, 2, + 3, mod_trezorcrypto_ed25519_sign); -/// def sign_ext(secret_key: bytes, secret_extension: bytes, message: bytes) -> bytes: +/// def sign_ext(secret_key: bytes, secret_extension: bytes, message: bytes) -> +/// bytes: /// ''' /// Uses secret key to produce the cardano signature of message. /// ''' -STATIC mp_obj_t mod_trezorcrypto_ed25519_sign_ext(mp_obj_t secret_key, mp_obj_t secret_extension, mp_obj_t message) { - mp_buffer_info_t sk, skext, msg; - mp_get_buffer_raise(secret_key, &sk, MP_BUFFER_READ); - mp_get_buffer_raise(secret_extension, &skext, MP_BUFFER_READ); - mp_get_buffer_raise(message, &msg, MP_BUFFER_READ); - if (sk.len != 32) { - mp_raise_ValueError("Invalid length of secret key"); - } - if (skext.len != 32) { - mp_raise_ValueError("Invalid length of secret key extension"); - } - if (msg.len == 0) { - mp_raise_ValueError("Empty data to sign"); - } - ed25519_public_key pk; +STATIC mp_obj_t mod_trezorcrypto_ed25519_sign_ext(mp_obj_t secret_key, + mp_obj_t secret_extension, + mp_obj_t message) { + mp_buffer_info_t sk, skext, msg; + mp_get_buffer_raise(secret_key, &sk, MP_BUFFER_READ); + mp_get_buffer_raise(secret_extension, &skext, MP_BUFFER_READ); + mp_get_buffer_raise(message, &msg, MP_BUFFER_READ); + if (sk.len != 32) { + mp_raise_ValueError("Invalid length of secret key"); + } + if (skext.len != 32) { + mp_raise_ValueError("Invalid length of secret key extension"); + } + if (msg.len == 0) { + mp_raise_ValueError("Empty data to sign"); + } + ed25519_public_key pk; - ed25519_publickey_ext(*(const ed25519_secret_key *)sk.buf, *(const ed25519_secret_key *)skext.buf, pk); - uint8_t out[64]; - ed25519_sign_ext(msg.buf, msg.len, *(const ed25519_secret_key *)sk.buf, *(const ed25519_secret_key *)skext.buf, pk, *(ed25519_signature *)out); - return mp_obj_new_bytes(out, sizeof(out)); + ed25519_publickey_ext(*(const ed25519_secret_key *)sk.buf, + *(const ed25519_secret_key *)skext.buf, pk); + uint8_t out[64]; + ed25519_sign_ext(msg.buf, msg.len, *(const ed25519_secret_key *)sk.buf, + *(const ed25519_secret_key *)skext.buf, pk, + *(ed25519_signature *)out); + return mp_obj_new_bytes(out, sizeof(out)); } -STATIC MP_DEFINE_CONST_FUN_OBJ_3(mod_trezorcrypto_ed25519_sign_ext_obj, mod_trezorcrypto_ed25519_sign_ext); +STATIC MP_DEFINE_CONST_FUN_OBJ_3(mod_trezorcrypto_ed25519_sign_ext_obj, + mod_trezorcrypto_ed25519_sign_ext); /// def verify(public_key: bytes, signature: bytes, message: bytes) -> bool: /// ''' /// Uses public key to verify the signature of the message. /// Returns True on success. /// ''' -STATIC mp_obj_t mod_trezorcrypto_ed25519_verify(mp_obj_t public_key, mp_obj_t signature, mp_obj_t message) { - mp_buffer_info_t pk, sig, msg; - mp_get_buffer_raise(public_key, &pk, MP_BUFFER_READ); - mp_get_buffer_raise(signature, &sig, MP_BUFFER_READ); - mp_get_buffer_raise(message, &msg, MP_BUFFER_READ); - if (pk.len != 32) { - mp_raise_ValueError("Invalid length of public key"); - } - if (sig.len != 64) { - mp_raise_ValueError("Invalid length of signature"); - } - if (msg.len == 0) { - mp_raise_ValueError("Empty data to verify"); - } - return (0 == ed25519_sign_open(msg.buf, msg.len, *(const ed25519_public_key *)pk.buf, *(const ed25519_signature *)sig.buf)) ? mp_const_true : mp_const_false; +STATIC mp_obj_t mod_trezorcrypto_ed25519_verify(mp_obj_t public_key, + mp_obj_t signature, + mp_obj_t message) { + mp_buffer_info_t pk, sig, msg; + mp_get_buffer_raise(public_key, &pk, MP_BUFFER_READ); + mp_get_buffer_raise(signature, &sig, MP_BUFFER_READ); + mp_get_buffer_raise(message, &msg, MP_BUFFER_READ); + if (pk.len != 32) { + mp_raise_ValueError("Invalid length of public key"); + } + if (sig.len != 64) { + mp_raise_ValueError("Invalid length of signature"); + } + if (msg.len == 0) { + mp_raise_ValueError("Empty data to verify"); + } + return (0 == ed25519_sign_open(msg.buf, msg.len, + *(const ed25519_public_key *)pk.buf, + *(const ed25519_signature *)sig.buf)) + ? mp_const_true + : mp_const_false; } -STATIC MP_DEFINE_CONST_FUN_OBJ_3(mod_trezorcrypto_ed25519_verify_obj, mod_trezorcrypto_ed25519_verify); +STATIC MP_DEFINE_CONST_FUN_OBJ_3(mod_trezorcrypto_ed25519_verify_obj, + mod_trezorcrypto_ed25519_verify); /// def cosi_combine_publickeys(public_keys: List[bytes]) -> bytes: /// ''' /// Combines a list of public keys used in COSI cosigning scheme. /// ''' -STATIC mp_obj_t mod_trezorcrypto_ed25519_cosi_combine_publickeys(mp_obj_t public_keys) { - size_t pklen; - mp_obj_t *pkitems; - mp_obj_get_array(public_keys, &pklen, &pkitems); - if (pklen > 15) { - mp_raise_ValueError("Can't combine more than 15 public keys"); - } - mp_buffer_info_t buf; - ed25519_public_key pks[pklen]; - for (int i = 0; i < pklen; i++) { - mp_get_buffer_raise(pkitems[i], &buf, MP_BUFFER_READ); - if (buf.len != 32) { - mp_raise_ValueError("Invalid length of public key"); - } - memcpy(pks[i], buf.buf, buf.len); +STATIC mp_obj_t +mod_trezorcrypto_ed25519_cosi_combine_publickeys(mp_obj_t public_keys) { + size_t pklen; + mp_obj_t *pkitems; + mp_obj_get_array(public_keys, &pklen, &pkitems); + if (pklen > 15) { + mp_raise_ValueError("Can't combine more than 15 public keys"); + } + mp_buffer_info_t buf; + ed25519_public_key pks[pklen]; + for (int i = 0; i < pklen; i++) { + mp_get_buffer_raise(pkitems[i], &buf, MP_BUFFER_READ); + if (buf.len != 32) { + mp_raise_ValueError("Invalid length of public key"); } - uint8_t out[32]; - if (0 != ed25519_cosi_combine_publickeys(*(ed25519_public_key *)out, pks, pklen)) { - mp_raise_ValueError("Error combining public keys"); - } - return mp_obj_new_bytes(out, sizeof(out)); + memcpy(pks[i], buf.buf, buf.len); + } + uint8_t out[32]; + if (0 != + ed25519_cosi_combine_publickeys(*(ed25519_public_key *)out, pks, pklen)) { + mp_raise_ValueError("Error combining public keys"); + } + return mp_obj_new_bytes(out, sizeof(out)); } -STATIC MP_DEFINE_CONST_FUN_OBJ_1(mod_trezorcrypto_ed25519_cosi_combine_publickeys_obj, mod_trezorcrypto_ed25519_cosi_combine_publickeys); +STATIC MP_DEFINE_CONST_FUN_OBJ_1( + mod_trezorcrypto_ed25519_cosi_combine_publickeys_obj, + mod_trezorcrypto_ed25519_cosi_combine_publickeys); /// def cosi_combine_signatures(R: bytes, signatures: List[bytes]) -> bytes: /// ''' /// Combines a list of signatures used in COSI cosigning scheme. /// ''' -STATIC mp_obj_t mod_trezorcrypto_ed25519_cosi_combine_signatures(mp_obj_t R, mp_obj_t signatures) { - mp_buffer_info_t sigR; - mp_get_buffer_raise(R, &sigR, MP_BUFFER_READ); - if (sigR.len != 32) { - mp_raise_ValueError("Invalid length of R"); - } - size_t siglen; - mp_obj_t *sigitems; - mp_obj_get_array(signatures, &siglen, &sigitems); - if (siglen > 15) { - mp_raise_ValueError("Can't combine more than 15 COSI signatures"); +STATIC mp_obj_t mod_trezorcrypto_ed25519_cosi_combine_signatures( + mp_obj_t R, mp_obj_t signatures) { + mp_buffer_info_t sigR; + mp_get_buffer_raise(R, &sigR, MP_BUFFER_READ); + if (sigR.len != 32) { + mp_raise_ValueError("Invalid length of R"); + } + size_t siglen; + mp_obj_t *sigitems; + mp_obj_get_array(signatures, &siglen, &sigitems); + if (siglen > 15) { + mp_raise_ValueError("Can't combine more than 15 COSI signatures"); + } + mp_buffer_info_t buf; + ed25519_cosi_signature sigs[siglen]; + for (int i = 0; i < siglen; i++) { + mp_get_buffer_raise(sigitems[i], &buf, MP_BUFFER_READ); + if (buf.len != 32) { + mp_raise_ValueError("Invalid length of COSI signature"); } - mp_buffer_info_t buf; - ed25519_cosi_signature sigs[siglen]; - for (int i = 0; i < siglen; i++) { - mp_get_buffer_raise(sigitems[i], &buf, MP_BUFFER_READ); - if (buf.len != 32) { - mp_raise_ValueError("Invalid length of COSI signature"); - } - memcpy(sigs[i], buf.buf, buf.len); - } - uint8_t out[64]; - ed25519_cosi_combine_signatures(*(ed25519_signature *)out, *(const ed25519_public_key *)sigR.buf, sigs, siglen); - return mp_obj_new_bytes(out, sizeof(out)); + memcpy(sigs[i], buf.buf, buf.len); + } + uint8_t out[64]; + ed25519_cosi_combine_signatures(*(ed25519_signature *)out, + *(const ed25519_public_key *)sigR.buf, sigs, + siglen); + return mp_obj_new_bytes(out, sizeof(out)); } -STATIC MP_DEFINE_CONST_FUN_OBJ_2(mod_trezorcrypto_ed25519_cosi_combine_signatures_obj, mod_trezorcrypto_ed25519_cosi_combine_signatures); +STATIC MP_DEFINE_CONST_FUN_OBJ_2( + mod_trezorcrypto_ed25519_cosi_combine_signatures_obj, + mod_trezorcrypto_ed25519_cosi_combine_signatures); -/// def cosi_sign(secret_key: bytes, message: bytes, nonce: bytes, sigR: bytes, combined_pubkey: bytes) -> bytes: +/// def cosi_sign(secret_key: bytes, message: bytes, nonce: bytes, sigR: bytes, +/// combined_pubkey: bytes) -> bytes: /// ''' /// Produce signature of message using COSI cosigning scheme. /// ''' -STATIC mp_obj_t mod_trezorcrypto_ed25519_cosi_sign(size_t n_args, const mp_obj_t *args) { - mp_buffer_info_t sk, msg, nonce, sigR, pk; - mp_get_buffer_raise(args[0], &sk, MP_BUFFER_READ); - mp_get_buffer_raise(args[1], &msg, MP_BUFFER_READ); - mp_get_buffer_raise(args[2], &nonce, MP_BUFFER_READ); - mp_get_buffer_raise(args[3], &sigR, MP_BUFFER_READ); - mp_get_buffer_raise(args[4], &pk, MP_BUFFER_READ); - if (sk.len != 32) { - mp_raise_ValueError("Invalid length of secret key"); - } - if (nonce.len != 32) { - mp_raise_ValueError("Invalid length of nonce"); - } - if (sigR.len != 32) { - mp_raise_ValueError("Invalid length of R"); - } - if (pk.len != 32) { - mp_raise_ValueError("Invalid length of aggregated public key"); - } - uint8_t out[32]; - ed25519_cosi_sign(msg.buf, msg.len, *(const ed25519_secret_key *)sk.buf, *(const ed25519_secret_key *)nonce.buf, *(const ed25519_public_key *)sigR.buf, *(const ed25519_secret_key *)pk.buf, *(ed25519_cosi_signature *)out); - return mp_obj_new_bytes(out, sizeof(out)); +STATIC mp_obj_t mod_trezorcrypto_ed25519_cosi_sign(size_t n_args, + const mp_obj_t *args) { + mp_buffer_info_t sk, msg, nonce, sigR, pk; + mp_get_buffer_raise(args[0], &sk, MP_BUFFER_READ); + mp_get_buffer_raise(args[1], &msg, MP_BUFFER_READ); + mp_get_buffer_raise(args[2], &nonce, MP_BUFFER_READ); + mp_get_buffer_raise(args[3], &sigR, MP_BUFFER_READ); + mp_get_buffer_raise(args[4], &pk, MP_BUFFER_READ); + if (sk.len != 32) { + mp_raise_ValueError("Invalid length of secret key"); + } + if (nonce.len != 32) { + mp_raise_ValueError("Invalid length of nonce"); + } + if (sigR.len != 32) { + mp_raise_ValueError("Invalid length of R"); + } + if (pk.len != 32) { + mp_raise_ValueError("Invalid length of aggregated public key"); + } + uint8_t out[32]; + ed25519_cosi_sign(msg.buf, msg.len, *(const ed25519_secret_key *)sk.buf, + *(const ed25519_secret_key *)nonce.buf, + *(const ed25519_public_key *)sigR.buf, + *(const ed25519_secret_key *)pk.buf, + *(ed25519_cosi_signature *)out); + return mp_obj_new_bytes(out, sizeof(out)); } -STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(mod_trezorcrypto_ed25519_cosi_sign_obj, 5, 5, mod_trezorcrypto_ed25519_cosi_sign); +STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN( + mod_trezorcrypto_ed25519_cosi_sign_obj, 5, 5, + mod_trezorcrypto_ed25519_cosi_sign); STATIC const mp_rom_map_elem_t mod_trezorcrypto_ed25519_globals_table[] = { - { MP_ROM_QSTR(MP_QSTR___name__), MP_ROM_QSTR(MP_QSTR_ed25519) }, - { MP_ROM_QSTR(MP_QSTR_generate_secret), MP_ROM_PTR(&mod_trezorcrypto_ed25519_generate_secret_obj) }, - { MP_ROM_QSTR(MP_QSTR_publickey), MP_ROM_PTR(&mod_trezorcrypto_ed25519_publickey_obj) }, - { MP_ROM_QSTR(MP_QSTR_sign), MP_ROM_PTR(&mod_trezorcrypto_ed25519_sign_obj) }, - { MP_ROM_QSTR(MP_QSTR_sign_ext), MP_ROM_PTR(&mod_trezorcrypto_ed25519_sign_ext_obj) }, - { MP_ROM_QSTR(MP_QSTR_verify), MP_ROM_PTR(&mod_trezorcrypto_ed25519_verify_obj) }, - { MP_ROM_QSTR(MP_QSTR_cosi_combine_publickeys), MP_ROM_PTR(&mod_trezorcrypto_ed25519_cosi_combine_publickeys_obj) }, - { MP_ROM_QSTR(MP_QSTR_cosi_combine_signatures), MP_ROM_PTR(&mod_trezorcrypto_ed25519_cosi_combine_signatures_obj) }, - { MP_ROM_QSTR(MP_QSTR_cosi_sign), MP_ROM_PTR(&mod_trezorcrypto_ed25519_cosi_sign_obj) }, + {MP_ROM_QSTR(MP_QSTR___name__), MP_ROM_QSTR(MP_QSTR_ed25519)}, + {MP_ROM_QSTR(MP_QSTR_generate_secret), + MP_ROM_PTR(&mod_trezorcrypto_ed25519_generate_secret_obj)}, + {MP_ROM_QSTR(MP_QSTR_publickey), + MP_ROM_PTR(&mod_trezorcrypto_ed25519_publickey_obj)}, + {MP_ROM_QSTR(MP_QSTR_sign), MP_ROM_PTR(&mod_trezorcrypto_ed25519_sign_obj)}, + {MP_ROM_QSTR(MP_QSTR_sign_ext), + MP_ROM_PTR(&mod_trezorcrypto_ed25519_sign_ext_obj)}, + {MP_ROM_QSTR(MP_QSTR_verify), + MP_ROM_PTR(&mod_trezorcrypto_ed25519_verify_obj)}, + {MP_ROM_QSTR(MP_QSTR_cosi_combine_publickeys), + MP_ROM_PTR(&mod_trezorcrypto_ed25519_cosi_combine_publickeys_obj)}, + {MP_ROM_QSTR(MP_QSTR_cosi_combine_signatures), + MP_ROM_PTR(&mod_trezorcrypto_ed25519_cosi_combine_signatures_obj)}, + {MP_ROM_QSTR(MP_QSTR_cosi_sign), + MP_ROM_PTR(&mod_trezorcrypto_ed25519_cosi_sign_obj)}, }; -STATIC MP_DEFINE_CONST_DICT(mod_trezorcrypto_ed25519_globals, mod_trezorcrypto_ed25519_globals_table); +STATIC MP_DEFINE_CONST_DICT(mod_trezorcrypto_ed25519_globals, + mod_trezorcrypto_ed25519_globals_table); STATIC const mp_obj_module_t mod_trezorcrypto_ed25519_module = { - .base = { &mp_type_module }, - .globals = (mp_obj_dict_t*)&mod_trezorcrypto_ed25519_globals, + .base = {&mp_type_module}, + .globals = (mp_obj_dict_t *)&mod_trezorcrypto_ed25519_globals, }; diff --git a/embed/extmod/modtrezorcrypto/modtrezorcrypto-groestl.h b/embed/extmod/modtrezorcrypto/modtrezorcrypto-groestl.h index 396d536aa..637453e28 100644 --- a/embed/extmod/modtrezorcrypto/modtrezorcrypto-groestl.h +++ b/embed/extmod/modtrezorcrypto/modtrezorcrypto-groestl.h @@ -32,76 +32,90 @@ /// GROESTL512 context. /// ''' typedef struct _mp_obj_Groestl512_t { - mp_obj_base_t base; - GROESTL512_CTX ctx; + mp_obj_base_t base; + GROESTL512_CTX ctx; } mp_obj_Groestl512_t; -STATIC mp_obj_t mod_trezorcrypto_Groestl512_update(mp_obj_t self, mp_obj_t data); +STATIC mp_obj_t mod_trezorcrypto_Groestl512_update(mp_obj_t self, + mp_obj_t data); /// def __init__(self, data: bytes = None) -> None: /// ''' /// Creates a hash context object. /// ''' -STATIC mp_obj_t mod_trezorcrypto_Groestl512_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_kw, const mp_obj_t *args) { - mp_arg_check_num(n_args, n_kw, 0, 1, false); - mp_obj_Groestl512_t *o = m_new_obj(mp_obj_Groestl512_t); - o->base.type = type; - groestl512_Init(&(o->ctx)); - if (n_args == 1) { - mod_trezorcrypto_Groestl512_update(MP_OBJ_FROM_PTR(o), args[0]); - } - return MP_OBJ_FROM_PTR(o); +STATIC mp_obj_t mod_trezorcrypto_Groestl512_make_new(const mp_obj_type_t *type, + size_t n_args, size_t n_kw, + const mp_obj_t *args) { + mp_arg_check_num(n_args, n_kw, 0, 1, false); + mp_obj_Groestl512_t *o = m_new_obj(mp_obj_Groestl512_t); + o->base.type = type; + groestl512_Init(&(o->ctx)); + if (n_args == 1) { + mod_trezorcrypto_Groestl512_update(MP_OBJ_FROM_PTR(o), args[0]); + } + return MP_OBJ_FROM_PTR(o); } /// def update(self, data: bytes) -> None: /// ''' /// Update the hash context with hashed data. /// ''' -STATIC mp_obj_t mod_trezorcrypto_Groestl512_update(mp_obj_t self, mp_obj_t data) { - mp_obj_Groestl512_t *o = MP_OBJ_TO_PTR(self); - mp_buffer_info_t msg; - mp_get_buffer_raise(data, &msg, MP_BUFFER_READ); - if (msg.len > 0) { - groestl512_Update(&(o->ctx), msg.buf, msg.len); - } - return mp_const_none; +STATIC mp_obj_t mod_trezorcrypto_Groestl512_update(mp_obj_t self, + mp_obj_t data) { + mp_obj_Groestl512_t *o = MP_OBJ_TO_PTR(self); + mp_buffer_info_t msg; + mp_get_buffer_raise(data, &msg, MP_BUFFER_READ); + if (msg.len > 0) { + groestl512_Update(&(o->ctx), msg.buf, msg.len); + } + return mp_const_none; } -STATIC MP_DEFINE_CONST_FUN_OBJ_2(mod_trezorcrypto_Groestl512_update_obj, mod_trezorcrypto_Groestl512_update); +STATIC MP_DEFINE_CONST_FUN_OBJ_2(mod_trezorcrypto_Groestl512_update_obj, + mod_trezorcrypto_Groestl512_update); /// def digest(self) -> bytes: /// ''' /// Returns the digest of hashed data. /// ''' STATIC mp_obj_t mod_trezorcrypto_Groestl512_digest(mp_obj_t self) { - mp_obj_Groestl512_t *o = MP_OBJ_TO_PTR(self); - uint8_t out[GROESTL512_DIGEST_LENGTH]; - GROESTL512_CTX ctx; - memcpy(&ctx, &(o->ctx), sizeof(GROESTL512_CTX)); - groestl512_Final(&ctx, out); - memzero(&ctx, sizeof(GROESTL512_CTX)); - return mp_obj_new_bytes(out, sizeof(out)); + mp_obj_Groestl512_t *o = MP_OBJ_TO_PTR(self); + uint8_t out[GROESTL512_DIGEST_LENGTH]; + GROESTL512_CTX ctx; + memcpy(&ctx, &(o->ctx), sizeof(GROESTL512_CTX)); + groestl512_Final(&ctx, out); + memzero(&ctx, sizeof(GROESTL512_CTX)); + return mp_obj_new_bytes(out, sizeof(out)); } -STATIC MP_DEFINE_CONST_FUN_OBJ_1(mod_trezorcrypto_Groestl512_digest_obj, mod_trezorcrypto_Groestl512_digest); +STATIC MP_DEFINE_CONST_FUN_OBJ_1(mod_trezorcrypto_Groestl512_digest_obj, + mod_trezorcrypto_Groestl512_digest); STATIC mp_obj_t mod_trezorcrypto_Groestl512___del__(mp_obj_t self) { - mp_obj_Groestl512_t *o = MP_OBJ_TO_PTR(self); - memzero(&(o->ctx), sizeof(GROESTL512_CTX)); - return mp_const_none; + mp_obj_Groestl512_t *o = MP_OBJ_TO_PTR(self); + memzero(&(o->ctx), sizeof(GROESTL512_CTX)); + return mp_const_none; } -STATIC MP_DEFINE_CONST_FUN_OBJ_1(mod_trezorcrypto_Groestl512___del___obj, mod_trezorcrypto_Groestl512___del__); +STATIC MP_DEFINE_CONST_FUN_OBJ_1(mod_trezorcrypto_Groestl512___del___obj, + mod_trezorcrypto_Groestl512___del__); -STATIC const mp_rom_map_elem_t mod_trezorcrypto_Groestl512_locals_dict_table[] = { - { MP_ROM_QSTR(MP_QSTR_update), MP_ROM_PTR(&mod_trezorcrypto_Groestl512_update_obj) }, - { MP_ROM_QSTR(MP_QSTR_digest), MP_ROM_PTR(&mod_trezorcrypto_Groestl512_digest_obj) }, - { MP_ROM_QSTR(MP_QSTR___del__), MP_ROM_PTR(&mod_trezorcrypto_Groestl512___del___obj) }, - { MP_ROM_QSTR(MP_QSTR_block_size), MP_OBJ_NEW_SMALL_INT(GROESTL512_BLOCK_LENGTH) }, - { MP_ROM_QSTR(MP_QSTR_digest_size), MP_OBJ_NEW_SMALL_INT(GROESTL512_DIGEST_LENGTH) }, +STATIC const mp_rom_map_elem_t + mod_trezorcrypto_Groestl512_locals_dict_table[] = { + {MP_ROM_QSTR(MP_QSTR_update), + MP_ROM_PTR(&mod_trezorcrypto_Groestl512_update_obj)}, + {MP_ROM_QSTR(MP_QSTR_digest), + MP_ROM_PTR(&mod_trezorcrypto_Groestl512_digest_obj)}, + {MP_ROM_QSTR(MP_QSTR___del__), + MP_ROM_PTR(&mod_trezorcrypto_Groestl512___del___obj)}, + {MP_ROM_QSTR(MP_QSTR_block_size), + MP_OBJ_NEW_SMALL_INT(GROESTL512_BLOCK_LENGTH)}, + {MP_ROM_QSTR(MP_QSTR_digest_size), + MP_OBJ_NEW_SMALL_INT(GROESTL512_DIGEST_LENGTH)}, }; -STATIC MP_DEFINE_CONST_DICT(mod_trezorcrypto_Groestl512_locals_dict, mod_trezorcrypto_Groestl512_locals_dict_table); +STATIC MP_DEFINE_CONST_DICT(mod_trezorcrypto_Groestl512_locals_dict, + mod_trezorcrypto_Groestl512_locals_dict_table); STATIC const mp_obj_type_t mod_trezorcrypto_Groestl512_type = { - { &mp_type_type }, + {&mp_type_type}, .name = MP_QSTR_Groestl512, .make_new = mod_trezorcrypto_Groestl512_make_new, - .locals_dict = (void*)&mod_trezorcrypto_Groestl512_locals_dict, + .locals_dict = (void *)&mod_trezorcrypto_Groestl512_locals_dict, }; diff --git a/embed/extmod/modtrezorcrypto/modtrezorcrypto-monero.h b/embed/extmod/modtrezorcrypto/modtrezorcrypto-monero.h index 995f47961..5993eed20 100644 --- a/embed/extmod/modtrezorcrypto/modtrezorcrypto-monero.h +++ b/embed/extmod/modtrezorcrypto/modtrezorcrypto-monero.h @@ -17,34 +17,31 @@ * along with this program. If not, see . */ -#include "py/objstr.h" -#include "py/objint.h" #include "py/mpz.h" +#include "py/objint.h" +#include "py/objstr.h" -#include "monero/monero.h" #include "bignum.h" #include "memzero.h" +#include "monero/monero.h" /// package: trezorcrypto.monero - - typedef struct _mp_obj_hasher_t { - mp_obj_base_t base; - Hasher h; + mp_obj_base_t base; + Hasher h; } mp_obj_hasher_t; typedef struct _mp_obj_ge25519_t { - mp_obj_base_t base; - ge25519 p; + mp_obj_base_t base; + ge25519 p; } mp_obj_ge25519_t; typedef struct _mp_obj_bignum256modm_t { - mp_obj_base_t base; - bignum256modm p; + mp_obj_base_t base; + bignum256modm p; } mp_obj_bignum256modm_t; - // // Helpers // @@ -53,126 +50,127 @@ STATIC const mp_obj_type_t mod_trezorcrypto_monero_ge25519_type; STATIC const mp_obj_type_t mod_trezorcrypto_monero_bignum256modm_type; STATIC const mp_obj_type_t mod_trezorcrypto_monero_hasher_type; -#define MP_OBJ_IS_GE25519(o) MP_OBJ_IS_TYPE((o), &mod_trezorcrypto_monero_ge25519_type) -#define MP_OBJ_IS_SCALAR(o) MP_OBJ_IS_TYPE((o), &mod_trezorcrypto_monero_bignum256modm_type) -#define MP_OBJ_PTR_MPC_GE25519(o) ((const mp_obj_ge25519_t*) (o)) -#define MP_OBJ_PTR_MPC_SCALAR(o) ((const mp_obj_bignum256modm_t*) (o)) -#define MP_OBJ_PTR_MP_GE25519(o) ((mp_obj_ge25519_t*) (o)) -#define MP_OBJ_PTR_MP_SCALAR(o) ((mp_obj_bignum256modm_t*) (o)) +#define MP_OBJ_IS_GE25519(o) \ + MP_OBJ_IS_TYPE((o), &mod_trezorcrypto_monero_ge25519_type) +#define MP_OBJ_IS_SCALAR(o) \ + MP_OBJ_IS_TYPE((o), &mod_trezorcrypto_monero_bignum256modm_type) +#define MP_OBJ_PTR_MPC_GE25519(o) ((const mp_obj_ge25519_t *)(o)) +#define MP_OBJ_PTR_MPC_SCALAR(o) ((const mp_obj_bignum256modm_t *)(o)) +#define MP_OBJ_PTR_MP_GE25519(o) ((mp_obj_ge25519_t *)(o)) +#define MP_OBJ_PTR_MP_SCALAR(o) ((mp_obj_bignum256modm_t *)(o)) #define MP_OBJ_C_GE25519(o) (MP_OBJ_PTR_MPC_GE25519(o)->p) #define MP_OBJ_GE25519(o) (MP_OBJ_PTR_MP_GE25519(o)->p) #define MP_OBJ_C_SCALAR(o) (MP_OBJ_PTR_MPC_SCALAR(o)->p) #define MP_OBJ_SCALAR(o) (MP_OBJ_PTR_MP_SCALAR(o)->p) -STATIC inline void assert_ge25519(const mp_obj_t o){ - if (!MP_OBJ_IS_GE25519(o)){ - mp_raise_ValueError("ge25519 expected"); - } +STATIC inline void assert_ge25519(const mp_obj_t o) { + if (!MP_OBJ_IS_GE25519(o)) { + mp_raise_ValueError("ge25519 expected"); + } } -STATIC inline void assert_scalar(const mp_obj_t o){ - if (!MP_OBJ_IS_SCALAR(o)){ - mp_raise_ValueError("scalar expected"); - } +STATIC inline void assert_scalar(const mp_obj_t o) { + if (!MP_OBJ_IS_SCALAR(o)) { + mp_raise_ValueError("scalar expected"); + } } - static uint64_t mp_obj_uint64_get_checked(mp_const_obj_t self_in) { #if MICROPY_LONGINT_IMPL != MICROPY_LONGINT_IMPL_MPZ -# error "MPZ supported only" +#error "MPZ supported only" #endif - if (MP_OBJ_IS_SMALL_INT(self_in)) { - return MP_OBJ_SMALL_INT_VALUE(self_in); - } else { - byte buff[8]; - uint64_t res = 0; - mp_obj_t * o = MP_OBJ_TO_PTR(self_in); - - mp_obj_int_to_bytes_impl(o, true, 8, buff); - for (int i = 0; i<8; i++){ - res <<= i > 0 ? 8 : 0; - res |= (uint64_t)(buff[i] & 0xff); - } - return res; + if (MP_OBJ_IS_SMALL_INT(self_in)) { + return MP_OBJ_SMALL_INT_VALUE(self_in); + } else { + byte buff[8]; + uint64_t res = 0; + mp_obj_t *o = MP_OBJ_TO_PTR(self_in); + + mp_obj_int_to_bytes_impl(o, true, 8, buff); + for (int i = 0; i < 8; i++) { + res <<= i > 0 ? 8 : 0; + res |= (uint64_t)(buff[i] & 0xff); } + return res; + } } static uint64_t mp_obj_get_uint64(mp_const_obj_t arg) { - if (arg == mp_const_false) { - return 0; - } else if (arg == mp_const_true) { - return 1; - } else if (MP_OBJ_IS_SMALL_INT(arg)) { - return MP_OBJ_SMALL_INT_VALUE(arg); - } else if (MP_OBJ_IS_TYPE(arg, &mp_type_int)) { - return mp_obj_uint64_get_checked(arg); + if (arg == mp_const_false) { + return 0; + } else if (arg == mp_const_true) { + return 1; + } else if (MP_OBJ_IS_SMALL_INT(arg)) { + return MP_OBJ_SMALL_INT_VALUE(arg); + } else if (MP_OBJ_IS_TYPE(arg, &mp_type_int)) { + return mp_obj_uint64_get_checked(arg); + } else { + if (MICROPY_ERROR_REPORTING == MICROPY_ERROR_REPORTING_TERSE) { + mp_raise_TypeError("can't convert to int"); } else { - if (MICROPY_ERROR_REPORTING == MICROPY_ERROR_REPORTING_TERSE) { - mp_raise_TypeError("can't convert to int"); - } else { - nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_TypeError, - "can't convert %s to int", mp_obj_get_type_str(arg))); - } + nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_TypeError, + "can't convert %s to int", + mp_obj_get_type_str(arg))); } + } } -STATIC mp_obj_t mp_obj_new_scalar(){ +STATIC mp_obj_t mp_obj_new_scalar() { mp_obj_bignum256modm_t *o = m_new_obj(mp_obj_bignum256modm_t); o->base.type = &mod_trezorcrypto_monero_bignum256modm_type; set256_modm(o->p, 0); return MP_OBJ_FROM_PTR(o); } -STATIC mp_obj_t mp_obj_new_scalar_r(mp_obj_t r){ - if (r == mp_const_none){ - return mp_obj_new_scalar(); - } +STATIC mp_obj_t mp_obj_new_scalar_r(mp_obj_t r) { + if (r == mp_const_none) { + return mp_obj_new_scalar(); + } - assert_scalar(r); - return r; + assert_scalar(r); + return r; } -STATIC mp_obj_t mp_obj_new_ge25519(){ - mp_obj_ge25519_t *o = m_new_obj(mp_obj_ge25519_t); - o->base.type = &mod_trezorcrypto_monero_ge25519_type; - ge25519_set_neutral(&o->p); - return MP_OBJ_FROM_PTR(o); +STATIC mp_obj_t mp_obj_new_ge25519() { + mp_obj_ge25519_t *o = m_new_obj(mp_obj_ge25519_t); + o->base.type = &mod_trezorcrypto_monero_ge25519_type; + ge25519_set_neutral(&o->p); + return MP_OBJ_FROM_PTR(o); } -STATIC mp_obj_t mp_obj_new_ge25519_r(mp_obj_t r){ - if (r == mp_const_none){ - return mp_obj_new_ge25519(); - } +STATIC mp_obj_t mp_obj_new_ge25519_r(mp_obj_t r) { + if (r == mp_const_none) { + return mp_obj_new_ge25519(); + } - assert_ge25519(r); - return r; + assert_ge25519(r); + return r; } -STATIC void mp_unpack_ge25519(ge25519 * r, const mp_obj_t arg, mp_int_t offset){ - mp_buffer_info_t buff; - mp_get_buffer_raise(arg, &buff, MP_BUFFER_READ); - if (buff.len < 32 + offset) { - mp_raise_ValueError("Invalid length of the EC point"); - } +STATIC void mp_unpack_ge25519(ge25519 *r, const mp_obj_t arg, mp_int_t offset) { + mp_buffer_info_t buff; + mp_get_buffer_raise(arg, &buff, MP_BUFFER_READ); + if (buff.len < 32 + offset) { + mp_raise_ValueError("Invalid length of the EC point"); + } - const int res = ge25519_unpack_vartime(r, ((uint8_t*)buff.buf) + offset); - if (res != 1){ - mp_raise_ValueError("Point decoding error"); - } + const int res = ge25519_unpack_vartime(r, ((uint8_t *)buff.buf) + offset); + if (res != 1) { + mp_raise_ValueError("Point decoding error"); + } } -STATIC void mp_unpack_scalar(bignum256modm r, const mp_obj_t arg, mp_int_t offset){ - mp_buffer_info_t buff; - mp_get_buffer_raise(arg, &buff, MP_BUFFER_READ); - if (buff.len < 32 + offset) { - mp_raise_ValueError("Invalid length of secret key"); - } - expand256_modm(r, ((uint8_t*)buff.buf) + offset, 32); +STATIC void mp_unpack_scalar(bignum256modm r, const mp_obj_t arg, + mp_int_t offset) { + mp_buffer_info_t buff; + mp_get_buffer_raise(arg, &buff, MP_BUFFER_READ); + if (buff.len < 32 + offset) { + mp_raise_ValueError("Invalid length of secret key"); + } + expand256_modm(r, ((uint8_t *)buff.buf) + offset, 32); } - - // // Constructors // @@ -187,31 +185,33 @@ STATIC void mp_unpack_scalar(bignum256modm r, const mp_obj_t arg, mp_int_t offse /// Constructor /// ''' -STATIC mp_obj_t mod_trezorcrypto_monero_ge25519_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_kw, const mp_obj_t *args) { - mp_arg_check_num(n_args, n_kw, 0, 1, false); - mp_obj_ge25519_t *o = m_new_obj(mp_obj_ge25519_t); - o->base.type = type; - - if (n_args == 0 || args[0] == mp_const_none) { - ge25519_set_neutral(&o->p); - } else if (n_args == 1 && MP_OBJ_IS_GE25519(args[0])) { - ge25519_copy(&o->p, &MP_OBJ_C_GE25519(args[0])); - } else if (n_args == 1 && MP_OBJ_IS_STR_OR_BYTES(args[0])) { - mp_unpack_ge25519(&o->p, args[0], 0); - } else { - mp_raise_ValueError("Invalid ge25519 constructor"); - } +STATIC mp_obj_t mod_trezorcrypto_monero_ge25519_make_new( + const mp_obj_type_t *type, size_t n_args, size_t n_kw, + const mp_obj_t *args) { + mp_arg_check_num(n_args, n_kw, 0, 1, false); + mp_obj_ge25519_t *o = m_new_obj(mp_obj_ge25519_t); + o->base.type = type; - return MP_OBJ_FROM_PTR(o); + if (n_args == 0 || args[0] == mp_const_none) { + ge25519_set_neutral(&o->p); + } else if (n_args == 1 && MP_OBJ_IS_GE25519(args[0])) { + ge25519_copy(&o->p, &MP_OBJ_C_GE25519(args[0])); + } else if (n_args == 1 && MP_OBJ_IS_STR_OR_BYTES(args[0])) { + mp_unpack_ge25519(&o->p, args[0], 0); + } else { + mp_raise_ValueError("Invalid ge25519 constructor"); + } + + return MP_OBJ_FROM_PTR(o); } STATIC mp_obj_t mod_trezorcrypto_monero_ge25519___del__(mp_obj_t self) { - mp_obj_ge25519_t *o = MP_OBJ_TO_PTR(self); - memzero(&(o->p), sizeof(ge25519)); - return mp_const_none; + mp_obj_ge25519_t *o = MP_OBJ_TO_PTR(self); + memzero(&(o->p), sizeof(ge25519)); + return mp_const_none; } -STATIC MP_DEFINE_CONST_FUN_OBJ_1(mod_trezorcrypto_monero_ge25519___del___obj, mod_trezorcrypto_monero_ge25519___del__); - +STATIC MP_DEFINE_CONST_FUN_OBJ_1(mod_trezorcrypto_monero_ge25519___del___obj, + mod_trezorcrypto_monero_ge25519___del__); /// class Sc25519: /// ''' @@ -224,34 +224,37 @@ STATIC MP_DEFINE_CONST_FUN_OBJ_1(mod_trezorcrypto_monero_ge25519___del___obj, mo /// ''' /// /// -STATIC mp_obj_t mod_trezorcrypto_monero_bignum256modm_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_kw, const mp_obj_t *args) { - mp_arg_check_num(n_args, n_kw, 0, 1, false); - mp_obj_bignum256modm_t *o = m_new_obj(mp_obj_bignum256modm_t); - o->base.type = type; - - if (n_args == 0 || args[0] == mp_const_none) { - set256_modm(o->p, 0); - } else if (n_args == 1 && MP_OBJ_IS_SCALAR(args[0])) { - copy256_modm(o->p, MP_OBJ_C_SCALAR(args[0])); - } else if (n_args == 1 && MP_OBJ_IS_STR_OR_BYTES(args[0])) { - mp_unpack_scalar(o->p, args[0], 0); - } else if (n_args == 1 && mp_obj_is_integer(args[0])) { - uint64_t v = mp_obj_get_uint64(args[0]); - set256_modm(o->p, v); - } else { - mp_raise_ValueError("Invalid scalar constructor"); - } +STATIC mp_obj_t mod_trezorcrypto_monero_bignum256modm_make_new( + const mp_obj_type_t *type, size_t n_args, size_t n_kw, + const mp_obj_t *args) { + mp_arg_check_num(n_args, n_kw, 0, 1, false); + mp_obj_bignum256modm_t *o = m_new_obj(mp_obj_bignum256modm_t); + o->base.type = type; - return MP_OBJ_FROM_PTR(o); + if (n_args == 0 || args[0] == mp_const_none) { + set256_modm(o->p, 0); + } else if (n_args == 1 && MP_OBJ_IS_SCALAR(args[0])) { + copy256_modm(o->p, MP_OBJ_C_SCALAR(args[0])); + } else if (n_args == 1 && MP_OBJ_IS_STR_OR_BYTES(args[0])) { + mp_unpack_scalar(o->p, args[0], 0); + } else if (n_args == 1 && mp_obj_is_integer(args[0])) { + uint64_t v = mp_obj_get_uint64(args[0]); + set256_modm(o->p, v); + } else { + mp_raise_ValueError("Invalid scalar constructor"); + } + + return MP_OBJ_FROM_PTR(o); } STATIC mp_obj_t mod_trezorcrypto_monero_bignum256modm___del__(mp_obj_t self) { - mp_obj_bignum256modm_t *o = MP_OBJ_TO_PTR(self); - memzero(o->p, sizeof(bignum256modm)); - return mp_const_none; + mp_obj_bignum256modm_t *o = MP_OBJ_TO_PTR(self); + memzero(o->p, sizeof(bignum256modm)); + return mp_const_none; } -STATIC MP_DEFINE_CONST_FUN_OBJ_1(mod_trezorcrypto_monero_bignum256modm___del___obj, mod_trezorcrypto_monero_bignum256modm___del__); - +STATIC MP_DEFINE_CONST_FUN_OBJ_1( + mod_trezorcrypto_monero_bignum256modm___del___obj, + mod_trezorcrypto_monero_bignum256modm___del__); /// class Hasher: /// ''' @@ -279,7 +282,9 @@ STATIC MP_DEFINE_CONST_FUN_OBJ_1(mod_trezorcrypto_monero_bignum256modm___del___o /// ''' /// /// -STATIC mp_obj_t mod_trezorcrypto_monero_hasher_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_kw, const mp_obj_t *args) { +STATIC mp_obj_t mod_trezorcrypto_monero_hasher_make_new( + const mp_obj_type_t *type, size_t n_args, size_t n_kw, + const mp_obj_t *args) { mp_arg_check_num(n_args, n_kw, 0, 1, false); mp_obj_hasher_t *o = m_new_obj(mp_obj_hasher_t); o->base.type = type; @@ -299,8 +304,8 @@ STATIC mp_obj_t mod_trezorcrypto_monero_hasher___del__(mp_obj_t self) { memzero(&(o->h), sizeof(Hasher)); return mp_const_none; } -STATIC MP_DEFINE_CONST_FUN_OBJ_1(mod_trezorcrypto_monero_hasher___del___obj, mod_trezorcrypto_monero_hasher___del__); - +STATIC MP_DEFINE_CONST_FUN_OBJ_1(mod_trezorcrypto_monero_hasher___del___obj, + mod_trezorcrypto_monero_hasher___del__); // // Scalar defs @@ -308,246 +313,294 @@ STATIC MP_DEFINE_CONST_FUN_OBJ_1(mod_trezorcrypto_monero_hasher___del___obj, mod /// mock:global -/// def init256_modm(dst: Optional[Sc25519], val: Union[int, bytes, Sc25519]) -> Sc25519: +/// def init256_modm(dst: Optional[Sc25519], val: Union[int, bytes, Sc25519]) -> +/// Sc25519: /// ''' /// Initializes Sc25519 scalar /// ''' -STATIC mp_obj_t mod_trezorcrypto_monero_init256_modm(size_t n_args, const mp_obj_t *args){ - const bool res_arg = n_args == 2; - const int off = res_arg ? 0 : -1; - mp_obj_t res = mp_obj_new_scalar_r(res_arg ? args[0] : mp_const_none); - - if (n_args == 0 || args[0] == mp_const_none) { - set256_modm(MP_OBJ_SCALAR(res), 0); - } else if (n_args > 0 && MP_OBJ_IS_SCALAR(args[1+off])) { - copy256_modm(MP_OBJ_SCALAR(res), MP_OBJ_C_SCALAR(args[1+off])); - } else if (n_args > 0 && MP_OBJ_IS_STR_OR_BYTES(args[1+off])) { - mp_unpack_scalar(MP_OBJ_SCALAR(res), args[1+off], 0); - } else if (n_args > 0 && mp_obj_is_integer(args[1+off])) { - uint64_t v = mp_obj_get_uint64(args[1+off]); - set256_modm(MP_OBJ_SCALAR(res), v); - } else { - mp_raise_ValueError("Invalid scalar def"); - } - return res; +STATIC mp_obj_t mod_trezorcrypto_monero_init256_modm(size_t n_args, + const mp_obj_t *args) { + const bool res_arg = n_args == 2; + const int off = res_arg ? 0 : -1; + mp_obj_t res = mp_obj_new_scalar_r(res_arg ? args[0] : mp_const_none); + + if (n_args == 0 || args[0] == mp_const_none) { + set256_modm(MP_OBJ_SCALAR(res), 0); + } else if (n_args > 0 && MP_OBJ_IS_SCALAR(args[1 + off])) { + copy256_modm(MP_OBJ_SCALAR(res), MP_OBJ_C_SCALAR(args[1 + off])); + } else if (n_args > 0 && MP_OBJ_IS_STR_OR_BYTES(args[1 + off])) { + mp_unpack_scalar(MP_OBJ_SCALAR(res), args[1 + off], 0); + } else if (n_args > 0 && mp_obj_is_integer(args[1 + off])) { + uint64_t v = mp_obj_get_uint64(args[1 + off]); + set256_modm(MP_OBJ_SCALAR(res), v); + } else { + mp_raise_ValueError("Invalid scalar def"); + } + return res; } -STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(mod_trezorcrypto_monero_init256_modm_obj, 0, 2, mod_trezorcrypto_monero_init256_modm); +STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN( + mod_trezorcrypto_monero_init256_modm_obj, 0, 2, + mod_trezorcrypto_monero_init256_modm); /// def check256_modm(val: Sc25519): /// ''' /// Throws exception if scalar is invalid /// ''' -STATIC mp_obj_t mod_trezorcrypto_monero_check256_modm(const mp_obj_t arg){ - assert_scalar(arg); - if (check256_modm(MP_OBJ_C_SCALAR(arg)) != 1){ - mp_raise_ValueError("Ed25519 scalar invalid"); - } - return mp_const_none; +STATIC mp_obj_t mod_trezorcrypto_monero_check256_modm(const mp_obj_t arg) { + assert_scalar(arg); + if (check256_modm(MP_OBJ_C_SCALAR(arg)) != 1) { + mp_raise_ValueError("Ed25519 scalar invalid"); + } + return mp_const_none; } -STATIC MP_DEFINE_CONST_FUN_OBJ_1(mod_trezorcrypto_monero_check256_modm_obj, mod_trezorcrypto_monero_check256_modm); +STATIC MP_DEFINE_CONST_FUN_OBJ_1(mod_trezorcrypto_monero_check256_modm_obj, + mod_trezorcrypto_monero_check256_modm); /// def iszero256_modm(val: Sc25519) -> bool: /// ''' /// Returns False if the scalar is zero /// ''' -STATIC mp_obj_t mod_trezorcrypto_monero_iszero256_modm(const mp_obj_t arg){ - assert_scalar(arg); - const int r = iszero256_modm(MP_OBJ_C_SCALAR(arg)); - return mp_obj_new_int(r); +STATIC mp_obj_t mod_trezorcrypto_monero_iszero256_modm(const mp_obj_t arg) { + assert_scalar(arg); + const int r = iszero256_modm(MP_OBJ_C_SCALAR(arg)); + return mp_obj_new_int(r); } -STATIC MP_DEFINE_CONST_FUN_OBJ_1(mod_trezorcrypto_monero_iszero256_modm_obj, mod_trezorcrypto_monero_iszero256_modm); +STATIC MP_DEFINE_CONST_FUN_OBJ_1(mod_trezorcrypto_monero_iszero256_modm_obj, + mod_trezorcrypto_monero_iszero256_modm); /// def eq256_modm(a: Sc25519, b: Sc25519) -> int: /// ''' /// Compares scalars, returns 1 on the same value /// ''' -STATIC mp_obj_t mod_trezorcrypto_monero_eq256_modm(const mp_obj_t a, const mp_obj_t b){ - assert_scalar(a); - assert_scalar(b); - int r = eq256_modm(MP_OBJ_C_SCALAR(a), MP_OBJ_C_SCALAR(b)); - return MP_OBJ_NEW_SMALL_INT(r); +STATIC mp_obj_t mod_trezorcrypto_monero_eq256_modm(const mp_obj_t a, + const mp_obj_t b) { + assert_scalar(a); + assert_scalar(b); + int r = eq256_modm(MP_OBJ_C_SCALAR(a), MP_OBJ_C_SCALAR(b)); + return MP_OBJ_NEW_SMALL_INT(r); } -STATIC MP_DEFINE_CONST_FUN_OBJ_2(mod_trezorcrypto_monero_eq256_modm_obj, mod_trezorcrypto_monero_eq256_modm); - +STATIC MP_DEFINE_CONST_FUN_OBJ_2(mod_trezorcrypto_monero_eq256_modm_obj, + mod_trezorcrypto_monero_eq256_modm); /// def get256_modm(a: Sc25519) -> int: /// ''' -/// Extracts 64bit integer from the scalar. Raises exception if scalar is bigger than 2^64 +/// Extracts 64bit integer from the scalar. Raises exception if scalar is +/// bigger than 2^64 /// ''' -STATIC mp_obj_t mod_trezorcrypto_monero_get256_modm(const mp_obj_t arg){ - assert_scalar(arg); - uint64_t v; - if (!get256_modm(&v, MP_OBJ_C_SCALAR(arg))){ - mp_raise_ValueError("Ed25519 scalar too big"); - } - return mp_obj_new_int_from_ull(v); +STATIC mp_obj_t mod_trezorcrypto_monero_get256_modm(const mp_obj_t arg) { + assert_scalar(arg); + uint64_t v; + if (!get256_modm(&v, MP_OBJ_C_SCALAR(arg))) { + mp_raise_ValueError("Ed25519 scalar too big"); + } + return mp_obj_new_int_from_ull(v); } -STATIC MP_DEFINE_CONST_FUN_OBJ_1(mod_trezorcrypto_monero_get256_modm_obj, mod_trezorcrypto_monero_get256_modm); - +STATIC MP_DEFINE_CONST_FUN_OBJ_1(mod_trezorcrypto_monero_get256_modm_obj, + mod_trezorcrypto_monero_get256_modm); /// def add256_modm(r: Optional[Sc25519], a: Sc25519, b: Sc25519) -> Sc25519: /// ''' /// Scalar addition /// ''' -STATIC mp_obj_t mod_trezorcrypto_monero_add256_modm(size_t n_args, const mp_obj_t *args){ - const bool res_arg = n_args == 3; - const int off = res_arg ? 0 : -1; - mp_obj_t res = mp_obj_new_scalar_r(res_arg ? args[0] : mp_const_none); +STATIC mp_obj_t mod_trezorcrypto_monero_add256_modm(size_t n_args, + const mp_obj_t *args) { + const bool res_arg = n_args == 3; + const int off = res_arg ? 0 : -1; + mp_obj_t res = mp_obj_new_scalar_r(res_arg ? args[0] : mp_const_none); - assert_scalar(args[1+off]); - assert_scalar(args[2+off]); - add256_modm(MP_OBJ_SCALAR(res), MP_OBJ_C_SCALAR(args[1+off]), MP_OBJ_C_SCALAR(args[2+off])); - return res; + assert_scalar(args[1 + off]); + assert_scalar(args[2 + off]); + add256_modm(MP_OBJ_SCALAR(res), MP_OBJ_C_SCALAR(args[1 + off]), + MP_OBJ_C_SCALAR(args[2 + off])); + return res; } -STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(mod_trezorcrypto_monero_add256_modm_obj, 2, 3, mod_trezorcrypto_monero_add256_modm); +STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN( + mod_trezorcrypto_monero_add256_modm_obj, 2, 3, + mod_trezorcrypto_monero_add256_modm); /// def sub256_modm(r: Optional[Sc25519], a: Sc25519, b: Sc25519) -> Sc25519: /// ''' /// Scalar subtraction /// ''' -STATIC mp_obj_t mod_trezorcrypto_monero_sub256_modm(size_t n_args, const mp_obj_t *args){ - const bool res_arg = n_args == 3; - const int off = res_arg ? 0 : -1; - mp_obj_t res = mp_obj_new_scalar_r(res_arg ? args[0] : mp_const_none); +STATIC mp_obj_t mod_trezorcrypto_monero_sub256_modm(size_t n_args, + const mp_obj_t *args) { + const bool res_arg = n_args == 3; + const int off = res_arg ? 0 : -1; + mp_obj_t res = mp_obj_new_scalar_r(res_arg ? args[0] : mp_const_none); - assert_scalar(args[1+off]); - assert_scalar(args[2+off]); - sub256_modm(MP_OBJ_SCALAR(res), MP_OBJ_C_SCALAR(args[1+off]), MP_OBJ_C_SCALAR(args[2+off])); - return res; + assert_scalar(args[1 + off]); + assert_scalar(args[2 + off]); + sub256_modm(MP_OBJ_SCALAR(res), MP_OBJ_C_SCALAR(args[1 + off]), + MP_OBJ_C_SCALAR(args[2 + off])); + return res; } -STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(mod_trezorcrypto_monero_sub256_modm_obj, 2, 3, mod_trezorcrypto_monero_sub256_modm); +STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN( + mod_trezorcrypto_monero_sub256_modm_obj, 2, 3, + mod_trezorcrypto_monero_sub256_modm); /// def mul256_modm(r: Optional[Sc25519], a: Sc25519, b: Sc25519) -> Sc25519: /// ''' /// Scalar multiplication /// ''' -STATIC mp_obj_t mod_trezorcrypto_monero_mul256_modm(size_t n_args, const mp_obj_t *args){ - const bool res_arg = n_args == 3; - const int off = res_arg ? 0 : -1; - mp_obj_t res = mp_obj_new_scalar_r(res_arg ? args[0] : mp_const_none); +STATIC mp_obj_t mod_trezorcrypto_monero_mul256_modm(size_t n_args, + const mp_obj_t *args) { + const bool res_arg = n_args == 3; + const int off = res_arg ? 0 : -1; + mp_obj_t res = mp_obj_new_scalar_r(res_arg ? args[0] : mp_const_none); - assert_scalar(args[1+off]); - assert_scalar(args[2+off]); - mul256_modm(MP_OBJ_SCALAR(res), MP_OBJ_C_SCALAR(args[1+off]), MP_OBJ_C_SCALAR(args[2+off])); - return res; + assert_scalar(args[1 + off]); + assert_scalar(args[2 + off]); + mul256_modm(MP_OBJ_SCALAR(res), MP_OBJ_C_SCALAR(args[1 + off]), + MP_OBJ_C_SCALAR(args[2 + off])); + return res; } -STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(mod_trezorcrypto_monero_mul256_modm_obj, 2, 3, mod_trezorcrypto_monero_mul256_modm); +STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN( + mod_trezorcrypto_monero_mul256_modm_obj, 2, 3, + mod_trezorcrypto_monero_mul256_modm); -/// def mulsub256_modm(r: Optional[Sc25519], a: Sc25519, b: Sc25519, c: Sc25519) -> Sc25519: +/// def mulsub256_modm(r: Optional[Sc25519], a: Sc25519, b: Sc25519, c: Sc25519) +/// -> Sc25519: /// ''' /// c - a*b /// ''' -STATIC mp_obj_t mod_trezorcrypto_monero_mulsub256_modm(size_t n_args, const mp_obj_t *args){ - const bool res_arg = n_args == 4; - const int off = res_arg ? 0 : -1; - mp_obj_t res = mp_obj_new_scalar_r(res_arg ? args[0] : mp_const_none); +STATIC mp_obj_t mod_trezorcrypto_monero_mulsub256_modm(size_t n_args, + const mp_obj_t *args) { + const bool res_arg = n_args == 4; + const int off = res_arg ? 0 : -1; + mp_obj_t res = mp_obj_new_scalar_r(res_arg ? args[0] : mp_const_none); - assert_scalar(args[1+off]); - assert_scalar(args[2+off]); - assert_scalar(args[3+off]); - mulsub256_modm(MP_OBJ_SCALAR(res), MP_OBJ_C_SCALAR(args[1+off]), MP_OBJ_C_SCALAR(args[2+off]), MP_OBJ_C_SCALAR(args[3+off])); - return res; + assert_scalar(args[1 + off]); + assert_scalar(args[2 + off]); + assert_scalar(args[3 + off]); + mulsub256_modm(MP_OBJ_SCALAR(res), MP_OBJ_C_SCALAR(args[1 + off]), + MP_OBJ_C_SCALAR(args[2 + off]), + MP_OBJ_C_SCALAR(args[3 + off])); + return res; } -STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(mod_trezorcrypto_monero_mulsub256_modm_obj, 3, 4, mod_trezorcrypto_monero_mulsub256_modm); +STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN( + mod_trezorcrypto_monero_mulsub256_modm_obj, 3, 4, + mod_trezorcrypto_monero_mulsub256_modm); -/// def muladd256_modm(r: Optional[Sc25519], a: Sc25519, b: Sc25519, c: Sc25519) -> Sc25519: +/// def muladd256_modm(r: Optional[Sc25519], a: Sc25519, b: Sc25519, c: Sc25519) +/// -> Sc25519: /// ''' /// c + a*b /// ''' -STATIC mp_obj_t mod_trezorcrypto_monero_muladd256_modm(size_t n_args, const mp_obj_t *args){ - const bool res_arg = n_args == 4; - const int off = res_arg ? 0 : -1; - mp_obj_t res = mp_obj_new_scalar_r(res_arg ? args[0] : mp_const_none); +STATIC mp_obj_t mod_trezorcrypto_monero_muladd256_modm(size_t n_args, + const mp_obj_t *args) { + const bool res_arg = n_args == 4; + const int off = res_arg ? 0 : -1; + mp_obj_t res = mp_obj_new_scalar_r(res_arg ? args[0] : mp_const_none); - assert_scalar(args[1+off]); - assert_scalar(args[2+off]); - assert_scalar(args[3+off]); - muladd256_modm(MP_OBJ_SCALAR(res), MP_OBJ_C_SCALAR(args[1+off]), MP_OBJ_C_SCALAR(args[2+off]), MP_OBJ_C_SCALAR(args[3+off])); - return res; + assert_scalar(args[1 + off]); + assert_scalar(args[2 + off]); + assert_scalar(args[3 + off]); + muladd256_modm(MP_OBJ_SCALAR(res), MP_OBJ_C_SCALAR(args[1 + off]), + MP_OBJ_C_SCALAR(args[2 + off]), + MP_OBJ_C_SCALAR(args[3 + off])); + return res; } -STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(mod_trezorcrypto_monero_muladd256_modm_obj, 3, 4, mod_trezorcrypto_monero_muladd256_modm); +STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN( + mod_trezorcrypto_monero_muladd256_modm_obj, 3, 4, + mod_trezorcrypto_monero_muladd256_modm); /// def inv256_modm(r: Optional[Sc25519], a: Sc25519) -> Sc25519: /// ''' /// Scalar modular inversion /// ''' -STATIC mp_obj_t mod_trezorcrypto_monero_inv256_modm(size_t n_args, const mp_obj_t *args){ - const bool res_arg = n_args == 2; - const int off = res_arg ? 0 : -1; - mp_obj_t res = mp_obj_new_scalar_r(res_arg ? args[0] : mp_const_none); - assert_scalar(args[1+off]); +STATIC mp_obj_t mod_trezorcrypto_monero_inv256_modm(size_t n_args, + const mp_obj_t *args) { + const bool res_arg = n_args == 2; + const int off = res_arg ? 0 : -1; + mp_obj_t res = mp_obj_new_scalar_r(res_arg ? args[0] : mp_const_none); + assert_scalar(args[1 + off]); - // bn_prime = curve order, little endian encoded - bignum256 bn_prime = {.val={0x1cf5d3ed, 0x20498c69, 0x2f79cd65, 0x37be77a8, 0x14, 0x0, 0x0, 0x0, 0x1000}}; - bignum256 bn_x; + // bn_prime = curve order, little endian encoded + bignum256 bn_prime = {.val = {0x1cf5d3ed, 0x20498c69, 0x2f79cd65, 0x37be77a8, + 0x14, 0x0, 0x0, 0x0, 0x1000}}; + bignum256 bn_x; - memcpy(&bn_x.val, MP_OBJ_C_SCALAR(args[1+off]), sizeof(bignum256modm)); - bn_inverse(&bn_x, &bn_prime); - memcpy(MP_OBJ_SCALAR(res), bn_x.val, sizeof(bignum256modm)); + memcpy(&bn_x.val, MP_OBJ_C_SCALAR(args[1 + off]), sizeof(bignum256modm)); + bn_inverse(&bn_x, &bn_prime); + memcpy(MP_OBJ_SCALAR(res), bn_x.val, sizeof(bignum256modm)); - return res; + return res; } -STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(mod_trezorcrypto_monero_inv256_modm_obj, 1, 2, mod_trezorcrypto_monero_inv256_modm); +STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN( + mod_trezorcrypto_monero_inv256_modm_obj, 1, 2, + mod_trezorcrypto_monero_inv256_modm); -/// def pack256_modm(r: Optional[bytes], a: Sc25519, offset: Optional[int] = 0) -> bytes: +/// def pack256_modm(r: Optional[bytes], a: Sc25519, offset: Optional[int] = 0) +/// -> bytes: /// ''' /// Scalar compression /// ''' -STATIC mp_obj_t mod_trezorcrypto_monero_pack256_modm(size_t n_args, const mp_obj_t *args){ - if (n_args == 1 || args[0] == mp_const_none){ - assert_scalar(args[0]); - uint8_t buff[32]; - contract256_modm(buff, MP_OBJ_C_SCALAR(args[0])); - return mp_obj_new_bytes(buff, 32); - - } else { - mp_buffer_info_t bufm; - mp_get_buffer_raise(args[0], &bufm, MP_BUFFER_WRITE); - const mp_int_t offset = n_args >= 3 ? mp_obj_get_int(args[2]) : 0; - if (bufm.len < 32 + offset) { - mp_raise_ValueError("Buffer too small"); - } - - contract256_modm(((uint8_t*)bufm.buf) + offset, MP_OBJ_C_SCALAR(args[1])); - return args[0]; +STATIC mp_obj_t mod_trezorcrypto_monero_pack256_modm(size_t n_args, + const mp_obj_t *args) { + if (n_args == 1 || args[0] == mp_const_none) { + assert_scalar(args[0]); + uint8_t buff[32]; + contract256_modm(buff, MP_OBJ_C_SCALAR(args[0])); + return mp_obj_new_bytes(buff, 32); + + } else { + mp_buffer_info_t bufm; + mp_get_buffer_raise(args[0], &bufm, MP_BUFFER_WRITE); + const mp_int_t offset = n_args >= 3 ? mp_obj_get_int(args[2]) : 0; + if (bufm.len < 32 + offset) { + mp_raise_ValueError("Buffer too small"); } + + contract256_modm(((uint8_t *)bufm.buf) + offset, MP_OBJ_C_SCALAR(args[1])); + return args[0]; + } } -STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(mod_trezorcrypto_monero_pack256_modm_obj, 1, 3, mod_trezorcrypto_monero_pack256_modm); +STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN( + mod_trezorcrypto_monero_pack256_modm_obj, 1, 3, + mod_trezorcrypto_monero_pack256_modm); -/// def unpack256_modm(r: Optional[Sc25519], a: bytes, offset: int = 0) -> Sc25519: +/// def unpack256_modm(r: Optional[Sc25519], a: bytes, offset: int = 0) -> +/// Sc25519: /// ''' /// Scalar decompression /// ''' -STATIC mp_obj_t mod_trezorcrypto_monero_unpack256_modm(size_t n_args, const mp_obj_t *args){ - const bool res_arg = n_args >= 2; - const int off = res_arg ? 0 : -1; - mp_obj_t res = mp_obj_new_scalar_r(res_arg ? args[0] : mp_const_none); - const mp_int_t offset = n_args >= 3 ? mp_obj_get_int(args[2]) : 0; - mp_unpack_scalar(MP_OBJ_SCALAR(res), args[1+off], offset); - return res; +STATIC mp_obj_t mod_trezorcrypto_monero_unpack256_modm(size_t n_args, + const mp_obj_t *args) { + const bool res_arg = n_args >= 2; + const int off = res_arg ? 0 : -1; + mp_obj_t res = mp_obj_new_scalar_r(res_arg ? args[0] : mp_const_none); + const mp_int_t offset = n_args >= 3 ? mp_obj_get_int(args[2]) : 0; + mp_unpack_scalar(MP_OBJ_SCALAR(res), args[1 + off], offset); + return res; } -STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(mod_trezorcrypto_monero_unpack256_modm_obj, 1, 3, mod_trezorcrypto_monero_unpack256_modm); +STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN( + mod_trezorcrypto_monero_unpack256_modm_obj, 1, 3, + mod_trezorcrypto_monero_unpack256_modm); -/// def unpack256_modm_noreduce(r: Optional[Sc25519], a: bytes, offset: int = 0) -> Sc25519: +/// def unpack256_modm_noreduce(r: Optional[Sc25519], a: bytes, offset: int = 0) +/// -> Sc25519: /// ''' /// Scalar decompression, raw, without modular reduction /// ''' -STATIC mp_obj_t mod_trezorcrypto_monero_unpack256_modm_noreduce(size_t n_args, const mp_obj_t *args){ - const bool res_arg = n_args >= 2; - const int off = res_arg ? 0 : -1; - mp_obj_t res = mp_obj_new_scalar_r(res_arg ? args[0] : mp_const_none); - const mp_int_t offset = n_args >= 3 ? mp_obj_get_int(args[2]) : 0; - - mp_buffer_info_t buff; - mp_get_buffer_raise(args[1+off], &buff, MP_BUFFER_READ); - if (buff.len != 32 + offset) { - mp_raise_ValueError("Invalid length of secret key"); - } +STATIC mp_obj_t mod_trezorcrypto_monero_unpack256_modm_noreduce( + size_t n_args, const mp_obj_t *args) { + const bool res_arg = n_args >= 2; + const int off = res_arg ? 0 : -1; + mp_obj_t res = mp_obj_new_scalar_r(res_arg ? args[0] : mp_const_none); + const mp_int_t offset = n_args >= 3 ? mp_obj_get_int(args[2]) : 0; + + mp_buffer_info_t buff; + mp_get_buffer_raise(args[1 + off], &buff, MP_BUFFER_READ); + if (buff.len != 32 + offset) { + mp_raise_ValueError("Invalid length of secret key"); + } - expand_raw256_modm(MP_OBJ_SCALAR(res), ((uint8_t*)buff.buf) + offset); - return res; + expand_raw256_modm(MP_OBJ_SCALAR(res), ((uint8_t *)buff.buf) + offset); + return res; } -STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(mod_trezorcrypto_monero_unpack256_modm_noreduce_obj, 1, 3, mod_trezorcrypto_monero_unpack256_modm_noreduce); +STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN( + mod_trezorcrypto_monero_unpack256_modm_noreduce_obj, 1, 3, + mod_trezorcrypto_monero_unpack256_modm_noreduce); // // GE25519 Defs @@ -557,233 +610,284 @@ STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(mod_trezorcrypto_monero_unpack256_mod /// ''' /// Sets neutral point /// ''' -STATIC mp_obj_t mod_trezorcrypto_monero_ge25519_set_neutral(size_t n_args, const mp_obj_t *args){ - mp_obj_t res = mp_obj_new_ge25519_r(n_args == 1 ? args[0] : mp_const_none); - ge25519_set_neutral(&MP_OBJ_GE25519(res)); - return res; +STATIC mp_obj_t mod_trezorcrypto_monero_ge25519_set_neutral( + size_t n_args, const mp_obj_t *args) { + mp_obj_t res = mp_obj_new_ge25519_r(n_args == 1 ? args[0] : mp_const_none); + ge25519_set_neutral(&MP_OBJ_GE25519(res)); + return res; } -STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(mod_trezorcrypto_monero_ge25519_set_neutral_obj, 0, 1, mod_trezorcrypto_monero_ge25519_set_neutral); +STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN( + mod_trezorcrypto_monero_ge25519_set_neutral_obj, 0, 1, + mod_trezorcrypto_monero_ge25519_set_neutral); /// def ge25519_set_xmr_h(r: Optional[Ge25519]) -> Ge25519: /// ''' /// Sets H point /// ''' -STATIC mp_obj_t mod_trezorcrypto_monero_ge25519_set_xmr_h(size_t n_args, const mp_obj_t *args){ - mp_obj_t res = mp_obj_new_ge25519_r(n_args == 1 ? args[0] : mp_const_none); - ge25519_set_xmr_h(&MP_OBJ_GE25519(res)); - return res; +STATIC mp_obj_t +mod_trezorcrypto_monero_ge25519_set_xmr_h(size_t n_args, const mp_obj_t *args) { + mp_obj_t res = mp_obj_new_ge25519_r(n_args == 1 ? args[0] : mp_const_none); + ge25519_set_xmr_h(&MP_OBJ_GE25519(res)); + return res; } -STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(mod_trezorcrypto_monero_ge25519_set_xmr_h_obj, 0, 1, mod_trezorcrypto_monero_ge25519_set_xmr_h); +STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN( + mod_trezorcrypto_monero_ge25519_set_xmr_h_obj, 0, 1, + mod_trezorcrypto_monero_ge25519_set_xmr_h); /// def ge25519_check(r: Ge25519): /// ''' /// Checks point, throws if not on curve /// ''' -STATIC mp_obj_t mod_trezorcrypto_monero_ge25519_check(const mp_obj_t arg){ +STATIC mp_obj_t mod_trezorcrypto_monero_ge25519_check(const mp_obj_t arg) { assert_ge25519(arg); - if (ge25519_check(&MP_OBJ_C_GE25519(arg)) != 1){ + if (ge25519_check(&MP_OBJ_C_GE25519(arg)) != 1) { mp_raise_ValueError("Ed25519 point not on curve"); } return mp_const_none; } -STATIC MP_DEFINE_CONST_FUN_OBJ_1(mod_trezorcrypto_monero_ge25519_check_obj, mod_trezorcrypto_monero_ge25519_check); +STATIC MP_DEFINE_CONST_FUN_OBJ_1(mod_trezorcrypto_monero_ge25519_check_obj, + mod_trezorcrypto_monero_ge25519_check); /// def ge25519_eq(a: Ge25519, b: Ge25519) -> bool: /// ''' /// Compares EC points /// ''' -STATIC mp_obj_t mod_trezorcrypto_monero_ge25519_eq(const mp_obj_t a, const mp_obj_t b){ - assert_ge25519(a); - assert_ge25519(b); - int r = ge25519_eq(&MP_OBJ_C_GE25519(a), &MP_OBJ_C_GE25519(b)); - return MP_OBJ_NEW_SMALL_INT(r); +STATIC mp_obj_t mod_trezorcrypto_monero_ge25519_eq(const mp_obj_t a, + const mp_obj_t b) { + assert_ge25519(a); + assert_ge25519(b); + int r = ge25519_eq(&MP_OBJ_C_GE25519(a), &MP_OBJ_C_GE25519(b)); + return MP_OBJ_NEW_SMALL_INT(r); } -STATIC MP_DEFINE_CONST_FUN_OBJ_2(mod_trezorcrypto_monero_ge25519_eq_obj, mod_trezorcrypto_monero_ge25519_eq); +STATIC MP_DEFINE_CONST_FUN_OBJ_2(mod_trezorcrypto_monero_ge25519_eq_obj, + mod_trezorcrypto_monero_ge25519_eq); /// def ge25519_add(r: Optional[Ge25519], a: Ge25519, b: Ge25519) -> Ge25519: /// ''' /// Adds EC points /// ''' -STATIC mp_obj_t mod_trezorcrypto_monero_ge25519_add(size_t n_args, const mp_obj_t *args){ - const bool res_arg = n_args == 3; - const int off = res_arg ? 0 : -1; - mp_obj_t res = mp_obj_new_ge25519_r(res_arg ? args[0] : mp_const_none); +STATIC mp_obj_t mod_trezorcrypto_monero_ge25519_add(size_t n_args, + const mp_obj_t *args) { + const bool res_arg = n_args == 3; + const int off = res_arg ? 0 : -1; + mp_obj_t res = mp_obj_new_ge25519_r(res_arg ? args[0] : mp_const_none); - assert_ge25519(args[1+off]); - assert_ge25519(args[2+off]); - ge25519_add(&MP_OBJ_GE25519(res), &MP_OBJ_C_GE25519(args[1+off]), &MP_OBJ_C_GE25519(args[2+off]), 0); - return res; + assert_ge25519(args[1 + off]); + assert_ge25519(args[2 + off]); + ge25519_add(&MP_OBJ_GE25519(res), &MP_OBJ_C_GE25519(args[1 + off]), + &MP_OBJ_C_GE25519(args[2 + off]), 0); + return res; } -STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(mod_trezorcrypto_monero_ge25519_add_obj, 2, 3, mod_trezorcrypto_monero_ge25519_add); +STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN( + mod_trezorcrypto_monero_ge25519_add_obj, 2, 3, + mod_trezorcrypto_monero_ge25519_add); /// def ge25519_sub(r: Optional[Ge25519], a: Ge25519, b: Ge25519) -> Ge25519: /// ''' /// Subtracts EC points /// ''' -STATIC mp_obj_t mod_trezorcrypto_monero_ge25519_sub(size_t n_args, const mp_obj_t *args){ - const bool res_arg = n_args == 3; - const int off = res_arg ? 0 : -1; - mp_obj_t res = mp_obj_new_ge25519_r(res_arg ? args[0] : mp_const_none); +STATIC mp_obj_t mod_trezorcrypto_monero_ge25519_sub(size_t n_args, + const mp_obj_t *args) { + const bool res_arg = n_args == 3; + const int off = res_arg ? 0 : -1; + mp_obj_t res = mp_obj_new_ge25519_r(res_arg ? args[0] : mp_const_none); - assert_ge25519(args[1+off]); - assert_ge25519(args[2+off]); - ge25519_add(&MP_OBJ_GE25519(res), &MP_OBJ_C_GE25519(args[1+off]), &MP_OBJ_C_GE25519(args[2+off]), 1); - return res; + assert_ge25519(args[1 + off]); + assert_ge25519(args[2 + off]); + ge25519_add(&MP_OBJ_GE25519(res), &MP_OBJ_C_GE25519(args[1 + off]), + &MP_OBJ_C_GE25519(args[2 + off]), 1); + return res; } -STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(mod_trezorcrypto_monero_ge25519_sub_obj, 2, 3, mod_trezorcrypto_monero_ge25519_sub); +STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN( + mod_trezorcrypto_monero_ge25519_sub_obj, 2, 3, + mod_trezorcrypto_monero_ge25519_sub); /// def ge25519_double(r: Optional[Ge25519], p: Ge25519) -> Ge25519: /// ''' /// EC point doubling /// ''' -STATIC mp_obj_t mod_trezorcrypto_monero_ge25519_double(size_t n_args, const mp_obj_t *args){ - const bool res_arg = n_args == 2; - mp_obj_t res = mp_obj_new_ge25519_r(res_arg ? args[0] : mp_const_none); - mp_obj_t src = res_arg ? args[1] : args[0]; - assert_ge25519(src); - ge25519_double(&MP_OBJ_GE25519(res), &MP_OBJ_C_GE25519(src)); - return res; +STATIC mp_obj_t mod_trezorcrypto_monero_ge25519_double(size_t n_args, + const mp_obj_t *args) { + const bool res_arg = n_args == 2; + mp_obj_t res = mp_obj_new_ge25519_r(res_arg ? args[0] : mp_const_none); + mp_obj_t src = res_arg ? args[1] : args[0]; + assert_ge25519(src); + ge25519_double(&MP_OBJ_GE25519(res), &MP_OBJ_C_GE25519(src)); + return res; } -STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(mod_trezorcrypto_monero_ge25519_double_obj, 1, 2, mod_trezorcrypto_monero_ge25519_double); +STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN( + mod_trezorcrypto_monero_ge25519_double_obj, 1, 2, + mod_trezorcrypto_monero_ge25519_double); /// def ge25519_mul8(r: Optional[Ge25519], p: Ge25519) -> Ge25519: /// ''' /// EC point * 8 /// ''' -STATIC mp_obj_t mod_trezorcrypto_monero_ge25519_mul8(size_t n_args, const mp_obj_t *args){ - const bool res_arg = n_args == 2; - mp_obj_t res = mp_obj_new_ge25519_r(res_arg ? args[0] : mp_const_none); - mp_obj_t src = res_arg ? args[1] : args[0]; - assert_ge25519(src); - ge25519_mul8(&MP_OBJ_GE25519(res), &MP_OBJ_C_GE25519(src)); - return res; +STATIC mp_obj_t mod_trezorcrypto_monero_ge25519_mul8(size_t n_args, + const mp_obj_t *args) { + const bool res_arg = n_args == 2; + mp_obj_t res = mp_obj_new_ge25519_r(res_arg ? args[0] : mp_const_none); + mp_obj_t src = res_arg ? args[1] : args[0]; + assert_ge25519(src); + ge25519_mul8(&MP_OBJ_GE25519(res), &MP_OBJ_C_GE25519(src)); + return res; } -STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(mod_trezorcrypto_monero_ge25519_mul8_obj, 1, 2, mod_trezorcrypto_monero_ge25519_mul8); +STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN( + mod_trezorcrypto_monero_ge25519_mul8_obj, 1, 2, + mod_trezorcrypto_monero_ge25519_mul8); -/// def ge25519_double_scalarmult_vartime(r: Optional[Ge25519], p1: Ge25519, s1: Sc25519, s2: Sc25519) -> Ge25519: +/// def ge25519_double_scalarmult_vartime(r: Optional[Ge25519], p1: Ge25519, s1: +/// Sc25519, s2: Sc25519) -> Ge25519: /// ''' /// s1 * G + s2 * p1 /// ''' -STATIC mp_obj_t mod_trezorcrypto_monero_ge25519_double_scalarmult_vartime(size_t n_args, const mp_obj_t *args){ - const bool res_arg = n_args == 4; - const int off = res_arg ? 0 : -1; - mp_obj_t res = mp_obj_new_ge25519_r(res_arg ? args[0] : mp_const_none); - assert_ge25519(args[1+off]); - assert_scalar(args[2+off]); - assert_scalar(args[3+off]); +STATIC mp_obj_t mod_trezorcrypto_monero_ge25519_double_scalarmult_vartime( + size_t n_args, const mp_obj_t *args) { + const bool res_arg = n_args == 4; + const int off = res_arg ? 0 : -1; + mp_obj_t res = mp_obj_new_ge25519_r(res_arg ? args[0] : mp_const_none); + assert_ge25519(args[1 + off]); + assert_scalar(args[2 + off]); + assert_scalar(args[3 + off]); - ge25519_double_scalarmult_vartime(&MP_OBJ_GE25519(res), &MP_OBJ_C_GE25519(args[1+off]), - MP_OBJ_C_SCALAR(args[2+off]), MP_OBJ_C_SCALAR(args[3+off])); - return res; + ge25519_double_scalarmult_vartime( + &MP_OBJ_GE25519(res), &MP_OBJ_C_GE25519(args[1 + off]), + MP_OBJ_C_SCALAR(args[2 + off]), MP_OBJ_C_SCALAR(args[3 + off])); + return res; } -STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(mod_trezorcrypto_monero_ge25519_double_scalarmult_vartime_obj, 3, 4, mod_trezorcrypto_monero_ge25519_double_scalarmult_vartime); +STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN( + mod_trezorcrypto_monero_ge25519_double_scalarmult_vartime_obj, 3, 4, + mod_trezorcrypto_monero_ge25519_double_scalarmult_vartime); -/// def ge25519_double_scalarmult_vartime2(r: Optional[Ge25519], p1: Ge25519, s1: Sc25519, p2: Ge25519, s2: Sc25519) -> Ge25519: +/// def ge25519_double_scalarmult_vartime2(r: Optional[Ge25519], p1: Ge25519, +/// s1: Sc25519, p2: Ge25519, s2: Sc25519) -> Ge25519: /// ''' /// s1 * p1 + s2 * p2 /// ''' -STATIC mp_obj_t mod_trezorcrypto_monero_ge25519_double_scalarmult_vartime2(size_t n_args, const mp_obj_t *args){ - const bool res_arg = n_args == 5; - const int off = res_arg ? 0 : -1; - mp_obj_t res = mp_obj_new_ge25519_r(res_arg ? args[0] : mp_const_none); +STATIC mp_obj_t mod_trezorcrypto_monero_ge25519_double_scalarmult_vartime2( + size_t n_args, const mp_obj_t *args) { + const bool res_arg = n_args == 5; + const int off = res_arg ? 0 : -1; + mp_obj_t res = mp_obj_new_ge25519_r(res_arg ? args[0] : mp_const_none); - assert_ge25519(args[1+off]); - assert_scalar(args[2+off]); - assert_ge25519(args[3+off]); - assert_scalar(args[4+off]); + assert_ge25519(args[1 + off]); + assert_scalar(args[2 + off]); + assert_ge25519(args[3 + off]); + assert_scalar(args[4 + off]); - ge25519_double_scalarmult_vartime2(&MP_OBJ_GE25519(res), &MP_OBJ_C_GE25519(args[1+off]), MP_OBJ_C_SCALAR(args[2+off]), - &MP_OBJ_C_GE25519(args[3+off]), MP_OBJ_C_SCALAR(args[4+off])); - return res; + ge25519_double_scalarmult_vartime2( + &MP_OBJ_GE25519(res), &MP_OBJ_C_GE25519(args[1 + off]), + MP_OBJ_C_SCALAR(args[2 + off]), &MP_OBJ_C_GE25519(args[3 + off]), + MP_OBJ_C_SCALAR(args[4 + off])); + return res; } -STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(mod_trezorcrypto_monero_ge25519_double_scalarmult_vartime2_obj, 4, 5, mod_trezorcrypto_monero_ge25519_double_scalarmult_vartime2); +STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN( + mod_trezorcrypto_monero_ge25519_double_scalarmult_vartime2_obj, 4, 5, + mod_trezorcrypto_monero_ge25519_double_scalarmult_vartime2); -/// def ge25519_scalarmult_base(r: Optional[Ge25519], s: Union[Sc25519, int]) -> Ge25519: +/// def ge25519_scalarmult_base(r: Optional[Ge25519], s: Union[Sc25519, int]) -> +/// Ge25519: /// ''' /// s * G /// ''' -STATIC mp_obj_t mod_trezorcrypto_monero_ge25519_scalarmult_base(size_t n_args, const mp_obj_t *args){ - const bool res_arg = n_args == 2; - const int off = res_arg ? 0 : -1; - mp_obj_t res = mp_obj_new_ge25519_r(res_arg ? args[0] : mp_const_none); - - if (MP_OBJ_IS_SCALAR(args[1+off])){ - ge25519_scalarmult_base_wrapper(&MP_OBJ_GE25519(res), MP_OBJ_C_SCALAR(args[1+off])); - } else if (mp_obj_is_integer(args[1+off])){ - bignum256modm mlt; - set256_modm(mlt, mp_obj_get_int(args[1+off])); - ge25519_scalarmult_base_wrapper(&MP_OBJ_GE25519(res), mlt); - } else { - mp_raise_ValueError("unknown base mult type"); - } +STATIC mp_obj_t mod_trezorcrypto_monero_ge25519_scalarmult_base( + size_t n_args, const mp_obj_t *args) { + const bool res_arg = n_args == 2; + const int off = res_arg ? 0 : -1; + mp_obj_t res = mp_obj_new_ge25519_r(res_arg ? args[0] : mp_const_none); + + if (MP_OBJ_IS_SCALAR(args[1 + off])) { + ge25519_scalarmult_base_wrapper(&MP_OBJ_GE25519(res), + MP_OBJ_C_SCALAR(args[1 + off])); + } else if (mp_obj_is_integer(args[1 + off])) { + bignum256modm mlt; + set256_modm(mlt, mp_obj_get_int(args[1 + off])); + ge25519_scalarmult_base_wrapper(&MP_OBJ_GE25519(res), mlt); + } else { + mp_raise_ValueError("unknown base mult type"); + } - return res; + return res; } -STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(mod_trezorcrypto_monero_ge25519_scalarmult_base_obj, 1, 2, mod_trezorcrypto_monero_ge25519_scalarmult_base); +STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN( + mod_trezorcrypto_monero_ge25519_scalarmult_base_obj, 1, 2, + mod_trezorcrypto_monero_ge25519_scalarmult_base); -/// def ge25519_scalarmult(r: Optional[Ge25519], p: Ge25519, s: Union[Sc25519, int]) -> Ge25519: +/// def ge25519_scalarmult(r: Optional[Ge25519], p: Ge25519, s: Union[Sc25519, +/// int]) -> Ge25519: /// ''' /// s * p /// ''' -STATIC mp_obj_t mod_trezorcrypto_monero_ge25519_scalarmult(size_t n_args, const mp_obj_t *args){ - const bool res_arg = n_args == 3; - const int off = res_arg ? 0 : -1; - mp_obj_t res = mp_obj_new_ge25519_r(res_arg ? args[0] : mp_const_none); - assert_ge25519(args[1+off]); - - if (MP_OBJ_IS_SCALAR(args[2+off])){ - ge25519_scalarmult(&MP_OBJ_GE25519(res), &MP_OBJ_C_GE25519(args[1+off]), MP_OBJ_C_SCALAR(args[2+off])); - } else if (mp_obj_is_integer(args[2+off])){ - bignum256modm mlt; - set256_modm(mlt, mp_obj_get_int(args[2+off])); - ge25519_scalarmult(&MP_OBJ_GE25519(res), &MP_OBJ_C_GE25519(args[1+off]), mlt); - } else { - mp_raise_ValueError("unknown mult type"); - } +STATIC mp_obj_t mod_trezorcrypto_monero_ge25519_scalarmult( + size_t n_args, const mp_obj_t *args) { + const bool res_arg = n_args == 3; + const int off = res_arg ? 0 : -1; + mp_obj_t res = mp_obj_new_ge25519_r(res_arg ? args[0] : mp_const_none); + assert_ge25519(args[1 + off]); + + if (MP_OBJ_IS_SCALAR(args[2 + off])) { + ge25519_scalarmult(&MP_OBJ_GE25519(res), &MP_OBJ_C_GE25519(args[1 + off]), + MP_OBJ_C_SCALAR(args[2 + off])); + } else if (mp_obj_is_integer(args[2 + off])) { + bignum256modm mlt; + set256_modm(mlt, mp_obj_get_int(args[2 + off])); + ge25519_scalarmult(&MP_OBJ_GE25519(res), &MP_OBJ_C_GE25519(args[1 + off]), + mlt); + } else { + mp_raise_ValueError("unknown mult type"); + } - return res; + return res; } -STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(mod_trezorcrypto_monero_ge25519_scalarmult_obj, 2, 3, mod_trezorcrypto_monero_ge25519_scalarmult); +STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN( + mod_trezorcrypto_monero_ge25519_scalarmult_obj, 2, 3, + mod_trezorcrypto_monero_ge25519_scalarmult); /// def ge25519_pack(r: bytes, p: Ge25519, offset: int = 0) -> bytes: /// ''' /// Point compression /// ''' -STATIC mp_obj_t mod_trezorcrypto_monero_ge25519_pack(size_t n_args, const mp_obj_t *args){ - if (n_args == 1 || args[0] == mp_const_none){ - assert_ge25519(args[0]); - uint8_t buff[32]; - ge25519_pack(buff, &MP_OBJ_C_GE25519(args[0])); - return mp_obj_new_bytes(buff, 32); - - } else { - mp_buffer_info_t bufm; - mp_get_buffer_raise(args[0], &bufm, MP_BUFFER_WRITE); - const mp_int_t offset = n_args >= 3 ? mp_obj_get_int(args[2]) : 0; - if (bufm.len < 32 + offset) { - mp_raise_ValueError("Buffer too small"); - } - - ge25519_pack(((uint8_t*)bufm.buf) + offset, &MP_OBJ_C_GE25519(args[1])); - return args[0]; +STATIC mp_obj_t mod_trezorcrypto_monero_ge25519_pack(size_t n_args, + const mp_obj_t *args) { + if (n_args == 1 || args[0] == mp_const_none) { + assert_ge25519(args[0]); + uint8_t buff[32]; + ge25519_pack(buff, &MP_OBJ_C_GE25519(args[0])); + return mp_obj_new_bytes(buff, 32); + + } else { + mp_buffer_info_t bufm; + mp_get_buffer_raise(args[0], &bufm, MP_BUFFER_WRITE); + const mp_int_t offset = n_args >= 3 ? mp_obj_get_int(args[2]) : 0; + if (bufm.len < 32 + offset) { + mp_raise_ValueError("Buffer too small"); } + ge25519_pack(((uint8_t *)bufm.buf) + offset, &MP_OBJ_C_GE25519(args[1])); + return args[0]; + } } -STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(mod_trezorcrypto_monero_ge25519_pack_obj, 1, 3, mod_trezorcrypto_monero_ge25519_pack); +STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN( + mod_trezorcrypto_monero_ge25519_pack_obj, 1, 3, + mod_trezorcrypto_monero_ge25519_pack); -/// def ge25519_unpack_vartime(r: Optional[Ge25519], buff: bytes, offset: int = 0) -> Ge25519: +/// def ge25519_unpack_vartime(r: Optional[Ge25519], buff: bytes, offset: int = +/// 0) -> Ge25519: /// ''' /// Point decompression /// ''' -STATIC mp_obj_t mod_trezorcrypto_monero_ge25519_unpack_vartime(size_t n_args, const mp_obj_t *args){ - const bool res_arg = n_args >= 2; - const int off = res_arg ? 0 : -1; - mp_obj_t res = mp_obj_new_ge25519_r(res_arg ? args[0] : mp_const_none); - const mp_int_t offset = n_args >= 3 ? mp_obj_get_int(args[2]) : 0; - mp_unpack_ge25519(&MP_OBJ_GE25519(res), args[1+off], offset); - return res; +STATIC mp_obj_t mod_trezorcrypto_monero_ge25519_unpack_vartime( + size_t n_args, const mp_obj_t *args) { + const bool res_arg = n_args >= 2; + const int off = res_arg ? 0 : -1; + mp_obj_t res = mp_obj_new_ge25519_r(res_arg ? args[0] : mp_const_none); + const mp_int_t offset = n_args >= 3 ? mp_obj_get_int(args[2]) : 0; + mp_unpack_ge25519(&MP_OBJ_GE25519(res), args[1 + off], offset); + return res; } -STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(mod_trezorcrypto_monero_ge25519_unpack_vartime_obj, 1, 3, mod_trezorcrypto_monero_ge25519_unpack_vartime); +STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN( + mod_trezorcrypto_monero_ge25519_unpack_vartime_obj, 1, 3, + mod_trezorcrypto_monero_ge25519_unpack_vartime); // // XMR defs @@ -793,430 +897,571 @@ STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(mod_trezorcrypto_monero_ge25519_unpac /// ''' /// Monero block base 58 encoding /// ''' -STATIC mp_obj_t mod_trezorcrypto_monero_xmr_base58_addr_encode_check(size_t n_args, const mp_obj_t *args){ - uint8_t out[128]; - mp_buffer_info_t data; - mp_get_buffer_raise(args[1], &data, MP_BUFFER_READ); +STATIC mp_obj_t mod_trezorcrypto_monero_xmr_base58_addr_encode_check( + size_t n_args, const mp_obj_t *args) { + uint8_t out[128]; + mp_buffer_info_t data; + mp_get_buffer_raise(args[1], &data, MP_BUFFER_READ); - int sz = xmr_base58_addr_encode_check(mp_obj_get_int(args[0]), data.buf, data.len, (char *)out, sizeof(out)); - if (sz == 0){ - mp_raise_ValueError("b58 encoding error"); - } + int sz = xmr_base58_addr_encode_check(mp_obj_get_int(args[0]), data.buf, + data.len, (char *)out, sizeof(out)); + if (sz == 0) { + mp_raise_ValueError("b58 encoding error"); + } - return mp_obj_new_bytes(out, sz); + return mp_obj_new_bytes(out, sz); } -STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(mod_trezorcrypto_monero_xmr_base58_addr_encode_check_obj, 2, 2, mod_trezorcrypto_monero_xmr_base58_addr_encode_check); +STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN( + mod_trezorcrypto_monero_xmr_base58_addr_encode_check_obj, 2, 2, + mod_trezorcrypto_monero_xmr_base58_addr_encode_check); /// def base58_addr_decode_check(buff: bytes) -> Tuple[bytes, int]: /// ''' -/// Monero block base 58 decoding, returning (decoded, tag) or raising on error. +/// Monero block base 58 decoding, returning (decoded, tag) or raising on +/// error. /// ''' -STATIC mp_obj_t mod_trezorcrypto_monero_xmr_base58_addr_decode_check(size_t n_args, const mp_obj_t *args){ - uint8_t out[128]; - uint64_t tag; +STATIC mp_obj_t mod_trezorcrypto_monero_xmr_base58_addr_decode_check( + size_t n_args, const mp_obj_t *args) { + uint8_t out[128]; + uint64_t tag; - mp_buffer_info_t data; - mp_get_buffer_raise(args[0], &data, MP_BUFFER_READ); + mp_buffer_info_t data; + mp_get_buffer_raise(args[0], &data, MP_BUFFER_READ); - int sz = xmr_base58_addr_decode_check(data.buf, data.len, &tag, out, sizeof(out)); - if (sz == 0){ - mp_raise_ValueError("b58 decoding error"); - } + int sz = + xmr_base58_addr_decode_check(data.buf, data.len, &tag, out, sizeof(out)); + if (sz == 0) { + mp_raise_ValueError("b58 decoding error"); + } - mp_obj_tuple_t *tuple = MP_OBJ_TO_PTR(mp_obj_new_tuple(2, NULL)); - tuple->items[0] = mp_obj_new_bytes(out, sz); - tuple->items[1] = mp_obj_new_int_from_ull(tag); - return MP_OBJ_FROM_PTR(tuple); + mp_obj_tuple_t *tuple = MP_OBJ_TO_PTR(mp_obj_new_tuple(2, NULL)); + tuple->items[0] = mp_obj_new_bytes(out, sz); + tuple->items[1] = mp_obj_new_int_from_ull(tag); + return MP_OBJ_FROM_PTR(tuple); } -STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(mod_trezorcrypto_monero_xmr_base58_addr_decode_check_obj, 1, 1, mod_trezorcrypto_monero_xmr_base58_addr_decode_check); +STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN( + mod_trezorcrypto_monero_xmr_base58_addr_decode_check_obj, 1, 1, + mod_trezorcrypto_monero_xmr_base58_addr_decode_check); /// def xmr_random_scalar(r: Optional[Sc25519] = None) -> Sc25519: /// ''' /// Generates a random scalar /// ''' -STATIC mp_obj_t mod_trezorcrypto_monero_xmr_random_scalar(size_t n_args, const mp_obj_t *args){ - mp_obj_t res = mp_obj_new_scalar_r(n_args == 1 ? args[0] : mp_const_none); - xmr_random_scalar(MP_OBJ_SCALAR(res)); - return res; +STATIC mp_obj_t +mod_trezorcrypto_monero_xmr_random_scalar(size_t n_args, const mp_obj_t *args) { + mp_obj_t res = mp_obj_new_scalar_r(n_args == 1 ? args[0] : mp_const_none); + xmr_random_scalar(MP_OBJ_SCALAR(res)); + return res; } -STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(mod_trezorcrypto_monero_xmr_random_scalar_obj, 0, 1, mod_trezorcrypto_monero_xmr_random_scalar); +STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN( + mod_trezorcrypto_monero_xmr_random_scalar_obj, 0, 1, + mod_trezorcrypto_monero_xmr_random_scalar); /// def xmr_fast_hash(r: Optional[bytes], buff: bytes) -> bytes: /// ''' /// XMR fast hash /// ''' -STATIC mp_obj_t mod_trezorcrypto_monero_xmr_fast_hash(size_t n_args, const mp_obj_t *args){ - const int off = n_args == 2 ? 0 : -1; - uint8_t buff[32]; - uint8_t * buff_use = buff; - if (n_args > 1){ - mp_buffer_info_t odata; - mp_get_buffer_raise(args[0], &odata, MP_BUFFER_WRITE); - if (odata.len < 32){ - mp_raise_ValueError("Output buffer too small"); - } - buff_use = odata.buf; +STATIC mp_obj_t mod_trezorcrypto_monero_xmr_fast_hash(size_t n_args, + const mp_obj_t *args) { + const int off = n_args == 2 ? 0 : -1; + uint8_t buff[32]; + uint8_t *buff_use = buff; + if (n_args > 1) { + mp_buffer_info_t odata; + mp_get_buffer_raise(args[0], &odata, MP_BUFFER_WRITE); + if (odata.len < 32) { + mp_raise_ValueError("Output buffer too small"); } + buff_use = odata.buf; + } - mp_buffer_info_t data; - mp_get_buffer_raise(args[1+off], &data, MP_BUFFER_READ); - xmr_fast_hash(buff_use, data.buf, data.len); - return n_args == 2 ? args[0] : mp_obj_new_bytes(buff, 32); + mp_buffer_info_t data; + mp_get_buffer_raise(args[1 + off], &data, MP_BUFFER_READ); + xmr_fast_hash(buff_use, data.buf, data.len); + return n_args == 2 ? args[0] : mp_obj_new_bytes(buff, 32); } -STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(mod_trezorcrypto_monero_xmr_fast_hash_obj, 1, 2, mod_trezorcrypto_monero_xmr_fast_hash); +STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN( + mod_trezorcrypto_monero_xmr_fast_hash_obj, 1, 2, + mod_trezorcrypto_monero_xmr_fast_hash); /// def xmr_hash_to_ec(r: Optional[Ge25519], buff: bytes) -> Ge25519: /// ''' /// XMR hashing to EC point /// ''' -STATIC mp_obj_t mod_trezorcrypto_monero_xmr_hash_to_ec(size_t n_args, const mp_obj_t *args){ - const bool res_arg = n_args == 2; - const int off = res_arg ? 0 : -1; - mp_obj_t res = mp_obj_new_ge25519_r(res_arg ? args[0] : mp_const_none); - mp_buffer_info_t data; - mp_get_buffer_raise(args[1+off], &data, MP_BUFFER_READ); - xmr_hash_to_ec(&MP_OBJ_GE25519(res), data.buf, data.len); - return res; +STATIC mp_obj_t mod_trezorcrypto_monero_xmr_hash_to_ec(size_t n_args, + const mp_obj_t *args) { + const bool res_arg = n_args == 2; + const int off = res_arg ? 0 : -1; + mp_obj_t res = mp_obj_new_ge25519_r(res_arg ? args[0] : mp_const_none); + mp_buffer_info_t data; + mp_get_buffer_raise(args[1 + off], &data, MP_BUFFER_READ); + xmr_hash_to_ec(&MP_OBJ_GE25519(res), data.buf, data.len); + return res; } -STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(mod_trezorcrypto_monero_xmr_hash_to_ec_obj, 1, 2, mod_trezorcrypto_monero_xmr_hash_to_ec); +STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN( + mod_trezorcrypto_monero_xmr_hash_to_ec_obj, 1, 2, + mod_trezorcrypto_monero_xmr_hash_to_ec); /// def xmr_hash_to_scalar(r: Optional[Sc25519], buff: bytes) -> Sc25519: /// ''' /// XMR hashing to EC scalar /// ''' -STATIC mp_obj_t mod_trezorcrypto_monero_xmr_hash_to_scalar(size_t n_args, const mp_obj_t *args){ - const bool res_arg = n_args == 2; - const int off = res_arg ? 0 : -1; - mp_obj_t res = mp_obj_new_scalar_r(res_arg ? args[0] : mp_const_none); - mp_buffer_info_t data; - mp_get_buffer_raise(args[1+off], &data, MP_BUFFER_READ); - xmr_hash_to_scalar(MP_OBJ_SCALAR(res), data.buf, data.len); - return res; +STATIC mp_obj_t mod_trezorcrypto_monero_xmr_hash_to_scalar( + size_t n_args, const mp_obj_t *args) { + const bool res_arg = n_args == 2; + const int off = res_arg ? 0 : -1; + mp_obj_t res = mp_obj_new_scalar_r(res_arg ? args[0] : mp_const_none); + mp_buffer_info_t data; + mp_get_buffer_raise(args[1 + off], &data, MP_BUFFER_READ); + xmr_hash_to_scalar(MP_OBJ_SCALAR(res), data.buf, data.len); + return res; } -STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(mod_trezorcrypto_monero_xmr_hash_to_scalar_obj, 1, 2, mod_trezorcrypto_monero_xmr_hash_to_scalar); +STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN( + mod_trezorcrypto_monero_xmr_hash_to_scalar_obj, 1, 2, + mod_trezorcrypto_monero_xmr_hash_to_scalar); -/// def xmr_derivation_to_scalar(r: Optional[Sc25519], p: Ge25519, output_index: int) -> Sc25519: +/// def xmr_derivation_to_scalar(r: Optional[Sc25519], p: Ge25519, output_index: +/// int) -> Sc25519: /// ''' /// H_s(derivation || varint(output_index)) /// ''' -STATIC mp_obj_t mod_trezorcrypto_monero_xmr_derivation_to_scalar(size_t n_args, const mp_obj_t *args){ - const bool res_arg = n_args == 3; - const int off = res_arg ? 0 : -1; - mp_obj_t res = mp_obj_new_scalar_r(res_arg ? args[0] : mp_const_none); - assert_ge25519(args[1+off]); - xmr_derivation_to_scalar(MP_OBJ_SCALAR(res), &MP_OBJ_C_GE25519(args[1+off]), mp_obj_get_int(args[2+off])); - return res; +STATIC mp_obj_t mod_trezorcrypto_monero_xmr_derivation_to_scalar( + size_t n_args, const mp_obj_t *args) { + const bool res_arg = n_args == 3; + const int off = res_arg ? 0 : -1; + mp_obj_t res = mp_obj_new_scalar_r(res_arg ? args[0] : mp_const_none); + assert_ge25519(args[1 + off]); + xmr_derivation_to_scalar(MP_OBJ_SCALAR(res), &MP_OBJ_C_GE25519(args[1 + off]), + mp_obj_get_int(args[2 + off])); + return res; } -STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(mod_trezorcrypto_monero_xmr_derivation_to_scalar_obj, 2, 3, mod_trezorcrypto_monero_xmr_derivation_to_scalar); +STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN( + mod_trezorcrypto_monero_xmr_derivation_to_scalar_obj, 2, 3, + mod_trezorcrypto_monero_xmr_derivation_to_scalar); -/// def xmr_generate_key_derivation(r: Optional[Ge25519], A: Ge25519, b: Sc25519) -> Ge25519: +/// def xmr_generate_key_derivation(r: Optional[Ge25519], A: Ge25519, b: +/// Sc25519) -> Ge25519: /// ''' /// 8*(key2*key1) /// ''' -STATIC mp_obj_t mod_trezorcrypto_monero_xmr_generate_key_derivation(size_t n_args, const mp_obj_t *args){ - const bool res_arg = n_args == 3; - const int off = res_arg ? 0 : -1; - mp_obj_t res = mp_obj_new_ge25519_r(res_arg ? args[0] : mp_const_none); - assert_ge25519(args[1+off]); - assert_scalar(args[2+off]); - xmr_generate_key_derivation(&MP_OBJ_GE25519(res), &MP_OBJ_C_GE25519(args[1+off]), MP_OBJ_C_SCALAR(args[2+off])); - return res; -} -STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(mod_trezorcrypto_monero_xmr_generate_key_derivation_obj, 2, 3, mod_trezorcrypto_monero_xmr_generate_key_derivation); - -/// def xmr_derive_private_key(r: Optional[Sc25519], deriv: Ge25519, idx: int, base: Sc25519) -> Sc25519: +STATIC mp_obj_t mod_trezorcrypto_monero_xmr_generate_key_derivation( + size_t n_args, const mp_obj_t *args) { + const bool res_arg = n_args == 3; + const int off = res_arg ? 0 : -1; + mp_obj_t res = mp_obj_new_ge25519_r(res_arg ? args[0] : mp_const_none); + assert_ge25519(args[1 + off]); + assert_scalar(args[2 + off]); + xmr_generate_key_derivation(&MP_OBJ_GE25519(res), + &MP_OBJ_C_GE25519(args[1 + off]), + MP_OBJ_C_SCALAR(args[2 + off])); + return res; +} +STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN( + mod_trezorcrypto_monero_xmr_generate_key_derivation_obj, 2, 3, + mod_trezorcrypto_monero_xmr_generate_key_derivation); + +/// def xmr_derive_private_key(r: Optional[Sc25519], deriv: Ge25519, idx: int, +/// base: Sc25519) -> Sc25519: /// ''' /// base + H_s(derivation || varint(output_index)) /// ''' -STATIC mp_obj_t mod_trezorcrypto_monero_xmr_derive_private_key(size_t n_args, const mp_obj_t *args){ - const bool res_arg = n_args == 4; - const int off = res_arg ? 0 : -1; - mp_obj_t res = mp_obj_new_scalar_r(res_arg ? args[0] : mp_const_none); - assert_ge25519(args[1+off]); - assert_scalar(args[3+off]); - xmr_derive_private_key(MP_OBJ_SCALAR(res), &MP_OBJ_C_GE25519(args[1+off]), mp_obj_get_int(args[2+off]), MP_OBJ_C_SCALAR(args[3+off])); - return res; -} -STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(mod_trezorcrypto_monero_xmr_derive_private_key_obj, 3, 4, mod_trezorcrypto_monero_xmr_derive_private_key); - -/// def xmr_derive_public_key(r: Optional[Ge25519], deriv: Ge25519, idx: int, base: Ge25519) -> Ge25519: +STATIC mp_obj_t mod_trezorcrypto_monero_xmr_derive_private_key( + size_t n_args, const mp_obj_t *args) { + const bool res_arg = n_args == 4; + const int off = res_arg ? 0 : -1; + mp_obj_t res = mp_obj_new_scalar_r(res_arg ? args[0] : mp_const_none); + assert_ge25519(args[1 + off]); + assert_scalar(args[3 + off]); + xmr_derive_private_key(MP_OBJ_SCALAR(res), &MP_OBJ_C_GE25519(args[1 + off]), + mp_obj_get_int(args[2 + off]), + MP_OBJ_C_SCALAR(args[3 + off])); + return res; +} +STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN( + mod_trezorcrypto_monero_xmr_derive_private_key_obj, 3, 4, + mod_trezorcrypto_monero_xmr_derive_private_key); + +/// def xmr_derive_public_key(r: Optional[Ge25519], deriv: Ge25519, idx: int, +/// base: Ge25519) -> Ge25519: /// ''' /// H_s(derivation || varint(output_index))G + base /// ''' -STATIC mp_obj_t mod_trezorcrypto_monero_xmr_derive_public_key(size_t n_args, const mp_obj_t *args){ - const bool res_arg = n_args == 4; - const int off = res_arg ? 0 : -1; - mp_obj_t res = mp_obj_new_ge25519_r(res_arg ? args[0] : mp_const_none); - assert_ge25519(args[1+off]); - assert_ge25519(args[3+off]); - xmr_derive_public_key(&MP_OBJ_GE25519(res), &MP_OBJ_C_GE25519(args[1+off]), mp_obj_get_int(args[2+off]), &MP_OBJ_C_GE25519(args[3+off])); - return res; -} -STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(mod_trezorcrypto_monero_xmr_derive_public_key_obj, 3, 4, mod_trezorcrypto_monero_xmr_derive_public_key); - -/// def xmr_add_keys2(r: Optional[Ge25519], a: Sc25519, b: Sc25519, B: Ge25519) -> Ge25519: +STATIC mp_obj_t mod_trezorcrypto_monero_xmr_derive_public_key( + size_t n_args, const mp_obj_t *args) { + const bool res_arg = n_args == 4; + const int off = res_arg ? 0 : -1; + mp_obj_t res = mp_obj_new_ge25519_r(res_arg ? args[0] : mp_const_none); + assert_ge25519(args[1 + off]); + assert_ge25519(args[3 + off]); + xmr_derive_public_key(&MP_OBJ_GE25519(res), &MP_OBJ_C_GE25519(args[1 + off]), + mp_obj_get_int(args[2 + off]), + &MP_OBJ_C_GE25519(args[3 + off])); + return res; +} +STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN( + mod_trezorcrypto_monero_xmr_derive_public_key_obj, 3, 4, + mod_trezorcrypto_monero_xmr_derive_public_key); + +/// def xmr_add_keys2(r: Optional[Ge25519], a: Sc25519, b: Sc25519, B: Ge25519) +/// -> Ge25519: /// ''' /// aG + bB, G is basepoint /// ''' -STATIC mp_obj_t mod_trezorcrypto_monero_xmr_add_keys2(size_t n_args, const mp_obj_t *args){ - const bool res_arg = n_args == 4; - const int off = res_arg ? 0 : -1; - mp_obj_t res = mp_obj_new_ge25519_r(res_arg ? args[0] : mp_const_none); - assert_scalar(args[1+off]); - assert_scalar(args[2+off]); - assert_ge25519(args[3+off]); - xmr_add_keys2(&MP_OBJ_GE25519(res), MP_OBJ_SCALAR(args[1+off]), MP_OBJ_SCALAR(args[2+off]), &MP_OBJ_C_GE25519(args[3+off])); - return res; -} -STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(mod_trezorcrypto_monero_xmr_add_keys2_obj, 3, 4, mod_trezorcrypto_monero_xmr_add_keys2); - -/// def xmr_add_keys2_vartime(r: Optional[Ge25519], a: Sc25519, b: Sc25519, B: Ge25519) -> Ge25519: +STATIC mp_obj_t mod_trezorcrypto_monero_xmr_add_keys2(size_t n_args, + const mp_obj_t *args) { + const bool res_arg = n_args == 4; + const int off = res_arg ? 0 : -1; + mp_obj_t res = mp_obj_new_ge25519_r(res_arg ? args[0] : mp_const_none); + assert_scalar(args[1 + off]); + assert_scalar(args[2 + off]); + assert_ge25519(args[3 + off]); + xmr_add_keys2(&MP_OBJ_GE25519(res), MP_OBJ_SCALAR(args[1 + off]), + MP_OBJ_SCALAR(args[2 + off]), &MP_OBJ_C_GE25519(args[3 + off])); + return res; +} +STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN( + mod_trezorcrypto_monero_xmr_add_keys2_obj, 3, 4, + mod_trezorcrypto_monero_xmr_add_keys2); + +/// def xmr_add_keys2_vartime(r: Optional[Ge25519], a: Sc25519, b: Sc25519, B: +/// Ge25519) -> Ge25519: /// ''' /// aG + bB, G is basepoint /// ''' -STATIC mp_obj_t mod_trezorcrypto_monero_xmr_add_keys2_vartime(size_t n_args, const mp_obj_t *args){ - const bool res_arg = n_args == 4; - const int off = res_arg ? 0 : -1; - mp_obj_t res = mp_obj_new_ge25519_r(res_arg ? args[0] : mp_const_none); - assert_scalar(args[1+off]); - assert_scalar(args[2+off]); - assert_ge25519(args[3+off]); - xmr_add_keys2_vartime(&MP_OBJ_GE25519(res), MP_OBJ_SCALAR(args[1+off]), MP_OBJ_SCALAR(args[2+off]), &MP_OBJ_C_GE25519(args[3+off])); - return res; -} -STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(mod_trezorcrypto_monero_xmr_add_keys2_vartime_obj, 3, 4, mod_trezorcrypto_monero_xmr_add_keys2_vartime); - -/// def xmr_add_keys3(r: Optional[Ge25519], a: Sc25519, A: Ge25519, b: Sc25519, B: Ge25519) -> Ge25519: +STATIC mp_obj_t mod_trezorcrypto_monero_xmr_add_keys2_vartime( + size_t n_args, const mp_obj_t *args) { + const bool res_arg = n_args == 4; + const int off = res_arg ? 0 : -1; + mp_obj_t res = mp_obj_new_ge25519_r(res_arg ? args[0] : mp_const_none); + assert_scalar(args[1 + off]); + assert_scalar(args[2 + off]); + assert_ge25519(args[3 + off]); + xmr_add_keys2_vartime(&MP_OBJ_GE25519(res), MP_OBJ_SCALAR(args[1 + off]), + MP_OBJ_SCALAR(args[2 + off]), + &MP_OBJ_C_GE25519(args[3 + off])); + return res; +} +STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN( + mod_trezorcrypto_monero_xmr_add_keys2_vartime_obj, 3, 4, + mod_trezorcrypto_monero_xmr_add_keys2_vartime); + +/// def xmr_add_keys3(r: Optional[Ge25519], a: Sc25519, A: Ge25519, b: Sc25519, +/// B: Ge25519) -> Ge25519: /// ''' /// aA + bB /// ''' -STATIC mp_obj_t mod_trezorcrypto_monero_xmr_add_keys3(size_t n_args, const mp_obj_t *args){ - const bool res_arg = n_args == 5; - const int off = res_arg ? 0 : -1; - mp_obj_t res = mp_obj_new_ge25519_r(res_arg ? args[0] : mp_const_none); - assert_scalar(args[1+off]); - assert_ge25519(args[2+off]); - assert_scalar(args[3+off]); - assert_ge25519(args[4+off]); - xmr_add_keys3(&MP_OBJ_GE25519(res), - MP_OBJ_SCALAR(args[1+off]), &MP_OBJ_C_GE25519(args[2+off]), - MP_OBJ_SCALAR(args[3+off]), &MP_OBJ_C_GE25519(args[4+off])); - return res; -} -STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(mod_trezorcrypto_monero_xmr_add_keys3_obj, 4, 5, mod_trezorcrypto_monero_xmr_add_keys3); - -/// def xmr_add_keys3_vartime(r: Optional[Ge25519], a: Sc25519, A: Ge25519, b: Sc25519, B: Ge25519) -> Ge25519: +STATIC mp_obj_t mod_trezorcrypto_monero_xmr_add_keys3(size_t n_args, + const mp_obj_t *args) { + const bool res_arg = n_args == 5; + const int off = res_arg ? 0 : -1; + mp_obj_t res = mp_obj_new_ge25519_r(res_arg ? args[0] : mp_const_none); + assert_scalar(args[1 + off]); + assert_ge25519(args[2 + off]); + assert_scalar(args[3 + off]); + assert_ge25519(args[4 + off]); + xmr_add_keys3(&MP_OBJ_GE25519(res), MP_OBJ_SCALAR(args[1 + off]), + &MP_OBJ_C_GE25519(args[2 + off]), MP_OBJ_SCALAR(args[3 + off]), + &MP_OBJ_C_GE25519(args[4 + off])); + return res; +} +STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN( + mod_trezorcrypto_monero_xmr_add_keys3_obj, 4, 5, + mod_trezorcrypto_monero_xmr_add_keys3); + +/// def xmr_add_keys3_vartime(r: Optional[Ge25519], a: Sc25519, A: Ge25519, b: +/// Sc25519, B: Ge25519) -> Ge25519: /// ''' /// aA + bB /// ''' -STATIC mp_obj_t mod_trezorcrypto_monero_xmr_add_keys3_vartime(size_t n_args, const mp_obj_t *args){ - const bool res_arg = n_args == 5; - const int off = res_arg ? 0 : -1; - mp_obj_t res = mp_obj_new_ge25519_r(res_arg ? args[0] : mp_const_none); - assert_scalar(args[1+off]); - assert_ge25519(args[2+off]); - assert_scalar(args[3+off]); - assert_ge25519(args[4+off]); - xmr_add_keys3_vartime(&MP_OBJ_GE25519(res), - MP_OBJ_SCALAR(args[1+off]), &MP_OBJ_C_GE25519(args[2+off]), - MP_OBJ_SCALAR(args[3+off]), &MP_OBJ_C_GE25519(args[4+off])); - return res; -} -STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(mod_trezorcrypto_monero_xmr_add_keys3_vartime_obj, 4, 5, mod_trezorcrypto_monero_xmr_add_keys3_vartime); - -/// def xmr_get_subaddress_secret_key(r: Optional[Sc25519], major: int, minor: int, m: Sc25519) -> Sc25519: +STATIC mp_obj_t mod_trezorcrypto_monero_xmr_add_keys3_vartime( + size_t n_args, const mp_obj_t *args) { + const bool res_arg = n_args == 5; + const int off = res_arg ? 0 : -1; + mp_obj_t res = mp_obj_new_ge25519_r(res_arg ? args[0] : mp_const_none); + assert_scalar(args[1 + off]); + assert_ge25519(args[2 + off]); + assert_scalar(args[3 + off]); + assert_ge25519(args[4 + off]); + xmr_add_keys3_vartime(&MP_OBJ_GE25519(res), MP_OBJ_SCALAR(args[1 + off]), + &MP_OBJ_C_GE25519(args[2 + off]), + MP_OBJ_SCALAR(args[3 + off]), + &MP_OBJ_C_GE25519(args[4 + off])); + return res; +} +STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN( + mod_trezorcrypto_monero_xmr_add_keys3_vartime_obj, 4, 5, + mod_trezorcrypto_monero_xmr_add_keys3_vartime); + +/// def xmr_get_subaddress_secret_key(r: Optional[Sc25519], major: int, minor: +/// int, m: Sc25519) -> Sc25519: /// ''' /// Hs(SubAddr || a || index_major || index_minor) /// ''' -STATIC mp_obj_t mod_trezorcrypto_monero_xmr_get_subaddress_secret_key(size_t n_args, const mp_obj_t *args){ - const bool res_arg = n_args == 4; - const int off = res_arg ? 0 : -1; - mp_obj_t res = mp_obj_new_scalar_r(res_arg ? args[0] : mp_const_none); - assert_scalar(args[3+off]); - xmr_get_subaddress_secret_key(MP_OBJ_SCALAR(res), mp_obj_get_int(args[1+off]), mp_obj_get_int(args[2+off]), MP_OBJ_C_SCALAR(args[3+off])); - return res; -} -STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(mod_trezorcrypto_monero_xmr_get_subaddress_secret_key_obj, 3, 4, mod_trezorcrypto_monero_xmr_get_subaddress_secret_key); +STATIC mp_obj_t mod_trezorcrypto_monero_xmr_get_subaddress_secret_key( + size_t n_args, const mp_obj_t *args) { + const bool res_arg = n_args == 4; + const int off = res_arg ? 0 : -1; + mp_obj_t res = mp_obj_new_scalar_r(res_arg ? args[0] : mp_const_none); + assert_scalar(args[3 + off]); + xmr_get_subaddress_secret_key( + MP_OBJ_SCALAR(res), mp_obj_get_int(args[1 + off]), + mp_obj_get_int(args[2 + off]), MP_OBJ_C_SCALAR(args[3 + off])); + return res; +} +STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN( + mod_trezorcrypto_monero_xmr_get_subaddress_secret_key_obj, 3, 4, + mod_trezorcrypto_monero_xmr_get_subaddress_secret_key); /// def xmr_gen_c(r: Optional[Ge25519], a: Sc25519, amount: int) -> Ge25519: /// ''' /// aG + amount * H /// ''' -STATIC mp_obj_t mod_trezorcrypto_monero_xmr_gen_c(size_t n_args, const mp_obj_t *args){ - const bool res_arg = n_args == 3; - const int off = res_arg ? 0 : -1; - mp_obj_t res = mp_obj_new_ge25519_r(res_arg ? args[0] : mp_const_none); - assert_scalar(args[1+off]); - xmr_gen_c(&MP_OBJ_GE25519(res), MP_OBJ_C_SCALAR(args[1+off]), mp_obj_get_uint64(args[2+off])); - return res; +STATIC mp_obj_t mod_trezorcrypto_monero_xmr_gen_c(size_t n_args, + const mp_obj_t *args) { + const bool res_arg = n_args == 3; + const int off = res_arg ? 0 : -1; + mp_obj_t res = mp_obj_new_ge25519_r(res_arg ? args[0] : mp_const_none); + assert_scalar(args[1 + off]); + xmr_gen_c(&MP_OBJ_GE25519(res), MP_OBJ_C_SCALAR(args[1 + off]), + mp_obj_get_uint64(args[2 + off])); + return res; } -STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(mod_trezorcrypto_monero_xmr_gen_c_obj, 2, 3, mod_trezorcrypto_monero_xmr_gen_c); +STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN( + mod_trezorcrypto_monero_xmr_gen_c_obj, 2, 3, + mod_trezorcrypto_monero_xmr_gen_c); /// def ct_equals(a: bytes, b: bytes) -> bool: /// ''' /// Constant time buffer comparison /// ''' -STATIC mp_obj_t mod_trezorcrypto_ct_equals(const mp_obj_t a, const mp_obj_t b){ - mp_buffer_info_t buff_a, buff_b; - mp_get_buffer_raise(a, &buff_a, MP_BUFFER_READ); - mp_get_buffer_raise(b, &buff_b, MP_BUFFER_READ); +STATIC mp_obj_t mod_trezorcrypto_ct_equals(const mp_obj_t a, const mp_obj_t b) { + mp_buffer_info_t buff_a, buff_b; + mp_get_buffer_raise(a, &buff_a, MP_BUFFER_READ); + mp_get_buffer_raise(b, &buff_b, MP_BUFFER_READ); - if (buff_a.len != buff_b.len) { - return MP_OBJ_NEW_SMALL_INT(0); - } + if (buff_a.len != buff_b.len) { + return MP_OBJ_NEW_SMALL_INT(0); + } - int r = ed25519_verify(buff_a.buf, buff_b.buf, buff_a.len); - return MP_OBJ_NEW_SMALL_INT(r); + int r = ed25519_verify(buff_a.buf, buff_b.buf, buff_a.len); + return MP_OBJ_NEW_SMALL_INT(r); } -STATIC MP_DEFINE_CONST_FUN_OBJ_2(mod_trezorcrypto_ct_equals_obj, mod_trezorcrypto_ct_equals); +STATIC MP_DEFINE_CONST_FUN_OBJ_2(mod_trezorcrypto_ct_equals_obj, + mod_trezorcrypto_ct_equals); // Hasher -STATIC mp_obj_t mod_trezorcrypto_monero_hasher_update(mp_obj_t self, const mp_obj_t arg){ - mp_obj_hasher_t *o = MP_OBJ_TO_PTR(self); - mp_buffer_info_t buff; - mp_get_buffer_raise(arg, &buff, MP_BUFFER_READ); - if (buff.len > 0) { - xmr_hasher_update(&o->h, buff.buf, buff.len); - } - return mp_const_none; +STATIC mp_obj_t mod_trezorcrypto_monero_hasher_update(mp_obj_t self, + const mp_obj_t arg) { + mp_obj_hasher_t *o = MP_OBJ_TO_PTR(self); + mp_buffer_info_t buff; + mp_get_buffer_raise(arg, &buff, MP_BUFFER_READ); + if (buff.len > 0) { + xmr_hasher_update(&o->h, buff.buf, buff.len); + } + return mp_const_none; } -STATIC MP_DEFINE_CONST_FUN_OBJ_2(mod_trezorcrypto_monero_hasher_update_obj, mod_trezorcrypto_monero_hasher_update); +STATIC MP_DEFINE_CONST_FUN_OBJ_2(mod_trezorcrypto_monero_hasher_update_obj, + mod_trezorcrypto_monero_hasher_update); -STATIC mp_obj_t mod_trezorcrypto_monero_hasher_digest(size_t n_args, const mp_obj_t *args){ - mp_obj_hasher_t *o = MP_OBJ_TO_PTR(args[0]); +STATIC mp_obj_t mod_trezorcrypto_monero_hasher_digest(size_t n_args, + const mp_obj_t *args) { + mp_obj_hasher_t *o = MP_OBJ_TO_PTR(args[0]); - Hasher ctx; - memcpy(&ctx, &(o->h), sizeof(Hasher)); + Hasher ctx; + memcpy(&ctx, &(o->h), sizeof(Hasher)); - uint8_t out[SHA3_256_DIGEST_LENGTH]; - xmr_hasher_final(&ctx, out); - memzero(&ctx, sizeof(SHA3_CTX)); + uint8_t out[SHA3_256_DIGEST_LENGTH]; + xmr_hasher_final(&ctx, out); + memzero(&ctx, sizeof(SHA3_CTX)); - if (n_args == 1 || args[1] == mp_const_none){ - return mp_obj_new_bytes(out, sizeof(out)); + if (n_args == 1 || args[1] == mp_const_none) { + return mp_obj_new_bytes(out, sizeof(out)); - } else { - mp_buffer_info_t bufm; - mp_get_buffer_raise(args[1], &bufm, MP_BUFFER_WRITE); - const mp_int_t offset = n_args >= 3 ? mp_obj_get_int(args[2]) : 0; - if (bufm.len < 32 + offset) { - mp_raise_ValueError("Buffer too small"); - } - - memcpy((uint8_t*)bufm.buf + offset, out, SHA3_256_DIGEST_LENGTH); - return args[1]; + } else { + mp_buffer_info_t bufm; + mp_get_buffer_raise(args[1], &bufm, MP_BUFFER_WRITE); + const mp_int_t offset = n_args >= 3 ? mp_obj_get_int(args[2]) : 0; + if (bufm.len < 32 + offset) { + mp_raise_ValueError("Buffer too small"); } -} -STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(mod_trezorcrypto_monero_hasher_digest_obj, 1, 3, mod_trezorcrypto_monero_hasher_digest); -STATIC mp_obj_t mod_trezorcrypto_monero_hasher_copy(mp_obj_t self){ - mp_obj_hasher_t *o = MP_OBJ_TO_PTR(self); - mp_obj_hasher_t *cp = m_new_obj(mp_obj_hasher_t); - cp->base.type = o->base.type; - memcpy(&(cp->h), &(o->h), sizeof(Hasher)); - return MP_OBJ_FROM_PTR(o); + memcpy((uint8_t *)bufm.buf + offset, out, SHA3_256_DIGEST_LENGTH); + return args[1]; + } } -STATIC MP_DEFINE_CONST_FUN_OBJ_1(mod_trezorcrypto_monero_hasher_copy_obj, mod_trezorcrypto_monero_hasher_copy); +STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN( + mod_trezorcrypto_monero_hasher_digest_obj, 1, 3, + mod_trezorcrypto_monero_hasher_digest); +STATIC mp_obj_t mod_trezorcrypto_monero_hasher_copy(mp_obj_t self) { + mp_obj_hasher_t *o = MP_OBJ_TO_PTR(self); + mp_obj_hasher_t *cp = m_new_obj(mp_obj_hasher_t); + cp->base.type = o->base.type; + memcpy(&(cp->h), &(o->h), sizeof(Hasher)); + return MP_OBJ_FROM_PTR(o); +} +STATIC MP_DEFINE_CONST_FUN_OBJ_1(mod_trezorcrypto_monero_hasher_copy_obj, + mod_trezorcrypto_monero_hasher_copy); // // Type defs // -STATIC const mp_rom_map_elem_t mod_trezorcrypto_monero_ge25519_locals_dict_table[] = { - { MP_ROM_QSTR(MP_QSTR___del__), MP_ROM_PTR(&mod_trezorcrypto_monero_ge25519___del___obj) }, +STATIC const mp_rom_map_elem_t + mod_trezorcrypto_monero_ge25519_locals_dict_table[] = { + {MP_ROM_QSTR(MP_QSTR___del__), + MP_ROM_PTR(&mod_trezorcrypto_monero_ge25519___del___obj)}, }; -STATIC MP_DEFINE_CONST_DICT(mod_trezorcrypto_monero_ge25519_locals_dict, mod_trezorcrypto_monero_ge25519_locals_dict_table); +STATIC MP_DEFINE_CONST_DICT(mod_trezorcrypto_monero_ge25519_locals_dict, + mod_trezorcrypto_monero_ge25519_locals_dict_table); STATIC const mp_obj_type_t mod_trezorcrypto_monero_ge25519_type = { - { &mp_type_type }, + {&mp_type_type}, .name = MP_QSTR_Ge25519, .make_new = mod_trezorcrypto_monero_ge25519_make_new, - .locals_dict = (void*)&mod_trezorcrypto_monero_ge25519_locals_dict, + .locals_dict = (void *)&mod_trezorcrypto_monero_ge25519_locals_dict, }; -STATIC const mp_rom_map_elem_t mod_trezorcrypto_monero_bignum256modm_locals_dict_table[] = { - { MP_ROM_QSTR(MP_QSTR___del__), MP_ROM_PTR(&mod_trezorcrypto_monero_bignum256modm___del___obj) }, +STATIC const mp_rom_map_elem_t + mod_trezorcrypto_monero_bignum256modm_locals_dict_table[] = { + {MP_ROM_QSTR(MP_QSTR___del__), + MP_ROM_PTR(&mod_trezorcrypto_monero_bignum256modm___del___obj)}, }; -STATIC MP_DEFINE_CONST_DICT(mod_trezorcrypto_monero_bignum256modm_locals_dict, mod_trezorcrypto_monero_bignum256modm_locals_dict_table); - +STATIC MP_DEFINE_CONST_DICT( + mod_trezorcrypto_monero_bignum256modm_locals_dict, + mod_trezorcrypto_monero_bignum256modm_locals_dict_table); STATIC const mp_obj_type_t mod_trezorcrypto_monero_bignum256modm_type = { - { &mp_type_type }, + {&mp_type_type}, .name = MP_QSTR_Sc25519, .make_new = mod_trezorcrypto_monero_bignum256modm_make_new, - .locals_dict = (void*)&mod_trezorcrypto_monero_bignum256modm_locals_dict, + .locals_dict = (void *)&mod_trezorcrypto_monero_bignum256modm_locals_dict, }; -STATIC const mp_rom_map_elem_t mod_trezorcrypto_monero_hasher_locals_dict_table[] = { - { MP_ROM_QSTR(MP_QSTR_update), MP_ROM_PTR(&mod_trezorcrypto_monero_hasher_update_obj) }, - { MP_ROM_QSTR(MP_QSTR_digest), MP_ROM_PTR(&mod_trezorcrypto_monero_hasher_digest_obj) }, - { MP_ROM_QSTR(MP_QSTR_copy), MP_ROM_PTR(&mod_trezorcrypto_monero_hasher_copy_obj) }, - { MP_ROM_QSTR(MP_QSTR___del__), MP_ROM_PTR(&mod_trezorcrypto_monero_hasher___del___obj) }, - { MP_ROM_QSTR(MP_QSTR_block_size), MP_OBJ_NEW_SMALL_INT(SHA3_256_BLOCK_LENGTH) }, - { MP_ROM_QSTR(MP_QSTR_digest_size), MP_OBJ_NEW_SMALL_INT(SHA3_256_DIGEST_LENGTH) }, +STATIC const mp_rom_map_elem_t + mod_trezorcrypto_monero_hasher_locals_dict_table[] = { + {MP_ROM_QSTR(MP_QSTR_update), + MP_ROM_PTR(&mod_trezorcrypto_monero_hasher_update_obj)}, + {MP_ROM_QSTR(MP_QSTR_digest), + MP_ROM_PTR(&mod_trezorcrypto_monero_hasher_digest_obj)}, + {MP_ROM_QSTR(MP_QSTR_copy), + MP_ROM_PTR(&mod_trezorcrypto_monero_hasher_copy_obj)}, + {MP_ROM_QSTR(MP_QSTR___del__), + MP_ROM_PTR(&mod_trezorcrypto_monero_hasher___del___obj)}, + {MP_ROM_QSTR(MP_QSTR_block_size), + MP_OBJ_NEW_SMALL_INT(SHA3_256_BLOCK_LENGTH)}, + {MP_ROM_QSTR(MP_QSTR_digest_size), + MP_OBJ_NEW_SMALL_INT(SHA3_256_DIGEST_LENGTH)}, }; -STATIC MP_DEFINE_CONST_DICT(mod_trezorcrypto_monero_hasher_locals_dict, mod_trezorcrypto_monero_hasher_locals_dict_table); - +STATIC MP_DEFINE_CONST_DICT(mod_trezorcrypto_monero_hasher_locals_dict, + mod_trezorcrypto_monero_hasher_locals_dict_table); STATIC const mp_obj_type_t mod_trezorcrypto_monero_hasher_type = { - { &mp_type_type }, + {&mp_type_type}, .name = MP_QSTR_hasher, .make_new = mod_trezorcrypto_monero_hasher_make_new, - .locals_dict = (void*)&mod_trezorcrypto_monero_hasher_locals_dict, + .locals_dict = (void *)&mod_trezorcrypto_monero_hasher_locals_dict, }; STATIC const mp_rom_map_elem_t mod_trezorcrypto_monero_globals_table[] = { - { MP_ROM_QSTR(MP_QSTR___name__), MP_ROM_QSTR(MP_QSTR_monero) }, - { MP_ROM_QSTR(MP_QSTR_init256_modm), MP_ROM_PTR(&mod_trezorcrypto_monero_init256_modm_obj) }, - { MP_ROM_QSTR(MP_QSTR_check256_modm), MP_ROM_PTR(&mod_trezorcrypto_monero_check256_modm_obj) }, - { MP_ROM_QSTR(MP_QSTR_iszero256_modm), MP_ROM_PTR(&mod_trezorcrypto_monero_iszero256_modm_obj) }, - { MP_ROM_QSTR(MP_QSTR_eq256_modm), MP_ROM_PTR(&mod_trezorcrypto_monero_eq256_modm_obj) }, - { MP_ROM_QSTR(MP_QSTR_get256_modm), MP_ROM_PTR(&mod_trezorcrypto_monero_get256_modm_obj) }, - { MP_ROM_QSTR(MP_QSTR_add256_modm), MP_ROM_PTR(&mod_trezorcrypto_monero_add256_modm_obj) }, - { MP_ROM_QSTR(MP_QSTR_sub256_modm), MP_ROM_PTR(&mod_trezorcrypto_monero_sub256_modm_obj) }, - { MP_ROM_QSTR(MP_QSTR_mul256_modm), MP_ROM_PTR(&mod_trezorcrypto_monero_mul256_modm_obj) }, - { MP_ROM_QSTR(MP_QSTR_mulsub256_modm), MP_ROM_PTR(&mod_trezorcrypto_monero_mulsub256_modm_obj) }, - { MP_ROM_QSTR(MP_QSTR_muladd256_modm), MP_ROM_PTR(&mod_trezorcrypto_monero_muladd256_modm_obj) }, - { MP_ROM_QSTR(MP_QSTR_inv256_modm), MP_ROM_PTR(&mod_trezorcrypto_monero_inv256_modm_obj) }, - { MP_ROM_QSTR(MP_QSTR_pack256_modm), MP_ROM_PTR(&mod_trezorcrypto_monero_pack256_modm_obj) }, - { MP_ROM_QSTR(MP_QSTR_unpack256_modm), MP_ROM_PTR(&mod_trezorcrypto_monero_unpack256_modm_obj) }, - { MP_ROM_QSTR(MP_QSTR_unpack256_modm_noreduce), MP_ROM_PTR(&mod_trezorcrypto_monero_unpack256_modm_noreduce_obj) }, - { MP_ROM_QSTR(MP_QSTR_ge25519_set_neutral), MP_ROM_PTR(&mod_trezorcrypto_monero_ge25519_set_neutral_obj) }, - { MP_ROM_QSTR(MP_QSTR_ge25519_set_h), MP_ROM_PTR(&mod_trezorcrypto_monero_ge25519_set_xmr_h_obj) }, - { MP_ROM_QSTR(MP_QSTR_ge25519_pack), MP_ROM_PTR(&mod_trezorcrypto_monero_ge25519_pack_obj) }, - { MP_ROM_QSTR(MP_QSTR_ge25519_unpack_vartime), MP_ROM_PTR(&mod_trezorcrypto_monero_ge25519_unpack_vartime_obj) }, - { MP_ROM_QSTR(MP_QSTR_ge25519_check), MP_ROM_PTR(&mod_trezorcrypto_monero_ge25519_check_obj) }, - { MP_ROM_QSTR(MP_QSTR_ge25519_eq), MP_ROM_PTR(&mod_trezorcrypto_monero_ge25519_eq_obj) }, - { MP_ROM_QSTR(MP_QSTR_ge25519_add), MP_ROM_PTR(&mod_trezorcrypto_monero_ge25519_add_obj) }, - { MP_ROM_QSTR(MP_QSTR_ge25519_sub), MP_ROM_PTR(&mod_trezorcrypto_monero_ge25519_sub_obj) }, - { MP_ROM_QSTR(MP_QSTR_ge25519_double), MP_ROM_PTR(&mod_trezorcrypto_monero_ge25519_double_obj) }, - { MP_ROM_QSTR(MP_QSTR_ge25519_mul8), MP_ROM_PTR(&mod_trezorcrypto_monero_ge25519_mul8_obj) }, - { MP_ROM_QSTR(MP_QSTR_ge25519_double_scalarmult_vartime), MP_ROM_PTR(&mod_trezorcrypto_monero_ge25519_double_scalarmult_vartime_obj) }, - { MP_ROM_QSTR(MP_QSTR_ge25519_double_scalarmult_vartime2), MP_ROM_PTR(&mod_trezorcrypto_monero_ge25519_double_scalarmult_vartime2_obj) }, - { MP_ROM_QSTR(MP_QSTR_ge25519_scalarmult_base), MP_ROM_PTR(&mod_trezorcrypto_monero_ge25519_scalarmult_base_obj) }, - { MP_ROM_QSTR(MP_QSTR_ge25519_scalarmult), MP_ROM_PTR(&mod_trezorcrypto_monero_ge25519_scalarmult_obj) }, - { MP_ROM_QSTR(MP_QSTR_xmr_base58_addr_encode_check), MP_ROM_PTR(&mod_trezorcrypto_monero_xmr_base58_addr_encode_check_obj) }, - { MP_ROM_QSTR(MP_QSTR_xmr_base58_addr_decode_check), MP_ROM_PTR(&mod_trezorcrypto_monero_xmr_base58_addr_decode_check_obj) }, - { MP_ROM_QSTR(MP_QSTR_xmr_random_scalar), MP_ROM_PTR(&mod_trezorcrypto_monero_xmr_random_scalar_obj) }, - { MP_ROM_QSTR(MP_QSTR_xmr_fast_hash), MP_ROM_PTR(&mod_trezorcrypto_monero_xmr_fast_hash_obj) }, - { MP_ROM_QSTR(MP_QSTR_xmr_hash_to_ec), MP_ROM_PTR(&mod_trezorcrypto_monero_xmr_hash_to_ec_obj) }, - { MP_ROM_QSTR(MP_QSTR_xmr_hash_to_scalar), MP_ROM_PTR(&mod_trezorcrypto_monero_xmr_hash_to_scalar_obj) }, - { MP_ROM_QSTR(MP_QSTR_xmr_derivation_to_scalar), MP_ROM_PTR(&mod_trezorcrypto_monero_xmr_derivation_to_scalar_obj) }, - { MP_ROM_QSTR(MP_QSTR_xmr_generate_key_derivation), MP_ROM_PTR(&mod_trezorcrypto_monero_xmr_generate_key_derivation_obj) }, - { MP_ROM_QSTR(MP_QSTR_xmr_derive_private_key), MP_ROM_PTR(&mod_trezorcrypto_monero_xmr_derive_private_key_obj) }, - { MP_ROM_QSTR(MP_QSTR_xmr_derive_public_key), MP_ROM_PTR(&mod_trezorcrypto_monero_xmr_derive_public_key_obj) }, - { MP_ROM_QSTR(MP_QSTR_xmr_add_keys2), MP_ROM_PTR(&mod_trezorcrypto_monero_xmr_add_keys2_obj) }, - { MP_ROM_QSTR(MP_QSTR_xmr_add_keys2_vartime), MP_ROM_PTR(&mod_trezorcrypto_monero_xmr_add_keys2_vartime_obj) }, - { MP_ROM_QSTR(MP_QSTR_xmr_add_keys3), MP_ROM_PTR(&mod_trezorcrypto_monero_xmr_add_keys3_obj) }, - { MP_ROM_QSTR(MP_QSTR_xmr_add_keys3_vartime), MP_ROM_PTR(&mod_trezorcrypto_monero_xmr_add_keys3_vartime_obj) }, - { MP_ROM_QSTR(MP_QSTR_xmr_get_subaddress_secret_key), MP_ROM_PTR(&mod_trezorcrypto_monero_xmr_get_subaddress_secret_key_obj) }, - { MP_ROM_QSTR(MP_QSTR_xmr_gen_c), MP_ROM_PTR(&mod_trezorcrypto_monero_xmr_gen_c_obj) }, - { MP_ROM_QSTR(MP_QSTR_ct_equals), MP_ROM_PTR(&mod_trezorcrypto_ct_equals_obj) }, + {MP_ROM_QSTR(MP_QSTR___name__), MP_ROM_QSTR(MP_QSTR_monero)}, + {MP_ROM_QSTR(MP_QSTR_init256_modm), + MP_ROM_PTR(&mod_trezorcrypto_monero_init256_modm_obj)}, + {MP_ROM_QSTR(MP_QSTR_check256_modm), + MP_ROM_PTR(&mod_trezorcrypto_monero_check256_modm_obj)}, + {MP_ROM_QSTR(MP_QSTR_iszero256_modm), + MP_ROM_PTR(&mod_trezorcrypto_monero_iszero256_modm_obj)}, + {MP_ROM_QSTR(MP_QSTR_eq256_modm), + MP_ROM_PTR(&mod_trezorcrypto_monero_eq256_modm_obj)}, + {MP_ROM_QSTR(MP_QSTR_get256_modm), + MP_ROM_PTR(&mod_trezorcrypto_monero_get256_modm_obj)}, + {MP_ROM_QSTR(MP_QSTR_add256_modm), + MP_ROM_PTR(&mod_trezorcrypto_monero_add256_modm_obj)}, + {MP_ROM_QSTR(MP_QSTR_sub256_modm), + MP_ROM_PTR(&mod_trezorcrypto_monero_sub256_modm_obj)}, + {MP_ROM_QSTR(MP_QSTR_mul256_modm), + MP_ROM_PTR(&mod_trezorcrypto_monero_mul256_modm_obj)}, + {MP_ROM_QSTR(MP_QSTR_mulsub256_modm), + MP_ROM_PTR(&mod_trezorcrypto_monero_mulsub256_modm_obj)}, + {MP_ROM_QSTR(MP_QSTR_muladd256_modm), + MP_ROM_PTR(&mod_trezorcrypto_monero_muladd256_modm_obj)}, + {MP_ROM_QSTR(MP_QSTR_inv256_modm), + MP_ROM_PTR(&mod_trezorcrypto_monero_inv256_modm_obj)}, + {MP_ROM_QSTR(MP_QSTR_pack256_modm), + MP_ROM_PTR(&mod_trezorcrypto_monero_pack256_modm_obj)}, + {MP_ROM_QSTR(MP_QSTR_unpack256_modm), + MP_ROM_PTR(&mod_trezorcrypto_monero_unpack256_modm_obj)}, + {MP_ROM_QSTR(MP_QSTR_unpack256_modm_noreduce), + MP_ROM_PTR(&mod_trezorcrypto_monero_unpack256_modm_noreduce_obj)}, + {MP_ROM_QSTR(MP_QSTR_ge25519_set_neutral), + MP_ROM_PTR(&mod_trezorcrypto_monero_ge25519_set_neutral_obj)}, + {MP_ROM_QSTR(MP_QSTR_ge25519_set_h), + MP_ROM_PTR(&mod_trezorcrypto_monero_ge25519_set_xmr_h_obj)}, + {MP_ROM_QSTR(MP_QSTR_ge25519_pack), + MP_ROM_PTR(&mod_trezorcrypto_monero_ge25519_pack_obj)}, + {MP_ROM_QSTR(MP_QSTR_ge25519_unpack_vartime), + MP_ROM_PTR(&mod_trezorcrypto_monero_ge25519_unpack_vartime_obj)}, + {MP_ROM_QSTR(MP_QSTR_ge25519_check), + MP_ROM_PTR(&mod_trezorcrypto_monero_ge25519_check_obj)}, + {MP_ROM_QSTR(MP_QSTR_ge25519_eq), + MP_ROM_PTR(&mod_trezorcrypto_monero_ge25519_eq_obj)}, + {MP_ROM_QSTR(MP_QSTR_ge25519_add), + MP_ROM_PTR(&mod_trezorcrypto_monero_ge25519_add_obj)}, + {MP_ROM_QSTR(MP_QSTR_ge25519_sub), + MP_ROM_PTR(&mod_trezorcrypto_monero_ge25519_sub_obj)}, + {MP_ROM_QSTR(MP_QSTR_ge25519_double), + MP_ROM_PTR(&mod_trezorcrypto_monero_ge25519_double_obj)}, + {MP_ROM_QSTR(MP_QSTR_ge25519_mul8), + MP_ROM_PTR(&mod_trezorcrypto_monero_ge25519_mul8_obj)}, + {MP_ROM_QSTR(MP_QSTR_ge25519_double_scalarmult_vartime), + MP_ROM_PTR( + &mod_trezorcrypto_monero_ge25519_double_scalarmult_vartime_obj)}, + {MP_ROM_QSTR(MP_QSTR_ge25519_double_scalarmult_vartime2), + MP_ROM_PTR( + &mod_trezorcrypto_monero_ge25519_double_scalarmult_vartime2_obj)}, + {MP_ROM_QSTR(MP_QSTR_ge25519_scalarmult_base), + MP_ROM_PTR(&mod_trezorcrypto_monero_ge25519_scalarmult_base_obj)}, + {MP_ROM_QSTR(MP_QSTR_ge25519_scalarmult), + MP_ROM_PTR(&mod_trezorcrypto_monero_ge25519_scalarmult_obj)}, + {MP_ROM_QSTR(MP_QSTR_xmr_base58_addr_encode_check), + MP_ROM_PTR(&mod_trezorcrypto_monero_xmr_base58_addr_encode_check_obj)}, + {MP_ROM_QSTR(MP_QSTR_xmr_base58_addr_decode_check), + MP_ROM_PTR(&mod_trezorcrypto_monero_xmr_base58_addr_decode_check_obj)}, + {MP_ROM_QSTR(MP_QSTR_xmr_random_scalar), + MP_ROM_PTR(&mod_trezorcrypto_monero_xmr_random_scalar_obj)}, + {MP_ROM_QSTR(MP_QSTR_xmr_fast_hash), + MP_ROM_PTR(&mod_trezorcrypto_monero_xmr_fast_hash_obj)}, + {MP_ROM_QSTR(MP_QSTR_xmr_hash_to_ec), + MP_ROM_PTR(&mod_trezorcrypto_monero_xmr_hash_to_ec_obj)}, + {MP_ROM_QSTR(MP_QSTR_xmr_hash_to_scalar), + MP_ROM_PTR(&mod_trezorcrypto_monero_xmr_hash_to_scalar_obj)}, + {MP_ROM_QSTR(MP_QSTR_xmr_derivation_to_scalar), + MP_ROM_PTR(&mod_trezorcrypto_monero_xmr_derivation_to_scalar_obj)}, + {MP_ROM_QSTR(MP_QSTR_xmr_generate_key_derivation), + MP_ROM_PTR(&mod_trezorcrypto_monero_xmr_generate_key_derivation_obj)}, + {MP_ROM_QSTR(MP_QSTR_xmr_derive_private_key), + MP_ROM_PTR(&mod_trezorcrypto_monero_xmr_derive_private_key_obj)}, + {MP_ROM_QSTR(MP_QSTR_xmr_derive_public_key), + MP_ROM_PTR(&mod_trezorcrypto_monero_xmr_derive_public_key_obj)}, + {MP_ROM_QSTR(MP_QSTR_xmr_add_keys2), + MP_ROM_PTR(&mod_trezorcrypto_monero_xmr_add_keys2_obj)}, + {MP_ROM_QSTR(MP_QSTR_xmr_add_keys2_vartime), + MP_ROM_PTR(&mod_trezorcrypto_monero_xmr_add_keys2_vartime_obj)}, + {MP_ROM_QSTR(MP_QSTR_xmr_add_keys3), + MP_ROM_PTR(&mod_trezorcrypto_monero_xmr_add_keys3_obj)}, + {MP_ROM_QSTR(MP_QSTR_xmr_add_keys3_vartime), + MP_ROM_PTR(&mod_trezorcrypto_monero_xmr_add_keys3_vartime_obj)}, + {MP_ROM_QSTR(MP_QSTR_xmr_get_subaddress_secret_key), + MP_ROM_PTR(&mod_trezorcrypto_monero_xmr_get_subaddress_secret_key_obj)}, + {MP_ROM_QSTR(MP_QSTR_xmr_gen_c), + MP_ROM_PTR(&mod_trezorcrypto_monero_xmr_gen_c_obj)}, + {MP_ROM_QSTR(MP_QSTR_ct_equals), + MP_ROM_PTR(&mod_trezorcrypto_ct_equals_obj)}, }; -STATIC MP_DEFINE_CONST_DICT(mod_trezorcrypto_monero_globals, mod_trezorcrypto_monero_globals_table); +STATIC MP_DEFINE_CONST_DICT(mod_trezorcrypto_monero_globals, + mod_trezorcrypto_monero_globals_table); STATIC const mp_obj_module_t mod_trezorcrypto_monero_module = { - .base = { &mp_type_module }, - .globals = (mp_obj_dict_t*)&mod_trezorcrypto_monero_globals, + .base = {&mp_type_module}, + .globals = (mp_obj_dict_t *)&mod_trezorcrypto_monero_globals, }; diff --git a/embed/extmod/modtrezorcrypto/modtrezorcrypto-nem.h b/embed/extmod/modtrezorcrypto/modtrezorcrypto-nem.h index 11fa0b01d..fd2edaa9d 100644 --- a/embed/extmod/modtrezorcrypto/modtrezorcrypto-nem.h +++ b/embed/extmod/modtrezorcrypto/modtrezorcrypto-nem.h @@ -29,43 +29,51 @@ /// ''' /// Validate a NEM address /// ''' -STATIC mp_obj_t mod_trezorcrypto_nem_validate_address(mp_obj_t address, mp_obj_t network) { +STATIC mp_obj_t mod_trezorcrypto_nem_validate_address(mp_obj_t address, + mp_obj_t network) { + mp_buffer_info_t addr; + mp_get_buffer_raise(address, &addr, MP_BUFFER_READ); - mp_buffer_info_t addr; - mp_get_buffer_raise(address, &addr, MP_BUFFER_READ); - - uint32_t n = trezor_obj_get_uint(network); - return mp_obj_new_bool(nem_validate_address(addr.buf, n)); + uint32_t n = trezor_obj_get_uint(network); + return mp_obj_new_bool(nem_validate_address(addr.buf, n)); } -STATIC MP_DEFINE_CONST_FUN_OBJ_2(mod_trezorcrypto_nem_validate_address_obj, mod_trezorcrypto_nem_validate_address); +STATIC MP_DEFINE_CONST_FUN_OBJ_2(mod_trezorcrypto_nem_validate_address_obj, + mod_trezorcrypto_nem_validate_address); /// def compute_address(public_key: bytes, network: int) -> str: /// ''' /// Compute a NEM address from a public key /// ''' -STATIC mp_obj_t mod_trezorcrypto_nem_compute_address(mp_obj_t public_key, mp_obj_t network) { - mp_buffer_info_t p; - mp_get_buffer_raise(public_key, &p, MP_BUFFER_READ); +STATIC mp_obj_t mod_trezorcrypto_nem_compute_address(mp_obj_t public_key, + mp_obj_t network) { + mp_buffer_info_t p; + mp_get_buffer_raise(public_key, &p, MP_BUFFER_READ); - uint32_t n = trezor_obj_get_uint(network); + uint32_t n = trezor_obj_get_uint(network); - char address[NEM_ADDRESS_SIZE + 1]; // + 1 for the 0 byte - if (!nem_get_address(p.buf, n, address)) { - mp_raise_ValueError("Failed to compute a NEM address from provided public key"); - } - return mp_obj_new_str_of_type(&mp_type_str, (const uint8_t *)address, strlen(address)); + char address[NEM_ADDRESS_SIZE + 1]; // + 1 for the 0 byte + if (!nem_get_address(p.buf, n, address)) { + mp_raise_ValueError( + "Failed to compute a NEM address from provided public key"); + } + return mp_obj_new_str_of_type(&mp_type_str, (const uint8_t *)address, + strlen(address)); } -STATIC MP_DEFINE_CONST_FUN_OBJ_2(mod_trezorcrypto_nem_compute_address_obj, mod_trezorcrypto_nem_compute_address); +STATIC MP_DEFINE_CONST_FUN_OBJ_2(mod_trezorcrypto_nem_compute_address_obj, + mod_trezorcrypto_nem_compute_address); // objects definition STATIC const mp_rom_map_elem_t mod_trezorcrypto_nem_globals_table[] = { - { MP_ROM_QSTR(MP_QSTR_validate_address), MP_ROM_PTR(&mod_trezorcrypto_nem_validate_address_obj) }, - { MP_ROM_QSTR(MP_QSTR_compute_address), MP_ROM_PTR(&mod_trezorcrypto_nem_compute_address_obj) }, + {MP_ROM_QSTR(MP_QSTR_validate_address), + MP_ROM_PTR(&mod_trezorcrypto_nem_validate_address_obj)}, + {MP_ROM_QSTR(MP_QSTR_compute_address), + MP_ROM_PTR(&mod_trezorcrypto_nem_compute_address_obj)}, }; -STATIC MP_DEFINE_CONST_DICT(mod_trezorcrypto_nem_globals, mod_trezorcrypto_nem_globals_table); +STATIC MP_DEFINE_CONST_DICT(mod_trezorcrypto_nem_globals, + mod_trezorcrypto_nem_globals_table); // module definition STATIC const mp_obj_module_t mod_trezorcrypto_nem_module = { - .base = { &mp_type_module }, - .globals = (mp_obj_dict_t*)&mod_trezorcrypto_nem_globals, + .base = {&mp_type_module}, + .globals = (mp_obj_dict_t *)&mod_trezorcrypto_nem_globals, }; diff --git a/embed/extmod/modtrezorcrypto/modtrezorcrypto-nist256p1.h b/embed/extmod/modtrezorcrypto/modtrezorcrypto-nist256p1.h index 8c6b5e5c1..84c98af16 100644 --- a/embed/extmod/modtrezorcrypto/modtrezorcrypto-nist256p1.h +++ b/embed/extmod/modtrezorcrypto/modtrezorcrypto-nist256p1.h @@ -29,158 +29,199 @@ /// Generate secret key. /// ''' STATIC mp_obj_t mod_trezorcrypto_nist256p1_generate_secret() { - uint8_t out[32]; - for (;;) { - random_buffer(out, 32); - // check whether secret > 0 && secret < curve_order - if (0 == memcmp(out, "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00", 32)) continue; - if (0 <= memcmp(out, "\xFF\xFF\xFF\xFF\x00\x00\x00\x00\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xBC\xE6\xFA\xAD\xA7\x17\x9E\x84\xF3\xB9\xCA\xC2\xFC\x63\x25\x51", 32)) continue; - break; - } - return mp_obj_new_bytes(out, sizeof(out)); + uint8_t out[32]; + for (;;) { + random_buffer(out, 32); + // check whether secret > 0 && secret < curve_order + if (0 == + memcmp( + out, + "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00", + 32)) + continue; + if (0 <= + memcmp( + out, + "\xFF\xFF\xFF\xFF\x00\x00\x00\x00\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF" + "\xBC\xE6\xFA\xAD\xA7\x17\x9E\x84\xF3\xB9\xCA\xC2\xFC\x63\x25\x51", + 32)) + continue; + break; + } + return mp_obj_new_bytes(out, sizeof(out)); } -STATIC MP_DEFINE_CONST_FUN_OBJ_0(mod_trezorcrypto_nist256p1_generate_secret_obj, mod_trezorcrypto_nist256p1_generate_secret); +STATIC MP_DEFINE_CONST_FUN_OBJ_0(mod_trezorcrypto_nist256p1_generate_secret_obj, + mod_trezorcrypto_nist256p1_generate_secret); /// def publickey(secret_key: bytes, compressed: bool = True) -> bytes: /// ''' /// Computes public key from secret key. /// ''' -STATIC mp_obj_t mod_trezorcrypto_nist256p1_publickey(size_t n_args, const mp_obj_t *args) { - mp_buffer_info_t sk; - mp_get_buffer_raise(args[0], &sk, MP_BUFFER_READ); - if (sk.len != 32) { - mp_raise_ValueError("Invalid length of secret key"); - } - bool compressed = n_args < 2 || args[1] == mp_const_true; - if (compressed) { - uint8_t out[33]; - ecdsa_get_public_key33(&nist256p1, (const uint8_t *)sk.buf, out); - return mp_obj_new_bytes(out, sizeof(out)); - } else { - uint8_t out[65]; - ecdsa_get_public_key65(&nist256p1, (const uint8_t *)sk.buf, out); - return mp_obj_new_bytes(out, sizeof(out)); - } +STATIC mp_obj_t mod_trezorcrypto_nist256p1_publickey(size_t n_args, + const mp_obj_t *args) { + mp_buffer_info_t sk; + mp_get_buffer_raise(args[0], &sk, MP_BUFFER_READ); + if (sk.len != 32) { + mp_raise_ValueError("Invalid length of secret key"); + } + bool compressed = n_args < 2 || args[1] == mp_const_true; + if (compressed) { + uint8_t out[33]; + ecdsa_get_public_key33(&nist256p1, (const uint8_t *)sk.buf, out); + return mp_obj_new_bytes(out, sizeof(out)); + } else { + uint8_t out[65]; + ecdsa_get_public_key65(&nist256p1, (const uint8_t *)sk.buf, out); + return mp_obj_new_bytes(out, sizeof(out)); + } } -STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(mod_trezorcrypto_nist256p1_publickey_obj, 1, 2, mod_trezorcrypto_nist256p1_publickey); +STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN( + mod_trezorcrypto_nist256p1_publickey_obj, 1, 2, + mod_trezorcrypto_nist256p1_publickey); -/// def sign(secret_key: bytes, digest: bytes, compressed: bool = True) -> bytes: +/// def sign(secret_key: bytes, digest: bytes, compressed: bool = True) -> +/// bytes: /// ''' /// Uses secret key to produce the signature of the digest. /// ''' -STATIC mp_obj_t mod_trezorcrypto_nist256p1_sign(size_t n_args, const mp_obj_t *args) { - mp_buffer_info_t sk, dig; - mp_get_buffer_raise(args[0], &sk, MP_BUFFER_READ); - mp_get_buffer_raise(args[1], &dig, MP_BUFFER_READ); - bool compressed = n_args < 3 || args[2] == mp_const_true; - if (sk.len != 32) { - mp_raise_ValueError("Invalid length of secret key"); - } - if (dig.len != 32) { - mp_raise_ValueError("Invalid length of digest"); - } - uint8_t out[65], pby; - if (0 != ecdsa_sign_digest(&nist256p1, (const uint8_t *)sk.buf, (const uint8_t *)dig.buf, out + 1, &pby, NULL)) { - mp_raise_ValueError("Signing failed"); - } - out[0] = 27 + pby + compressed * 4; - return mp_obj_new_bytes(out, sizeof(out)); +STATIC mp_obj_t mod_trezorcrypto_nist256p1_sign(size_t n_args, + const mp_obj_t *args) { + mp_buffer_info_t sk, dig; + mp_get_buffer_raise(args[0], &sk, MP_BUFFER_READ); + mp_get_buffer_raise(args[1], &dig, MP_BUFFER_READ); + bool compressed = n_args < 3 || args[2] == mp_const_true; + if (sk.len != 32) { + mp_raise_ValueError("Invalid length of secret key"); + } + if (dig.len != 32) { + mp_raise_ValueError("Invalid length of digest"); + } + uint8_t out[65], pby; + if (0 != ecdsa_sign_digest(&nist256p1, (const uint8_t *)sk.buf, + (const uint8_t *)dig.buf, out + 1, &pby, NULL)) { + mp_raise_ValueError("Signing failed"); + } + out[0] = 27 + pby + compressed * 4; + return mp_obj_new_bytes(out, sizeof(out)); } -STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(mod_trezorcrypto_nist256p1_sign_obj, 2, 3, mod_trezorcrypto_nist256p1_sign); +STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(mod_trezorcrypto_nist256p1_sign_obj, + 2, 3, + mod_trezorcrypto_nist256p1_sign); /// def verify(public_key: bytes, signature: bytes, digest: bytes) -> bool: /// ''' /// Uses public key to verify the signature of the digest. /// Returns True on success. /// ''' -STATIC mp_obj_t mod_trezorcrypto_nist256p1_verify(mp_obj_t public_key, mp_obj_t signature, mp_obj_t digest) { - mp_buffer_info_t pk, sig, dig; - mp_get_buffer_raise(public_key, &pk, MP_BUFFER_READ); - mp_get_buffer_raise(signature, &sig, MP_BUFFER_READ); - mp_get_buffer_raise(digest, &dig, MP_BUFFER_READ); - if (pk.len != 33 && pk.len != 65) { - mp_raise_ValueError("Invalid length of public key"); - } - if (sig.len != 64 && sig.len != 65) { - mp_raise_ValueError("Invalid length of signature"); - } - int offset = sig.len - 64; - if (dig.len != 32) { - mp_raise_ValueError("Invalid length of digest"); - } - return mp_obj_new_bool(0 == ecdsa_verify_digest(&nist256p1, (const uint8_t *)pk.buf, (const uint8_t *)sig.buf + offset, (const uint8_t *)dig.buf)); +STATIC mp_obj_t mod_trezorcrypto_nist256p1_verify(mp_obj_t public_key, + mp_obj_t signature, + mp_obj_t digest) { + mp_buffer_info_t pk, sig, dig; + mp_get_buffer_raise(public_key, &pk, MP_BUFFER_READ); + mp_get_buffer_raise(signature, &sig, MP_BUFFER_READ); + mp_get_buffer_raise(digest, &dig, MP_BUFFER_READ); + if (pk.len != 33 && pk.len != 65) { + mp_raise_ValueError("Invalid length of public key"); + } + if (sig.len != 64 && sig.len != 65) { + mp_raise_ValueError("Invalid length of signature"); + } + int offset = sig.len - 64; + if (dig.len != 32) { + mp_raise_ValueError("Invalid length of digest"); + } + return mp_obj_new_bool( + 0 == ecdsa_verify_digest(&nist256p1, (const uint8_t *)pk.buf, + (const uint8_t *)sig.buf + offset, + (const uint8_t *)dig.buf)); } -STATIC MP_DEFINE_CONST_FUN_OBJ_3(mod_trezorcrypto_nist256p1_verify_obj, mod_trezorcrypto_nist256p1_verify); +STATIC MP_DEFINE_CONST_FUN_OBJ_3(mod_trezorcrypto_nist256p1_verify_obj, + mod_trezorcrypto_nist256p1_verify); /// def verify_recover(signature: bytes, digest: bytes) -> bytes: /// ''' -/// Uses signature of the digest to verify the digest and recover the public key. -/// Returns public key on success, None on failure. +/// Uses signature of the digest to verify the digest and recover the public +/// key. Returns public key on success, None on failure. /// ''' -STATIC mp_obj_t mod_trezorcrypto_nist256p1_verify_recover(mp_obj_t signature, mp_obj_t digest) { - mp_buffer_info_t sig, dig; - mp_get_buffer_raise(signature, &sig, MP_BUFFER_READ); - mp_get_buffer_raise(digest, &dig, MP_BUFFER_READ); - if (sig.len != 65) { - mp_raise_ValueError("Invalid length of signature"); - } - if (dig.len != 32) { - mp_raise_ValueError("Invalid length of digest"); - } - uint8_t recid = ((const uint8_t *)sig.buf)[0] - 27; - if (recid >= 8) { - mp_raise_ValueError("Invalid recid in signature"); - } - bool compressed = (recid >= 4); - recid &= 3; - uint8_t out[65]; - if (0 == ecdsa_recover_pub_from_sig(&nist256p1, out, (const uint8_t *)sig.buf + 1, (const uint8_t *)dig.buf, recid)) { - if (compressed) { - out[0] = 0x02 | (out[64] & 1); - return mp_obj_new_bytes(out, 33); - } - return mp_obj_new_bytes(out, sizeof(out)); - } else { - return mp_const_none; +STATIC mp_obj_t mod_trezorcrypto_nist256p1_verify_recover(mp_obj_t signature, + mp_obj_t digest) { + mp_buffer_info_t sig, dig; + mp_get_buffer_raise(signature, &sig, MP_BUFFER_READ); + mp_get_buffer_raise(digest, &dig, MP_BUFFER_READ); + if (sig.len != 65) { + mp_raise_ValueError("Invalid length of signature"); + } + if (dig.len != 32) { + mp_raise_ValueError("Invalid length of digest"); + } + uint8_t recid = ((const uint8_t *)sig.buf)[0] - 27; + if (recid >= 8) { + mp_raise_ValueError("Invalid recid in signature"); + } + bool compressed = (recid >= 4); + recid &= 3; + uint8_t out[65]; + if (0 == ecdsa_recover_pub_from_sig(&nist256p1, out, + (const uint8_t *)sig.buf + 1, + (const uint8_t *)dig.buf, recid)) { + if (compressed) { + out[0] = 0x02 | (out[64] & 1); + return mp_obj_new_bytes(out, 33); } + return mp_obj_new_bytes(out, sizeof(out)); + } else { + return mp_const_none; + } } -STATIC MP_DEFINE_CONST_FUN_OBJ_2(mod_trezorcrypto_nist256p1_verify_recover_obj, mod_trezorcrypto_nist256p1_verify_recover); +STATIC MP_DEFINE_CONST_FUN_OBJ_2(mod_trezorcrypto_nist256p1_verify_recover_obj, + mod_trezorcrypto_nist256p1_verify_recover); /// def multiply(secret_key: bytes, public_key: bytes) -> bytes: /// ''' -/// Multiplies point defined by public_key with scalar defined by secret_key. -/// Useful for ECDH. +/// Multiplies point defined by public_key with scalar defined by +/// secret_key. Useful for ECDH. /// ''' -STATIC mp_obj_t mod_trezorcrypto_nist256p1_multiply(mp_obj_t secret_key, mp_obj_t public_key) { - mp_buffer_info_t sk, pk; - mp_get_buffer_raise(secret_key, &sk, MP_BUFFER_READ); - mp_get_buffer_raise(public_key, &pk, MP_BUFFER_READ); - if (sk.len != 32) { - mp_raise_ValueError("Invalid length of secret key"); - } - if (pk.len != 33 && pk.len != 65) { - mp_raise_ValueError("Invalid length of public key"); - } - uint8_t out[65]; - if (0 != ecdh_multiply(&nist256p1, (const uint8_t *)sk.buf, (const uint8_t *)pk.buf, out)) { - mp_raise_ValueError("Multiply failed"); - } - return mp_obj_new_bytes(out, sizeof(out)); +STATIC mp_obj_t mod_trezorcrypto_nist256p1_multiply(mp_obj_t secret_key, + mp_obj_t public_key) { + mp_buffer_info_t sk, pk; + mp_get_buffer_raise(secret_key, &sk, MP_BUFFER_READ); + mp_get_buffer_raise(public_key, &pk, MP_BUFFER_READ); + if (sk.len != 32) { + mp_raise_ValueError("Invalid length of secret key"); + } + if (pk.len != 33 && pk.len != 65) { + mp_raise_ValueError("Invalid length of public key"); + } + uint8_t out[65]; + if (0 != ecdh_multiply(&nist256p1, (const uint8_t *)sk.buf, + (const uint8_t *)pk.buf, out)) { + mp_raise_ValueError("Multiply failed"); + } + return mp_obj_new_bytes(out, sizeof(out)); } -STATIC MP_DEFINE_CONST_FUN_OBJ_2(mod_trezorcrypto_nist256p1_multiply_obj, mod_trezorcrypto_nist256p1_multiply); +STATIC MP_DEFINE_CONST_FUN_OBJ_2(mod_trezorcrypto_nist256p1_multiply_obj, + mod_trezorcrypto_nist256p1_multiply); STATIC const mp_rom_map_elem_t mod_trezorcrypto_nist256p1_globals_table[] = { - { MP_ROM_QSTR(MP_QSTR___name__), MP_ROM_QSTR(MP_QSTR_nist256p1) }, - { MP_ROM_QSTR(MP_QSTR_generate_secret), MP_ROM_PTR(&mod_trezorcrypto_nist256p1_generate_secret_obj) }, - { MP_ROM_QSTR(MP_QSTR_publickey), MP_ROM_PTR(&mod_trezorcrypto_nist256p1_publickey_obj) }, - { MP_ROM_QSTR(MP_QSTR_sign), MP_ROM_PTR(&mod_trezorcrypto_nist256p1_sign_obj) }, - { MP_ROM_QSTR(MP_QSTR_verify), MP_ROM_PTR(&mod_trezorcrypto_nist256p1_verify_obj) }, - { MP_ROM_QSTR(MP_QSTR_verify_recover), MP_ROM_PTR(&mod_trezorcrypto_nist256p1_verify_recover_obj) }, - { MP_ROM_QSTR(MP_QSTR_multiply), MP_ROM_PTR(&mod_trezorcrypto_nist256p1_multiply_obj) }, + {MP_ROM_QSTR(MP_QSTR___name__), MP_ROM_QSTR(MP_QSTR_nist256p1)}, + {MP_ROM_QSTR(MP_QSTR_generate_secret), + MP_ROM_PTR(&mod_trezorcrypto_nist256p1_generate_secret_obj)}, + {MP_ROM_QSTR(MP_QSTR_publickey), + MP_ROM_PTR(&mod_trezorcrypto_nist256p1_publickey_obj)}, + {MP_ROM_QSTR(MP_QSTR_sign), + MP_ROM_PTR(&mod_trezorcrypto_nist256p1_sign_obj)}, + {MP_ROM_QSTR(MP_QSTR_verify), + MP_ROM_PTR(&mod_trezorcrypto_nist256p1_verify_obj)}, + {MP_ROM_QSTR(MP_QSTR_verify_recover), + MP_ROM_PTR(&mod_trezorcrypto_nist256p1_verify_recover_obj)}, + {MP_ROM_QSTR(MP_QSTR_multiply), + MP_ROM_PTR(&mod_trezorcrypto_nist256p1_multiply_obj)}, }; -STATIC MP_DEFINE_CONST_DICT(mod_trezorcrypto_nist256p1_globals, mod_trezorcrypto_nist256p1_globals_table); +STATIC MP_DEFINE_CONST_DICT(mod_trezorcrypto_nist256p1_globals, + mod_trezorcrypto_nist256p1_globals_table); STATIC const mp_obj_module_t mod_trezorcrypto_nist256p1_module = { - .base = { &mp_type_module }, - .globals = (mp_obj_dict_t*)&mod_trezorcrypto_nist256p1_globals, + .base = {&mp_type_module}, + .globals = (mp_obj_dict_t *)&mod_trezorcrypto_nist256p1_globals, }; diff --git a/embed/extmod/modtrezorcrypto/modtrezorcrypto-pbkdf2.h b/embed/extmod/modtrezorcrypto/modtrezorcrypto-pbkdf2.h index 13777a01c..d92b4f345 100644 --- a/embed/extmod/modtrezorcrypto/modtrezorcrypto-pbkdf2.h +++ b/embed/extmod/modtrezorcrypto/modtrezorcrypto-pbkdf2.h @@ -19,8 +19,8 @@ #include "py/objstr.h" -#include "pbkdf2.h" #include "memzero.h" +#include "pbkdf2.h" #define PRF_HMAC_SHA256 256 #define PRF_HMAC_SHA512 512 @@ -32,121 +32,132 @@ /// PBKDF2 context. /// ''' typedef struct _mp_obj_Pbkdf2_t { - mp_obj_base_t base; - union { - PBKDF2_HMAC_SHA256_CTX ctx256; - PBKDF2_HMAC_SHA512_CTX ctx512; - }; - uint32_t prf; + mp_obj_base_t base; + union { + PBKDF2_HMAC_SHA256_CTX ctx256; + PBKDF2_HMAC_SHA512_CTX ctx512; + }; + uint32_t prf; } mp_obj_Pbkdf2_t; STATIC mp_obj_t mod_trezorcrypto_Pbkdf2_update(mp_obj_t self, mp_obj_t data); -/// def __init__(self, prf: int, password: bytes, salt: bytes, iterations: int = None, blocknr: int = 1) -> None: +/// def __init__(self, prf: int, password: bytes, salt: bytes, iterations: int = +/// None, blocknr: int = 1) -> None: /// ''' /// Create a PBKDF2 context. /// ''' -STATIC mp_obj_t mod_trezorcrypto_Pbkdf2_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_kw, const mp_obj_t *args) { - mp_arg_check_num(n_args, n_kw, 3, 4, false); - mp_obj_Pbkdf2_t *o = m_new_obj(mp_obj_Pbkdf2_t); - o->base.type = type; - - mp_buffer_info_t password; - mp_get_buffer_raise(args[1], &password, MP_BUFFER_READ); - mp_buffer_info_t salt; - mp_get_buffer_raise(args[2], &salt, MP_BUFFER_READ); - - if (password.len == 0) { - password.buf = ""; - } - if (salt.len == 0) { - salt.buf = ""; - } - - uint32_t blocknr = 1; - if (n_args > 4) { // blocknr is set - blocknr = trezor_obj_get_uint(args[4]); - } - - o->prf = trezor_obj_get_uint(args[0]); - if (o->prf == PRF_HMAC_SHA256) { - pbkdf2_hmac_sha256_Init(&(o->ctx256), password.buf, password.len, salt.buf, salt.len, blocknr); - } else - if (o->prf == PRF_HMAC_SHA512) { - pbkdf2_hmac_sha512_Init(&(o->ctx512), password.buf, password.len, salt.buf, salt.len, blocknr); - } else { - mp_raise_ValueError("Invalid PRF"); - } - // constructor called with iterations as fourth parameter - if (n_args > 3) { - mod_trezorcrypto_Pbkdf2_update(MP_OBJ_FROM_PTR(o), args[3]); - } - return MP_OBJ_FROM_PTR(o); +STATIC mp_obj_t mod_trezorcrypto_Pbkdf2_make_new(const mp_obj_type_t *type, + size_t n_args, size_t n_kw, + const mp_obj_t *args) { + mp_arg_check_num(n_args, n_kw, 3, 4, false); + mp_obj_Pbkdf2_t *o = m_new_obj(mp_obj_Pbkdf2_t); + o->base.type = type; + + mp_buffer_info_t password; + mp_get_buffer_raise(args[1], &password, MP_BUFFER_READ); + mp_buffer_info_t salt; + mp_get_buffer_raise(args[2], &salt, MP_BUFFER_READ); + + if (password.len == 0) { + password.buf = ""; + } + if (salt.len == 0) { + salt.buf = ""; + } + + uint32_t blocknr = 1; + if (n_args > 4) { // blocknr is set + blocknr = trezor_obj_get_uint(args[4]); + } + + o->prf = trezor_obj_get_uint(args[0]); + if (o->prf == PRF_HMAC_SHA256) { + pbkdf2_hmac_sha256_Init(&(o->ctx256), password.buf, password.len, salt.buf, + salt.len, blocknr); + } else if (o->prf == PRF_HMAC_SHA512) { + pbkdf2_hmac_sha512_Init(&(o->ctx512), password.buf, password.len, salt.buf, + salt.len, blocknr); + } else { + mp_raise_ValueError("Invalid PRF"); + } + // constructor called with iterations as fourth parameter + if (n_args > 3) { + mod_trezorcrypto_Pbkdf2_update(MP_OBJ_FROM_PTR(o), args[3]); + } + return MP_OBJ_FROM_PTR(o); } /// def update(self, iterations: int) -> None: /// ''' /// Update a PBKDF2 context. /// ''' -STATIC mp_obj_t mod_trezorcrypto_Pbkdf2_update(mp_obj_t self, mp_obj_t iterations) { - mp_obj_Pbkdf2_t *o = MP_OBJ_TO_PTR(self); - uint32_t iter = trezor_obj_get_uint(iterations); - if (o->prf == PRF_HMAC_SHA256) { - pbkdf2_hmac_sha256_Update(&(o->ctx256), iter); - } - if (o->prf == PRF_HMAC_SHA512) { - pbkdf2_hmac_sha512_Update(&(o->ctx512), iter); - } - return mp_const_none; +STATIC mp_obj_t mod_trezorcrypto_Pbkdf2_update(mp_obj_t self, + mp_obj_t iterations) { + mp_obj_Pbkdf2_t *o = MP_OBJ_TO_PTR(self); + uint32_t iter = trezor_obj_get_uint(iterations); + if (o->prf == PRF_HMAC_SHA256) { + pbkdf2_hmac_sha256_Update(&(o->ctx256), iter); + } + if (o->prf == PRF_HMAC_SHA512) { + pbkdf2_hmac_sha512_Update(&(o->ctx512), iter); + } + return mp_const_none; } -STATIC MP_DEFINE_CONST_FUN_OBJ_2(mod_trezorcrypto_Pbkdf2_update_obj, mod_trezorcrypto_Pbkdf2_update); +STATIC MP_DEFINE_CONST_FUN_OBJ_2(mod_trezorcrypto_Pbkdf2_update_obj, + mod_trezorcrypto_Pbkdf2_update); /// def key(self) -> bytes: /// ''' /// Retrieve derived key. /// ''' STATIC mp_obj_t mod_trezorcrypto_Pbkdf2_key(mp_obj_t self) { - mp_obj_Pbkdf2_t *o = MP_OBJ_TO_PTR(self); - if (o->prf == PRF_HMAC_SHA256) { - PBKDF2_HMAC_SHA256_CTX ctx; - memcpy(&ctx, &(o->ctx256), sizeof(PBKDF2_HMAC_SHA256_CTX)); - uint8_t out[SHA256_DIGEST_LENGTH]; - pbkdf2_hmac_sha256_Final(&ctx, out); - memzero(&ctx, sizeof(PBKDF2_HMAC_SHA256_CTX)); - return mp_obj_new_bytes(out, sizeof(out)); - } - if (o->prf == PRF_HMAC_SHA512) { - PBKDF2_HMAC_SHA512_CTX ctx; - memcpy(&ctx, &(o->ctx512), sizeof(PBKDF2_HMAC_SHA512_CTX)); - uint8_t out[SHA512_DIGEST_LENGTH]; - pbkdf2_hmac_sha512_Final(&ctx, out); - memzero(&ctx, sizeof(PBKDF2_HMAC_SHA512_CTX)); - return mp_obj_new_bytes(out, sizeof(out)); - } - return mp_const_none; + mp_obj_Pbkdf2_t *o = MP_OBJ_TO_PTR(self); + if (o->prf == PRF_HMAC_SHA256) { + PBKDF2_HMAC_SHA256_CTX ctx; + memcpy(&ctx, &(o->ctx256), sizeof(PBKDF2_HMAC_SHA256_CTX)); + uint8_t out[SHA256_DIGEST_LENGTH]; + pbkdf2_hmac_sha256_Final(&ctx, out); + memzero(&ctx, sizeof(PBKDF2_HMAC_SHA256_CTX)); + return mp_obj_new_bytes(out, sizeof(out)); + } + if (o->prf == PRF_HMAC_SHA512) { + PBKDF2_HMAC_SHA512_CTX ctx; + memcpy(&ctx, &(o->ctx512), sizeof(PBKDF2_HMAC_SHA512_CTX)); + uint8_t out[SHA512_DIGEST_LENGTH]; + pbkdf2_hmac_sha512_Final(&ctx, out); + memzero(&ctx, sizeof(PBKDF2_HMAC_SHA512_CTX)); + return mp_obj_new_bytes(out, sizeof(out)); + } + return mp_const_none; } -STATIC MP_DEFINE_CONST_FUN_OBJ_1(mod_trezorcrypto_Pbkdf2_key_obj, mod_trezorcrypto_Pbkdf2_key); +STATIC MP_DEFINE_CONST_FUN_OBJ_1(mod_trezorcrypto_Pbkdf2_key_obj, + mod_trezorcrypto_Pbkdf2_key); STATIC mp_obj_t mod_trezorcrypto_Pbkdf2___del__(mp_obj_t self) { - mp_obj_Pbkdf2_t *o = MP_OBJ_TO_PTR(self); - memzero(&(o->ctx256), sizeof(PBKDF2_HMAC_SHA256_CTX)); - memzero(&(o->ctx512), sizeof(PBKDF2_HMAC_SHA512_CTX)); - return mp_const_none; + mp_obj_Pbkdf2_t *o = MP_OBJ_TO_PTR(self); + memzero(&(o->ctx256), sizeof(PBKDF2_HMAC_SHA256_CTX)); + memzero(&(o->ctx512), sizeof(PBKDF2_HMAC_SHA512_CTX)); + return mp_const_none; } -STATIC MP_DEFINE_CONST_FUN_OBJ_1(mod_trezorcrypto_Pbkdf2___del___obj, mod_trezorcrypto_Pbkdf2___del__); +STATIC MP_DEFINE_CONST_FUN_OBJ_1(mod_trezorcrypto_Pbkdf2___del___obj, + mod_trezorcrypto_Pbkdf2___del__); STATIC const mp_rom_map_elem_t mod_trezorcrypto_Pbkdf2_locals_dict_table[] = { - { MP_ROM_QSTR(MP_QSTR_update), MP_ROM_PTR(&mod_trezorcrypto_Pbkdf2_update_obj) }, - { MP_ROM_QSTR(MP_QSTR_key), MP_ROM_PTR(&mod_trezorcrypto_Pbkdf2_key_obj) }, - { MP_ROM_QSTR(MP_QSTR___del__), MP_ROM_PTR(&mod_trezorcrypto_Pbkdf2___del___obj) }, - { MP_ROM_QSTR(MP_QSTR_HMAC_SHA256), MP_OBJ_NEW_SMALL_INT(PRF_HMAC_SHA256) }, - { MP_ROM_QSTR(MP_QSTR_HMAC_SHA512), MP_OBJ_NEW_SMALL_INT(PRF_HMAC_SHA512) }, + {MP_ROM_QSTR(MP_QSTR_update), + MP_ROM_PTR(&mod_trezorcrypto_Pbkdf2_update_obj)}, + {MP_ROM_QSTR(MP_QSTR_key), MP_ROM_PTR(&mod_trezorcrypto_Pbkdf2_key_obj)}, + {MP_ROM_QSTR(MP_QSTR___del__), + MP_ROM_PTR(&mod_trezorcrypto_Pbkdf2___del___obj)}, + {MP_ROM_QSTR(MP_QSTR_HMAC_SHA256), MP_OBJ_NEW_SMALL_INT(PRF_HMAC_SHA256)}, + {MP_ROM_QSTR(MP_QSTR_HMAC_SHA512), MP_OBJ_NEW_SMALL_INT(PRF_HMAC_SHA512)}, }; -STATIC MP_DEFINE_CONST_DICT(mod_trezorcrypto_Pbkdf2_locals_dict, mod_trezorcrypto_Pbkdf2_locals_dict_table); +STATIC MP_DEFINE_CONST_DICT(mod_trezorcrypto_Pbkdf2_locals_dict, + mod_trezorcrypto_Pbkdf2_locals_dict_table); STATIC const mp_obj_type_t mod_trezorcrypto_Pbkdf2_type = { - { &mp_type_type }, + {&mp_type_type}, .name = MP_QSTR_Pbkdf2, .make_new = mod_trezorcrypto_Pbkdf2_make_new, - .locals_dict = (void*)&mod_trezorcrypto_Pbkdf2_locals_dict, + .locals_dict = (void *)&mod_trezorcrypto_Pbkdf2_locals_dict, }; diff --git a/embed/extmod/modtrezorcrypto/modtrezorcrypto-random.h b/embed/extmod/modtrezorcrypto/modtrezorcrypto-random.h index 57e00bd83..112192dfd 100644 --- a/embed/extmod/modtrezorcrypto/modtrezorcrypto-random.h +++ b/embed/extmod/modtrezorcrypto/modtrezorcrypto-random.h @@ -30,65 +30,72 @@ /// Compute uniform random number from interval 0 ... n - 1. /// ''' STATIC mp_obj_t mod_trezorcrypto_random_uniform(mp_obj_t n) { - uint32_t nn = trezor_obj_get_uint(n); - if (nn == 0) { - mp_raise_ValueError("Maximum can't be zero"); - } - return mp_obj_new_int_from_uint(random_uniform(nn)); + uint32_t nn = trezor_obj_get_uint(n); + if (nn == 0) { + mp_raise_ValueError("Maximum can't be zero"); + } + return mp_obj_new_int_from_uint(random_uniform(nn)); } -STATIC MP_DEFINE_CONST_FUN_OBJ_1(mod_trezorcrypto_random_uniform_obj, mod_trezorcrypto_random_uniform); +STATIC MP_DEFINE_CONST_FUN_OBJ_1(mod_trezorcrypto_random_uniform_obj, + mod_trezorcrypto_random_uniform); /// def bytes(len: int) -> bytes: /// ''' /// Generate random bytes sequence of length len. /// ''' STATIC mp_obj_t mod_trezorcrypto_random_bytes(mp_obj_t len) { - uint32_t l = trezor_obj_get_uint(len); - if (l > 1024) { - mp_raise_ValueError("Maximum requested size is 1024"); - } - vstr_t vstr; - vstr_init_len(&vstr, l); - random_buffer((uint8_t *)vstr.buf, l); - return mp_obj_new_str_from_vstr(&mp_type_bytes, &vstr); + uint32_t l = trezor_obj_get_uint(len); + if (l > 1024) { + mp_raise_ValueError("Maximum requested size is 1024"); + } + vstr_t vstr; + vstr_init_len(&vstr, l); + random_buffer((uint8_t *)vstr.buf, l); + return mp_obj_new_str_from_vstr(&mp_type_bytes, &vstr); } -STATIC MP_DEFINE_CONST_FUN_OBJ_1(mod_trezorcrypto_random_bytes_obj, mod_trezorcrypto_random_bytes); +STATIC MP_DEFINE_CONST_FUN_OBJ_1(mod_trezorcrypto_random_bytes_obj, + mod_trezorcrypto_random_bytes); /// def shuffle(data: list) -> None: /// ''' /// Shuffles items of given list (in-place). /// ''' STATIC mp_obj_t mod_trezorcrypto_random_shuffle(mp_obj_t data) { - size_t count; - mp_obj_t *items; - mp_obj_get_array(data, &count, &items); - if (count > 256) { - mp_raise_ValueError("Maximum list size is 256 items"); - } - if (count <= 1) { - return mp_const_none; - } - // Fisher-Yates shuffle - mp_obj_t t; - for (size_t i = count - 1; i >= 1; i--) { - size_t j = random_uniform(i + 1); - t = items[i]; - items[i] = items[j]; - items[j] = t; - } + size_t count; + mp_obj_t *items; + mp_obj_get_array(data, &count, &items); + if (count > 256) { + mp_raise_ValueError("Maximum list size is 256 items"); + } + if (count <= 1) { return mp_const_none; + } + // Fisher-Yates shuffle + mp_obj_t t; + for (size_t i = count - 1; i >= 1; i--) { + size_t j = random_uniform(i + 1); + t = items[i]; + items[i] = items[j]; + items[j] = t; + } + return mp_const_none; } -STATIC MP_DEFINE_CONST_FUN_OBJ_1(mod_trezorcrypto_random_shuffle_obj, mod_trezorcrypto_random_shuffle); +STATIC MP_DEFINE_CONST_FUN_OBJ_1(mod_trezorcrypto_random_shuffle_obj, + mod_trezorcrypto_random_shuffle); STATIC const mp_rom_map_elem_t mod_trezorcrypto_random_globals_table[] = { - { MP_ROM_QSTR(MP_QSTR___name__), MP_ROM_QSTR(MP_QSTR_random) }, - { MP_ROM_QSTR(MP_QSTR_uniform), MP_ROM_PTR(&mod_trezorcrypto_random_uniform_obj) }, - { MP_ROM_QSTR(MP_QSTR_bytes), MP_ROM_PTR(&mod_trezorcrypto_random_bytes_obj) }, - { MP_ROM_QSTR(MP_QSTR_shuffle), MP_ROM_PTR(&mod_trezorcrypto_random_shuffle_obj) }, + {MP_ROM_QSTR(MP_QSTR___name__), MP_ROM_QSTR(MP_QSTR_random)}, + {MP_ROM_QSTR(MP_QSTR_uniform), + MP_ROM_PTR(&mod_trezorcrypto_random_uniform_obj)}, + {MP_ROM_QSTR(MP_QSTR_bytes), + MP_ROM_PTR(&mod_trezorcrypto_random_bytes_obj)}, + {MP_ROM_QSTR(MP_QSTR_shuffle), + MP_ROM_PTR(&mod_trezorcrypto_random_shuffle_obj)}, }; -STATIC MP_DEFINE_CONST_DICT(mod_trezorcrypto_random_globals, mod_trezorcrypto_random_globals_table); +STATIC MP_DEFINE_CONST_DICT(mod_trezorcrypto_random_globals, + mod_trezorcrypto_random_globals_table); STATIC const mp_obj_module_t mod_trezorcrypto_random_module = { - .base = { &mp_type_module }, - .globals = (mp_obj_dict_t*)&mod_trezorcrypto_random_globals, + .base = {&mp_type_module}, + .globals = (mp_obj_dict_t *)&mod_trezorcrypto_random_globals, }; diff --git a/embed/extmod/modtrezorcrypto/modtrezorcrypto-rfc6979.h b/embed/extmod/modtrezorcrypto/modtrezorcrypto-rfc6979.h index f89294de0..16711c3cd 100644 --- a/embed/extmod/modtrezorcrypto/modtrezorcrypto-rfc6979.h +++ b/embed/extmod/modtrezorcrypto/modtrezorcrypto-rfc6979.h @@ -28,29 +28,31 @@ /// RFC6979 context. /// ''' typedef struct _mp_obj_Rfc6979_t { - mp_obj_base_t base; - rfc6979_state rng; + mp_obj_base_t base; + rfc6979_state rng; } mp_obj_Rfc6979_t; /// def __init__(self, secret_key: bytes, hash: bytes) -> None: /// ''' /// Initialize RFC6979 context from secret key and a hash. /// ''' -STATIC mp_obj_t mod_trezorcrypto_Rfc6979_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_kw, const mp_obj_t *args) { - mp_arg_check_num(n_args, n_kw, 2, 2, false); - mp_obj_Rfc6979_t *o = m_new_obj(mp_obj_Rfc6979_t); - o->base.type = type; - mp_buffer_info_t pkey, hash; - mp_get_buffer_raise(args[0], &pkey, MP_BUFFER_READ); - mp_get_buffer_raise(args[1], &hash, MP_BUFFER_READ); - if (pkey.len != 32) { - mp_raise_ValueError("Secret key has to be 32 bytes long"); - } - if (hash.len != 32) { - mp_raise_ValueError("Hash has to be 32 bytes long"); - } - init_rfc6979((const uint8_t *)pkey.buf, (const uint8_t *)hash.buf, &(o->rng)); - return MP_OBJ_FROM_PTR(o); +STATIC mp_obj_t mod_trezorcrypto_Rfc6979_make_new(const mp_obj_type_t *type, + size_t n_args, size_t n_kw, + const mp_obj_t *args) { + mp_arg_check_num(n_args, n_kw, 2, 2, false); + mp_obj_Rfc6979_t *o = m_new_obj(mp_obj_Rfc6979_t); + o->base.type = type; + mp_buffer_info_t pkey, hash; + mp_get_buffer_raise(args[0], &pkey, MP_BUFFER_READ); + mp_get_buffer_raise(args[1], &hash, MP_BUFFER_READ); + if (pkey.len != 32) { + mp_raise_ValueError("Secret key has to be 32 bytes long"); + } + if (hash.len != 32) { + mp_raise_ValueError("Hash has to be 32 bytes long"); + } + init_rfc6979((const uint8_t *)pkey.buf, (const uint8_t *)hash.buf, &(o->rng)); + return MP_OBJ_FROM_PTR(o); } /// def next(self) -> bytes: @@ -58,21 +60,23 @@ STATIC mp_obj_t mod_trezorcrypto_Rfc6979_make_new(const mp_obj_type_t *type, siz /// Compute next 32-bytes of pseudorandom data. /// ''' STATIC mp_obj_t mod_trezorcrypto_Rfc6979_next(mp_obj_t self) { - mp_obj_Rfc6979_t *o = MP_OBJ_TO_PTR(self); - uint8_t out[32]; - generate_rfc6979(out, &(o->rng)); - return mp_obj_new_bytes(out, sizeof(out)); + mp_obj_Rfc6979_t *o = MP_OBJ_TO_PTR(self); + uint8_t out[32]; + generate_rfc6979(out, &(o->rng)); + return mp_obj_new_bytes(out, sizeof(out)); } -STATIC MP_DEFINE_CONST_FUN_OBJ_1(mod_trezorcrypto_Rfc6979_next_obj, mod_trezorcrypto_Rfc6979_next); +STATIC MP_DEFINE_CONST_FUN_OBJ_1(mod_trezorcrypto_Rfc6979_next_obj, + mod_trezorcrypto_Rfc6979_next); STATIC const mp_rom_map_elem_t mod_trezorcrypto_Rfc6979_locals_dict_table[] = { - { MP_ROM_QSTR(MP_QSTR_next), MP_ROM_PTR(&mod_trezorcrypto_Rfc6979_next_obj) }, + {MP_ROM_QSTR(MP_QSTR_next), MP_ROM_PTR(&mod_trezorcrypto_Rfc6979_next_obj)}, }; -STATIC MP_DEFINE_CONST_DICT(mod_trezorcrypto_Rfc6979_locals_dict, mod_trezorcrypto_Rfc6979_locals_dict_table); +STATIC MP_DEFINE_CONST_DICT(mod_trezorcrypto_Rfc6979_locals_dict, + mod_trezorcrypto_Rfc6979_locals_dict_table); STATIC const mp_obj_type_t mod_trezorcrypto_Rfc6979_type = { - { &mp_type_type }, + {&mp_type_type}, .name = MP_QSTR_Rfc6979, .make_new = mod_trezorcrypto_Rfc6979_make_new, - .locals_dict = (void*)&mod_trezorcrypto_Rfc6979_locals_dict, + .locals_dict = (void *)&mod_trezorcrypto_Rfc6979_locals_dict, }; diff --git a/embed/extmod/modtrezorcrypto/modtrezorcrypto-ripemd160.h b/embed/extmod/modtrezorcrypto/modtrezorcrypto-ripemd160.h index 6ceba0655..edb56181a 100644 --- a/embed/extmod/modtrezorcrypto/modtrezorcrypto-ripemd160.h +++ b/embed/extmod/modtrezorcrypto/modtrezorcrypto-ripemd160.h @@ -19,8 +19,8 @@ #include "py/objstr.h" -#include "ripemd160.h" #include "memzero.h" +#include "ripemd160.h" /// package: trezorcrypto.__init__ @@ -29,8 +29,8 @@ /// RIPEMD160 context. /// ''' typedef struct _mp_obj_Ripemd160_t { - mp_obj_base_t base; - RIPEMD160_CTX ctx; + mp_obj_base_t base; + RIPEMD160_CTX ctx; } mp_obj_Ripemd160_t; STATIC mp_obj_t mod_trezorcrypto_Ripemd160_update(mp_obj_t self, mp_obj_t data); @@ -39,67 +39,80 @@ STATIC mp_obj_t mod_trezorcrypto_Ripemd160_update(mp_obj_t self, mp_obj_t data); /// ''' /// Creates a hash context object. /// ''' -STATIC mp_obj_t mod_trezorcrypto_Ripemd160_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_kw, const mp_obj_t *args) { - mp_arg_check_num(n_args, n_kw, 0, 1, false); - mp_obj_Ripemd160_t *o = m_new_obj(mp_obj_Ripemd160_t); - o->base.type = type; - ripemd160_Init(&(o->ctx)); - // constructor called with bytes/str as first parameter - if (n_args == 1) { - mod_trezorcrypto_Ripemd160_update(MP_OBJ_FROM_PTR(o), args[0]); - } - return MP_OBJ_FROM_PTR(o); +STATIC mp_obj_t mod_trezorcrypto_Ripemd160_make_new(const mp_obj_type_t *type, + size_t n_args, size_t n_kw, + const mp_obj_t *args) { + mp_arg_check_num(n_args, n_kw, 0, 1, false); + mp_obj_Ripemd160_t *o = m_new_obj(mp_obj_Ripemd160_t); + o->base.type = type; + ripemd160_Init(&(o->ctx)); + // constructor called with bytes/str as first parameter + if (n_args == 1) { + mod_trezorcrypto_Ripemd160_update(MP_OBJ_FROM_PTR(o), args[0]); + } + return MP_OBJ_FROM_PTR(o); } /// def update(self, data: bytes) -> None: /// ''' /// Update the hash context with hashed data. /// ''' -STATIC mp_obj_t mod_trezorcrypto_Ripemd160_update(mp_obj_t self, mp_obj_t data) { - mp_obj_Ripemd160_t *o = MP_OBJ_TO_PTR(self); - mp_buffer_info_t msg; - mp_get_buffer_raise(data, &msg, MP_BUFFER_READ); - if (msg.len > 0) { - ripemd160_Update(&(o->ctx), msg.buf, msg.len); - } - return mp_const_none; +STATIC mp_obj_t mod_trezorcrypto_Ripemd160_update(mp_obj_t self, + mp_obj_t data) { + mp_obj_Ripemd160_t *o = MP_OBJ_TO_PTR(self); + mp_buffer_info_t msg; + mp_get_buffer_raise(data, &msg, MP_BUFFER_READ); + if (msg.len > 0) { + ripemd160_Update(&(o->ctx), msg.buf, msg.len); + } + return mp_const_none; } -STATIC MP_DEFINE_CONST_FUN_OBJ_2(mod_trezorcrypto_Ripemd160_update_obj, mod_trezorcrypto_Ripemd160_update); +STATIC MP_DEFINE_CONST_FUN_OBJ_2(mod_trezorcrypto_Ripemd160_update_obj, + mod_trezorcrypto_Ripemd160_update); /// def digest(self) -> bytes: /// ''' /// Returns the digest of hashed data. /// ''' STATIC mp_obj_t mod_trezorcrypto_Ripemd160_digest(mp_obj_t self) { - mp_obj_Ripemd160_t *o = MP_OBJ_TO_PTR(self); - uint8_t out[RIPEMD160_DIGEST_LENGTH]; - RIPEMD160_CTX ctx; - memcpy(&ctx, &(o->ctx), sizeof(RIPEMD160_CTX)); - ripemd160_Final(&ctx, out); - memzero(&ctx, sizeof(RIPEMD160_CTX)); - return mp_obj_new_bytes(out, sizeof(out)); + mp_obj_Ripemd160_t *o = MP_OBJ_TO_PTR(self); + uint8_t out[RIPEMD160_DIGEST_LENGTH]; + RIPEMD160_CTX ctx; + memcpy(&ctx, &(o->ctx), sizeof(RIPEMD160_CTX)); + ripemd160_Final(&ctx, out); + memzero(&ctx, sizeof(RIPEMD160_CTX)); + return mp_obj_new_bytes(out, sizeof(out)); } -STATIC MP_DEFINE_CONST_FUN_OBJ_1(mod_trezorcrypto_Ripemd160_digest_obj, mod_trezorcrypto_Ripemd160_digest); +STATIC MP_DEFINE_CONST_FUN_OBJ_1(mod_trezorcrypto_Ripemd160_digest_obj, + mod_trezorcrypto_Ripemd160_digest); STATIC mp_obj_t mod_trezorcrypto_Ripemd160___del__(mp_obj_t self) { - mp_obj_Ripemd160_t *o = MP_OBJ_TO_PTR(self); - memzero(&(o->ctx), sizeof(RIPEMD160_CTX)); - return mp_const_none; + mp_obj_Ripemd160_t *o = MP_OBJ_TO_PTR(self); + memzero(&(o->ctx), sizeof(RIPEMD160_CTX)); + return mp_const_none; } -STATIC MP_DEFINE_CONST_FUN_OBJ_1(mod_trezorcrypto_Ripemd160___del___obj, mod_trezorcrypto_Ripemd160___del__); +STATIC MP_DEFINE_CONST_FUN_OBJ_1(mod_trezorcrypto_Ripemd160___del___obj, + mod_trezorcrypto_Ripemd160___del__); -STATIC const mp_rom_map_elem_t mod_trezorcrypto_Ripemd160_locals_dict_table[] = { - { MP_ROM_QSTR(MP_QSTR_update), MP_ROM_PTR(&mod_trezorcrypto_Ripemd160_update_obj) }, - { MP_ROM_QSTR(MP_QSTR_digest), MP_ROM_PTR(&mod_trezorcrypto_Ripemd160_digest_obj) }, - { MP_ROM_QSTR(MP_QSTR___del__), MP_ROM_PTR(&mod_trezorcrypto_Ripemd160___del___obj) }, - { MP_ROM_QSTR(MP_QSTR_block_size), MP_OBJ_NEW_SMALL_INT(RIPEMD160_BLOCK_LENGTH) }, - { MP_ROM_QSTR(MP_QSTR_digest_size), MP_OBJ_NEW_SMALL_INT(RIPEMD160_DIGEST_LENGTH) }, +STATIC const mp_rom_map_elem_t + mod_trezorcrypto_Ripemd160_locals_dict_table[] = { + {MP_ROM_QSTR(MP_QSTR_update), + MP_ROM_PTR(&mod_trezorcrypto_Ripemd160_update_obj)}, + {MP_ROM_QSTR(MP_QSTR_digest), + MP_ROM_PTR(&mod_trezorcrypto_Ripemd160_digest_obj)}, + {MP_ROM_QSTR(MP_QSTR___del__), + MP_ROM_PTR(&mod_trezorcrypto_Ripemd160___del___obj)}, + {MP_ROM_QSTR(MP_QSTR_block_size), + MP_OBJ_NEW_SMALL_INT(RIPEMD160_BLOCK_LENGTH)}, + {MP_ROM_QSTR(MP_QSTR_digest_size), + MP_OBJ_NEW_SMALL_INT(RIPEMD160_DIGEST_LENGTH)}, }; -STATIC MP_DEFINE_CONST_DICT(mod_trezorcrypto_Ripemd160_locals_dict, mod_trezorcrypto_Ripemd160_locals_dict_table); +STATIC MP_DEFINE_CONST_DICT(mod_trezorcrypto_Ripemd160_locals_dict, + mod_trezorcrypto_Ripemd160_locals_dict_table); STATIC const mp_obj_type_t mod_trezorcrypto_Ripemd160_type = { - { &mp_type_type }, + {&mp_type_type}, .name = MP_QSTR_Ripemd160, .make_new = mod_trezorcrypto_Ripemd160_make_new, - .locals_dict = (void*)&mod_trezorcrypto_Ripemd160_locals_dict, + .locals_dict = (void *)&mod_trezorcrypto_Ripemd160_locals_dict, }; diff --git a/embed/extmod/modtrezorcrypto/modtrezorcrypto-secp256k1.h b/embed/extmod/modtrezorcrypto/modtrezorcrypto-secp256k1.h index e994aa0ee..647ef5f26 100644 --- a/embed/extmod/modtrezorcrypto/modtrezorcrypto-secp256k1.h +++ b/embed/extmod/modtrezorcrypto/modtrezorcrypto-secp256k1.h @@ -29,176 +29,218 @@ /// Generate secret key. /// ''' STATIC mp_obj_t mod_trezorcrypto_secp256k1_generate_secret() { - uint8_t out[32]; - for (;;) { - random_buffer(out, 32); - // check whether secret > 0 && secret < curve_order - if (0 == memcmp(out, "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00", 32)) continue; - if (0 <= memcmp(out, "\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFE\xBA\xAE\xDC\xE6\xAF\x48\xA0\x3B\xBF\xD2\x5E\x8C\xD0\x36\x41\x41", 32)) continue; - break; - } - return mp_obj_new_bytes(out, sizeof(out)); + uint8_t out[32]; + for (;;) { + random_buffer(out, 32); + // check whether secret > 0 && secret < curve_order + if (0 == + memcmp( + out, + "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00", + 32)) + continue; + if (0 <= + memcmp( + out, + "\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFE" + "\xBA\xAE\xDC\xE6\xAF\x48\xA0\x3B\xBF\xD2\x5E\x8C\xD0\x36\x41\x41", + 32)) + continue; + break; + } + return mp_obj_new_bytes(out, sizeof(out)); } -STATIC MP_DEFINE_CONST_FUN_OBJ_0(mod_trezorcrypto_secp256k1_generate_secret_obj, mod_trezorcrypto_secp256k1_generate_secret); +STATIC MP_DEFINE_CONST_FUN_OBJ_0(mod_trezorcrypto_secp256k1_generate_secret_obj, + mod_trezorcrypto_secp256k1_generate_secret); /// def publickey(secret_key: bytes, compressed: bool = True) -> bytes: /// ''' /// Computes public key from secret key. /// ''' -STATIC mp_obj_t mod_trezorcrypto_secp256k1_publickey(size_t n_args, const mp_obj_t *args) { - mp_buffer_info_t sk; - mp_get_buffer_raise(args[0], &sk, MP_BUFFER_READ); - if (sk.len != 32) { - mp_raise_ValueError("Invalid length of secret key"); - } - bool compressed = n_args < 2 || args[1] == mp_const_true; - if (compressed) { - uint8_t out[33]; - ecdsa_get_public_key33(&secp256k1, (const uint8_t *)sk.buf, out); - return mp_obj_new_bytes(out, sizeof(out)); - } else { - uint8_t out[65]; - ecdsa_get_public_key65(&secp256k1, (const uint8_t *)sk.buf, out); - return mp_obj_new_bytes(out, sizeof(out)); - } +STATIC mp_obj_t mod_trezorcrypto_secp256k1_publickey(size_t n_args, + const mp_obj_t *args) { + mp_buffer_info_t sk; + mp_get_buffer_raise(args[0], &sk, MP_BUFFER_READ); + if (sk.len != 32) { + mp_raise_ValueError("Invalid length of secret key"); + } + bool compressed = n_args < 2 || args[1] == mp_const_true; + if (compressed) { + uint8_t out[33]; + ecdsa_get_public_key33(&secp256k1, (const uint8_t *)sk.buf, out); + return mp_obj_new_bytes(out, sizeof(out)); + } else { + uint8_t out[65]; + ecdsa_get_public_key65(&secp256k1, (const uint8_t *)sk.buf, out); + return mp_obj_new_bytes(out, sizeof(out)); + } } -STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(mod_trezorcrypto_secp256k1_publickey_obj, 1, 2, mod_trezorcrypto_secp256k1_publickey); +STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN( + mod_trezorcrypto_secp256k1_publickey_obj, 1, 2, + mod_trezorcrypto_secp256k1_publickey); -static int ethereum_is_canonical(uint8_t v, uint8_t signature[64]) -{ - (void)signature; - return (v & 2) == 0; +static int ethereum_is_canonical(uint8_t v, uint8_t signature[64]) { + (void)signature; + return (v & 2) == 0; } enum { - CANONICAL_SIG_ETHEREUM = 1, + CANONICAL_SIG_ETHEREUM = 1, }; -/// def sign(secret_key: bytes, digest: bytes, compressed: bool = True, canonical: int = None) -> bytes: +/// def sign(secret_key: bytes, digest: bytes, compressed: bool = True, +/// canonical: int = None) -> bytes: /// ''' /// Uses secret key to produce the signature of the digest. /// ''' -STATIC mp_obj_t mod_trezorcrypto_secp256k1_sign(size_t n_args, const mp_obj_t *args) { - mp_buffer_info_t sk, dig; - mp_get_buffer_raise(args[0], &sk, MP_BUFFER_READ); - mp_get_buffer_raise(args[1], &dig, MP_BUFFER_READ); - bool compressed = (n_args < 3) || (args[2] == mp_const_true); - mp_int_t canonical = (n_args > 3) ? mp_obj_get_int(args[3]) : 0; - int (*is_canonical)(uint8_t by, uint8_t sig[64]) = NULL; - switch (canonical) { - case CANONICAL_SIG_ETHEREUM: - is_canonical = ethereum_is_canonical; - break; - } - if (sk.len != 32) { - mp_raise_ValueError("Invalid length of secret key"); - } - if (dig.len != 32) { - mp_raise_ValueError("Invalid length of digest"); - } - uint8_t out[65], pby; - if (0 != ecdsa_sign_digest(&secp256k1, (const uint8_t *)sk.buf, (const uint8_t *)dig.buf, out + 1, &pby, is_canonical)) { - mp_raise_ValueError("Signing failed"); - } - out[0] = 27 + pby + compressed * 4; - return mp_obj_new_bytes(out, sizeof(out)); +STATIC mp_obj_t mod_trezorcrypto_secp256k1_sign(size_t n_args, + const mp_obj_t *args) { + mp_buffer_info_t sk, dig; + mp_get_buffer_raise(args[0], &sk, MP_BUFFER_READ); + mp_get_buffer_raise(args[1], &dig, MP_BUFFER_READ); + bool compressed = (n_args < 3) || (args[2] == mp_const_true); + mp_int_t canonical = (n_args > 3) ? mp_obj_get_int(args[3]) : 0; + int (*is_canonical)(uint8_t by, uint8_t sig[64]) = NULL; + switch (canonical) { + case CANONICAL_SIG_ETHEREUM: + is_canonical = ethereum_is_canonical; + break; + } + if (sk.len != 32) { + mp_raise_ValueError("Invalid length of secret key"); + } + if (dig.len != 32) { + mp_raise_ValueError("Invalid length of digest"); + } + uint8_t out[65], pby; + if (0 != ecdsa_sign_digest(&secp256k1, (const uint8_t *)sk.buf, + (const uint8_t *)dig.buf, out + 1, &pby, + is_canonical)) { + mp_raise_ValueError("Signing failed"); + } + out[0] = 27 + pby + compressed * 4; + return mp_obj_new_bytes(out, sizeof(out)); } -STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(mod_trezorcrypto_secp256k1_sign_obj, 2, 4, mod_trezorcrypto_secp256k1_sign); +STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(mod_trezorcrypto_secp256k1_sign_obj, + 2, 4, + mod_trezorcrypto_secp256k1_sign); /// def verify(public_key: bytes, signature: bytes, digest: bytes) -> bool: /// ''' /// Uses public key to verify the signature of the digest. /// Returns True on success. /// ''' -STATIC mp_obj_t mod_trezorcrypto_secp256k1_verify(mp_obj_t public_key, mp_obj_t signature, mp_obj_t digest) { - mp_buffer_info_t pk, sig, dig; - mp_get_buffer_raise(public_key, &pk, MP_BUFFER_READ); - mp_get_buffer_raise(signature, &sig, MP_BUFFER_READ); - mp_get_buffer_raise(digest, &dig, MP_BUFFER_READ); - if (pk.len != 33 && pk.len != 65) { - mp_raise_ValueError("Invalid length of public key"); - } - if (sig.len != 64 && sig.len != 65) { - mp_raise_ValueError("Invalid length of signature"); - } - int offset = sig.len - 64; - if (dig.len != 32) { - mp_raise_ValueError("Invalid length of digest"); - } - return mp_obj_new_bool(0 == ecdsa_verify_digest(&secp256k1, (const uint8_t *)pk.buf, (const uint8_t *)sig.buf + offset, (const uint8_t *)dig.buf)); +STATIC mp_obj_t mod_trezorcrypto_secp256k1_verify(mp_obj_t public_key, + mp_obj_t signature, + mp_obj_t digest) { + mp_buffer_info_t pk, sig, dig; + mp_get_buffer_raise(public_key, &pk, MP_BUFFER_READ); + mp_get_buffer_raise(signature, &sig, MP_BUFFER_READ); + mp_get_buffer_raise(digest, &dig, MP_BUFFER_READ); + if (pk.len != 33 && pk.len != 65) { + mp_raise_ValueError("Invalid length of public key"); + } + if (sig.len != 64 && sig.len != 65) { + mp_raise_ValueError("Invalid length of signature"); + } + int offset = sig.len - 64; + if (dig.len != 32) { + mp_raise_ValueError("Invalid length of digest"); + } + return mp_obj_new_bool( + 0 == ecdsa_verify_digest(&secp256k1, (const uint8_t *)pk.buf, + (const uint8_t *)sig.buf + offset, + (const uint8_t *)dig.buf)); } -STATIC MP_DEFINE_CONST_FUN_OBJ_3(mod_trezorcrypto_secp256k1_verify_obj, mod_trezorcrypto_secp256k1_verify); +STATIC MP_DEFINE_CONST_FUN_OBJ_3(mod_trezorcrypto_secp256k1_verify_obj, + mod_trezorcrypto_secp256k1_verify); /// def verify_recover(signature: bytes, digest: bytes) -> bytes: /// ''' -/// Uses signature of the digest to verify the digest and recover the public key. -/// Returns public key on success, None on failure. +/// Uses signature of the digest to verify the digest and recover the public +/// key. Returns public key on success, None on failure. /// ''' -STATIC mp_obj_t mod_trezorcrypto_secp256k1_verify_recover(mp_obj_t signature, mp_obj_t digest) { - mp_buffer_info_t sig, dig; - mp_get_buffer_raise(signature, &sig, MP_BUFFER_READ); - mp_get_buffer_raise(digest, &dig, MP_BUFFER_READ); - if (sig.len != 65) { - mp_raise_ValueError("Invalid length of signature"); - } - if (dig.len != 32) { - mp_raise_ValueError("Invalid length of digest"); - } - uint8_t recid = ((const uint8_t *)sig.buf)[0] - 27; - if (recid >= 8) { - mp_raise_ValueError("Invalid recid in signature"); - } - bool compressed = (recid >= 4); - recid &= 3; - uint8_t out[65]; - if (0 == ecdsa_recover_pub_from_sig(&secp256k1, out, (const uint8_t *)sig.buf + 1, (const uint8_t *)dig.buf, recid)) { - if (compressed) { - out[0] = 0x02 | (out[64] & 1); - return mp_obj_new_bytes(out, 33); - } - return mp_obj_new_bytes(out, sizeof(out)); - } else { - return mp_const_none; +STATIC mp_obj_t mod_trezorcrypto_secp256k1_verify_recover(mp_obj_t signature, + mp_obj_t digest) { + mp_buffer_info_t sig, dig; + mp_get_buffer_raise(signature, &sig, MP_BUFFER_READ); + mp_get_buffer_raise(digest, &dig, MP_BUFFER_READ); + if (sig.len != 65) { + mp_raise_ValueError("Invalid length of signature"); + } + if (dig.len != 32) { + mp_raise_ValueError("Invalid length of digest"); + } + uint8_t recid = ((const uint8_t *)sig.buf)[0] - 27; + if (recid >= 8) { + mp_raise_ValueError("Invalid recid in signature"); + } + bool compressed = (recid >= 4); + recid &= 3; + uint8_t out[65]; + if (0 == ecdsa_recover_pub_from_sig(&secp256k1, out, + (const uint8_t *)sig.buf + 1, + (const uint8_t *)dig.buf, recid)) { + if (compressed) { + out[0] = 0x02 | (out[64] & 1); + return mp_obj_new_bytes(out, 33); } + return mp_obj_new_bytes(out, sizeof(out)); + } else { + return mp_const_none; + } } -STATIC MP_DEFINE_CONST_FUN_OBJ_2(mod_trezorcrypto_secp256k1_verify_recover_obj, mod_trezorcrypto_secp256k1_verify_recover); +STATIC MP_DEFINE_CONST_FUN_OBJ_2(mod_trezorcrypto_secp256k1_verify_recover_obj, + mod_trezorcrypto_secp256k1_verify_recover); /// def multiply(secret_key: bytes, public_key: bytes) -> bytes: /// ''' -/// Multiplies point defined by public_key with scalar defined by secret_key. -/// Useful for ECDH. +/// Multiplies point defined by public_key with scalar defined by +/// secret_key. Useful for ECDH. /// ''' -STATIC mp_obj_t mod_trezorcrypto_secp256k1_multiply(mp_obj_t secret_key, mp_obj_t public_key) { - mp_buffer_info_t sk, pk; - mp_get_buffer_raise(secret_key, &sk, MP_BUFFER_READ); - mp_get_buffer_raise(public_key, &pk, MP_BUFFER_READ); - if (sk.len != 32) { - mp_raise_ValueError("Invalid length of secret key"); - } - if (pk.len != 33 && pk.len != 65) { - mp_raise_ValueError("Invalid length of public key"); - } - uint8_t out[65]; - if (0 != ecdh_multiply(&secp256k1, (const uint8_t *)sk.buf, (const uint8_t *)pk.buf, out)) { - mp_raise_ValueError("Multiply failed"); - } - return mp_obj_new_bytes(out, sizeof(out)); +STATIC mp_obj_t mod_trezorcrypto_secp256k1_multiply(mp_obj_t secret_key, + mp_obj_t public_key) { + mp_buffer_info_t sk, pk; + mp_get_buffer_raise(secret_key, &sk, MP_BUFFER_READ); + mp_get_buffer_raise(public_key, &pk, MP_BUFFER_READ); + if (sk.len != 32) { + mp_raise_ValueError("Invalid length of secret key"); + } + if (pk.len != 33 && pk.len != 65) { + mp_raise_ValueError("Invalid length of public key"); + } + uint8_t out[65]; + if (0 != ecdh_multiply(&secp256k1, (const uint8_t *)sk.buf, + (const uint8_t *)pk.buf, out)) { + mp_raise_ValueError("Multiply failed"); + } + return mp_obj_new_bytes(out, sizeof(out)); } -STATIC MP_DEFINE_CONST_FUN_OBJ_2(mod_trezorcrypto_secp256k1_multiply_obj, mod_trezorcrypto_secp256k1_multiply); +STATIC MP_DEFINE_CONST_FUN_OBJ_2(mod_trezorcrypto_secp256k1_multiply_obj, + mod_trezorcrypto_secp256k1_multiply); STATIC const mp_rom_map_elem_t mod_trezorcrypto_secp256k1_globals_table[] = { - { MP_ROM_QSTR(MP_QSTR___name__), MP_ROM_QSTR(MP_QSTR_secp256k1) }, - { MP_ROM_QSTR(MP_QSTR_generate_secret), MP_ROM_PTR(&mod_trezorcrypto_secp256k1_generate_secret_obj) }, - { MP_ROM_QSTR(MP_QSTR_publickey), MP_ROM_PTR(&mod_trezorcrypto_secp256k1_publickey_obj) }, - { MP_ROM_QSTR(MP_QSTR_sign), MP_ROM_PTR(&mod_trezorcrypto_secp256k1_sign_obj) }, - { MP_ROM_QSTR(MP_QSTR_verify), MP_ROM_PTR(&mod_trezorcrypto_secp256k1_verify_obj) }, - { MP_ROM_QSTR(MP_QSTR_verify_recover), MP_ROM_PTR(&mod_trezorcrypto_secp256k1_verify_recover_obj) }, - { MP_ROM_QSTR(MP_QSTR_multiply), MP_ROM_PTR(&mod_trezorcrypto_secp256k1_multiply_obj) }, - { MP_ROM_QSTR(MP_QSTR_CANONICAL_SIG_ETHEREUM), MP_OBJ_NEW_SMALL_INT(CANONICAL_SIG_ETHEREUM) }, + {MP_ROM_QSTR(MP_QSTR___name__), MP_ROM_QSTR(MP_QSTR_secp256k1)}, + {MP_ROM_QSTR(MP_QSTR_generate_secret), + MP_ROM_PTR(&mod_trezorcrypto_secp256k1_generate_secret_obj)}, + {MP_ROM_QSTR(MP_QSTR_publickey), + MP_ROM_PTR(&mod_trezorcrypto_secp256k1_publickey_obj)}, + {MP_ROM_QSTR(MP_QSTR_sign), + MP_ROM_PTR(&mod_trezorcrypto_secp256k1_sign_obj)}, + {MP_ROM_QSTR(MP_QSTR_verify), + MP_ROM_PTR(&mod_trezorcrypto_secp256k1_verify_obj)}, + {MP_ROM_QSTR(MP_QSTR_verify_recover), + MP_ROM_PTR(&mod_trezorcrypto_secp256k1_verify_recover_obj)}, + {MP_ROM_QSTR(MP_QSTR_multiply), + MP_ROM_PTR(&mod_trezorcrypto_secp256k1_multiply_obj)}, + {MP_ROM_QSTR(MP_QSTR_CANONICAL_SIG_ETHEREUM), + MP_OBJ_NEW_SMALL_INT(CANONICAL_SIG_ETHEREUM)}, }; -STATIC MP_DEFINE_CONST_DICT(mod_trezorcrypto_secp256k1_globals, mod_trezorcrypto_secp256k1_globals_table); +STATIC MP_DEFINE_CONST_DICT(mod_trezorcrypto_secp256k1_globals, + mod_trezorcrypto_secp256k1_globals_table); STATIC const mp_obj_module_t mod_trezorcrypto_secp256k1_module = { - .base = { &mp_type_module }, - .globals = (mp_obj_dict_t*)&mod_trezorcrypto_secp256k1_globals, + .base = {&mp_type_module}, + .globals = (mp_obj_dict_t *)&mod_trezorcrypto_secp256k1_globals, }; diff --git a/embed/extmod/modtrezorcrypto/modtrezorcrypto-sha1.h b/embed/extmod/modtrezorcrypto/modtrezorcrypto-sha1.h index 5bfad34e9..16808ffc7 100644 --- a/embed/extmod/modtrezorcrypto/modtrezorcrypto-sha1.h +++ b/embed/extmod/modtrezorcrypto/modtrezorcrypto-sha1.h @@ -19,8 +19,8 @@ #include "py/objstr.h" -#include "sha2.h" #include "memzero.h" +#include "sha2.h" /// package: trezorcrypto.__init__ @@ -29,8 +29,8 @@ /// SHA1 context. /// ''' typedef struct _mp_obj_Sha1_t { - mp_obj_base_t base; - SHA1_CTX ctx; + mp_obj_base_t base; + SHA1_CTX ctx; } mp_obj_Sha1_t; STATIC mp_obj_t mod_trezorcrypto_Sha1_update(mp_obj_t self, mp_obj_t data); @@ -39,16 +39,18 @@ STATIC mp_obj_t mod_trezorcrypto_Sha1_update(mp_obj_t self, mp_obj_t data); /// ''' /// Creates a hash context object. /// ''' -STATIC mp_obj_t mod_trezorcrypto_Sha1_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_kw, const mp_obj_t *args) { - mp_arg_check_num(n_args, n_kw, 0, 1, false); - mp_obj_Sha1_t *o = m_new_obj(mp_obj_Sha1_t); - o->base.type = type; - sha1_Init(&(o->ctx)); - // constructor called with bytes/str as first parameter - if (n_args == 1) { - mod_trezorcrypto_Sha1_update(MP_OBJ_FROM_PTR(o), args[0]); - } - return MP_OBJ_FROM_PTR(o); +STATIC mp_obj_t mod_trezorcrypto_Sha1_make_new(const mp_obj_type_t *type, + size_t n_args, size_t n_kw, + const mp_obj_t *args) { + mp_arg_check_num(n_args, n_kw, 0, 1, false); + mp_obj_Sha1_t *o = m_new_obj(mp_obj_Sha1_t); + o->base.type = type; + sha1_Init(&(o->ctx)); + // constructor called with bytes/str as first parameter + if (n_args == 1) { + mod_trezorcrypto_Sha1_update(MP_OBJ_FROM_PTR(o), args[0]); + } + return MP_OBJ_FROM_PTR(o); } /// def update(self, data: bytes) -> None: @@ -56,50 +58,58 @@ STATIC mp_obj_t mod_trezorcrypto_Sha1_make_new(const mp_obj_type_t *type, size_t /// Update the hash context with hashed data. /// ''' STATIC mp_obj_t mod_trezorcrypto_Sha1_update(mp_obj_t self, mp_obj_t data) { - mp_obj_Sha1_t *o = MP_OBJ_TO_PTR(self); - mp_buffer_info_t msg; - mp_get_buffer_raise(data, &msg, MP_BUFFER_READ); - if (msg.len > 0) { - sha1_Update(&(o->ctx), msg.buf, msg.len); - } - return mp_const_none; + mp_obj_Sha1_t *o = MP_OBJ_TO_PTR(self); + mp_buffer_info_t msg; + mp_get_buffer_raise(data, &msg, MP_BUFFER_READ); + if (msg.len > 0) { + sha1_Update(&(o->ctx), msg.buf, msg.len); + } + return mp_const_none; } -STATIC MP_DEFINE_CONST_FUN_OBJ_2(mod_trezorcrypto_Sha1_update_obj, mod_trezorcrypto_Sha1_update); +STATIC MP_DEFINE_CONST_FUN_OBJ_2(mod_trezorcrypto_Sha1_update_obj, + mod_trezorcrypto_Sha1_update); /// def digest(self) -> bytes: /// ''' /// Returns the digest of hashed data. /// ''' STATIC mp_obj_t mod_trezorcrypto_Sha1_digest(mp_obj_t self) { - mp_obj_Sha1_t *o = MP_OBJ_TO_PTR(self); - uint8_t out[SHA1_DIGEST_LENGTH]; - SHA1_CTX ctx; - memcpy(&ctx, &(o->ctx), sizeof(SHA1_CTX)); - sha1_Final(&ctx, out); - memzero(&ctx, sizeof(SHA1_CTX)); - return mp_obj_new_bytes(out, sizeof(out)); + mp_obj_Sha1_t *o = MP_OBJ_TO_PTR(self); + uint8_t out[SHA1_DIGEST_LENGTH]; + SHA1_CTX ctx; + memcpy(&ctx, &(o->ctx), sizeof(SHA1_CTX)); + sha1_Final(&ctx, out); + memzero(&ctx, sizeof(SHA1_CTX)); + return mp_obj_new_bytes(out, sizeof(out)); } -STATIC MP_DEFINE_CONST_FUN_OBJ_1(mod_trezorcrypto_Sha1_digest_obj, mod_trezorcrypto_Sha1_digest); +STATIC MP_DEFINE_CONST_FUN_OBJ_1(mod_trezorcrypto_Sha1_digest_obj, + mod_trezorcrypto_Sha1_digest); STATIC mp_obj_t mod_trezorcrypto_Sha1___del__(mp_obj_t self) { - mp_obj_Sha1_t *o = MP_OBJ_TO_PTR(self); - memzero(&(o->ctx), sizeof(SHA1_CTX)); - return mp_const_none; + mp_obj_Sha1_t *o = MP_OBJ_TO_PTR(self); + memzero(&(o->ctx), sizeof(SHA1_CTX)); + return mp_const_none; } -STATIC MP_DEFINE_CONST_FUN_OBJ_1(mod_trezorcrypto_Sha1___del___obj, mod_trezorcrypto_Sha1___del__); +STATIC MP_DEFINE_CONST_FUN_OBJ_1(mod_trezorcrypto_Sha1___del___obj, + mod_trezorcrypto_Sha1___del__); STATIC const mp_rom_map_elem_t mod_trezorcrypto_Sha1_locals_dict_table[] = { - { MP_ROM_QSTR(MP_QSTR_update), MP_ROM_PTR(&mod_trezorcrypto_Sha1_update_obj) }, - { MP_ROM_QSTR(MP_QSTR_digest), MP_ROM_PTR(&mod_trezorcrypto_Sha1_digest_obj) }, - { MP_ROM_QSTR(MP_QSTR___del__), MP_ROM_PTR(&mod_trezorcrypto_Sha1___del___obj) }, - { MP_ROM_QSTR(MP_QSTR_block_size), MP_OBJ_NEW_SMALL_INT(SHA1_BLOCK_LENGTH) }, - { MP_ROM_QSTR(MP_QSTR_digest_size), MP_OBJ_NEW_SMALL_INT(SHA1_DIGEST_LENGTH) }, + {MP_ROM_QSTR(MP_QSTR_update), + MP_ROM_PTR(&mod_trezorcrypto_Sha1_update_obj)}, + {MP_ROM_QSTR(MP_QSTR_digest), + MP_ROM_PTR(&mod_trezorcrypto_Sha1_digest_obj)}, + {MP_ROM_QSTR(MP_QSTR___del__), + MP_ROM_PTR(&mod_trezorcrypto_Sha1___del___obj)}, + {MP_ROM_QSTR(MP_QSTR_block_size), MP_OBJ_NEW_SMALL_INT(SHA1_BLOCK_LENGTH)}, + {MP_ROM_QSTR(MP_QSTR_digest_size), + MP_OBJ_NEW_SMALL_INT(SHA1_DIGEST_LENGTH)}, }; -STATIC MP_DEFINE_CONST_DICT(mod_trezorcrypto_Sha1_locals_dict, mod_trezorcrypto_Sha1_locals_dict_table); +STATIC MP_DEFINE_CONST_DICT(mod_trezorcrypto_Sha1_locals_dict, + mod_trezorcrypto_Sha1_locals_dict_table); STATIC const mp_obj_type_t mod_trezorcrypto_Sha1_type = { - { &mp_type_type }, + {&mp_type_type}, .name = MP_QSTR_Sha1, .make_new = mod_trezorcrypto_Sha1_make_new, - .locals_dict = (void*)&mod_trezorcrypto_Sha1_locals_dict, + .locals_dict = (void *)&mod_trezorcrypto_Sha1_locals_dict, }; diff --git a/embed/extmod/modtrezorcrypto/modtrezorcrypto-sha256.h b/embed/extmod/modtrezorcrypto/modtrezorcrypto-sha256.h index 85efd4e20..459f4a759 100644 --- a/embed/extmod/modtrezorcrypto/modtrezorcrypto-sha256.h +++ b/embed/extmod/modtrezorcrypto/modtrezorcrypto-sha256.h @@ -19,8 +19,8 @@ #include "py/objstr.h" -#include "sha2.h" #include "memzero.h" +#include "sha2.h" /// package: trezorcrypto.__init__ @@ -29,8 +29,8 @@ /// SHA256 context. /// ''' typedef struct _mp_obj_Sha256_t { - mp_obj_base_t base; - SHA256_CTX ctx; + mp_obj_base_t base; + SHA256_CTX ctx; } mp_obj_Sha256_t; STATIC mp_obj_t mod_trezorcrypto_Sha256_update(mp_obj_t self, mp_obj_t data); @@ -39,16 +39,18 @@ STATIC mp_obj_t mod_trezorcrypto_Sha256_update(mp_obj_t self, mp_obj_t data); /// ''' /// Creates a hash context object. /// ''' -STATIC mp_obj_t mod_trezorcrypto_Sha256_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_kw, const mp_obj_t *args) { - mp_arg_check_num(n_args, n_kw, 0, 1, false); - mp_obj_Sha256_t *o = m_new_obj(mp_obj_Sha256_t); - o->base.type = type; - sha256_Init(&(o->ctx)); - // constructor called with bytes/str as first parameter - if (n_args == 1) { - mod_trezorcrypto_Sha256_update(MP_OBJ_FROM_PTR(o), args[0]); - } - return MP_OBJ_FROM_PTR(o); +STATIC mp_obj_t mod_trezorcrypto_Sha256_make_new(const mp_obj_type_t *type, + size_t n_args, size_t n_kw, + const mp_obj_t *args) { + mp_arg_check_num(n_args, n_kw, 0, 1, false); + mp_obj_Sha256_t *o = m_new_obj(mp_obj_Sha256_t); + o->base.type = type; + sha256_Init(&(o->ctx)); + // constructor called with bytes/str as first parameter + if (n_args == 1) { + mod_trezorcrypto_Sha256_update(MP_OBJ_FROM_PTR(o), args[0]); + } + return MP_OBJ_FROM_PTR(o); } /// def update(self, data: bytes) -> None: @@ -56,50 +58,59 @@ STATIC mp_obj_t mod_trezorcrypto_Sha256_make_new(const mp_obj_type_t *type, size /// Update the hash context with hashed data. /// ''' STATIC mp_obj_t mod_trezorcrypto_Sha256_update(mp_obj_t self, mp_obj_t data) { - mp_obj_Sha256_t *o = MP_OBJ_TO_PTR(self); - mp_buffer_info_t msg; - mp_get_buffer_raise(data, &msg, MP_BUFFER_READ); - if (msg.len > 0) { - sha256_Update(&(o->ctx), msg.buf, msg.len); - } - return mp_const_none; + mp_obj_Sha256_t *o = MP_OBJ_TO_PTR(self); + mp_buffer_info_t msg; + mp_get_buffer_raise(data, &msg, MP_BUFFER_READ); + if (msg.len > 0) { + sha256_Update(&(o->ctx), msg.buf, msg.len); + } + return mp_const_none; } -STATIC MP_DEFINE_CONST_FUN_OBJ_2(mod_trezorcrypto_Sha256_update_obj, mod_trezorcrypto_Sha256_update); +STATIC MP_DEFINE_CONST_FUN_OBJ_2(mod_trezorcrypto_Sha256_update_obj, + mod_trezorcrypto_Sha256_update); /// def digest(self) -> bytes: /// ''' /// Returns the digest of hashed data. /// ''' STATIC mp_obj_t mod_trezorcrypto_Sha256_digest(mp_obj_t self) { - mp_obj_Sha256_t *o = MP_OBJ_TO_PTR(self); - uint8_t out[SHA256_DIGEST_LENGTH]; - SHA256_CTX ctx; - memcpy(&ctx, &(o->ctx), sizeof(SHA256_CTX)); - sha256_Final(&ctx, out); - memzero(&ctx, sizeof(SHA256_CTX)); - return mp_obj_new_bytes(out, sizeof(out)); + mp_obj_Sha256_t *o = MP_OBJ_TO_PTR(self); + uint8_t out[SHA256_DIGEST_LENGTH]; + SHA256_CTX ctx; + memcpy(&ctx, &(o->ctx), sizeof(SHA256_CTX)); + sha256_Final(&ctx, out); + memzero(&ctx, sizeof(SHA256_CTX)); + return mp_obj_new_bytes(out, sizeof(out)); } -STATIC MP_DEFINE_CONST_FUN_OBJ_1(mod_trezorcrypto_Sha256_digest_obj, mod_trezorcrypto_Sha256_digest); +STATIC MP_DEFINE_CONST_FUN_OBJ_1(mod_trezorcrypto_Sha256_digest_obj, + mod_trezorcrypto_Sha256_digest); STATIC mp_obj_t mod_trezorcrypto_Sha256___del__(mp_obj_t self) { - mp_obj_Sha256_t *o = MP_OBJ_TO_PTR(self); - memzero(&(o->ctx), sizeof(SHA256_CTX)); - return mp_const_none; + mp_obj_Sha256_t *o = MP_OBJ_TO_PTR(self); + memzero(&(o->ctx), sizeof(SHA256_CTX)); + return mp_const_none; } -STATIC MP_DEFINE_CONST_FUN_OBJ_1(mod_trezorcrypto_Sha256___del___obj, mod_trezorcrypto_Sha256___del__); +STATIC MP_DEFINE_CONST_FUN_OBJ_1(mod_trezorcrypto_Sha256___del___obj, + mod_trezorcrypto_Sha256___del__); STATIC const mp_rom_map_elem_t mod_trezorcrypto_Sha256_locals_dict_table[] = { - { MP_ROM_QSTR(MP_QSTR_update), MP_ROM_PTR(&mod_trezorcrypto_Sha256_update_obj) }, - { MP_ROM_QSTR(MP_QSTR_digest), MP_ROM_PTR(&mod_trezorcrypto_Sha256_digest_obj) }, - { MP_ROM_QSTR(MP_QSTR___del__), MP_ROM_PTR(&mod_trezorcrypto_Sha256___del___obj) }, - { MP_ROM_QSTR(MP_QSTR_block_size), MP_OBJ_NEW_SMALL_INT(SHA256_BLOCK_LENGTH) }, - { MP_ROM_QSTR(MP_QSTR_digest_size), MP_OBJ_NEW_SMALL_INT(SHA256_DIGEST_LENGTH) }, + {MP_ROM_QSTR(MP_QSTR_update), + MP_ROM_PTR(&mod_trezorcrypto_Sha256_update_obj)}, + {MP_ROM_QSTR(MP_QSTR_digest), + MP_ROM_PTR(&mod_trezorcrypto_Sha256_digest_obj)}, + {MP_ROM_QSTR(MP_QSTR___del__), + MP_ROM_PTR(&mod_trezorcrypto_Sha256___del___obj)}, + {MP_ROM_QSTR(MP_QSTR_block_size), + MP_OBJ_NEW_SMALL_INT(SHA256_BLOCK_LENGTH)}, + {MP_ROM_QSTR(MP_QSTR_digest_size), + MP_OBJ_NEW_SMALL_INT(SHA256_DIGEST_LENGTH)}, }; -STATIC MP_DEFINE_CONST_DICT(mod_trezorcrypto_Sha256_locals_dict, mod_trezorcrypto_Sha256_locals_dict_table); +STATIC MP_DEFINE_CONST_DICT(mod_trezorcrypto_Sha256_locals_dict, + mod_trezorcrypto_Sha256_locals_dict_table); STATIC const mp_obj_type_t mod_trezorcrypto_Sha256_type = { - { &mp_type_type }, + {&mp_type_type}, .name = MP_QSTR_Sha256, .make_new = mod_trezorcrypto_Sha256_make_new, - .locals_dict = (void*)&mod_trezorcrypto_Sha256_locals_dict, + .locals_dict = (void *)&mod_trezorcrypto_Sha256_locals_dict, }; diff --git a/embed/extmod/modtrezorcrypto/modtrezorcrypto-sha3-256.h b/embed/extmod/modtrezorcrypto/modtrezorcrypto-sha3-256.h index da480d284..246fefd98 100644 --- a/embed/extmod/modtrezorcrypto/modtrezorcrypto-sha3-256.h +++ b/embed/extmod/modtrezorcrypto/modtrezorcrypto-sha3-256.h @@ -19,8 +19,8 @@ #include "py/objstr.h" -#include "sha3.h" #include "memzero.h" +#include "sha3.h" /// package: trezorcrypto.__init__ @@ -29,9 +29,9 @@ /// SHA3_256 context. /// ''' typedef struct _mp_obj_Sha3_256_t { - mp_obj_base_t base; - SHA3_CTX ctx; - bool keccak; + mp_obj_base_t base; + SHA3_CTX ctx; + bool keccak; } mp_obj_Sha3_256_t; STATIC mp_obj_t mod_trezorcrypto_Sha3_256_update(mp_obj_t self, mp_obj_t data); @@ -40,27 +40,30 @@ STATIC mp_obj_t mod_trezorcrypto_Sha3_256_update(mp_obj_t self, mp_obj_t data); /// ''' /// Creates a hash context object. /// ''' -STATIC mp_obj_t mod_trezorcrypto_Sha3_256_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_kw, const mp_obj_t *args) { - mp_arg_check_num(n_args, n_kw, 0, 1, true); - mp_obj_Sha3_256_t *o = m_new_obj(mp_obj_Sha3_256_t); - o->base.type = type; - o->keccak = 0; - sha3_256_Init(&(o->ctx)); +STATIC mp_obj_t mod_trezorcrypto_Sha3_256_make_new(const mp_obj_type_t *type, + size_t n_args, size_t n_kw, + const mp_obj_t *args) { + mp_arg_check_num(n_args, n_kw, 0, 1, true); + mp_obj_Sha3_256_t *o = m_new_obj(mp_obj_Sha3_256_t); + o->base.type = type; + o->keccak = 0; + sha3_256_Init(&(o->ctx)); - STATIC const mp_arg_t allowed_args[] = { - { MP_QSTR_data, MP_ARG_OBJ, {.u_obj = mp_const_none} }, - { MP_QSTR_keccak, MP_ARG_OBJ | MP_ARG_KW_ONLY, {.u_obj = MP_OBJ_NULL} }, - }; - mp_arg_val_t vals[MP_ARRAY_SIZE(allowed_args)]; - mp_arg_parse_all_kw_array(n_args, n_kw, args, MP_ARRAY_SIZE(allowed_args), allowed_args, vals); - if (vals[1].u_obj != MP_OBJ_NULL){ - o->keccak = mp_obj_is_true(vals[1].u_obj); - } + STATIC const mp_arg_t allowed_args[] = { + {MP_QSTR_data, MP_ARG_OBJ, {.u_obj = mp_const_none}}, + {MP_QSTR_keccak, MP_ARG_OBJ | MP_ARG_KW_ONLY, {.u_obj = MP_OBJ_NULL}}, + }; + mp_arg_val_t vals[MP_ARRAY_SIZE(allowed_args)]; + mp_arg_parse_all_kw_array(n_args, n_kw, args, MP_ARRAY_SIZE(allowed_args), + allowed_args, vals); + if (vals[1].u_obj != MP_OBJ_NULL) { + o->keccak = mp_obj_is_true(vals[1].u_obj); + } - if (vals[0].u_obj != mp_const_none){ - mod_trezorcrypto_Sha3_256_update(MP_OBJ_FROM_PTR(o), vals[0].u_obj); - } - return MP_OBJ_FROM_PTR(o); + if (vals[0].u_obj != mp_const_none) { + mod_trezorcrypto_Sha3_256_update(MP_OBJ_FROM_PTR(o), vals[0].u_obj); + } + return MP_OBJ_FROM_PTR(o); } /// def update(self, data: bytes) -> None: @@ -68,70 +71,82 @@ STATIC mp_obj_t mod_trezorcrypto_Sha3_256_make_new(const mp_obj_type_t *type, si /// Update the hash context with hashed data. /// ''' STATIC mp_obj_t mod_trezorcrypto_Sha3_256_update(mp_obj_t self, mp_obj_t data) { - mp_obj_Sha3_256_t *o = MP_OBJ_TO_PTR(self); - mp_buffer_info_t msg; - mp_get_buffer_raise(data, &msg, MP_BUFFER_READ); - if (msg.len > 0) { - sha3_Update(&(o->ctx), msg.buf, msg.len); - } - return mp_const_none; + mp_obj_Sha3_256_t *o = MP_OBJ_TO_PTR(self); + mp_buffer_info_t msg; + mp_get_buffer_raise(data, &msg, MP_BUFFER_READ); + if (msg.len > 0) { + sha3_Update(&(o->ctx), msg.buf, msg.len); + } + return mp_const_none; } -STATIC MP_DEFINE_CONST_FUN_OBJ_2(mod_trezorcrypto_Sha3_256_update_obj, mod_trezorcrypto_Sha3_256_update); +STATIC MP_DEFINE_CONST_FUN_OBJ_2(mod_trezorcrypto_Sha3_256_update_obj, + mod_trezorcrypto_Sha3_256_update); /// def digest(self) -> bytes: /// ''' /// Returns the digest of hashed data. /// ''' STATIC mp_obj_t mod_trezorcrypto_Sha3_256_digest(mp_obj_t self) { - mp_obj_Sha3_256_t *o = MP_OBJ_TO_PTR(self); - uint8_t out[SHA3_256_DIGEST_LENGTH]; - SHA3_CTX ctx; - memcpy(&ctx, &(o->ctx), sizeof(SHA3_CTX)); - if (o->keccak) { - keccak_Final(&ctx, out); - } else { - sha3_Final(&ctx, out); - } - memzero(&ctx, sizeof(SHA3_CTX)); - return mp_obj_new_bytes(out, sizeof(out)); + mp_obj_Sha3_256_t *o = MP_OBJ_TO_PTR(self); + uint8_t out[SHA3_256_DIGEST_LENGTH]; + SHA3_CTX ctx; + memcpy(&ctx, &(o->ctx), sizeof(SHA3_CTX)); + if (o->keccak) { + keccak_Final(&ctx, out); + } else { + sha3_Final(&ctx, out); + } + memzero(&ctx, sizeof(SHA3_CTX)); + return mp_obj_new_bytes(out, sizeof(out)); } -STATIC MP_DEFINE_CONST_FUN_OBJ_1(mod_trezorcrypto_Sha3_256_digest_obj, mod_trezorcrypto_Sha3_256_digest); - +STATIC MP_DEFINE_CONST_FUN_OBJ_1(mod_trezorcrypto_Sha3_256_digest_obj, + mod_trezorcrypto_Sha3_256_digest); /// def copy(self) -> sha3: /// ''' /// Returns the copy of the digest object with the current state /// ''' -STATIC mp_obj_t mod_trezorcrypto_Sha3_256_copy(size_t n_args, const mp_obj_t *args) { - mp_obj_Sha3_256_t *o = MP_OBJ_TO_PTR(args[0]); - mp_obj_Sha3_256_t *out = m_new_obj(mp_obj_Sha3_256_t); - out->base.type = o->base.type; - out->keccak = o->keccak; - memcpy(&(out->ctx), &(o->ctx), sizeof(SHA3_CTX)); - return MP_OBJ_FROM_PTR(out); +STATIC mp_obj_t mod_trezorcrypto_Sha3_256_copy(size_t n_args, + const mp_obj_t *args) { + mp_obj_Sha3_256_t *o = MP_OBJ_TO_PTR(args[0]); + mp_obj_Sha3_256_t *out = m_new_obj(mp_obj_Sha3_256_t); + out->base.type = o->base.type; + out->keccak = o->keccak; + memcpy(&(out->ctx), &(o->ctx), sizeof(SHA3_CTX)); + return MP_OBJ_FROM_PTR(out); } -STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(mod_trezorcrypto_Sha3_256_copy_obj, 1, 1, mod_trezorcrypto_Sha3_256_copy); +STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(mod_trezorcrypto_Sha3_256_copy_obj, + 1, 1, + mod_trezorcrypto_Sha3_256_copy); STATIC mp_obj_t mod_trezorcrypto_Sha3_256___del__(mp_obj_t self) { - mp_obj_Sha3_256_t *o = MP_OBJ_TO_PTR(self); - memzero(&(o->ctx), sizeof(SHA3_CTX)); - return mp_const_none; + mp_obj_Sha3_256_t *o = MP_OBJ_TO_PTR(self); + memzero(&(o->ctx), sizeof(SHA3_CTX)); + return mp_const_none; } -STATIC MP_DEFINE_CONST_FUN_OBJ_1(mod_trezorcrypto_Sha3_256___del___obj, mod_trezorcrypto_Sha3_256___del__); +STATIC MP_DEFINE_CONST_FUN_OBJ_1(mod_trezorcrypto_Sha3_256___del___obj, + mod_trezorcrypto_Sha3_256___del__); STATIC const mp_rom_map_elem_t mod_trezorcrypto_Sha3_256_locals_dict_table[] = { - { MP_ROM_QSTR(MP_QSTR_update), MP_ROM_PTR(&mod_trezorcrypto_Sha3_256_update_obj) }, - { MP_ROM_QSTR(MP_QSTR_digest), MP_ROM_PTR(&mod_trezorcrypto_Sha3_256_digest_obj) }, - { MP_ROM_QSTR(MP_QSTR_copy), MP_ROM_PTR(&mod_trezorcrypto_Sha3_256_copy_obj) }, - { MP_ROM_QSTR(MP_QSTR___del__), MP_ROM_PTR(&mod_trezorcrypto_Sha3_256___del___obj) }, - { MP_ROM_QSTR(MP_QSTR_block_size), MP_OBJ_NEW_SMALL_INT(SHA3_256_BLOCK_LENGTH) }, - { MP_ROM_QSTR(MP_QSTR_digest_size), MP_OBJ_NEW_SMALL_INT(SHA3_256_DIGEST_LENGTH) }, + {MP_ROM_QSTR(MP_QSTR_update), + MP_ROM_PTR(&mod_trezorcrypto_Sha3_256_update_obj)}, + {MP_ROM_QSTR(MP_QSTR_digest), + MP_ROM_PTR(&mod_trezorcrypto_Sha3_256_digest_obj)}, + {MP_ROM_QSTR(MP_QSTR_copy), + MP_ROM_PTR(&mod_trezorcrypto_Sha3_256_copy_obj)}, + {MP_ROM_QSTR(MP_QSTR___del__), + MP_ROM_PTR(&mod_trezorcrypto_Sha3_256___del___obj)}, + {MP_ROM_QSTR(MP_QSTR_block_size), + MP_OBJ_NEW_SMALL_INT(SHA3_256_BLOCK_LENGTH)}, + {MP_ROM_QSTR(MP_QSTR_digest_size), + MP_OBJ_NEW_SMALL_INT(SHA3_256_DIGEST_LENGTH)}, }; -STATIC MP_DEFINE_CONST_DICT(mod_trezorcrypto_Sha3_256_locals_dict, mod_trezorcrypto_Sha3_256_locals_dict_table); +STATIC MP_DEFINE_CONST_DICT(mod_trezorcrypto_Sha3_256_locals_dict, + mod_trezorcrypto_Sha3_256_locals_dict_table); STATIC const mp_obj_type_t mod_trezorcrypto_Sha3_256_type = { - { &mp_type_type }, + {&mp_type_type}, .name = MP_QSTR_Sha3_256, .make_new = mod_trezorcrypto_Sha3_256_make_new, - .locals_dict = (void*)&mod_trezorcrypto_Sha3_256_locals_dict, + .locals_dict = (void *)&mod_trezorcrypto_Sha3_256_locals_dict, }; diff --git a/embed/extmod/modtrezorcrypto/modtrezorcrypto-sha3-512.h b/embed/extmod/modtrezorcrypto/modtrezorcrypto-sha3-512.h index f1c52c052..cb15f8c29 100644 --- a/embed/extmod/modtrezorcrypto/modtrezorcrypto-sha3-512.h +++ b/embed/extmod/modtrezorcrypto/modtrezorcrypto-sha3-512.h @@ -19,8 +19,8 @@ #include "py/objstr.h" -#include "sha3.h" #include "memzero.h" +#include "sha3.h" /// package: trezorcrypto.__init__ @@ -29,9 +29,9 @@ /// SHA3_512 context. /// ''' typedef struct _mp_obj_Sha3_512_t { - mp_obj_base_t base; - SHA3_CTX ctx; - bool keccak; + mp_obj_base_t base; + SHA3_CTX ctx; + bool keccak; } mp_obj_Sha3_512_t; STATIC mp_obj_t mod_trezorcrypto_Sha3_512_update(mp_obj_t self, mp_obj_t data); @@ -40,27 +40,30 @@ STATIC mp_obj_t mod_trezorcrypto_Sha3_512_update(mp_obj_t self, mp_obj_t data); /// ''' /// Creates a hash context object. /// ''' -STATIC mp_obj_t mod_trezorcrypto_Sha3_512_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_kw, const mp_obj_t *args) { - mp_arg_check_num(n_args, n_kw, 0, 1, true); - mp_obj_Sha3_512_t *o = m_new_obj(mp_obj_Sha3_512_t); - o->base.type = type; - o->keccak = 0; - sha3_512_Init(&(o->ctx)); +STATIC mp_obj_t mod_trezorcrypto_Sha3_512_make_new(const mp_obj_type_t *type, + size_t n_args, size_t n_kw, + const mp_obj_t *args) { + mp_arg_check_num(n_args, n_kw, 0, 1, true); + mp_obj_Sha3_512_t *o = m_new_obj(mp_obj_Sha3_512_t); + o->base.type = type; + o->keccak = 0; + sha3_512_Init(&(o->ctx)); - STATIC const mp_arg_t allowed_args[] = { - { MP_QSTR_data, MP_ARG_OBJ, {.u_obj = mp_const_none} }, - { MP_QSTR_keccak, MP_ARG_OBJ | MP_ARG_KW_ONLY, {.u_obj = MP_OBJ_NULL} }, - }; - mp_arg_val_t vals[MP_ARRAY_SIZE(allowed_args)]; - mp_arg_parse_all_kw_array(n_args, n_kw, args, MP_ARRAY_SIZE(allowed_args), allowed_args, vals); - if (vals[1].u_obj != MP_OBJ_NULL){ - o->keccak = mp_obj_is_true(vals[1].u_obj); - } + STATIC const mp_arg_t allowed_args[] = { + {MP_QSTR_data, MP_ARG_OBJ, {.u_obj = mp_const_none}}, + {MP_QSTR_keccak, MP_ARG_OBJ | MP_ARG_KW_ONLY, {.u_obj = MP_OBJ_NULL}}, + }; + mp_arg_val_t vals[MP_ARRAY_SIZE(allowed_args)]; + mp_arg_parse_all_kw_array(n_args, n_kw, args, MP_ARRAY_SIZE(allowed_args), + allowed_args, vals); + if (vals[1].u_obj != MP_OBJ_NULL) { + o->keccak = mp_obj_is_true(vals[1].u_obj); + } - if (vals[0].u_obj != mp_const_none){ - mod_trezorcrypto_Sha3_512_update(MP_OBJ_FROM_PTR(o), vals[0].u_obj); - } - return MP_OBJ_FROM_PTR(o); + if (vals[0].u_obj != mp_const_none) { + mod_trezorcrypto_Sha3_512_update(MP_OBJ_FROM_PTR(o), vals[0].u_obj); + } + return MP_OBJ_FROM_PTR(o); } /// def update(self, data: bytes) -> None: @@ -68,70 +71,82 @@ STATIC mp_obj_t mod_trezorcrypto_Sha3_512_make_new(const mp_obj_type_t *type, si /// Update the hash context with hashed data. /// ''' STATIC mp_obj_t mod_trezorcrypto_Sha3_512_update(mp_obj_t self, mp_obj_t data) { - mp_obj_Sha3_512_t *o = MP_OBJ_TO_PTR(self); - mp_buffer_info_t msg; - mp_get_buffer_raise(data, &msg, MP_BUFFER_READ); - if (msg.len > 0) { - sha3_Update(&(o->ctx), msg.buf, msg.len); - } - return mp_const_none; + mp_obj_Sha3_512_t *o = MP_OBJ_TO_PTR(self); + mp_buffer_info_t msg; + mp_get_buffer_raise(data, &msg, MP_BUFFER_READ); + if (msg.len > 0) { + sha3_Update(&(o->ctx), msg.buf, msg.len); + } + return mp_const_none; } -STATIC MP_DEFINE_CONST_FUN_OBJ_2(mod_trezorcrypto_Sha3_512_update_obj, mod_trezorcrypto_Sha3_512_update); +STATIC MP_DEFINE_CONST_FUN_OBJ_2(mod_trezorcrypto_Sha3_512_update_obj, + mod_trezorcrypto_Sha3_512_update); /// def digest(self) -> bytes: /// ''' /// Returns the digest of hashed data. /// ''' STATIC mp_obj_t mod_trezorcrypto_Sha3_512_digest(mp_obj_t self) { - mp_obj_Sha3_512_t *o = MP_OBJ_TO_PTR(self); - uint8_t out[SHA3_512_DIGEST_LENGTH]; - SHA3_CTX ctx; - memcpy(&ctx, &(o->ctx), sizeof(SHA3_CTX)); - if (o->keccak) { - keccak_Final(&ctx, out); - } else { - sha3_Final(&ctx, out); - } - memzero(&ctx, sizeof(SHA3_CTX)); - return mp_obj_new_bytes(out, sizeof(out)); + mp_obj_Sha3_512_t *o = MP_OBJ_TO_PTR(self); + uint8_t out[SHA3_512_DIGEST_LENGTH]; + SHA3_CTX ctx; + memcpy(&ctx, &(o->ctx), sizeof(SHA3_CTX)); + if (o->keccak) { + keccak_Final(&ctx, out); + } else { + sha3_Final(&ctx, out); + } + memzero(&ctx, sizeof(SHA3_CTX)); + return mp_obj_new_bytes(out, sizeof(out)); } -STATIC MP_DEFINE_CONST_FUN_OBJ_1(mod_trezorcrypto_Sha3_512_digest_obj, mod_trezorcrypto_Sha3_512_digest); - +STATIC MP_DEFINE_CONST_FUN_OBJ_1(mod_trezorcrypto_Sha3_512_digest_obj, + mod_trezorcrypto_Sha3_512_digest); /// def copy(self) -> sha3: /// ''' /// Returns the copy of the digest object with the current state /// ''' -STATIC mp_obj_t mod_trezorcrypto_Sha3_512_copy(size_t n_args, const mp_obj_t *args) { - mp_obj_Sha3_512_t *o = MP_OBJ_TO_PTR(args[0]); - mp_obj_Sha3_512_t *out = m_new_obj(mp_obj_Sha3_512_t); - out->base.type = o->base.type; - out->keccak = o->keccak; - memcpy(&(out->ctx), &(o->ctx), sizeof(SHA3_CTX)); - return MP_OBJ_FROM_PTR(out); +STATIC mp_obj_t mod_trezorcrypto_Sha3_512_copy(size_t n_args, + const mp_obj_t *args) { + mp_obj_Sha3_512_t *o = MP_OBJ_TO_PTR(args[0]); + mp_obj_Sha3_512_t *out = m_new_obj(mp_obj_Sha3_512_t); + out->base.type = o->base.type; + out->keccak = o->keccak; + memcpy(&(out->ctx), &(o->ctx), sizeof(SHA3_CTX)); + return MP_OBJ_FROM_PTR(out); } -STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(mod_trezorcrypto_Sha3_512_copy_obj, 1, 1, mod_trezorcrypto_Sha3_512_copy); +STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(mod_trezorcrypto_Sha3_512_copy_obj, + 1, 1, + mod_trezorcrypto_Sha3_512_copy); STATIC mp_obj_t mod_trezorcrypto_Sha3_512___del__(mp_obj_t self) { - mp_obj_Sha3_512_t *o = MP_OBJ_TO_PTR(self); - memzero(&(o->ctx), sizeof(SHA3_CTX)); - return mp_const_none; + mp_obj_Sha3_512_t *o = MP_OBJ_TO_PTR(self); + memzero(&(o->ctx), sizeof(SHA3_CTX)); + return mp_const_none; } -STATIC MP_DEFINE_CONST_FUN_OBJ_1(mod_trezorcrypto_Sha3_512___del___obj, mod_trezorcrypto_Sha3_512___del__); +STATIC MP_DEFINE_CONST_FUN_OBJ_1(mod_trezorcrypto_Sha3_512___del___obj, + mod_trezorcrypto_Sha3_512___del__); STATIC const mp_rom_map_elem_t mod_trezorcrypto_Sha3_512_locals_dict_table[] = { - { MP_ROM_QSTR(MP_QSTR_update), MP_ROM_PTR(&mod_trezorcrypto_Sha3_512_update_obj) }, - { MP_ROM_QSTR(MP_QSTR_digest), MP_ROM_PTR(&mod_trezorcrypto_Sha3_512_digest_obj) }, - { MP_ROM_QSTR(MP_QSTR_copy), MP_ROM_PTR(&mod_trezorcrypto_Sha3_512_copy_obj) }, - { MP_ROM_QSTR(MP_QSTR___del__), MP_ROM_PTR(&mod_trezorcrypto_Sha3_512___del___obj) }, - { MP_ROM_QSTR(MP_QSTR_block_size), MP_OBJ_NEW_SMALL_INT(SHA3_512_BLOCK_LENGTH) }, - { MP_ROM_QSTR(MP_QSTR_digest_size), MP_OBJ_NEW_SMALL_INT(SHA3_512_DIGEST_LENGTH) }, + {MP_ROM_QSTR(MP_QSTR_update), + MP_ROM_PTR(&mod_trezorcrypto_Sha3_512_update_obj)}, + {MP_ROM_QSTR(MP_QSTR_digest), + MP_ROM_PTR(&mod_trezorcrypto_Sha3_512_digest_obj)}, + {MP_ROM_QSTR(MP_QSTR_copy), + MP_ROM_PTR(&mod_trezorcrypto_Sha3_512_copy_obj)}, + {MP_ROM_QSTR(MP_QSTR___del__), + MP_ROM_PTR(&mod_trezorcrypto_Sha3_512___del___obj)}, + {MP_ROM_QSTR(MP_QSTR_block_size), + MP_OBJ_NEW_SMALL_INT(SHA3_512_BLOCK_LENGTH)}, + {MP_ROM_QSTR(MP_QSTR_digest_size), + MP_OBJ_NEW_SMALL_INT(SHA3_512_DIGEST_LENGTH)}, }; -STATIC MP_DEFINE_CONST_DICT(mod_trezorcrypto_Sha3_512_locals_dict, mod_trezorcrypto_Sha3_512_locals_dict_table); +STATIC MP_DEFINE_CONST_DICT(mod_trezorcrypto_Sha3_512_locals_dict, + mod_trezorcrypto_Sha3_512_locals_dict_table); STATIC const mp_obj_type_t mod_trezorcrypto_Sha3_512_type = { - { &mp_type_type }, + {&mp_type_type}, .name = MP_QSTR_Sha3_512, .make_new = mod_trezorcrypto_Sha3_512_make_new, - .locals_dict = (void*)&mod_trezorcrypto_Sha3_512_locals_dict, + .locals_dict = (void *)&mod_trezorcrypto_Sha3_512_locals_dict, }; diff --git a/embed/extmod/modtrezorcrypto/modtrezorcrypto-sha512.h b/embed/extmod/modtrezorcrypto/modtrezorcrypto-sha512.h index 713f02c17..d84d34bb5 100644 --- a/embed/extmod/modtrezorcrypto/modtrezorcrypto-sha512.h +++ b/embed/extmod/modtrezorcrypto/modtrezorcrypto-sha512.h @@ -19,8 +19,8 @@ #include "py/objstr.h" -#include "sha2.h" #include "memzero.h" +#include "sha2.h" /// package: trezorcrypto.__init__ @@ -29,8 +29,8 @@ /// SHA512 context. /// ''' typedef struct _mp_obj_Sha512_t { - mp_obj_base_t base; - SHA512_CTX ctx; + mp_obj_base_t base; + SHA512_CTX ctx; } mp_obj_Sha512_t; STATIC mp_obj_t mod_trezorcrypto_Sha512_update(mp_obj_t self, mp_obj_t data); @@ -39,15 +39,17 @@ STATIC mp_obj_t mod_trezorcrypto_Sha512_update(mp_obj_t self, mp_obj_t data); /// ''' /// Creates a hash context object. /// ''' -STATIC mp_obj_t mod_trezorcrypto_Sha512_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_kw, const mp_obj_t *args) { - mp_arg_check_num(n_args, n_kw, 0, 1, false); - mp_obj_Sha512_t *o = m_new_obj(mp_obj_Sha512_t); - o->base.type = type; - sha512_Init(&(o->ctx)); - if (n_args == 1) { - mod_trezorcrypto_Sha512_update(MP_OBJ_FROM_PTR(o), args[0]); - } - return MP_OBJ_FROM_PTR(o); +STATIC mp_obj_t mod_trezorcrypto_Sha512_make_new(const mp_obj_type_t *type, + size_t n_args, size_t n_kw, + const mp_obj_t *args) { + mp_arg_check_num(n_args, n_kw, 0, 1, false); + mp_obj_Sha512_t *o = m_new_obj(mp_obj_Sha512_t); + o->base.type = type; + sha512_Init(&(o->ctx)); + if (n_args == 1) { + mod_trezorcrypto_Sha512_update(MP_OBJ_FROM_PTR(o), args[0]); + } + return MP_OBJ_FROM_PTR(o); } /// def hash(self, data: bytes) -> None: @@ -55,50 +57,59 @@ STATIC mp_obj_t mod_trezorcrypto_Sha512_make_new(const mp_obj_type_t *type, size /// Update the hash context with hashed data. /// ''' STATIC mp_obj_t mod_trezorcrypto_Sha512_update(mp_obj_t self, mp_obj_t data) { - mp_obj_Sha512_t *o = MP_OBJ_TO_PTR(self); - mp_buffer_info_t msg; - mp_get_buffer_raise(data, &msg, MP_BUFFER_READ); - if (msg.len > 0) { - sha512_Update(&(o->ctx), msg.buf, msg.len); - } - return mp_const_none; + mp_obj_Sha512_t *o = MP_OBJ_TO_PTR(self); + mp_buffer_info_t msg; + mp_get_buffer_raise(data, &msg, MP_BUFFER_READ); + if (msg.len > 0) { + sha512_Update(&(o->ctx), msg.buf, msg.len); + } + return mp_const_none; } -STATIC MP_DEFINE_CONST_FUN_OBJ_2(mod_trezorcrypto_Sha512_update_obj, mod_trezorcrypto_Sha512_update); +STATIC MP_DEFINE_CONST_FUN_OBJ_2(mod_trezorcrypto_Sha512_update_obj, + mod_trezorcrypto_Sha512_update); /// def digest(self) -> bytes: /// ''' /// Returns the digest of hashed data. /// ''' STATIC mp_obj_t mod_trezorcrypto_Sha512_digest(mp_obj_t self) { - mp_obj_Sha512_t *o = MP_OBJ_TO_PTR(self); - uint8_t out[SHA512_DIGEST_LENGTH]; - SHA512_CTX ctx; - memcpy(&ctx, &(o->ctx), sizeof(SHA512_CTX)); - sha512_Final(&ctx, out); - memzero(&ctx, sizeof(SHA512_CTX)); - return mp_obj_new_bytes(out, sizeof(out)); + mp_obj_Sha512_t *o = MP_OBJ_TO_PTR(self); + uint8_t out[SHA512_DIGEST_LENGTH]; + SHA512_CTX ctx; + memcpy(&ctx, &(o->ctx), sizeof(SHA512_CTX)); + sha512_Final(&ctx, out); + memzero(&ctx, sizeof(SHA512_CTX)); + return mp_obj_new_bytes(out, sizeof(out)); } -STATIC MP_DEFINE_CONST_FUN_OBJ_1(mod_trezorcrypto_Sha512_digest_obj, mod_trezorcrypto_Sha512_digest); +STATIC MP_DEFINE_CONST_FUN_OBJ_1(mod_trezorcrypto_Sha512_digest_obj, + mod_trezorcrypto_Sha512_digest); STATIC mp_obj_t mod_trezorcrypto_Sha512___del__(mp_obj_t self) { - mp_obj_Sha512_t *o = MP_OBJ_TO_PTR(self); - memzero(&(o->ctx), sizeof(SHA512_CTX)); - return mp_const_none; + mp_obj_Sha512_t *o = MP_OBJ_TO_PTR(self); + memzero(&(o->ctx), sizeof(SHA512_CTX)); + return mp_const_none; } -STATIC MP_DEFINE_CONST_FUN_OBJ_1(mod_trezorcrypto_Sha512___del___obj, mod_trezorcrypto_Sha512___del__); +STATIC MP_DEFINE_CONST_FUN_OBJ_1(mod_trezorcrypto_Sha512___del___obj, + mod_trezorcrypto_Sha512___del__); STATIC const mp_rom_map_elem_t mod_trezorcrypto_Sha512_locals_dict_table[] = { - { MP_ROM_QSTR(MP_QSTR_update), MP_ROM_PTR(&mod_trezorcrypto_Sha512_update_obj) }, - { MP_ROM_QSTR(MP_QSTR_digest), MP_ROM_PTR(&mod_trezorcrypto_Sha512_digest_obj) }, - { MP_ROM_QSTR(MP_QSTR___del__), MP_ROM_PTR(&mod_trezorcrypto_Sha512___del___obj) }, - { MP_ROM_QSTR(MP_QSTR_block_size), MP_OBJ_NEW_SMALL_INT(SHA512_BLOCK_LENGTH) }, - { MP_ROM_QSTR(MP_QSTR_digest_size), MP_OBJ_NEW_SMALL_INT(SHA512_DIGEST_LENGTH) }, + {MP_ROM_QSTR(MP_QSTR_update), + MP_ROM_PTR(&mod_trezorcrypto_Sha512_update_obj)}, + {MP_ROM_QSTR(MP_QSTR_digest), + MP_ROM_PTR(&mod_trezorcrypto_Sha512_digest_obj)}, + {MP_ROM_QSTR(MP_QSTR___del__), + MP_ROM_PTR(&mod_trezorcrypto_Sha512___del___obj)}, + {MP_ROM_QSTR(MP_QSTR_block_size), + MP_OBJ_NEW_SMALL_INT(SHA512_BLOCK_LENGTH)}, + {MP_ROM_QSTR(MP_QSTR_digest_size), + MP_OBJ_NEW_SMALL_INT(SHA512_DIGEST_LENGTH)}, }; -STATIC MP_DEFINE_CONST_DICT(mod_trezorcrypto_Sha512_locals_dict, mod_trezorcrypto_Sha512_locals_dict_table); +STATIC MP_DEFINE_CONST_DICT(mod_trezorcrypto_Sha512_locals_dict, + mod_trezorcrypto_Sha512_locals_dict_table); STATIC const mp_obj_type_t mod_trezorcrypto_Sha512_type = { - { &mp_type_type }, + {&mp_type_type}, .name = MP_QSTR_Sha512, .make_new = mod_trezorcrypto_Sha512_make_new, - .locals_dict = (void*)&mod_trezorcrypto_Sha512_locals_dict, + .locals_dict = (void *)&mod_trezorcrypto_Sha512_locals_dict, }; diff --git a/embed/extmod/modtrezorcrypto/modtrezorcrypto.c b/embed/extmod/modtrezorcrypto/modtrezorcrypto.c index 9bd741123..227ee8817 100644 --- a/embed/extmod/modtrezorcrypto/modtrezorcrypto.c +++ b/embed/extmod/modtrezorcrypto/modtrezorcrypto.c @@ -17,9 +17,9 @@ * along with this program. If not, see . */ +#include #include #include -#include #include "py/runtime.h" @@ -35,9 +35,10 @@ #include "modtrezorcrypto-crc.h" #include "modtrezorcrypto-curve25519.h" #include "modtrezorcrypto-ed25519.h" -#include "modtrezorcrypto-nist256p1.h" #include "modtrezorcrypto-groestl.h" +#include "modtrezorcrypto-monero.h" #include "modtrezorcrypto-nem.h" +#include "modtrezorcrypto-nist256p1.h" #include "modtrezorcrypto-pbkdf2.h" #include "modtrezorcrypto-random.h" #include "modtrezorcrypto-rfc6979.h" @@ -45,43 +46,53 @@ #include "modtrezorcrypto-secp256k1.h" #include "modtrezorcrypto-sha1.h" #include "modtrezorcrypto-sha256.h" -#include "modtrezorcrypto-sha512.h" #include "modtrezorcrypto-sha3-256.h" #include "modtrezorcrypto-sha3-512.h" -#include "modtrezorcrypto-monero.h" +#include "modtrezorcrypto-sha512.h" STATIC const mp_rom_map_elem_t mp_module_trezorcrypto_globals_table[] = { - { MP_ROM_QSTR(MP_QSTR___name__), MP_ROM_QSTR(MP_QSTR_trezorcrypto) }, - { MP_ROM_QSTR(MP_QSTR_aes), MP_ROM_PTR(&mod_trezorcrypto_AES_type) }, - { MP_ROM_QSTR(MP_QSTR_bip32), MP_ROM_PTR(&mod_trezorcrypto_bip32_module) }, - { MP_ROM_QSTR(MP_QSTR_bip39), MP_ROM_PTR(&mod_trezorcrypto_bip39_module) }, - { MP_ROM_QSTR(MP_QSTR_blake256), MP_ROM_PTR(&mod_trezorcrypto_Blake256_type) }, - { MP_ROM_QSTR(MP_QSTR_blake2b), MP_ROM_PTR(&mod_trezorcrypto_Blake2b_type) }, - { MP_ROM_QSTR(MP_QSTR_blake2s), MP_ROM_PTR(&mod_trezorcrypto_Blake2s_type) }, - { MP_ROM_QSTR(MP_QSTR_chacha20poly1305), MP_ROM_PTR(&mod_trezorcrypto_ChaCha20Poly1305_type) }, - { MP_ROM_QSTR(MP_QSTR_crc), MP_ROM_PTR(&mod_trezorcrypto_crc_module) }, - { MP_ROM_QSTR(MP_QSTR_curve25519), MP_ROM_PTR(&mod_trezorcrypto_curve25519_module) }, - { MP_ROM_QSTR(MP_QSTR_ed25519), MP_ROM_PTR(&mod_trezorcrypto_ed25519_module) }, - { MP_ROM_QSTR(MP_QSTR_monero), MP_ROM_PTR(&mod_trezorcrypto_monero_module) }, - { MP_ROM_QSTR(MP_QSTR_nist256p1), MP_ROM_PTR(&mod_trezorcrypto_nist256p1_module) }, - { MP_ROM_QSTR(MP_QSTR_groestl512), MP_ROM_PTR(&mod_trezorcrypto_Groestl512_type) }, - { MP_ROM_QSTR(MP_QSTR_nem), MP_ROM_PTR(&mod_trezorcrypto_nem_module) }, - { MP_ROM_QSTR(MP_QSTR_pbkdf2), MP_ROM_PTR(&mod_trezorcrypto_Pbkdf2_type) }, - { MP_ROM_QSTR(MP_QSTR_random), MP_ROM_PTR(&mod_trezorcrypto_random_module) }, - { MP_ROM_QSTR(MP_QSTR_rfc6979), MP_ROM_PTR(&mod_trezorcrypto_Rfc6979_type) }, - { MP_ROM_QSTR(MP_QSTR_ripemd160), MP_ROM_PTR(&mod_trezorcrypto_Ripemd160_type) }, - { MP_ROM_QSTR(MP_QSTR_secp256k1), MP_ROM_PTR(&mod_trezorcrypto_secp256k1_module) }, - { MP_ROM_QSTR(MP_QSTR_sha1), MP_ROM_PTR(&mod_trezorcrypto_Sha1_type) }, - { MP_ROM_QSTR(MP_QSTR_sha256), MP_ROM_PTR(&mod_trezorcrypto_Sha256_type) }, - { MP_ROM_QSTR(MP_QSTR_sha512), MP_ROM_PTR(&mod_trezorcrypto_Sha512_type) }, - { MP_ROM_QSTR(MP_QSTR_sha3_256), MP_ROM_PTR(&mod_trezorcrypto_Sha3_256_type) }, - { MP_ROM_QSTR(MP_QSTR_sha3_512), MP_ROM_PTR(&mod_trezorcrypto_Sha3_512_type) }, + {MP_ROM_QSTR(MP_QSTR___name__), MP_ROM_QSTR(MP_QSTR_trezorcrypto)}, + {MP_ROM_QSTR(MP_QSTR_aes), MP_ROM_PTR(&mod_trezorcrypto_AES_type)}, + {MP_ROM_QSTR(MP_QSTR_bip32), MP_ROM_PTR(&mod_trezorcrypto_bip32_module)}, + {MP_ROM_QSTR(MP_QSTR_bip39), MP_ROM_PTR(&mod_trezorcrypto_bip39_module)}, + {MP_ROM_QSTR(MP_QSTR_blake256), + MP_ROM_PTR(&mod_trezorcrypto_Blake256_type)}, + {MP_ROM_QSTR(MP_QSTR_blake2b), MP_ROM_PTR(&mod_trezorcrypto_Blake2b_type)}, + {MP_ROM_QSTR(MP_QSTR_blake2s), MP_ROM_PTR(&mod_trezorcrypto_Blake2s_type)}, + {MP_ROM_QSTR(MP_QSTR_chacha20poly1305), + MP_ROM_PTR(&mod_trezorcrypto_ChaCha20Poly1305_type)}, + {MP_ROM_QSTR(MP_QSTR_crc), MP_ROM_PTR(&mod_trezorcrypto_crc_module)}, + {MP_ROM_QSTR(MP_QSTR_curve25519), + MP_ROM_PTR(&mod_trezorcrypto_curve25519_module)}, + {MP_ROM_QSTR(MP_QSTR_ed25519), + MP_ROM_PTR(&mod_trezorcrypto_ed25519_module)}, + {MP_ROM_QSTR(MP_QSTR_monero), MP_ROM_PTR(&mod_trezorcrypto_monero_module)}, + {MP_ROM_QSTR(MP_QSTR_nist256p1), + MP_ROM_PTR(&mod_trezorcrypto_nist256p1_module)}, + {MP_ROM_QSTR(MP_QSTR_groestl512), + MP_ROM_PTR(&mod_trezorcrypto_Groestl512_type)}, + {MP_ROM_QSTR(MP_QSTR_nem), MP_ROM_PTR(&mod_trezorcrypto_nem_module)}, + {MP_ROM_QSTR(MP_QSTR_pbkdf2), MP_ROM_PTR(&mod_trezorcrypto_Pbkdf2_type)}, + {MP_ROM_QSTR(MP_QSTR_random), MP_ROM_PTR(&mod_trezorcrypto_random_module)}, + {MP_ROM_QSTR(MP_QSTR_rfc6979), MP_ROM_PTR(&mod_trezorcrypto_Rfc6979_type)}, + {MP_ROM_QSTR(MP_QSTR_ripemd160), + MP_ROM_PTR(&mod_trezorcrypto_Ripemd160_type)}, + {MP_ROM_QSTR(MP_QSTR_secp256k1), + MP_ROM_PTR(&mod_trezorcrypto_secp256k1_module)}, + {MP_ROM_QSTR(MP_QSTR_sha1), MP_ROM_PTR(&mod_trezorcrypto_Sha1_type)}, + {MP_ROM_QSTR(MP_QSTR_sha256), MP_ROM_PTR(&mod_trezorcrypto_Sha256_type)}, + {MP_ROM_QSTR(MP_QSTR_sha512), MP_ROM_PTR(&mod_trezorcrypto_Sha512_type)}, + {MP_ROM_QSTR(MP_QSTR_sha3_256), + MP_ROM_PTR(&mod_trezorcrypto_Sha3_256_type)}, + {MP_ROM_QSTR(MP_QSTR_sha3_512), + MP_ROM_PTR(&mod_trezorcrypto_Sha3_512_type)}, }; -STATIC MP_DEFINE_CONST_DICT(mp_module_trezorcrypto_globals, mp_module_trezorcrypto_globals_table); +STATIC MP_DEFINE_CONST_DICT(mp_module_trezorcrypto_globals, + mp_module_trezorcrypto_globals_table); const mp_obj_module_t mp_module_trezorcrypto = { - .base = { &mp_type_module }, + .base = {&mp_type_module}, .globals = (mp_obj_dict_t*)&mp_module_trezorcrypto_globals, }; -#endif // MICROPY_PY_TREZORCRYPTO +#endif // MICROPY_PY_TREZORCRYPTO diff --git a/embed/extmod/modtrezorcrypto/rand.c b/embed/extmod/modtrezorcrypto/rand.c index 679e0fe82..fc5bdbc94 100644 --- a/embed/extmod/modtrezorcrypto/rand.c +++ b/embed/extmod/modtrezorcrypto/rand.c @@ -20,7 +20,4 @@ #include "rand.h" #include "rng.h" -uint32_t random32(void) -{ - return rng_get(); -} +uint32_t random32(void) { return rng_get(); } diff --git a/embed/extmod/modtrezorio/modtrezorio-flash.h b/embed/extmod/modtrezorio/modtrezorio-flash.h index 39bb75fb8..7f8d85ad5 100644 --- a/embed/extmod/modtrezorio/modtrezorio-flash.h +++ b/embed/extmod/modtrezorio/modtrezorio-flash.h @@ -25,85 +25,95 @@ /// ''' /// ''' typedef struct _mp_obj_FlashOTP_t { - mp_obj_base_t base; + mp_obj_base_t base; } mp_obj_FlashOTP_t; /// def __init__(self) -> None: /// ''' /// ''' -STATIC mp_obj_t mod_trezorio_FlashOTP_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_kw, const mp_obj_t *args) { - mp_arg_check_num(n_args, n_kw, 0, 0, false); - mp_obj_FlashOTP_t *o = m_new_obj(mp_obj_FlashOTP_t); - o->base.type = type; - return MP_OBJ_FROM_PTR(o); +STATIC mp_obj_t mod_trezorio_FlashOTP_make_new(const mp_obj_type_t *type, + size_t n_args, size_t n_kw, + const mp_obj_t *args) { + mp_arg_check_num(n_args, n_kw, 0, 0, false); + mp_obj_FlashOTP_t *o = m_new_obj(mp_obj_FlashOTP_t); + o->base.type = type; + return MP_OBJ_FROM_PTR(o); } /// def FlashOTP.write(self, block: int, offset: int, data: bytes) -> None: /// ''' /// Writes data to OTP flash /// ''' -STATIC mp_obj_t mod_trezorio_FlashOTP_write(size_t n_args, const mp_obj_t *args) { - uint8_t block = trezor_obj_get_uint8(args[1]); - uint8_t offset = trezor_obj_get_uint8(args[2]); - mp_buffer_info_t data; - mp_get_buffer_raise(args[3], &data, MP_BUFFER_READ); - if (sectrue != flash_otp_write(block, offset, data.buf, data.len)) { - mp_raise_ValueError("write failed"); - } - return mp_const_none; +STATIC mp_obj_t mod_trezorio_FlashOTP_write(size_t n_args, + const mp_obj_t *args) { + uint8_t block = trezor_obj_get_uint8(args[1]); + uint8_t offset = trezor_obj_get_uint8(args[2]); + mp_buffer_info_t data; + mp_get_buffer_raise(args[3], &data, MP_BUFFER_READ); + if (sectrue != flash_otp_write(block, offset, data.buf, data.len)) { + mp_raise_ValueError("write failed"); + } + return mp_const_none; } -STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(mod_trezorio_FlashOTP_write_obj, 4, 4, mod_trezorio_FlashOTP_write); +STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(mod_trezorio_FlashOTP_write_obj, 4, + 4, mod_trezorio_FlashOTP_write); /// def FlashOTP.read(self, block: int, offset: int, data: bytearray) -> None: /// ''' /// Reads data from OTP flash /// ''' -STATIC mp_obj_t mod_trezorio_FlashOTP_read(size_t n_args, const mp_obj_t *args) { - uint8_t block = trezor_obj_get_uint8(args[1]); - uint8_t offset = trezor_obj_get_uint8(args[2]); - mp_buffer_info_t data; - mp_get_buffer_raise(args[3], &data, MP_BUFFER_WRITE); - if (sectrue != flash_otp_read(block, offset, data.buf, data.len)) { - mp_raise_ValueError("read failed"); - } - return mp_const_none; +STATIC mp_obj_t mod_trezorio_FlashOTP_read(size_t n_args, + const mp_obj_t *args) { + uint8_t block = trezor_obj_get_uint8(args[1]); + uint8_t offset = trezor_obj_get_uint8(args[2]); + mp_buffer_info_t data; + mp_get_buffer_raise(args[3], &data, MP_BUFFER_WRITE); + if (sectrue != flash_otp_read(block, offset, data.buf, data.len)) { + mp_raise_ValueError("read failed"); + } + return mp_const_none; } -STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(mod_trezorio_FlashOTP_read_obj, 4, 4, mod_trezorio_FlashOTP_read); +STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(mod_trezorio_FlashOTP_read_obj, 4, 4, + mod_trezorio_FlashOTP_read); /// def FlashOTP.lock(self, block: int) -> None: /// ''' /// Lock OTP flash block /// ''' STATIC mp_obj_t mod_trezorio_FlashOTP_lock(mp_obj_t self, mp_obj_t block) { - uint8_t b = trezor_obj_get_uint8(block); - if (sectrue != flash_otp_lock(b)) { - mp_raise_ValueError("lock failed"); - } - return mp_const_none; + uint8_t b = trezor_obj_get_uint8(block); + if (sectrue != flash_otp_lock(b)) { + mp_raise_ValueError("lock failed"); + } + return mp_const_none; } -STATIC MP_DEFINE_CONST_FUN_OBJ_2(mod_trezorio_FlashOTP_lock_obj, mod_trezorio_FlashOTP_lock); +STATIC MP_DEFINE_CONST_FUN_OBJ_2(mod_trezorio_FlashOTP_lock_obj, + mod_trezorio_FlashOTP_lock); /// def FlashOTP.is_locked(self, block: int) -> bool: /// ''' /// Is OTP flash block locked? /// ''' STATIC mp_obj_t mod_trezorio_FlashOTP_is_locked(mp_obj_t self, mp_obj_t block) { - uint8_t b = trezor_obj_get_uint8(block); - return (sectrue == flash_otp_is_locked(b)) ? mp_const_true : mp_const_false; + uint8_t b = trezor_obj_get_uint8(block); + return (sectrue == flash_otp_is_locked(b)) ? mp_const_true : mp_const_false; } -STATIC MP_DEFINE_CONST_FUN_OBJ_2(mod_trezorio_FlashOTP_is_locked_obj, mod_trezorio_FlashOTP_is_locked); +STATIC MP_DEFINE_CONST_FUN_OBJ_2(mod_trezorio_FlashOTP_is_locked_obj, + mod_trezorio_FlashOTP_is_locked); STATIC const mp_rom_map_elem_t mod_trezorio_FlashOTP_locals_dict_table[] = { - { MP_ROM_QSTR(MP_QSTR_read), MP_ROM_PTR(&mod_trezorio_FlashOTP_read_obj) }, - { MP_ROM_QSTR(MP_QSTR_write), MP_ROM_PTR(&mod_trezorio_FlashOTP_write_obj) }, - { MP_ROM_QSTR(MP_QSTR_lock), MP_ROM_PTR(&mod_trezorio_FlashOTP_lock_obj) }, - { MP_ROM_QSTR(MP_QSTR_is_locked), MP_ROM_PTR(&mod_trezorio_FlashOTP_is_locked_obj) }, + {MP_ROM_QSTR(MP_QSTR_read), MP_ROM_PTR(&mod_trezorio_FlashOTP_read_obj)}, + {MP_ROM_QSTR(MP_QSTR_write), MP_ROM_PTR(&mod_trezorio_FlashOTP_write_obj)}, + {MP_ROM_QSTR(MP_QSTR_lock), MP_ROM_PTR(&mod_trezorio_FlashOTP_lock_obj)}, + {MP_ROM_QSTR(MP_QSTR_is_locked), + MP_ROM_PTR(&mod_trezorio_FlashOTP_is_locked_obj)}, }; -STATIC MP_DEFINE_CONST_DICT(mod_trezorio_FlashOTP_locals_dict, mod_trezorio_FlashOTP_locals_dict_table); +STATIC MP_DEFINE_CONST_DICT(mod_trezorio_FlashOTP_locals_dict, + mod_trezorio_FlashOTP_locals_dict_table); STATIC const mp_obj_type_t mod_trezorio_FlashOTP_type = { - { &mp_type_type }, + {&mp_type_type}, .name = MP_QSTR_FlashOTP, .make_new = mod_trezorio_FlashOTP_make_new, - .locals_dict = (void*)&mod_trezorio_FlashOTP_locals_dict, + .locals_dict = (void *)&mod_trezorio_FlashOTP_locals_dict, }; diff --git a/embed/extmod/modtrezorio/modtrezorio-hid.h b/embed/extmod/modtrezorio/modtrezorio-hid.h index d1071278d..8fd8b8c81 100644 --- a/embed/extmod/modtrezorio/modtrezorio-hid.h +++ b/embed/extmod/modtrezorio/modtrezorio-hid.h @@ -22,8 +22,8 @@ /// USB HID interface configuration. /// ''' typedef struct _mp_obj_HID_t { - mp_obj_base_t base; - usb_hid_info_t info; + mp_obj_base_t base; + usb_hid_info_t info; } mp_obj_HID_t; /// def __init__(self, @@ -37,57 +37,68 @@ typedef struct _mp_obj_HID_t { /// max_packet_len: int = 64) -> None: /// ''' /// ''' -STATIC mp_obj_t mod_trezorio_HID_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_kw, const mp_obj_t *args) { +STATIC mp_obj_t mod_trezorio_HID_make_new(const mp_obj_type_t *type, + size_t n_args, size_t n_kw, + const mp_obj_t *args) { + STATIC const mp_arg_t allowed_args[] = { + {MP_QSTR_iface_num, + MP_ARG_REQUIRED | MP_ARG_KW_ONLY | MP_ARG_INT, + {.u_int = 0}}, + {MP_QSTR_ep_in, + MP_ARG_REQUIRED | MP_ARG_KW_ONLY | MP_ARG_INT, + {.u_int = 0}}, + {MP_QSTR_ep_out, + MP_ARG_REQUIRED | MP_ARG_KW_ONLY | MP_ARG_INT, + {.u_int = 0}}, + {MP_QSTR_subclass, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = 0}}, + {MP_QSTR_protocol, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = 0}}, + {MP_QSTR_polling_interval, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = 1}}, + {MP_QSTR_max_packet_len, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = 64}}, + {MP_QSTR_report_desc, + MP_ARG_REQUIRED | MP_ARG_KW_ONLY | MP_ARG_OBJ, + {.u_obj = MP_OBJ_NULL}}, + }; + mp_arg_val_t vals[MP_ARRAY_SIZE(allowed_args)]; + mp_arg_parse_all_kw_array(n_args, n_kw, args, MP_ARRAY_SIZE(allowed_args), + allowed_args, vals); - STATIC const mp_arg_t allowed_args[] = { - { MP_QSTR_iface_num, MP_ARG_REQUIRED | MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = 0} }, - { MP_QSTR_ep_in, MP_ARG_REQUIRED | MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = 0} }, - { MP_QSTR_ep_out, MP_ARG_REQUIRED | MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = 0} }, - { MP_QSTR_subclass, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = 0} }, - { MP_QSTR_protocol, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = 0} }, - { MP_QSTR_polling_interval, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = 1} }, - { MP_QSTR_max_packet_len, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = 64} }, - { MP_QSTR_report_desc, MP_ARG_REQUIRED | MP_ARG_KW_ONLY | MP_ARG_OBJ, {.u_obj = MP_OBJ_NULL} }, - }; - mp_arg_val_t vals[MP_ARRAY_SIZE(allowed_args)]; - mp_arg_parse_all_kw_array(n_args, n_kw, args, MP_ARRAY_SIZE(allowed_args), allowed_args, vals); + const mp_int_t iface_num = vals[0].u_int; + const mp_int_t ep_in = vals[1].u_int; + const mp_int_t ep_out = vals[2].u_int; + const mp_int_t subclass = vals[3].u_int; + const mp_int_t protocol = vals[4].u_int; + const mp_int_t polling_interval = vals[5].u_int; + const mp_int_t max_packet_len = vals[6].u_int; + mp_buffer_info_t report_desc; + mp_get_buffer_raise(vals[7].u_obj, &report_desc, MP_BUFFER_READ); - const mp_int_t iface_num = vals[0].u_int; - const mp_int_t ep_in = vals[1].u_int; - const mp_int_t ep_out = vals[2].u_int; - const mp_int_t subclass = vals[3].u_int; - const mp_int_t protocol = vals[4].u_int; - const mp_int_t polling_interval = vals[5].u_int; - const mp_int_t max_packet_len = vals[6].u_int; - mp_buffer_info_t report_desc; - mp_get_buffer_raise(vals[7].u_obj, &report_desc, MP_BUFFER_READ); + if (report_desc.buf == NULL || report_desc.len == 0 || + report_desc.len > 255) { + mp_raise_ValueError("report_desc is invalid"); + } + CHECK_PARAM_RANGE(iface_num, 0, 32) + CHECK_PARAM_RANGE(ep_in, 0, 255) + CHECK_PARAM_RANGE(ep_out, 0, 255) + CHECK_PARAM_RANGE(subclass, 0, 255) + CHECK_PARAM_RANGE(protocol, 0, 255) + CHECK_PARAM_RANGE(polling_interval, 1, 255) + CHECK_PARAM_RANGE(max_packet_len, 64, 64) - if (report_desc.buf == NULL || report_desc.len == 0 || report_desc.len > 255) { - mp_raise_ValueError("report_desc is invalid"); - } - CHECK_PARAM_RANGE(iface_num, 0, 32) - CHECK_PARAM_RANGE(ep_in, 0, 255) - CHECK_PARAM_RANGE(ep_out, 0, 255) - CHECK_PARAM_RANGE(subclass, 0, 255) - CHECK_PARAM_RANGE(protocol, 0, 255) - CHECK_PARAM_RANGE(polling_interval, 1, 255) - CHECK_PARAM_RANGE(max_packet_len, 64, 64) + mp_obj_HID_t *o = m_new_obj(mp_obj_HID_t); + o->base.type = type; - mp_obj_HID_t *o = m_new_obj(mp_obj_HID_t); - o->base.type = type; + o->info.rx_buffer = m_new(uint8_t, max_packet_len); + o->info.report_desc = report_desc.buf; + o->info.iface_num = (uint8_t)(iface_num); + o->info.ep_in = (uint8_t)(ep_in); + o->info.ep_out = (uint8_t)(ep_out); + o->info.subclass = (uint8_t)(subclass); + o->info.protocol = (uint8_t)(protocol); + o->info.polling_interval = (uint8_t)(polling_interval); + o->info.max_packet_len = (uint8_t)(max_packet_len); + o->info.report_desc_len = (uint8_t)(report_desc.len); - o->info.rx_buffer = m_new(uint8_t, max_packet_len); - o->info.report_desc = report_desc.buf; - o->info.iface_num = (uint8_t)(iface_num); - o->info.ep_in = (uint8_t)(ep_in); - o->info.ep_out = (uint8_t)(ep_out); - o->info.subclass = (uint8_t)(subclass); - o->info.protocol = (uint8_t)(protocol); - o->info.polling_interval = (uint8_t)(polling_interval); - o->info.max_packet_len = (uint8_t)(max_packet_len); - o->info.report_desc_len = (uint8_t)(report_desc.len); - - return MP_OBJ_FROM_PTR(o); + return MP_OBJ_FROM_PTR(o); } /// def iface_num(self) -> int: @@ -95,33 +106,37 @@ STATIC mp_obj_t mod_trezorio_HID_make_new(const mp_obj_type_t *type, size_t n_ar /// Returns the configured number of this interface. /// ''' STATIC mp_obj_t mod_trezorio_HID_iface_num(mp_obj_t self) { - mp_obj_HID_t *o = MP_OBJ_TO_PTR(self); - return MP_OBJ_NEW_SMALL_INT(o->info.iface_num); + mp_obj_HID_t *o = MP_OBJ_TO_PTR(self); + return MP_OBJ_NEW_SMALL_INT(o->info.iface_num); } -STATIC MP_DEFINE_CONST_FUN_OBJ_1(mod_trezorio_HID_iface_num_obj, mod_trezorio_HID_iface_num); +STATIC MP_DEFINE_CONST_FUN_OBJ_1(mod_trezorio_HID_iface_num_obj, + mod_trezorio_HID_iface_num); /// def write(self, msg: bytes) -> int: /// ''' /// Sends message using USB HID (device) or UDP (emulator). /// ''' STATIC mp_obj_t mod_trezorio_HID_write(mp_obj_t self, mp_obj_t msg) { - mp_obj_HID_t *o = MP_OBJ_TO_PTR(self); - mp_buffer_info_t buf; - mp_get_buffer_raise(msg, &buf, MP_BUFFER_READ); - ssize_t r = usb_hid_write(o->info.iface_num, buf.buf, buf.len); - return MP_OBJ_NEW_SMALL_INT(r); + mp_obj_HID_t *o = MP_OBJ_TO_PTR(self); + mp_buffer_info_t buf; + mp_get_buffer_raise(msg, &buf, MP_BUFFER_READ); + ssize_t r = usb_hid_write(o->info.iface_num, buf.buf, buf.len); + return MP_OBJ_NEW_SMALL_INT(r); } -STATIC MP_DEFINE_CONST_FUN_OBJ_2(mod_trezorio_HID_write_obj, mod_trezorio_HID_write); +STATIC MP_DEFINE_CONST_FUN_OBJ_2(mod_trezorio_HID_write_obj, + mod_trezorio_HID_write); STATIC const mp_rom_map_elem_t mod_trezorio_HID_locals_dict_table[] = { - { MP_ROM_QSTR(MP_QSTR_iface_num), MP_ROM_PTR(&mod_trezorio_HID_iface_num_obj) }, - { MP_ROM_QSTR(MP_QSTR_write), MP_ROM_PTR(&mod_trezorio_HID_write_obj) }, + {MP_ROM_QSTR(MP_QSTR_iface_num), + MP_ROM_PTR(&mod_trezorio_HID_iface_num_obj)}, + {MP_ROM_QSTR(MP_QSTR_write), MP_ROM_PTR(&mod_trezorio_HID_write_obj)}, }; -STATIC MP_DEFINE_CONST_DICT(mod_trezorio_HID_locals_dict, mod_trezorio_HID_locals_dict_table); +STATIC MP_DEFINE_CONST_DICT(mod_trezorio_HID_locals_dict, + mod_trezorio_HID_locals_dict_table); STATIC const mp_obj_type_t mod_trezorio_HID_type = { - { &mp_type_type }, + {&mp_type_type}, .name = MP_QSTR_HID, .make_new = mod_trezorio_HID_make_new, - .locals_dict = (void*)&mod_trezorio_HID_locals_dict, + .locals_dict = (void *)&mod_trezorio_HID_locals_dict, }; diff --git a/embed/extmod/modtrezorio/modtrezorio-poll.h b/embed/extmod/modtrezorio/modtrezorio-poll.h index 1b121f3bf..9f3f2b806 100644 --- a/embed/extmod/modtrezorio/modtrezorio-poll.h +++ b/embed/extmod/modtrezorio/modtrezorio-poll.h @@ -18,21 +18,13 @@ */ #include -#include #include "embed/extmod/trezorobj.h" -#include "usb.h" - #define TOUCH_IFACE (255) -#define POLL_READ (0x0000) +#define POLL_READ (0x0000) #define POLL_WRITE (0x0100) -#define CHECK_PARAM_RANGE(value, minimum, maximum) \ - if (value < minimum || value > maximum) { \ - mp_raise_ValueError(#value " is out of range"); \ - } - /// def poll(ifaces: Iterable[int], list_ref: List, timeout_us: int) -> bool: /// ''' /// Wait until one of `ifaces` is ready to read or write (using masks @@ -40,80 +32,82 @@ /// `list_ref`: /// /// `list_ref[0]` - the interface number, including the mask -/// `list_ref[1]` - for touch event, tuple of (event_type, x_position, y_position) +/// `list_ref[1]` - for touch event, tuple of (event_type, x_position, +/// y_position) /// - for USB read event, received bytes /// /// If timeout occurs, False is returned, True otherwise. /// ''' -STATIC mp_obj_t mod_trezorio_poll(mp_obj_t ifaces, mp_obj_t list_ref, mp_obj_t timeout_us) { - mp_obj_list_t *ret = MP_OBJ_TO_PTR(list_ref); - if (!MP_OBJ_IS_TYPE(list_ref, &mp_type_list) || ret->len < 2) { - mp_raise_TypeError("invalid list_ref"); - } +STATIC mp_obj_t mod_trezorio_poll(mp_obj_t ifaces, mp_obj_t list_ref, + mp_obj_t timeout_us) { + mp_obj_list_t *ret = MP_OBJ_TO_PTR(list_ref); + if (!MP_OBJ_IS_TYPE(list_ref, &mp_type_list) || ret->len < 2) { + mp_raise_TypeError("invalid list_ref"); + } - const mp_uint_t timeout = trezor_obj_get_uint(timeout_us); - const mp_uint_t deadline = mp_hal_ticks_us() + timeout; - mp_obj_iter_buf_t iterbuf; + const mp_uint_t timeout = trezor_obj_get_uint(timeout_us); + const mp_uint_t deadline = mp_hal_ticks_us() + timeout; + mp_obj_iter_buf_t iterbuf; - for (;;) { - mp_obj_t iter = mp_getiter(ifaces, &iterbuf); - mp_obj_t item; - while ((item = mp_iternext(iter)) != MP_OBJ_STOP_ITERATION) { - const mp_uint_t i = trezor_obj_get_uint(item); - const mp_uint_t iface = i & 0x00FF; - const mp_uint_t mode = i & 0xFF00; + for (;;) { + mp_obj_t iter = mp_getiter(ifaces, &iterbuf); + mp_obj_t item; + while ((item = mp_iternext(iter)) != MP_OBJ_STOP_ITERATION) { + const mp_uint_t i = trezor_obj_get_uint(item); + const mp_uint_t iface = i & 0x00FF; + const mp_uint_t mode = i & 0xFF00; - if (iface == TOUCH_IFACE) { - const uint32_t evt = touch_read(); - if (evt) { - mp_obj_tuple_t *tuple = MP_OBJ_TO_PTR(mp_obj_new_tuple(3, NULL)); - tuple->items[0] = MP_OBJ_NEW_SMALL_INT((evt >> 24) & 0xFFU); // event type - tuple->items[1] = MP_OBJ_NEW_SMALL_INT((evt >> 12) & 0xFFFU); // x position - tuple->items[2] = MP_OBJ_NEW_SMALL_INT(evt & 0xFFFU); // y position - ret->items[0] = MP_OBJ_NEW_SMALL_INT(i); - ret->items[1] = MP_OBJ_FROM_PTR(tuple); - return mp_const_true; - } - } else - if (mode == POLL_READ) { - if (sectrue == usb_hid_can_read(iface)) { - uint8_t buf[64]; - int len = usb_hid_read(iface, buf, sizeof(buf)); - if (len > 0) { - ret->items[0] = MP_OBJ_NEW_SMALL_INT(i); - ret->items[1] = mp_obj_new_bytes(buf, len); - return mp_const_true; - } - } else if (sectrue == usb_webusb_can_read(iface)) { - uint8_t buf[64]; - int len = usb_webusb_read(iface, buf, sizeof(buf)); - if (len > 0) { - ret->items[0] = MP_OBJ_NEW_SMALL_INT(i); - ret->items[1] = mp_obj_new_bytes(buf, len); - return mp_const_true; - } - } - } else - if (mode == POLL_WRITE) { - if (sectrue == usb_hid_can_write(iface)) { - ret->items[0] = MP_OBJ_NEW_SMALL_INT(i); - ret->items[1] = mp_const_none; - return mp_const_true; - } else if (sectrue == usb_webusb_can_write(iface)) { - ret->items[0] = MP_OBJ_NEW_SMALL_INT(i); - ret->items[1] = mp_const_none; - return mp_const_true; - } - } + if (iface == TOUCH_IFACE) { + const uint32_t evt = touch_read(); + if (evt) { + mp_obj_tuple_t *tuple = MP_OBJ_TO_PTR(mp_obj_new_tuple(3, NULL)); + tuple->items[0] = + MP_OBJ_NEW_SMALL_INT((evt >> 24) & 0xFFU); // event type + tuple->items[1] = + MP_OBJ_NEW_SMALL_INT((evt >> 12) & 0xFFFU); // x position + tuple->items[2] = MP_OBJ_NEW_SMALL_INT(evt & 0xFFFU); // y position + ret->items[0] = MP_OBJ_NEW_SMALL_INT(i); + ret->items[1] = MP_OBJ_FROM_PTR(tuple); + return mp_const_true; } - - if (mp_hal_ticks_us() >= deadline) { - break; - } else { - MICROPY_EVENT_POLL_HOOK + } else if (mode == POLL_READ) { + if (sectrue == usb_hid_can_read(iface)) { + uint8_t buf[64]; + int len = usb_hid_read(iface, buf, sizeof(buf)); + if (len > 0) { + ret->items[0] = MP_OBJ_NEW_SMALL_INT(i); + ret->items[1] = mp_obj_new_bytes(buf, len); + return mp_const_true; + } + } else if (sectrue == usb_webusb_can_read(iface)) { + uint8_t buf[64]; + int len = usb_webusb_read(iface, buf, sizeof(buf)); + if (len > 0) { + ret->items[0] = MP_OBJ_NEW_SMALL_INT(i); + ret->items[1] = mp_obj_new_bytes(buf, len); + return mp_const_true; + } + } + } else if (mode == POLL_WRITE) { + if (sectrue == usb_hid_can_write(iface)) { + ret->items[0] = MP_OBJ_NEW_SMALL_INT(i); + ret->items[1] = mp_const_none; + return mp_const_true; + } else if (sectrue == usb_webusb_can_write(iface)) { + ret->items[0] = MP_OBJ_NEW_SMALL_INT(i); + ret->items[1] = mp_const_none; + return mp_const_true; } + } + } + + if (mp_hal_ticks_us() >= deadline) { + break; + } else { + MICROPY_EVENT_POLL_HOOK } + } - return mp_const_false; + return mp_const_false; } STATIC MP_DEFINE_CONST_FUN_OBJ_3(mod_trezorio_poll_obj, mod_trezorio_poll); diff --git a/embed/extmod/modtrezorio/modtrezorio-sbu.h b/embed/extmod/modtrezorio/modtrezorio-sbu.h index 2ed95b8f2..c37e01eb4 100644 --- a/embed/extmod/modtrezorio/modtrezorio-sbu.h +++ b/embed/extmod/modtrezorio/modtrezorio-sbu.h @@ -23,38 +23,43 @@ /// ''' /// ''' typedef struct _mp_obj_SBU_t { - mp_obj_base_t base; + mp_obj_base_t base; } mp_obj_SBU_t; /// def __init__(self) -> None: /// ''' /// ''' -STATIC mp_obj_t mod_trezorio_SBU_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_kw, const mp_obj_t *args) { - mp_arg_check_num(n_args, n_kw, 0, 0, false); - mp_obj_SBU_t *o = m_new_obj(mp_obj_SBU_t); - o->base.type = type; - sbu_init(); - return MP_OBJ_FROM_PTR(o); +STATIC mp_obj_t mod_trezorio_SBU_make_new(const mp_obj_type_t *type, + size_t n_args, size_t n_kw, + const mp_obj_t *args) { + mp_arg_check_num(n_args, n_kw, 0, 0, false); + mp_obj_SBU_t *o = m_new_obj(mp_obj_SBU_t); + o->base.type = type; + sbu_init(); + return MP_OBJ_FROM_PTR(o); } /// def set(self, sbu1: bool, sbu2: bool) -> None: /// ''' /// Sets SBU wires to sbu1 and sbu2 values respectively /// ''' -STATIC mp_obj_t mod_trezorio_SBU_set(mp_obj_t self, mp_obj_t sbu1, mp_obj_t sbu2) { - sbu_set(sectrue * mp_obj_is_true(sbu1), sectrue * mp_obj_is_true(sbu2)); - return mp_const_none; +STATIC mp_obj_t mod_trezorio_SBU_set(mp_obj_t self, mp_obj_t sbu1, + mp_obj_t sbu2) { + sbu_set(sectrue * mp_obj_is_true(sbu1), sectrue * mp_obj_is_true(sbu2)); + return mp_const_none; } -STATIC MP_DEFINE_CONST_FUN_OBJ_3(mod_trezorio_SBU_set_obj, mod_trezorio_SBU_set); +STATIC MP_DEFINE_CONST_FUN_OBJ_3(mod_trezorio_SBU_set_obj, + mod_trezorio_SBU_set); STATIC const mp_rom_map_elem_t mod_trezorio_SBU_locals_dict_table[] = { - { MP_ROM_QSTR(MP_QSTR_set), MP_ROM_PTR(&mod_trezorio_SBU_set_obj) }, + {MP_ROM_QSTR(MP_QSTR_set), MP_ROM_PTR(&mod_trezorio_SBU_set_obj)}, }; -STATIC MP_DEFINE_CONST_DICT(mod_trezorio_SBU_locals_dict, mod_trezorio_SBU_locals_dict_table); +STATIC MP_DEFINE_CONST_DICT(mod_trezorio_SBU_locals_dict, + mod_trezorio_SBU_locals_dict_table); STATIC const mp_obj_type_t mod_trezorio_SBU_type = { - { &mp_type_type }, + {&mp_type_type}, .name = MP_QSTR_SBU, .make_new = mod_trezorio_SBU_make_new, - .locals_dict = (void*)&mod_trezorio_SBU_locals_dict, + .locals_dict = (void *)&mod_trezorio_SBU_locals_dict, }; diff --git a/embed/extmod/modtrezorio/modtrezorio-sdcard.h b/embed/extmod/modtrezorio/modtrezorio-sdcard.h index 3a2c1d4d3..f338d7ee7 100644 --- a/embed/extmod/modtrezorio/modtrezorio-sdcard.h +++ b/embed/extmod/modtrezorio/modtrezorio-sdcard.h @@ -25,20 +25,22 @@ /// ''' /// ''' typedef struct _mp_obj_SDCard_t { - mp_obj_base_t base; + mp_obj_base_t base; } mp_obj_SDCard_t; /// def __init__(self) -> None: /// ''' /// ''' -STATIC mp_obj_t mod_trezorio_SDCard_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_kw, const mp_obj_t *args) { - mp_arg_check_num(n_args, n_kw, 0, 0, false); - mp_obj_SDCard_t *o = m_new_obj(mp_obj_SDCard_t); - o->base.type = type; +STATIC mp_obj_t mod_trezorio_SDCard_make_new(const mp_obj_type_t *type, + size_t n_args, size_t n_kw, + const mp_obj_t *args) { + mp_arg_check_num(n_args, n_kw, 0, 0, false); + mp_obj_SDCard_t *o = m_new_obj(mp_obj_SDCard_t); + o->base.type = type; #ifdef TREZOR_EMULATOR - sdcard_init(); + sdcard_init(); #endif - return MP_OBJ_FROM_PTR(o); + return MP_OBJ_FROM_PTR(o); } /// def present(self) -> bool: @@ -46,9 +48,10 @@ STATIC mp_obj_t mod_trezorio_SDCard_make_new(const mp_obj_type_t *type, size_t n /// Returns True if SD card is detected, False otherwise. /// ''' STATIC mp_obj_t mod_trezorio_SDCard_present(mp_obj_t self) { - return mp_obj_new_bool(sdcard_is_present()); + return mp_obj_new_bool(sdcard_is_present()); } -STATIC MP_DEFINE_CONST_FUN_OBJ_1(mod_trezorio_SDCard_present_obj, mod_trezorio_SDCard_present); +STATIC MP_DEFINE_CONST_FUN_OBJ_1(mod_trezorio_SDCard_present_obj, + mod_trezorio_SDCard_present); /// def power(self, state: bool) -> bool: /// ''' @@ -56,65 +59,76 @@ STATIC MP_DEFINE_CONST_FUN_OBJ_1(mod_trezorio_SDCard_present_obj, mod_trezorio_S /// Returns True if in case of success, False otherwise. /// ''' STATIC mp_obj_t mod_trezorio_SDCard_power(mp_obj_t self, mp_obj_t state) { - if (mp_obj_is_true(state)) { - return mp_obj_new_bool(sdcard_power_on()); - } else { - sdcard_power_off(); - return mp_const_true; - } + if (mp_obj_is_true(state)) { + return mp_obj_new_bool(sdcard_power_on()); + } else { + sdcard_power_off(); + return mp_const_true; + } } -STATIC MP_DEFINE_CONST_FUN_OBJ_2(mod_trezorio_SDCard_power_obj, mod_trezorio_SDCard_power); +STATIC MP_DEFINE_CONST_FUN_OBJ_2(mod_trezorio_SDCard_power_obj, + mod_trezorio_SDCard_power); /// def capacity(self) -> int: /// ''' /// Returns capacity of the SD card in bytes, or zero if not present. /// ''' STATIC mp_obj_t mod_trezorio_SDCard_capacity(mp_obj_t self) { - return mp_obj_new_int_from_ull(sdcard_get_capacity_in_bytes()); + return mp_obj_new_int_from_ull(sdcard_get_capacity_in_bytes()); } -STATIC MP_DEFINE_CONST_FUN_OBJ_1(mod_trezorio_SDCard_capacity_obj, mod_trezorio_SDCard_capacity); +STATIC MP_DEFINE_CONST_FUN_OBJ_1(mod_trezorio_SDCard_capacity_obj, + mod_trezorio_SDCard_capacity); /// def read(self, block_num: int, buf: bytearray) -> bool: /// ''' /// Reads blocks starting with block_num from the SD card into buf. -/// Number of bytes read is length of buf rounded down to multiply of SDCARD_BLOCK_SIZE. -/// Returns True if in case of success, False otherwise. +/// Number of bytes read is length of buf rounded down to multiply of +/// SDCARD_BLOCK_SIZE. Returns True if in case of success, False otherwise. /// ''' -STATIC mp_obj_t mod_trezorio_SDCard_read(mp_obj_t self, mp_obj_t block_num, mp_obj_t buf) { - uint32_t block = trezor_obj_get_uint(block_num); - mp_buffer_info_t bufinfo; - mp_get_buffer_raise(buf, &bufinfo, MP_BUFFER_WRITE); - return mp_obj_new_bool(sdcard_read_blocks(bufinfo.buf, block, bufinfo.len / SDCARD_BLOCK_SIZE)); +STATIC mp_obj_t mod_trezorio_SDCard_read(mp_obj_t self, mp_obj_t block_num, + mp_obj_t buf) { + uint32_t block = trezor_obj_get_uint(block_num); + mp_buffer_info_t bufinfo; + mp_get_buffer_raise(buf, &bufinfo, MP_BUFFER_WRITE); + return mp_obj_new_bool( + sdcard_read_blocks(bufinfo.buf, block, bufinfo.len / SDCARD_BLOCK_SIZE)); } -STATIC MP_DEFINE_CONST_FUN_OBJ_3(mod_trezorio_SDCard_read_obj, mod_trezorio_SDCard_read); +STATIC MP_DEFINE_CONST_FUN_OBJ_3(mod_trezorio_SDCard_read_obj, + mod_trezorio_SDCard_read); /// def write(self, block_num: int, buf: bytes) -> bool: /// ''' /// Writes blocks starting with block_num from buf to the SD card. -/// Number of bytes written is length of buf rounded down to multiply of SDCARD_BLOCK_SIZE. -/// Returns True if in case of success, False otherwise. +/// Number of bytes written is length of buf rounded down to multiply of +/// SDCARD_BLOCK_SIZE. Returns True if in case of success, False otherwise. /// ''' -STATIC mp_obj_t mod_trezorio_SDCard_write(mp_obj_t self, mp_obj_t block_num, mp_obj_t buf) { - uint32_t block = trezor_obj_get_uint(block_num); - mp_buffer_info_t bufinfo; - mp_get_buffer_raise(buf, &bufinfo, MP_BUFFER_READ); - return mp_obj_new_bool(sdcard_write_blocks(bufinfo.buf, block, bufinfo.len / SDCARD_BLOCK_SIZE)); +STATIC mp_obj_t mod_trezorio_SDCard_write(mp_obj_t self, mp_obj_t block_num, + mp_obj_t buf) { + uint32_t block = trezor_obj_get_uint(block_num); + mp_buffer_info_t bufinfo; + mp_get_buffer_raise(buf, &bufinfo, MP_BUFFER_READ); + return mp_obj_new_bool( + sdcard_write_blocks(bufinfo.buf, block, bufinfo.len / SDCARD_BLOCK_SIZE)); } -STATIC MP_DEFINE_CONST_FUN_OBJ_3(mod_trezorio_SDCard_write_obj, mod_trezorio_SDCard_write); +STATIC MP_DEFINE_CONST_FUN_OBJ_3(mod_trezorio_SDCard_write_obj, + mod_trezorio_SDCard_write); STATIC const mp_rom_map_elem_t mod_trezorio_SDCard_locals_dict_table[] = { - { MP_ROM_QSTR(MP_QSTR_present), MP_ROM_PTR(&mod_trezorio_SDCard_present_obj) }, - { MP_ROM_QSTR(MP_QSTR_power), MP_ROM_PTR(&mod_trezorio_SDCard_power_obj) }, - { MP_ROM_QSTR(MP_QSTR_capacity), MP_ROM_PTR(&mod_trezorio_SDCard_capacity_obj) }, - { MP_ROM_QSTR(MP_QSTR_block_size), MP_OBJ_NEW_SMALL_INT(SDCARD_BLOCK_SIZE) }, - { MP_ROM_QSTR(MP_QSTR_read), MP_ROM_PTR(&mod_trezorio_SDCard_read_obj) }, - { MP_ROM_QSTR(MP_QSTR_write), MP_ROM_PTR(&mod_trezorio_SDCard_write_obj) }, + {MP_ROM_QSTR(MP_QSTR_present), + MP_ROM_PTR(&mod_trezorio_SDCard_present_obj)}, + {MP_ROM_QSTR(MP_QSTR_power), MP_ROM_PTR(&mod_trezorio_SDCard_power_obj)}, + {MP_ROM_QSTR(MP_QSTR_capacity), + MP_ROM_PTR(&mod_trezorio_SDCard_capacity_obj)}, + {MP_ROM_QSTR(MP_QSTR_block_size), MP_OBJ_NEW_SMALL_INT(SDCARD_BLOCK_SIZE)}, + {MP_ROM_QSTR(MP_QSTR_read), MP_ROM_PTR(&mod_trezorio_SDCard_read_obj)}, + {MP_ROM_QSTR(MP_QSTR_write), MP_ROM_PTR(&mod_trezorio_SDCard_write_obj)}, }; -STATIC MP_DEFINE_CONST_DICT(mod_trezorio_SDCard_locals_dict, mod_trezorio_SDCard_locals_dict_table); +STATIC MP_DEFINE_CONST_DICT(mod_trezorio_SDCard_locals_dict, + mod_trezorio_SDCard_locals_dict_table); STATIC const mp_obj_type_t mod_trezorio_SDCard_type = { - { &mp_type_type }, + {&mp_type_type}, .name = MP_QSTR_SDCard, .make_new = mod_trezorio_SDCard_make_new, - .locals_dict = (void*)&mod_trezorio_SDCard_locals_dict, + .locals_dict = (void *)&mod_trezorio_SDCard_locals_dict, }; diff --git a/embed/extmod/modtrezorio/modtrezorio-usb.h b/embed/extmod/modtrezorio/modtrezorio-usb.h index e6045bab4..edfa8bd8e 100644 --- a/embed/extmod/modtrezorio/modtrezorio-usb.h +++ b/embed/extmod/modtrezorio/modtrezorio-usb.h @@ -20,8 +20,8 @@ void mp_hal_set_vcp_iface(int iface_num); enum { - USB_CLOSED = 0, - USB_OPENED = 1, + USB_CLOSED = 0, + USB_OPENED = 1, }; /// class USB: @@ -29,24 +29,24 @@ enum { /// USB device configuration. /// ''' typedef struct _mp_obj_USB_t { - mp_obj_base_t base; - mp_obj_list_t ifaces; - usb_dev_info_t info; - mp_int_t state; + mp_obj_base_t base; + mp_obj_list_t ifaces; + usb_dev_info_t info; + mp_int_t state; } mp_obj_USB_t; static const char *get_0str(mp_obj_t o, size_t min_len, size_t max_len) { - size_t len; - const char *s = mp_obj_str_get_data(o, &len); - if ((len >= min_len) && (len <= max_len)) { - if (len == 0 && s == NULL) { - return ""; - } else { - return s; - } + size_t len; + const char *s = mp_obj_str_get_data(o, &len); + if ((len >= min_len) && (len <= max_len)) { + if (len == 0 && s == NULL) { + return ""; } else { - return NULL; + return s; } + } else { + return NULL; + } } /// def __init__(self, @@ -64,78 +64,94 @@ static const char *get_0str(mp_obj_t o, size_t min_len, size_t max_len) { /// usb21_landing: bool=True) -> None: /// ''' /// ''' -STATIC mp_obj_t mod_trezorio_USB_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_kw, const mp_obj_t *args) { - - STATIC const mp_arg_t allowed_args[] = { - { MP_QSTR_device_class, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = 0} }, - { MP_QSTR_device_subclass, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = 0} }, - { MP_QSTR_device_protocol, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = 0} }, - { MP_QSTR_vendor_id, MP_ARG_REQUIRED | MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = 0} }, - { MP_QSTR_product_id, MP_ARG_REQUIRED | MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = 0} }, - { MP_QSTR_release_num, MP_ARG_REQUIRED | MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = 0} }, - { MP_QSTR_manufacturer, MP_ARG_KW_ONLY | MP_ARG_OBJ, {.u_obj = mp_const_empty_bytes} }, - { MP_QSTR_product, MP_ARG_KW_ONLY | MP_ARG_OBJ, {.u_obj = mp_const_empty_bytes} }, - { MP_QSTR_serial_number, MP_ARG_KW_ONLY | MP_ARG_OBJ, {.u_obj = mp_const_empty_bytes} }, - { MP_QSTR_interface, MP_ARG_KW_ONLY | MP_ARG_OBJ, {.u_obj = mp_const_empty_bytes} }, - { MP_QSTR_usb21_enabled, MP_ARG_KW_ONLY | MP_ARG_BOOL, {.u_bool = true} }, - { MP_QSTR_usb21_landing, MP_ARG_KW_ONLY | MP_ARG_BOOL, {.u_bool = true} }, - }; - mp_arg_val_t vals[MP_ARRAY_SIZE(allowed_args)]; - mp_arg_parse_all_kw_array(n_args, n_kw, args, MP_ARRAY_SIZE(allowed_args), allowed_args, vals); - - const mp_int_t device_class = vals[0].u_int; - const mp_int_t device_subclass = vals[1].u_int; - const mp_int_t device_protocol = vals[2].u_int; - const mp_int_t vendor_id = vals[3].u_int; - const mp_int_t product_id = vals[4].u_int; - const mp_int_t release_num = vals[5].u_int; - const char *manufacturer = get_0str(vals[6].u_obj, 0, 32); - const char *product = get_0str(vals[7].u_obj, 0, 32); - const char *serial_number = get_0str(vals[8].u_obj, 0, 32); - const char *interface = get_0str(vals[9].u_obj, 0, 32); - const secbool usb21_enabled = vals[10].u_bool ? sectrue : secfalse; - const secbool usb21_landing = vals[11].u_bool ? sectrue : secfalse; - - CHECK_PARAM_RANGE(device_class, 0, 255) - CHECK_PARAM_RANGE(device_subclass, 0, 255) - CHECK_PARAM_RANGE(device_protocol, 0, 255) - CHECK_PARAM_RANGE(vendor_id, 0, 65535) - CHECK_PARAM_RANGE(product_id, 0, 65535) - CHECK_PARAM_RANGE(release_num, 0, 65535) - if (manufacturer == NULL) { - mp_raise_ValueError("manufacturer is invalid"); - } - if (product == NULL) { - mp_raise_ValueError("product is invalid"); - } - if (serial_number == NULL) { - mp_raise_ValueError("serial_number is invalid"); - } - if (interface == NULL) { - mp_raise_ValueError("interface is invalid"); - } - - mp_obj_USB_t *o = m_new_obj(mp_obj_USB_t); - o->base.type = type; - - o->state = USB_CLOSED; - - o->info.device_class = (uint8_t)(device_class); - o->info.device_subclass = (uint8_t)(device_subclass); - o->info.device_protocol = (uint8_t)(device_protocol); - o->info.vendor_id = (uint16_t)(vendor_id); - o->info.product_id = (uint16_t)(product_id); - o->info.release_num = (uint16_t)(release_num); - o->info.manufacturer = manufacturer; - o->info.product = product; - o->info.serial_number = serial_number; - o->info.interface = interface; - o->info.usb21_enabled = usb21_enabled; - o->info.usb21_landing = usb21_landing; - - mp_obj_list_init(&o->ifaces, 0); - - return MP_OBJ_FROM_PTR(o); +STATIC mp_obj_t mod_trezorio_USB_make_new(const mp_obj_type_t *type, + size_t n_args, size_t n_kw, + const mp_obj_t *args) { + STATIC const mp_arg_t allowed_args[] = { + {MP_QSTR_device_class, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = 0}}, + {MP_QSTR_device_subclass, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = 0}}, + {MP_QSTR_device_protocol, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = 0}}, + {MP_QSTR_vendor_id, + MP_ARG_REQUIRED | MP_ARG_KW_ONLY | MP_ARG_INT, + {.u_int = 0}}, + {MP_QSTR_product_id, + MP_ARG_REQUIRED | MP_ARG_KW_ONLY | MP_ARG_INT, + {.u_int = 0}}, + {MP_QSTR_release_num, + MP_ARG_REQUIRED | MP_ARG_KW_ONLY | MP_ARG_INT, + {.u_int = 0}}, + {MP_QSTR_manufacturer, + MP_ARG_KW_ONLY | MP_ARG_OBJ, + {.u_obj = mp_const_empty_bytes}}, + {MP_QSTR_product, + MP_ARG_KW_ONLY | MP_ARG_OBJ, + {.u_obj = mp_const_empty_bytes}}, + {MP_QSTR_serial_number, + MP_ARG_KW_ONLY | MP_ARG_OBJ, + {.u_obj = mp_const_empty_bytes}}, + {MP_QSTR_interface, + MP_ARG_KW_ONLY | MP_ARG_OBJ, + {.u_obj = mp_const_empty_bytes}}, + {MP_QSTR_usb21_enabled, MP_ARG_KW_ONLY | MP_ARG_BOOL, {.u_bool = true}}, + {MP_QSTR_usb21_landing, MP_ARG_KW_ONLY | MP_ARG_BOOL, {.u_bool = true}}, + }; + mp_arg_val_t vals[MP_ARRAY_SIZE(allowed_args)]; + mp_arg_parse_all_kw_array(n_args, n_kw, args, MP_ARRAY_SIZE(allowed_args), + allowed_args, vals); + + const mp_int_t device_class = vals[0].u_int; + const mp_int_t device_subclass = vals[1].u_int; + const mp_int_t device_protocol = vals[2].u_int; + const mp_int_t vendor_id = vals[3].u_int; + const mp_int_t product_id = vals[4].u_int; + const mp_int_t release_num = vals[5].u_int; + const char *manufacturer = get_0str(vals[6].u_obj, 0, 32); + const char *product = get_0str(vals[7].u_obj, 0, 32); + const char *serial_number = get_0str(vals[8].u_obj, 0, 32); + const char *interface = get_0str(vals[9].u_obj, 0, 32); + const secbool usb21_enabled = vals[10].u_bool ? sectrue : secfalse; + const secbool usb21_landing = vals[11].u_bool ? sectrue : secfalse; + + CHECK_PARAM_RANGE(device_class, 0, 255) + CHECK_PARAM_RANGE(device_subclass, 0, 255) + CHECK_PARAM_RANGE(device_protocol, 0, 255) + CHECK_PARAM_RANGE(vendor_id, 0, 65535) + CHECK_PARAM_RANGE(product_id, 0, 65535) + CHECK_PARAM_RANGE(release_num, 0, 65535) + if (manufacturer == NULL) { + mp_raise_ValueError("manufacturer is invalid"); + } + if (product == NULL) { + mp_raise_ValueError("product is invalid"); + } + if (serial_number == NULL) { + mp_raise_ValueError("serial_number is invalid"); + } + if (interface == NULL) { + mp_raise_ValueError("interface is invalid"); + } + + mp_obj_USB_t *o = m_new_obj(mp_obj_USB_t); + o->base.type = type; + + o->state = USB_CLOSED; + + o->info.device_class = (uint8_t)(device_class); + o->info.device_subclass = (uint8_t)(device_subclass); + o->info.device_protocol = (uint8_t)(device_protocol); + o->info.vendor_id = (uint16_t)(vendor_id); + o->info.product_id = (uint16_t)(product_id); + o->info.release_num = (uint16_t)(release_num); + o->info.manufacturer = manufacturer; + o->info.product = product; + o->info.serial_number = serial_number; + o->info.interface = interface; + o->info.usb21_enabled = usb21_enabled; + o->info.usb21_landing = usb21_landing; + + mp_obj_list_init(&o->ifaces, 0); + + return MP_OBJ_FROM_PTR(o); } /// def add(self, iface: Union[HID, VCP, WebUSB]) -> None: @@ -143,126 +159,131 @@ STATIC mp_obj_t mod_trezorio_USB_make_new(const mp_obj_type_t *type, size_t n_ar /// Registers passed interface into the USB stack. /// ''' STATIC mp_obj_t mod_trezorio_USB_add(mp_obj_t self, mp_obj_t iface) { - mp_obj_USB_t *o = MP_OBJ_TO_PTR(self); + mp_obj_USB_t *o = MP_OBJ_TO_PTR(self); - if (o->state != USB_CLOSED) { - mp_raise_msg(&mp_type_RuntimeError, "already initialized"); - } - mp_obj_list_append(MP_OBJ_FROM_PTR(&o->ifaces), iface); + if (o->state != USB_CLOSED) { + mp_raise_msg(&mp_type_RuntimeError, "already initialized"); + } + mp_obj_list_append(MP_OBJ_FROM_PTR(&o->ifaces), iface); - return mp_const_none; + return mp_const_none; } -STATIC MP_DEFINE_CONST_FUN_OBJ_2(mod_trezorio_USB_add_obj, mod_trezorio_USB_add); +STATIC MP_DEFINE_CONST_FUN_OBJ_2(mod_trezorio_USB_add_obj, + mod_trezorio_USB_add); /// def open(self) -> None: /// ''' /// Initializes the USB stack. /// ''' STATIC mp_obj_t mod_trezorio_USB_open(mp_obj_t self) { - mp_obj_USB_t *o = MP_OBJ_TO_PTR(self); + mp_obj_USB_t *o = MP_OBJ_TO_PTR(self); - if (o->state != USB_CLOSED) { - mp_raise_msg(&mp_type_RuntimeError, "already initialized"); - } + if (o->state != USB_CLOSED) { + mp_raise_msg(&mp_type_RuntimeError, "already initialized"); + } - size_t iface_cnt; - mp_obj_t *iface_objs; - mp_obj_get_array(MP_OBJ_FROM_PTR(&o->ifaces), &iface_cnt, &iface_objs); + size_t iface_cnt; + mp_obj_t *iface_objs; + mp_obj_get_array(MP_OBJ_FROM_PTR(&o->ifaces), &iface_cnt, &iface_objs); - // Initialize the USB stack - usb_init(&o->info); + // Initialize the USB stack + usb_init(&o->info); - int vcp_iface_num = -1; + int vcp_iface_num = -1; - // Add all interfaces - for (size_t i = 0; i < iface_cnt; i++) { - mp_obj_t iface = iface_objs[i]; + // Add all interfaces + for (size_t i = 0; i < iface_cnt; i++) { + mp_obj_t iface = iface_objs[i]; - if (MP_OBJ_IS_TYPE(iface, &mod_trezorio_HID_type)) { - mp_obj_HID_t *hid = MP_OBJ_TO_PTR(iface); - if (sectrue != usb_hid_add(&hid->info)) { - usb_deinit(); - mp_raise_msg(&mp_type_RuntimeError, "failed to add HID interface"); - } - } else if (MP_OBJ_IS_TYPE(iface, &mod_trezorio_WebUSB_type)) { - mp_obj_WebUSB_t *webusb = MP_OBJ_TO_PTR(iface); - if (sectrue != usb_webusb_add(&webusb->info)) { - usb_deinit(); - mp_raise_msg(&mp_type_RuntimeError, "failed to add WebUSB interface"); - } - } else if (MP_OBJ_IS_TYPE(iface, &mod_trezorio_VCP_type)) { - mp_obj_VCP_t *vcp = MP_OBJ_TO_PTR(iface); - if (sectrue != usb_vcp_add(&vcp->info)) { - usb_deinit(); - mp_raise_msg(&mp_type_RuntimeError, "failed to add VCP interface"); - } - vcp_iface_num = vcp->info.iface_num; - } else { - usb_deinit(); - mp_raise_TypeError("expected HID, WebUSB or VCP type"); - } + if (MP_OBJ_IS_TYPE(iface, &mod_trezorio_HID_type)) { + mp_obj_HID_t *hid = MP_OBJ_TO_PTR(iface); + if (sectrue != usb_hid_add(&hid->info)) { + usb_deinit(); + mp_raise_msg(&mp_type_RuntimeError, "failed to add HID interface"); + } + } else if (MP_OBJ_IS_TYPE(iface, &mod_trezorio_WebUSB_type)) { + mp_obj_WebUSB_t *webusb = MP_OBJ_TO_PTR(iface); + if (sectrue != usb_webusb_add(&webusb->info)) { + usb_deinit(); + mp_raise_msg(&mp_type_RuntimeError, "failed to add WebUSB interface"); + } + } else if (MP_OBJ_IS_TYPE(iface, &mod_trezorio_VCP_type)) { + mp_obj_VCP_t *vcp = MP_OBJ_TO_PTR(iface); + if (sectrue != usb_vcp_add(&vcp->info)) { + usb_deinit(); + mp_raise_msg(&mp_type_RuntimeError, "failed to add VCP interface"); + } + vcp_iface_num = vcp->info.iface_num; + } else { + usb_deinit(); + mp_raise_TypeError("expected HID, WebUSB or VCP type"); } + } - // Start the USB stack - usb_start(); - o->state = USB_OPENED; + // Start the USB stack + usb_start(); + o->state = USB_OPENED; - // If we found any VCP interfaces, use the last one for stdio, - // otherwise disable the stdio support - mp_hal_set_vcp_iface(vcp_iface_num); + // If we found any VCP interfaces, use the last one for stdio, + // otherwise disable the stdio support + mp_hal_set_vcp_iface(vcp_iface_num); - return mp_const_none; + return mp_const_none; } -STATIC MP_DEFINE_CONST_FUN_OBJ_1(mod_trezorio_USB_open_obj, mod_trezorio_USB_open); +STATIC MP_DEFINE_CONST_FUN_OBJ_1(mod_trezorio_USB_open_obj, + mod_trezorio_USB_open); /// def close(self) -> None: /// ''' /// Cleans up the USB stack. /// ''' STATIC mp_obj_t mod_trezorio_USB_close(mp_obj_t self) { - mp_obj_USB_t *o = MP_OBJ_TO_PTR(self); + mp_obj_USB_t *o = MP_OBJ_TO_PTR(self); + + if (o->state != USB_OPENED) { + mp_raise_msg(&mp_type_RuntimeError, "not initialized"); + } + usb_stop(); + usb_deinit(); + mp_obj_list_set_len(MP_OBJ_FROM_PTR(&o->ifaces), 0); + mp_seq_clear(o->ifaces.items, 0, o->ifaces.alloc, sizeof(*o->ifaces.items)); + o->info.vendor_id = 0; + o->info.product_id = 0; + o->info.release_num = 0; + o->info.manufacturer = NULL; + o->info.product = NULL; + o->info.serial_number = NULL; + o->state = USB_CLOSED; + + return mp_const_none; +} +STATIC MP_DEFINE_CONST_FUN_OBJ_1(mod_trezorio_USB_close_obj, + mod_trezorio_USB_close); - if (o->state != USB_OPENED) { - mp_raise_msg(&mp_type_RuntimeError, "not initialized"); - } +STATIC mp_obj_t mod_trezorio_USB___del__(mp_obj_t self) { + mp_obj_USB_t *o = MP_OBJ_TO_PTR(self); + if (o->state != USB_CLOSED) { usb_stop(); usb_deinit(); - mp_obj_list_set_len(MP_OBJ_FROM_PTR(&o->ifaces), 0); - mp_seq_clear(o->ifaces.items, 0, o->ifaces.alloc, sizeof(*o->ifaces.items)); - o->info.vendor_id = 0; - o->info.product_id = 0; - o->info.release_num = 0; - o->info.manufacturer = NULL; - o->info.product = NULL; - o->info.serial_number = NULL; o->state = USB_CLOSED; - - return mp_const_none; -} -STATIC MP_DEFINE_CONST_FUN_OBJ_1(mod_trezorio_USB_close_obj, mod_trezorio_USB_close); - -STATIC mp_obj_t mod_trezorio_USB___del__(mp_obj_t self) { - mp_obj_USB_t *o = MP_OBJ_TO_PTR(self); - if (o->state != USB_CLOSED) { - usb_stop(); - usb_deinit(); - o->state = USB_CLOSED; - } - return mp_const_none; + } + return mp_const_none; } -STATIC MP_DEFINE_CONST_FUN_OBJ_1(mod_trezorio_USB___del___obj, mod_trezorio_USB___del__); +STATIC MP_DEFINE_CONST_FUN_OBJ_1(mod_trezorio_USB___del___obj, + mod_trezorio_USB___del__); STATIC const mp_rom_map_elem_t mod_trezorio_USB_locals_dict_table[] = { - { MP_ROM_QSTR(MP_QSTR_add), MP_ROM_PTR(&mod_trezorio_USB_add_obj) }, - { MP_ROM_QSTR(MP_QSTR_open), MP_ROM_PTR(&mod_trezorio_USB_open_obj) }, - { MP_ROM_QSTR(MP_QSTR_close), MP_ROM_PTR(&mod_trezorio_USB_close_obj) }, - { MP_ROM_QSTR(MP_QSTR___del__), MP_ROM_PTR(&mod_trezorio_USB___del___obj) }, + {MP_ROM_QSTR(MP_QSTR_add), MP_ROM_PTR(&mod_trezorio_USB_add_obj)}, + {MP_ROM_QSTR(MP_QSTR_open), MP_ROM_PTR(&mod_trezorio_USB_open_obj)}, + {MP_ROM_QSTR(MP_QSTR_close), MP_ROM_PTR(&mod_trezorio_USB_close_obj)}, + {MP_ROM_QSTR(MP_QSTR___del__), MP_ROM_PTR(&mod_trezorio_USB___del___obj)}, }; -STATIC MP_DEFINE_CONST_DICT(mod_trezorio_USB_locals_dict, mod_trezorio_USB_locals_dict_table); +STATIC MP_DEFINE_CONST_DICT(mod_trezorio_USB_locals_dict, + mod_trezorio_USB_locals_dict_table); STATIC const mp_obj_type_t mod_trezorio_USB_type = { - { &mp_type_type }, + {&mp_type_type}, .name = MP_QSTR_USB, .make_new = mod_trezorio_USB_make_new, - .locals_dict = (void*)&mod_trezorio_USB_locals_dict, + .locals_dict = (void *)&mod_trezorio_USB_locals_dict, }; diff --git a/embed/extmod/modtrezorio/modtrezorio-vcp.h b/embed/extmod/modtrezorio/modtrezorio-vcp.h index f9dd5bb6f..7a87a28de 100644 --- a/embed/extmod/modtrezorio/modtrezorio-vcp.h +++ b/embed/extmod/modtrezorio/modtrezorio-vcp.h @@ -24,8 +24,8 @@ void pendsv_kbd_intr(void); /// USB VCP interface configuration. /// ''' typedef struct _mp_obj_VCP_t { - mp_obj_base_t base; - usb_vcp_info_t info; + mp_obj_base_t base; + usb_vcp_info_t info; } mp_obj_VCP_t; /// def __init__(self, @@ -36,53 +36,65 @@ typedef struct _mp_obj_VCP_t { /// ep_cmd: int) -> None: /// ''' /// ''' -STATIC mp_obj_t mod_trezorio_VCP_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_kw, const mp_obj_t *args) { +STATIC mp_obj_t mod_trezorio_VCP_make_new(const mp_obj_type_t *type, + size_t n_args, size_t n_kw, + const mp_obj_t *args) { + STATIC const mp_arg_t allowed_args[] = { + {MP_QSTR_iface_num, + MP_ARG_REQUIRED | MP_ARG_KW_ONLY | MP_ARG_INT, + {.u_int = 0}}, + {MP_QSTR_data_iface_num, + MP_ARG_REQUIRED | MP_ARG_KW_ONLY | MP_ARG_INT, + {.u_int = 0}}, + {MP_QSTR_ep_in, + MP_ARG_REQUIRED | MP_ARG_KW_ONLY | MP_ARG_INT, + {.u_int = 0}}, + {MP_QSTR_ep_out, + MP_ARG_REQUIRED | MP_ARG_KW_ONLY | MP_ARG_INT, + {.u_int = 0}}, + {MP_QSTR_ep_cmd, + MP_ARG_REQUIRED | MP_ARG_KW_ONLY | MP_ARG_INT, + {.u_int = 0}}, + }; + mp_arg_val_t vals[MP_ARRAY_SIZE(allowed_args)]; + mp_arg_parse_all_kw_array(n_args, n_kw, args, MP_ARRAY_SIZE(allowed_args), + allowed_args, vals); - STATIC const mp_arg_t allowed_args[] = { - { MP_QSTR_iface_num, MP_ARG_REQUIRED | MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = 0} }, - { MP_QSTR_data_iface_num, MP_ARG_REQUIRED | MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = 0} }, - { MP_QSTR_ep_in, MP_ARG_REQUIRED | MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = 0} }, - { MP_QSTR_ep_out, MP_ARG_REQUIRED | MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = 0} }, - { MP_QSTR_ep_cmd, MP_ARG_REQUIRED | MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = 0} }, - }; - mp_arg_val_t vals[MP_ARRAY_SIZE(allowed_args)]; - mp_arg_parse_all_kw_array(n_args, n_kw, args, MP_ARRAY_SIZE(allowed_args), allowed_args, vals); + const mp_int_t iface_num = vals[0].u_int; + const mp_int_t data_iface_num = vals[1].u_int; + const mp_int_t ep_in = vals[2].u_int; + const mp_int_t ep_out = vals[3].u_int; + const mp_int_t ep_cmd = vals[4].u_int; - const mp_int_t iface_num = vals[0].u_int; - const mp_int_t data_iface_num = vals[1].u_int; - const mp_int_t ep_in = vals[2].u_int; - const mp_int_t ep_out = vals[3].u_int; - const mp_int_t ep_cmd = vals[4].u_int; + CHECK_PARAM_RANGE(iface_num, 0, 32) + CHECK_PARAM_RANGE(data_iface_num, 0, 32) + CHECK_PARAM_RANGE(ep_in, 0, 255) + CHECK_PARAM_RANGE(ep_out, 0, 255) + CHECK_PARAM_RANGE(ep_cmd, 0, 255) - CHECK_PARAM_RANGE(iface_num, 0, 32) - CHECK_PARAM_RANGE(data_iface_num, 0, 32) - CHECK_PARAM_RANGE(ep_in, 0, 255) - CHECK_PARAM_RANGE(ep_out, 0, 255) - CHECK_PARAM_RANGE(ep_cmd, 0, 255) + const size_t vcp_buffer_len = 1024; + const size_t vcp_packet_len = 64; - const size_t vcp_buffer_len = 1024; - const size_t vcp_packet_len = 64; + mp_obj_VCP_t *o = m_new_obj(mp_obj_VCP_t); + o->base.type = type; - mp_obj_VCP_t *o = m_new_obj(mp_obj_VCP_t); - o->base.type = type; + o->info.tx_packet = m_new(uint8_t, vcp_packet_len); + o->info.tx_buffer = m_new(uint8_t, vcp_buffer_len); + o->info.rx_packet = m_new(uint8_t, vcp_packet_len); + o->info.rx_buffer = m_new(uint8_t, vcp_buffer_len); + o->info.tx_buffer_len = vcp_buffer_len; + o->info.rx_buffer_len = vcp_buffer_len; + o->info.rx_intr_fn = pendsv_kbd_intr; + o->info.rx_intr_byte = 3; // Ctrl-C + o->info.iface_num = (uint8_t)(iface_num); + o->info.data_iface_num = (uint8_t)(data_iface_num); + o->info.ep_cmd = (uint8_t)(ep_cmd); + o->info.ep_in = (uint8_t)(ep_in); + o->info.ep_out = (uint8_t)(ep_out); + o->info.polling_interval = 10; + o->info.max_packet_len = (uint8_t)(vcp_packet_len); - o->info.tx_packet = m_new(uint8_t, vcp_packet_len); - o->info.tx_buffer = m_new(uint8_t, vcp_buffer_len); - o->info.rx_packet = m_new(uint8_t, vcp_packet_len); - o->info.rx_buffer = m_new(uint8_t, vcp_buffer_len); - o->info.tx_buffer_len = vcp_buffer_len; - o->info.rx_buffer_len = vcp_buffer_len; - o->info.rx_intr_fn = pendsv_kbd_intr; - o->info.rx_intr_byte = 3; // Ctrl-C - o->info.iface_num = (uint8_t)(iface_num); - o->info.data_iface_num = (uint8_t)(data_iface_num); - o->info.ep_cmd = (uint8_t)(ep_cmd); - o->info.ep_in = (uint8_t)(ep_in); - o->info.ep_out = (uint8_t)(ep_out); - o->info.polling_interval = 10; - o->info.max_packet_len = (uint8_t)(vcp_packet_len); - - return MP_OBJ_FROM_PTR(o); + return MP_OBJ_FROM_PTR(o); } /// def iface_num(self) -> int: @@ -90,19 +102,22 @@ STATIC mp_obj_t mod_trezorio_VCP_make_new(const mp_obj_type_t *type, size_t n_ar /// Returns the configured number of this interface. /// ''' STATIC mp_obj_t mod_trezorio_VCP_iface_num(mp_obj_t self) { - mp_obj_VCP_t *o = MP_OBJ_TO_PTR(self); - return MP_OBJ_NEW_SMALL_INT(o->info.iface_num); + mp_obj_VCP_t *o = MP_OBJ_TO_PTR(self); + return MP_OBJ_NEW_SMALL_INT(o->info.iface_num); } -STATIC MP_DEFINE_CONST_FUN_OBJ_1(mod_trezorio_VCP_iface_num_obj, mod_trezorio_VCP_iface_num); +STATIC MP_DEFINE_CONST_FUN_OBJ_1(mod_trezorio_VCP_iface_num_obj, + mod_trezorio_VCP_iface_num); STATIC const mp_rom_map_elem_t mod_trezorio_VCP_locals_dict_table[] = { - { MP_ROM_QSTR(MP_QSTR_iface_num), MP_ROM_PTR(&mod_trezorio_VCP_iface_num_obj) }, + {MP_ROM_QSTR(MP_QSTR_iface_num), + MP_ROM_PTR(&mod_trezorio_VCP_iface_num_obj)}, }; -STATIC MP_DEFINE_CONST_DICT(mod_trezorio_VCP_locals_dict, mod_trezorio_VCP_locals_dict_table); +STATIC MP_DEFINE_CONST_DICT(mod_trezorio_VCP_locals_dict, + mod_trezorio_VCP_locals_dict_table); STATIC const mp_obj_type_t mod_trezorio_VCP_type = { - { &mp_type_type }, + {&mp_type_type}, .name = MP_QSTR_VCP, .make_new = mod_trezorio_VCP_make_new, - .locals_dict = (void*)&mod_trezorio_VCP_locals_dict, + .locals_dict = (void *)&mod_trezorio_VCP_locals_dict, }; diff --git a/embed/extmod/modtrezorio/modtrezorio-webusb.h b/embed/extmod/modtrezorio/modtrezorio-webusb.h index 4ba104fea..e234b991b 100644 --- a/embed/extmod/modtrezorio/modtrezorio-webusb.h +++ b/embed/extmod/modtrezorio/modtrezorio-webusb.h @@ -22,8 +22,8 @@ /// USB WebUSB interface configuration. /// ''' typedef struct _mp_obj_WebUSB_t { - mp_obj_base_t base; - usb_webusb_info_t info; + mp_obj_base_t base; + usb_webusb_info_t info; } mp_obj_WebUSB_t; /// def __init__(self, @@ -36,49 +36,57 @@ typedef struct _mp_obj_WebUSB_t { /// max_packet_len: int = 64) -> None: /// ''' /// ''' -STATIC mp_obj_t mod_trezorio_WebUSB_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_kw, const mp_obj_t *args) { +STATIC mp_obj_t mod_trezorio_WebUSB_make_new(const mp_obj_type_t *type, + size_t n_args, size_t n_kw, + const mp_obj_t *args) { + STATIC const mp_arg_t allowed_args[] = { + {MP_QSTR_iface_num, + MP_ARG_REQUIRED | MP_ARG_KW_ONLY | MP_ARG_INT, + {.u_int = 0}}, + {MP_QSTR_ep_in, + MP_ARG_REQUIRED | MP_ARG_KW_ONLY | MP_ARG_INT, + {.u_int = 0}}, + {MP_QSTR_ep_out, + MP_ARG_REQUIRED | MP_ARG_KW_ONLY | MP_ARG_INT, + {.u_int = 0}}, + {MP_QSTR_subclass, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = 0}}, + {MP_QSTR_protocol, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = 0}}, + {MP_QSTR_polling_interval, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = 1}}, + {MP_QSTR_max_packet_len, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = 64}}, + }; + mp_arg_val_t vals[MP_ARRAY_SIZE(allowed_args)]; + mp_arg_parse_all_kw_array(n_args, n_kw, args, MP_ARRAY_SIZE(allowed_args), + allowed_args, vals); - STATIC const mp_arg_t allowed_args[] = { - { MP_QSTR_iface_num, MP_ARG_REQUIRED | MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = 0} }, - { MP_QSTR_ep_in, MP_ARG_REQUIRED | MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = 0} }, - { MP_QSTR_ep_out, MP_ARG_REQUIRED | MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = 0} }, - { MP_QSTR_subclass, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = 0} }, - { MP_QSTR_protocol, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = 0} }, - { MP_QSTR_polling_interval, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = 1} }, - { MP_QSTR_max_packet_len, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = 64} }, - }; - mp_arg_val_t vals[MP_ARRAY_SIZE(allowed_args)]; - mp_arg_parse_all_kw_array(n_args, n_kw, args, MP_ARRAY_SIZE(allowed_args), allowed_args, vals); + const mp_int_t iface_num = vals[0].u_int; + const mp_int_t ep_in = vals[1].u_int; + const mp_int_t ep_out = vals[2].u_int; + const mp_int_t subclass = vals[3].u_int; + const mp_int_t protocol = vals[4].u_int; + const mp_int_t polling_interval = vals[5].u_int; + const mp_int_t max_packet_len = vals[6].u_int; - const mp_int_t iface_num = vals[0].u_int; - const mp_int_t ep_in = vals[1].u_int; - const mp_int_t ep_out = vals[2].u_int; - const mp_int_t subclass = vals[3].u_int; - const mp_int_t protocol = vals[4].u_int; - const mp_int_t polling_interval = vals[5].u_int; - const mp_int_t max_packet_len = vals[6].u_int; + CHECK_PARAM_RANGE(iface_num, 0, 32) + CHECK_PARAM_RANGE(ep_in, 0, 255) + CHECK_PARAM_RANGE(ep_out, 0, 255) + CHECK_PARAM_RANGE(subclass, 0, 255) + CHECK_PARAM_RANGE(protocol, 0, 255) + CHECK_PARAM_RANGE(polling_interval, 1, 255) + CHECK_PARAM_RANGE(max_packet_len, 64, 64) - CHECK_PARAM_RANGE(iface_num, 0, 32) - CHECK_PARAM_RANGE(ep_in, 0, 255) - CHECK_PARAM_RANGE(ep_out, 0, 255) - CHECK_PARAM_RANGE(subclass, 0, 255) - CHECK_PARAM_RANGE(protocol, 0, 255) - CHECK_PARAM_RANGE(polling_interval, 1, 255) - CHECK_PARAM_RANGE(max_packet_len, 64, 64) + mp_obj_WebUSB_t *o = m_new_obj(mp_obj_WebUSB_t); + o->base.type = type; - mp_obj_WebUSB_t *o = m_new_obj(mp_obj_WebUSB_t); - o->base.type = type; + o->info.rx_buffer = m_new(uint8_t, max_packet_len); + o->info.iface_num = (uint8_t)(iface_num); + o->info.ep_in = (uint8_t)(ep_in); + o->info.ep_out = (uint8_t)(ep_out); + o->info.subclass = (uint8_t)(subclass); + o->info.protocol = (uint8_t)(protocol); + o->info.polling_interval = (uint8_t)(polling_interval); + o->info.max_packet_len = (uint8_t)(max_packet_len); - o->info.rx_buffer = m_new(uint8_t, max_packet_len); - o->info.iface_num = (uint8_t)(iface_num); - o->info.ep_in = (uint8_t)(ep_in); - o->info.ep_out = (uint8_t)(ep_out); - o->info.subclass = (uint8_t)(subclass); - o->info.protocol = (uint8_t)(protocol); - o->info.polling_interval = (uint8_t)(polling_interval); - o->info.max_packet_len = (uint8_t)(max_packet_len); - - return MP_OBJ_FROM_PTR(o); + return MP_OBJ_FROM_PTR(o); } /// def iface_num(self) -> int: @@ -86,33 +94,37 @@ STATIC mp_obj_t mod_trezorio_WebUSB_make_new(const mp_obj_type_t *type, size_t n /// Returns the configured number of this interface. /// ''' STATIC mp_obj_t mod_trezorio_WebUSB_iface_num(mp_obj_t self) { - mp_obj_WebUSB_t *o = MP_OBJ_TO_PTR(self); - return MP_OBJ_NEW_SMALL_INT(o->info.iface_num); + mp_obj_WebUSB_t *o = MP_OBJ_TO_PTR(self); + return MP_OBJ_NEW_SMALL_INT(o->info.iface_num); } -STATIC MP_DEFINE_CONST_FUN_OBJ_1(mod_trezorio_WebUSB_iface_num_obj, mod_trezorio_WebUSB_iface_num); +STATIC MP_DEFINE_CONST_FUN_OBJ_1(mod_trezorio_WebUSB_iface_num_obj, + mod_trezorio_WebUSB_iface_num); /// def write(self, msg: bytes) -> int: /// ''' /// Sends message using USB WebUSB (device) or UDP (emulator). /// ''' STATIC mp_obj_t mod_trezorio_WebUSB_write(mp_obj_t self, mp_obj_t msg) { - mp_obj_WebUSB_t *o = MP_OBJ_TO_PTR(self); - mp_buffer_info_t buf; - mp_get_buffer_raise(msg, &buf, MP_BUFFER_READ); - ssize_t r = usb_webusb_write(o->info.iface_num, buf.buf, buf.len); - return MP_OBJ_NEW_SMALL_INT(r); + mp_obj_WebUSB_t *o = MP_OBJ_TO_PTR(self); + mp_buffer_info_t buf; + mp_get_buffer_raise(msg, &buf, MP_BUFFER_READ); + ssize_t r = usb_webusb_write(o->info.iface_num, buf.buf, buf.len); + return MP_OBJ_NEW_SMALL_INT(r); } -STATIC MP_DEFINE_CONST_FUN_OBJ_2(mod_trezorio_WebUSB_write_obj, mod_trezorio_WebUSB_write); +STATIC MP_DEFINE_CONST_FUN_OBJ_2(mod_trezorio_WebUSB_write_obj, + mod_trezorio_WebUSB_write); STATIC const mp_rom_map_elem_t mod_trezorio_WebUSB_locals_dict_table[] = { - { MP_ROM_QSTR(MP_QSTR_iface_num), MP_ROM_PTR(&mod_trezorio_WebUSB_iface_num_obj) }, - { MP_ROM_QSTR(MP_QSTR_write), MP_ROM_PTR(&mod_trezorio_WebUSB_write_obj) }, + {MP_ROM_QSTR(MP_QSTR_iface_num), + MP_ROM_PTR(&mod_trezorio_WebUSB_iface_num_obj)}, + {MP_ROM_QSTR(MP_QSTR_write), MP_ROM_PTR(&mod_trezorio_WebUSB_write_obj)}, }; -STATIC MP_DEFINE_CONST_DICT(mod_trezorio_WebUSB_locals_dict, mod_trezorio_WebUSB_locals_dict_table); +STATIC MP_DEFINE_CONST_DICT(mod_trezorio_WebUSB_locals_dict, + mod_trezorio_WebUSB_locals_dict_table); STATIC const mp_obj_type_t mod_trezorio_WebUSB_type = { - { &mp_type_type }, + {&mp_type_type}, .name = MP_QSTR_WebUSB, .make_new = mod_trezorio_WebUSB_make_new, - .locals_dict = (void*)&mod_trezorio_WebUSB_locals_dict, + .locals_dict = (void *)&mod_trezorio_WebUSB_locals_dict, }; diff --git a/embed/extmod/modtrezorio/modtrezorio.c b/embed/extmod/modtrezorio/modtrezorio.c index c4c6e0aa9..38d6967e3 100644 --- a/embed/extmod/modtrezorio/modtrezorio.c +++ b/embed/extmod/modtrezorio/modtrezorio.c @@ -17,52 +17,66 @@ * along with this program. If not, see . */ -#include "py/runtime.h" #include "py/mphal.h" #include "py/objstr.h" +#include "py/runtime.h" #if MICROPY_PY_TREZORIO +#include + #include "touch.h" +#include "usb.h" + +#define CHECK_PARAM_RANGE(value, minimum, maximum) \ + if (value < minimum || value > maximum) { \ + mp_raise_ValueError(#value " is out of range"); \ + } +// clang-format off #include "modtrezorio-flash.h" +#include "modtrezorio-hid.h" +#include "modtrezorio-poll.h" #include "modtrezorio-sbu.h" #include "modtrezorio-sdcard.h" -#include "modtrezorio-poll.h" -#include "modtrezorio-hid.h" #include "modtrezorio-vcp.h" #include "modtrezorio-webusb.h" #include "modtrezorio-usb.h" +// clang-format on STATIC const mp_rom_map_elem_t mp_module_trezorio_globals_table[] = { - { MP_ROM_QSTR(MP_QSTR___name__), MP_ROM_QSTR(MP_QSTR_trezorio) }, + {MP_ROM_QSTR(MP_QSTR___name__), MP_ROM_QSTR(MP_QSTR_trezorio)}, - { MP_ROM_QSTR(MP_QSTR_FlashOTP), MP_ROM_PTR(&mod_trezorio_FlashOTP_type) }, + {MP_ROM_QSTR(MP_QSTR_FlashOTP), MP_ROM_PTR(&mod_trezorio_FlashOTP_type)}, - { MP_ROM_QSTR(MP_QSTR_SBU), MP_ROM_PTR(&mod_trezorio_SBU_type) }, + {MP_ROM_QSTR(MP_QSTR_SBU), MP_ROM_PTR(&mod_trezorio_SBU_type)}, - { MP_ROM_QSTR(MP_QSTR_SDCard), MP_ROM_PTR(&mod_trezorio_SDCard_type) }, + {MP_ROM_QSTR(MP_QSTR_SDCard), MP_ROM_PTR(&mod_trezorio_SDCard_type)}, - { MP_ROM_QSTR(MP_QSTR_USB), MP_ROM_PTR(&mod_trezorio_USB_type) }, - { MP_ROM_QSTR(MP_QSTR_HID), MP_ROM_PTR(&mod_trezorio_HID_type) }, - { MP_ROM_QSTR(MP_QSTR_VCP), MP_ROM_PTR(&mod_trezorio_VCP_type) }, - { MP_ROM_QSTR(MP_QSTR_WebUSB), MP_ROM_PTR(&mod_trezorio_WebUSB_type) }, + {MP_ROM_QSTR(MP_QSTR_USB), MP_ROM_PTR(&mod_trezorio_USB_type)}, + {MP_ROM_QSTR(MP_QSTR_HID), MP_ROM_PTR(&mod_trezorio_HID_type)}, + {MP_ROM_QSTR(MP_QSTR_VCP), MP_ROM_PTR(&mod_trezorio_VCP_type)}, + {MP_ROM_QSTR(MP_QSTR_WebUSB), MP_ROM_PTR(&mod_trezorio_WebUSB_type)}, - { MP_ROM_QSTR(MP_QSTR_poll), MP_ROM_PTR(&mod_trezorio_poll_obj) }, - { MP_ROM_QSTR(MP_QSTR_POLL_READ), MP_OBJ_NEW_SMALL_INT(POLL_READ) }, - { MP_ROM_QSTR(MP_QSTR_POLL_WRITE), MP_OBJ_NEW_SMALL_INT(POLL_WRITE) }, + {MP_ROM_QSTR(MP_QSTR_poll), MP_ROM_PTR(&mod_trezorio_poll_obj)}, + {MP_ROM_QSTR(MP_QSTR_POLL_READ), MP_OBJ_NEW_SMALL_INT(POLL_READ)}, + {MP_ROM_QSTR(MP_QSTR_POLL_WRITE), MP_OBJ_NEW_SMALL_INT(POLL_WRITE)}, - { MP_ROM_QSTR(MP_QSTR_TOUCH), MP_OBJ_NEW_SMALL_INT(TOUCH_IFACE) }, - { MP_ROM_QSTR(MP_QSTR_TOUCH_START), MP_OBJ_NEW_SMALL_INT((TOUCH_START >> 24) & 0xFFU) }, - { MP_ROM_QSTR(MP_QSTR_TOUCH_MOVE), MP_OBJ_NEW_SMALL_INT((TOUCH_MOVE >> 24) & 0xFFU) }, - { MP_ROM_QSTR(MP_QSTR_TOUCH_END), MP_OBJ_NEW_SMALL_INT((TOUCH_END >> 24) & 0xFFU) }, + {MP_ROM_QSTR(MP_QSTR_TOUCH), MP_OBJ_NEW_SMALL_INT(TOUCH_IFACE)}, + {MP_ROM_QSTR(MP_QSTR_TOUCH_START), + MP_OBJ_NEW_SMALL_INT((TOUCH_START >> 24) & 0xFFU)}, + {MP_ROM_QSTR(MP_QSTR_TOUCH_MOVE), + MP_OBJ_NEW_SMALL_INT((TOUCH_MOVE >> 24) & 0xFFU)}, + {MP_ROM_QSTR(MP_QSTR_TOUCH_END), + MP_OBJ_NEW_SMALL_INT((TOUCH_END >> 24) & 0xFFU)}, }; -STATIC MP_DEFINE_CONST_DICT(mp_module_trezorio_globals, mp_module_trezorio_globals_table); +STATIC MP_DEFINE_CONST_DICT(mp_module_trezorio_globals, + mp_module_trezorio_globals_table); const mp_obj_module_t mp_module_trezorio = { - .base = { &mp_type_module }, + .base = {&mp_type_module}, .globals = (mp_obj_dict_t*)&mp_module_trezorio_globals, }; -#endif // MICROPY_PY_TREZORIO +#endif // MICROPY_PY_TREZORIO diff --git a/embed/extmod/modtrezorui/display-stm32_1.h b/embed/extmod/modtrezorui/display-stm32_1.h index 8826b425a..e919d5584 100644 --- a/embed/extmod/modtrezorui/display-stm32_1.h +++ b/embed/extmod/modtrezorui/display-stm32_1.h @@ -19,231 +19,226 @@ #include STM32_HAL_H -#define OLED_BUFSIZE (DISPLAY_RESX * DISPLAY_RESY / 8) -#define OLED_OFFSET(x, y) (OLED_BUFSIZE - 1 - (x) - ((y)/8) * DISPLAY_RESX) -#define OLED_MASK(x, y) (1 << (7 - (y) % 8)) - -#define OLED_SETCONTRAST 0x81 -#define OLED_DISPLAYALLON_RESUME 0xA4 -#define OLED_DISPLAYALLON 0xA5 -#define OLED_NORMALDISPLAY 0xA6 -#define OLED_INVERTDISPLAY 0xA7 -#define OLED_DISPLAYOFF 0xAE -#define OLED_DISPLAYON 0xAF -#define OLED_SETDISPLAYOFFSET 0xD3 -#define OLED_SETCOMPINS 0xDA -#define OLED_SETVCOMDETECT 0xDB -#define OLED_SETDISPLAYCLOCKDIV 0xD5 -#define OLED_SETPRECHARGE 0xD9 -#define OLED_SETMULTIPLEX 0xA8 -#define OLED_SETLOWCOLUMN 0x00 -#define OLED_SETHIGHCOLUMN 0x10 -#define OLED_SETSTARTLINE 0x40 -#define OLED_MEMORYMODE 0x20 -#define OLED_COMSCANINC 0xC0 -#define OLED_COMSCANDEC 0xC8 -#define OLED_SEGREMAP 0xA0 -#define OLED_CHARGEPUMP 0x8D - -#define OLED_DC_PORT GPIOB -#define OLED_DC_PIN GPIO_PIN_0 // PB0 | Data/Command -#define OLED_CS_PORT GPIOA -#define OLED_CS_PIN GPIO_PIN_4 // PA4 | SPI Select -#define OLED_RST_PORT GPIOB -#define OLED_RST_PIN GPIO_PIN_1 // PB1 | Reset display +#define OLED_BUFSIZE (DISPLAY_RESX * DISPLAY_RESY / 8) +#define OLED_OFFSET(x, y) (OLED_BUFSIZE - 1 - (x) - ((y) / 8) * DISPLAY_RESX) +#define OLED_MASK(x, y) (1 << (7 - (y) % 8)) + +#define OLED_SETCONTRAST 0x81 +#define OLED_DISPLAYALLON_RESUME 0xA4 +#define OLED_DISPLAYALLON 0xA5 +#define OLED_NORMALDISPLAY 0xA6 +#define OLED_INVERTDISPLAY 0xA7 +#define OLED_DISPLAYOFF 0xAE +#define OLED_DISPLAYON 0xAF +#define OLED_SETDISPLAYOFFSET 0xD3 +#define OLED_SETCOMPINS 0xDA +#define OLED_SETVCOMDETECT 0xDB +#define OLED_SETDISPLAYCLOCKDIV 0xD5 +#define OLED_SETPRECHARGE 0xD9 +#define OLED_SETMULTIPLEX 0xA8 +#define OLED_SETLOWCOLUMN 0x00 +#define OLED_SETHIGHCOLUMN 0x10 +#define OLED_SETSTARTLINE 0x40 +#define OLED_MEMORYMODE 0x20 +#define OLED_COMSCANINC 0xC0 +#define OLED_COMSCANDEC 0xC8 +#define OLED_SEGREMAP 0xA0 +#define OLED_CHARGEPUMP 0x8D + +#define OLED_DC_PORT GPIOB +#define OLED_DC_PIN GPIO_PIN_0 // PB0 | Data/Command +#define OLED_CS_PORT GPIOA +#define OLED_CS_PIN GPIO_PIN_4 // PA4 | SPI Select +#define OLED_RST_PORT GPIOB +#define OLED_RST_PIN GPIO_PIN_1 // PB1 | Reset display static uint8_t OLED_BUFFER[OLED_BUFSIZE]; static struct { - struct { - uint16_t x, y; - } start; - struct { - uint16_t x, y; - } end; - struct { - uint16_t x, y; - } pos; + struct { + uint16_t x, y; + } start; + struct { + uint16_t x, y; + } end; + struct { + uint16_t x, y; + } pos; } PIXELWINDOW; void PIXELDATA(uint16_t c) { - if (PIXELWINDOW.pos.x <= PIXELWINDOW.end.x && PIXELWINDOW.pos.y <= PIXELWINDOW.end.y) { - // set to white if highest bits of all R, G, B values are set to 1 - // bin(10000 100000 10000) = hex(0x8410) - // otherwise set to black - if (c & 0x8410) { - OLED_BUFFER[OLED_OFFSET(PIXELWINDOW.pos.x, PIXELWINDOW.pos.y)] |= OLED_MASK(PIXELWINDOW.pos.x, PIXELWINDOW.pos.y); - } else { - OLED_BUFFER[OLED_OFFSET(PIXELWINDOW.pos.x, PIXELWINDOW.pos.y)] &= ~OLED_MASK(PIXELWINDOW.pos.x, PIXELWINDOW.pos.y); - } - } - PIXELWINDOW.pos.x++; - if (PIXELWINDOW.pos.x > PIXELWINDOW.end.x) { - PIXELWINDOW.pos.x = PIXELWINDOW.start.x; - PIXELWINDOW.pos.y++; + if (PIXELWINDOW.pos.x <= PIXELWINDOW.end.x && + PIXELWINDOW.pos.y <= PIXELWINDOW.end.y) { + // set to white if highest bits of all R, G, B values are set to 1 + // bin(10000 100000 10000) = hex(0x8410) + // otherwise set to black + if (c & 0x8410) { + OLED_BUFFER[OLED_OFFSET(PIXELWINDOW.pos.x, PIXELWINDOW.pos.y)] |= + OLED_MASK(PIXELWINDOW.pos.x, PIXELWINDOW.pos.y); + } else { + OLED_BUFFER[OLED_OFFSET(PIXELWINDOW.pos.x, PIXELWINDOW.pos.y)] &= + ~OLED_MASK(PIXELWINDOW.pos.x, PIXELWINDOW.pos.y); } + } + PIXELWINDOW.pos.x++; + if (PIXELWINDOW.pos.x > PIXELWINDOW.end.x) { + PIXELWINDOW.pos.x = PIXELWINDOW.start.x; + PIXELWINDOW.pos.y++; + } } -static void display_set_window(uint16_t x0, uint16_t y0, uint16_t x1, uint16_t y1) -{ - PIXELWINDOW.start.x = x0; PIXELWINDOW.start.y = y0; - PIXELWINDOW.end.x = x1; PIXELWINDOW.end.y = y1; - PIXELWINDOW.pos.x = x0; PIXELWINDOW.pos.y = y0; +static void display_set_window(uint16_t x0, uint16_t y0, uint16_t x1, + uint16_t y1) { + PIXELWINDOW.start.x = x0; + PIXELWINDOW.start.y = y0; + PIXELWINDOW.end.x = x1; + PIXELWINDOW.end.y = y1; + PIXELWINDOW.pos.x = x0; + PIXELWINDOW.pos.y = y0; } -static void display_set_orientation(int degrees) -{ - display_refresh(); -} +static void display_set_orientation(int degrees) { display_refresh(); } -static void display_set_backlight(int val) -{ -} +static void display_set_backlight(int val) {} SPI_HandleTypeDef spi_handle; -static inline void spi_send(const uint8_t *data, int len) -{ - HAL_Delay(1); - if (HAL_OK != HAL_SPI_Transmit(&spi_handle, (uint8_t *)data, len, 1000)) { - // TODO: error - return; - } - while (HAL_SPI_STATE_READY != HAL_SPI_GetState(&spi_handle)) { - } +static inline void spi_send(const uint8_t *data, int len) { + HAL_Delay(1); + if (HAL_OK != HAL_SPI_Transmit(&spi_handle, (uint8_t *)data, len, 1000)) { + // TODO: error + return; + } + while (HAL_SPI_STATE_READY != HAL_SPI_GetState(&spi_handle)) { + } } -void display_init(void) -{ - __HAL_RCC_GPIOA_CLK_ENABLE(); - __HAL_RCC_GPIOB_CLK_ENABLE(); - __HAL_RCC_SPI1_CLK_ENABLE(); - - GPIO_InitTypeDef GPIO_InitStructure; - - // set GPIO for OLED display - GPIO_InitStructure.Mode = GPIO_MODE_OUTPUT_PP; - GPIO_InitStructure.Pull = GPIO_NOPULL; - GPIO_InitStructure.Speed = GPIO_SPEED_FREQ_VERY_HIGH; - GPIO_InitStructure.Alternate = 0; - GPIO_InitStructure.Pin = GPIO_PIN_4; - HAL_GPIO_WritePin(GPIOA, GPIO_PIN_4, GPIO_PIN_RESET); - HAL_GPIO_Init(GPIOA, &GPIO_InitStructure); - GPIO_InitStructure.Pin = GPIO_PIN_0 | GPIO_PIN_4; - HAL_GPIO_WritePin(GPIOB, GPIO_PIN_0 | GPIO_PIN_4, GPIO_PIN_RESET); - HAL_GPIO_Init(GPIOB, &GPIO_InitStructure); - - // enable SPI 1 for OLED display - GPIO_InitStructure.Mode = GPIO_MODE_AF_PP; - GPIO_InitStructure.Pull = GPIO_NOPULL; - GPIO_InitStructure.Speed = GPIO_SPEED_FREQ_VERY_HIGH; - GPIO_InitStructure.Alternate = GPIO_AF5_SPI1; - GPIO_InitStructure.Pin = GPIO_PIN_5 | GPIO_PIN_7; - HAL_GPIO_Init(GPIOA, &GPIO_InitStructure); - - spi_handle.Instance = SPI1; - spi_handle.Init.BaudRatePrescaler = SPI_BAUDRATEPRESCALER_8; - spi_handle.Init.Direction = SPI_DIRECTION_2LINES; - spi_handle.Init.CLKPhase = SPI_PHASE_1EDGE; - spi_handle.Init.CLKPolarity = SPI_POLARITY_LOW; - spi_handle.Init.CRCCalculation = SPI_CRCCALCULATION_DISABLE; - spi_handle.Init.CRCPolynomial = 7; - spi_handle.Init.DataSize = SPI_DATASIZE_8BIT; - spi_handle.Init.FirstBit = SPI_FIRSTBIT_MSB; - spi_handle.Init.NSS = SPI_NSS_HARD_OUTPUT; - spi_handle.Init.TIMode = SPI_TIMODE_DISABLE; - spi_handle.Init.Mode = SPI_MODE_MASTER; - if (HAL_OK != HAL_SPI_Init(&spi_handle)) { - // TODO: error - return; - } - - // initialize display - - static const uint8_t s[25] = { - OLED_DISPLAYOFF, - OLED_SETDISPLAYCLOCKDIV, - 0x80, - OLED_SETMULTIPLEX, - 0x3F, // 128x64 - OLED_SETDISPLAYOFFSET, - 0x00, - OLED_SETSTARTLINE | 0x00, - OLED_CHARGEPUMP, - 0x14, - OLED_MEMORYMODE, - 0x00, - OLED_SEGREMAP | 0x01, - OLED_COMSCANDEC, - OLED_SETCOMPINS, - 0x12, // 128x64 - OLED_SETCONTRAST, - 0xCF, - OLED_SETPRECHARGE, - 0xF1, - OLED_SETVCOMDETECT, - 0x40, - OLED_DISPLAYALLON_RESUME, - OLED_NORMALDISPLAY, - OLED_DISPLAYON - }; - - HAL_GPIO_WritePin(OLED_DC_PORT, OLED_DC_PIN, GPIO_PIN_RESET); // set to CMD - HAL_GPIO_WritePin(OLED_CS_PORT, OLED_CS_PIN, GPIO_PIN_SET); // SPI deselect - - // Reset the LCD - HAL_GPIO_WritePin(OLED_RST_PORT, OLED_RST_PIN, GPIO_PIN_SET); - HAL_Delay(40); - HAL_GPIO_WritePin(OLED_RST_PORT, OLED_RST_PIN, GPIO_PIN_RESET); - HAL_Delay(400); - HAL_GPIO_WritePin(OLED_RST_PORT, OLED_RST_PIN, GPIO_PIN_SET); - - // init - HAL_GPIO_WritePin(OLED_CS_PORT, OLED_CS_PIN, GPIO_PIN_RESET); // SPI select - spi_send(s, 25); - HAL_GPIO_WritePin(OLED_CS_PORT, OLED_CS_PIN, GPIO_PIN_SET); // SPI deselect - - display_clear(); - display_refresh(); +void display_init(void) { + __HAL_RCC_GPIOA_CLK_ENABLE(); + __HAL_RCC_GPIOB_CLK_ENABLE(); + __HAL_RCC_SPI1_CLK_ENABLE(); + + GPIO_InitTypeDef GPIO_InitStructure; + + // set GPIO for OLED display + GPIO_InitStructure.Mode = GPIO_MODE_OUTPUT_PP; + GPIO_InitStructure.Pull = GPIO_NOPULL; + GPIO_InitStructure.Speed = GPIO_SPEED_FREQ_VERY_HIGH; + GPIO_InitStructure.Alternate = 0; + GPIO_InitStructure.Pin = GPIO_PIN_4; + HAL_GPIO_WritePin(GPIOA, GPIO_PIN_4, GPIO_PIN_RESET); + HAL_GPIO_Init(GPIOA, &GPIO_InitStructure); + GPIO_InitStructure.Pin = GPIO_PIN_0 | GPIO_PIN_4; + HAL_GPIO_WritePin(GPIOB, GPIO_PIN_0 | GPIO_PIN_4, GPIO_PIN_RESET); + HAL_GPIO_Init(GPIOB, &GPIO_InitStructure); + + // enable SPI 1 for OLED display + GPIO_InitStructure.Mode = GPIO_MODE_AF_PP; + GPIO_InitStructure.Pull = GPIO_NOPULL; + GPIO_InitStructure.Speed = GPIO_SPEED_FREQ_VERY_HIGH; + GPIO_InitStructure.Alternate = GPIO_AF5_SPI1; + GPIO_InitStructure.Pin = GPIO_PIN_5 | GPIO_PIN_7; + HAL_GPIO_Init(GPIOA, &GPIO_InitStructure); + + spi_handle.Instance = SPI1; + spi_handle.Init.BaudRatePrescaler = SPI_BAUDRATEPRESCALER_8; + spi_handle.Init.Direction = SPI_DIRECTION_2LINES; + spi_handle.Init.CLKPhase = SPI_PHASE_1EDGE; + spi_handle.Init.CLKPolarity = SPI_POLARITY_LOW; + spi_handle.Init.CRCCalculation = SPI_CRCCALCULATION_DISABLE; + spi_handle.Init.CRCPolynomial = 7; + spi_handle.Init.DataSize = SPI_DATASIZE_8BIT; + spi_handle.Init.FirstBit = SPI_FIRSTBIT_MSB; + spi_handle.Init.NSS = SPI_NSS_HARD_OUTPUT; + spi_handle.Init.TIMode = SPI_TIMODE_DISABLE; + spi_handle.Init.Mode = SPI_MODE_MASTER; + if (HAL_OK != HAL_SPI_Init(&spi_handle)) { + // TODO: error + return; + } + + // initialize display + + static const uint8_t s[25] = {OLED_DISPLAYOFF, + OLED_SETDISPLAYCLOCKDIV, + 0x80, + OLED_SETMULTIPLEX, + 0x3F, // 128x64 + OLED_SETDISPLAYOFFSET, + 0x00, + OLED_SETSTARTLINE | 0x00, + OLED_CHARGEPUMP, + 0x14, + OLED_MEMORYMODE, + 0x00, + OLED_SEGREMAP | 0x01, + OLED_COMSCANDEC, + OLED_SETCOMPINS, + 0x12, // 128x64 + OLED_SETCONTRAST, + 0xCF, + OLED_SETPRECHARGE, + 0xF1, + OLED_SETVCOMDETECT, + 0x40, + OLED_DISPLAYALLON_RESUME, + OLED_NORMALDISPLAY, + OLED_DISPLAYON}; + + HAL_GPIO_WritePin(OLED_DC_PORT, OLED_DC_PIN, GPIO_PIN_RESET); // set to CMD + HAL_GPIO_WritePin(OLED_CS_PORT, OLED_CS_PIN, GPIO_PIN_SET); // SPI deselect + + // Reset the LCD + HAL_GPIO_WritePin(OLED_RST_PORT, OLED_RST_PIN, GPIO_PIN_SET); + HAL_Delay(40); + HAL_GPIO_WritePin(OLED_RST_PORT, OLED_RST_PIN, GPIO_PIN_RESET); + HAL_Delay(400); + HAL_GPIO_WritePin(OLED_RST_PORT, OLED_RST_PIN, GPIO_PIN_SET); + + // init + HAL_GPIO_WritePin(OLED_CS_PORT, OLED_CS_PIN, GPIO_PIN_RESET); // SPI select + spi_send(s, 25); + HAL_GPIO_WritePin(OLED_CS_PORT, OLED_CS_PIN, GPIO_PIN_SET); // SPI deselect + + display_clear(); + display_refresh(); } static inline uint8_t reverse_byte(uint8_t b) { - b = (b & 0xF0) >> 4 | (b & 0x0F) << 4; - b = (b & 0xCC) >> 2 | (b & 0x33) << 2; - b = (b & 0xAA) >> 1 | (b & 0x55) << 1; - return b; + b = (b & 0xF0) >> 4 | (b & 0x0F) << 4; + b = (b & 0xCC) >> 2 | (b & 0x33) << 2; + b = (b & 0xAA) >> 1 | (b & 0x55) << 1; + return b; } -static void rotate_oled_buffer(void) -{ - for (int i = 0; i < OLED_BUFSIZE / 2; i++) { - uint8_t b = OLED_BUFFER[i]; - OLED_BUFFER[i] = reverse_byte(OLED_BUFFER[OLED_BUFSIZE - i]); - OLED_BUFFER[OLED_BUFSIZE - i] = reverse_byte(b); - } +static void rotate_oled_buffer(void) { + for (int i = 0; i < OLED_BUFSIZE / 2; i++) { + uint8_t b = OLED_BUFFER[i]; + OLED_BUFFER[i] = reverse_byte(OLED_BUFFER[OLED_BUFSIZE - i]); + OLED_BUFFER[OLED_BUFSIZE - i] = reverse_byte(b); + } } -void display_refresh(void) -{ - static const uint8_t s[3] = {OLED_SETLOWCOLUMN | 0x00, OLED_SETHIGHCOLUMN | 0x00, OLED_SETSTARTLINE | 0x00}; - - HAL_GPIO_WritePin(OLED_CS_PORT, OLED_CS_PIN, GPIO_PIN_RESET); // SPI select - spi_send(s, 3); - HAL_GPIO_WritePin(OLED_CS_PORT, OLED_CS_PIN, GPIO_PIN_SET); // SPI deselect - - HAL_GPIO_WritePin(OLED_DC_PORT, OLED_DC_PIN, GPIO_PIN_SET); // set to DATA - HAL_GPIO_WritePin(OLED_CS_PORT, OLED_CS_PIN, GPIO_PIN_RESET); // SPI select - if (DISPLAY_ORIENTATION == 180) { // rotate buffer if needed - rotate_oled_buffer(); - } - spi_send(OLED_BUFFER, OLED_BUFSIZE); - if (DISPLAY_ORIENTATION == 180) { // rotate buffer back to original position - rotate_oled_buffer(); - } - HAL_GPIO_WritePin(OLED_CS_PORT, OLED_CS_PIN, GPIO_PIN_SET); // SPI deselect - HAL_GPIO_WritePin(OLED_DC_PORT, OLED_DC_PIN, GPIO_PIN_RESET); // set to CMD +void display_refresh(void) { + static const uint8_t s[3] = {OLED_SETLOWCOLUMN | 0x00, + OLED_SETHIGHCOLUMN | 0x00, + OLED_SETSTARTLINE | 0x00}; + + HAL_GPIO_WritePin(OLED_CS_PORT, OLED_CS_PIN, GPIO_PIN_RESET); // SPI select + spi_send(s, 3); + HAL_GPIO_WritePin(OLED_CS_PORT, OLED_CS_PIN, GPIO_PIN_SET); // SPI deselect + + HAL_GPIO_WritePin(OLED_DC_PORT, OLED_DC_PIN, GPIO_PIN_SET); // set to DATA + HAL_GPIO_WritePin(OLED_CS_PORT, OLED_CS_PIN, GPIO_PIN_RESET); // SPI select + if (DISPLAY_ORIENTATION == 180) { // rotate buffer if needed + rotate_oled_buffer(); + } + spi_send(OLED_BUFFER, OLED_BUFSIZE); + if (DISPLAY_ORIENTATION == 180) { // rotate buffer back to original position + rotate_oled_buffer(); + } + HAL_GPIO_WritePin(OLED_CS_PORT, OLED_CS_PIN, GPIO_PIN_SET); // SPI deselect + HAL_GPIO_WritePin(OLED_DC_PORT, OLED_DC_PIN, GPIO_PIN_RESET); // set to CMD } -void display_save(const char *prefix) -{ -} +void display_save(const char *prefix) {} diff --git a/embed/extmod/modtrezorui/display-stm32_t.h b/embed/extmod/modtrezorui/display-stm32_t.h index 69fc30935..20f7e9371 100644 --- a/embed/extmod/modtrezorui/display-stm32_t.h +++ b/embed/extmod/modtrezorui/display-stm32_t.h @@ -20,332 +20,482 @@ #include STM32_HAL_H // FSMC/FMC Bank 1 - NOR/PSRAM 1 -#define DISPLAY_MEMORY_BASE 0x60000000 -#define DISPLAY_MEMORY_PIN 16 - -#define CMD(X) (*((__IO uint8_t *)((uint32_t)(DISPLAY_MEMORY_BASE))) = (X)) -#define ADDR (*((__IO uint8_t *)((uint32_t)(DISPLAY_MEMORY_BASE | (1 << DISPLAY_MEMORY_PIN))))) -#define DATA(X) (ADDR) = (X) -#define PIXELDATA(X) DATA((X) >> 8); DATA((X) & 0xFF) +#define DISPLAY_MEMORY_BASE 0x60000000 +#define DISPLAY_MEMORY_PIN 16 + +#define CMD(X) (*((__IO uint8_t *)((uint32_t)(DISPLAY_MEMORY_BASE))) = (X)) +#define ADDR \ + (*((__IO uint8_t *)((uint32_t)(DISPLAY_MEMORY_BASE | \ + (1 << DISPLAY_MEMORY_PIN))))) +#define DATA(X) (ADDR) = (X) +#define PIXELDATA(X) \ + DATA((X) >> 8); \ + DATA((X)&0xFF) #define LED_PWM_TIM_PERIOD (10000) -#define DISPLAY_ID_ST7789V 0x858552U // section "9.1.3 RDDID (04h): Read Display ID" of ST7789V datasheet -#define DISPLAY_ID_GC9307 0x009307U // section "6.2.1. Read display identification information (04h)" of GC9307 datasheet -#define DISPLAY_ID_ILI9341V 0x009341U // section "8.3.23 Read ID4 (D3h)" of ILI9341V datasheet +#define DISPLAY_ID_ST7789V \ + 0x858552U // section "9.1.3 RDDID (04h): Read Display ID" of ST7789V + // datasheet +#define DISPLAY_ID_GC9307 \ + 0x009307U // section "6.2.1. Read display identification information (04h)" + // of GC9307 datasheet +#define DISPLAY_ID_ILI9341V \ + 0x009341U // section "8.3.23 Read ID4 (D3h)" of ILI9341V datasheet static uint32_t read_display_id(uint8_t command) { - volatile uint8_t c; - uint32_t id = 0; - CMD(command); - c = ADDR; // first returned value is a dummy value and should be discarded - c = ADDR; id |= (c << 16); - c = ADDR; id |= (c << 8); - c = ADDR; id |= c; - return id; + volatile uint8_t c; + uint32_t id = 0; + CMD(command); + c = ADDR; // first returned value is a dummy value and should be discarded + c = ADDR; + id |= (c << 16); + c = ADDR; + id |= (c << 8); + c = ADDR; + id |= c; + return id; } -static uint32_t display_identify(void) -{ - static uint32_t id = 0x000000U; - static char id_set = 0; - - if (id_set) return id; // return if id has been already set - - id = read_display_id(0x04); // RDDID: Read Display ID - // the default RDDID for ILI9341 should be 0x8000. - // some display modules return 0x0. - // the ILI9341 has an extra id, let's check it here. - if ((id != DISPLAY_ID_ST7789V) && (id != DISPLAY_ID_GC9307)) { // if not ST7789V and not GC9307 - uint32_t id4 = read_display_id(0xD3); // Read ID4 - if (id4 == DISPLAY_ID_ILI9341V) { // definitely found a ILI9341 - id = id4; - } +static uint32_t display_identify(void) { + static uint32_t id = 0x000000U; + static char id_set = 0; + + if (id_set) return id; // return if id has been already set + + id = read_display_id(0x04); // RDDID: Read Display ID + // the default RDDID for ILI9341 should be 0x8000. + // some display modules return 0x0. + // the ILI9341 has an extra id, let's check it here. + if ((id != DISPLAY_ID_ST7789V) && + (id != DISPLAY_ID_GC9307)) { // if not ST7789V and not GC9307 + uint32_t id4 = read_display_id(0xD3); // Read ID4 + if (id4 == DISPLAY_ID_ILI9341V) { // definitely found a ILI9341 + id = id4; } - id_set = 1; - return id; + } + id_set = 1; + return id; } -static void __attribute__((unused)) display_sleep(void) -{ - uint32_t id = display_identify(); - if ((id == DISPLAY_ID_ILI9341V) || (id == DISPLAY_ID_GC9307) || (id == DISPLAY_ID_ST7789V)) { - CMD(0x28); // DISPOFF: Display Off - CMD(0x10); // SLPIN: Sleep in - HAL_Delay(5); // need to wait 5 milliseconds after "sleep in" before sending any new commands - } +static void __attribute__((unused)) display_sleep(void) { + uint32_t id = display_identify(); + if ((id == DISPLAY_ID_ILI9341V) || (id == DISPLAY_ID_GC9307) || + (id == DISPLAY_ID_ST7789V)) { + CMD(0x28); // DISPOFF: Display Off + CMD(0x10); // SLPIN: Sleep in + HAL_Delay(5); // need to wait 5 milliseconds after "sleep in" before + // sending any new commands + } } -static void display_unsleep(void) -{ - uint32_t id = display_identify(); - if ((id == DISPLAY_ID_ILI9341V) || (id == DISPLAY_ID_GC9307) || (id == DISPLAY_ID_ST7789V)) { - CMD(0x11); // SLPOUT: Sleep Out - HAL_Delay(5); // need to wait 5 milliseconds after "sleep out" before sending any new commands - CMD(0x29); // DISPON: Display On - } +static void display_unsleep(void) { + uint32_t id = display_identify(); + if ((id == DISPLAY_ID_ILI9341V) || (id == DISPLAY_ID_GC9307) || + (id == DISPLAY_ID_ST7789V)) { + CMD(0x11); // SLPOUT: Sleep Out + HAL_Delay(5); // need to wait 5 milliseconds after "sleep out" before + // sending any new commands + CMD(0x29); // DISPON: Display On + } } -static struct { - uint16_t x, y; -} BUFFER_OFFSET; - -static void display_set_window(uint16_t x0, uint16_t y0, uint16_t x1, uint16_t y1) -{ - x0 += BUFFER_OFFSET.x; x1 += BUFFER_OFFSET.x; - y0 += BUFFER_OFFSET.y; y1 += BUFFER_OFFSET.y; - uint32_t id = display_identify(); - if ((id == DISPLAY_ID_ILI9341V) || (id == DISPLAY_ID_GC9307) || (id == DISPLAY_ID_ST7789V)) { - CMD(0x2A); DATA(x0 >> 8); DATA(x0 & 0xFF); DATA(x1 >> 8); DATA(x1 & 0xFF); // column addr set - CMD(0x2B); DATA(y0 >> 8); DATA(y0 & 0xFF); DATA(y1 >> 8); DATA(y1 & 0xFF); // row addr set - CMD(0x2C); - } +static struct { uint16_t x, y; } BUFFER_OFFSET; + +static void display_set_window(uint16_t x0, uint16_t y0, uint16_t x1, + uint16_t y1) { + x0 += BUFFER_OFFSET.x; + x1 += BUFFER_OFFSET.x; + y0 += BUFFER_OFFSET.y; + y1 += BUFFER_OFFSET.y; + uint32_t id = display_identify(); + if ((id == DISPLAY_ID_ILI9341V) || (id == DISPLAY_ID_GC9307) || + (id == DISPLAY_ID_ST7789V)) { + CMD(0x2A); + DATA(x0 >> 8); + DATA(x0 & 0xFF); + DATA(x1 >> 8); + DATA(x1 & 0xFF); // column addr set + CMD(0x2B); + DATA(y0 >> 8); + DATA(y0 & 0xFF); + DATA(y1 >> 8); + DATA(y1 & 0xFF); // row addr set + CMD(0x2C); + } } -static void display_set_orientation(int degrees) -{ - char BX = 0, BY = 0; - uint32_t id = display_identify(); - if ((id == DISPLAY_ID_ILI9341V) || (id == DISPLAY_ID_GC9307) || (id == DISPLAY_ID_ST7789V)) { - #define RGB (1 << 3) - #define MV (1 << 5) - #define MX (1 << 6) - #define MY (1 << 7) - // MADCTL: Memory Data Access Control - reference: - // section 9.3 in the ILI9341 manual - // section 6.2.18 in the GC9307 manual - // section 8.12 in the ST7789V manual - uint8_t display_command_parameter = 0; - switch (degrees) { - case 0: - display_command_parameter = 0; - BY = (id == DISPLAY_ID_GC9307); - break; - case 90: - display_command_parameter = MV | MX; - BX = (id == DISPLAY_ID_GC9307); - break; - case 180: - display_command_parameter = MX | MY; - BY = (id != DISPLAY_ID_GC9307); - break; - case 270: - display_command_parameter = MV | MY; - BX = (id != DISPLAY_ID_GC9307); - break; - } - if (id == DISPLAY_ID_GC9307) { - display_command_parameter ^= RGB | MY; // XOR RGB and MY settings - } - CMD(0x36); DATA(display_command_parameter); - display_set_window(0, 0, DISPLAY_RESX - 1, DISPLAY_RESY - 1); // reset the column and page extents +static void display_set_orientation(int degrees) { + char BX = 0, BY = 0; + uint32_t id = display_identify(); + if ((id == DISPLAY_ID_ILI9341V) || (id == DISPLAY_ID_GC9307) || + (id == DISPLAY_ID_ST7789V)) { +#define RGB (1 << 3) +#define MV (1 << 5) +#define MX (1 << 6) +#define MY (1 << 7) + // MADCTL: Memory Data Access Control - reference: + // section 9.3 in the ILI9341 manual + // section 6.2.18 in the GC9307 manual + // section 8.12 in the ST7789V manual + uint8_t display_command_parameter = 0; + switch (degrees) { + case 0: + display_command_parameter = 0; + BY = (id == DISPLAY_ID_GC9307); + break; + case 90: + display_command_parameter = MV | MX; + BX = (id == DISPLAY_ID_GC9307); + break; + case 180: + display_command_parameter = MX | MY; + BY = (id != DISPLAY_ID_GC9307); + break; + case 270: + display_command_parameter = MV | MY; + BX = (id != DISPLAY_ID_GC9307); + break; + } + if (id == DISPLAY_ID_GC9307) { + display_command_parameter ^= RGB | MY; // XOR RGB and MY settings } - BUFFER_OFFSET.x = BX ? (MAX_DISPLAY_RESY - DISPLAY_RESY) : 0; - BUFFER_OFFSET.y = BY ? (MAX_DISPLAY_RESY - DISPLAY_RESY) : 0; + CMD(0x36); + DATA(display_command_parameter); + display_set_window(0, 0, DISPLAY_RESX - 1, + DISPLAY_RESY - 1); // reset the column and page extents + } + BUFFER_OFFSET.x = BX ? (MAX_DISPLAY_RESY - DISPLAY_RESY) : 0; + BUFFER_OFFSET.y = BY ? (MAX_DISPLAY_RESY - DISPLAY_RESY) : 0; } -static void display_set_backlight(int val) -{ - TIM1->CCR1 = LED_PWM_TIM_PERIOD * val / 255; +static void display_set_backlight(int val) { + TIM1->CCR1 = LED_PWM_TIM_PERIOD * val / 255; } -static void display_hardware_reset(void) -{ - HAL_GPIO_WritePin(GPIOC, GPIO_PIN_14, GPIO_PIN_RESET); // LCD_RST/PC14 - // wait 10 milliseconds. only needs to be low for 10 microseconds. - // my dev display module ties display reset and touch panel reset together. - // keeping this low for max(display_reset_time, ctpm_reset_time) aids development and does not hurt. - HAL_Delay(10); - HAL_GPIO_WritePin(GPIOC, GPIO_PIN_14, GPIO_PIN_SET); // LCD_RST/PC14 - HAL_Delay(120); // max wait time for hardware reset is 120 milliseconds (experienced display flakiness using only 5ms wait before sending commands) - // identify the controller we will communicate with +static void display_hardware_reset(void) { + HAL_GPIO_WritePin(GPIOC, GPIO_PIN_14, GPIO_PIN_RESET); // LCD_RST/PC14 + // wait 10 milliseconds. only needs to be low for 10 microseconds. + // my dev display module ties display reset and touch panel reset together. + // keeping this low for max(display_reset_time, ctpm_reset_time) aids + // development and does not hurt. + HAL_Delay(10); + HAL_GPIO_WritePin(GPIOC, GPIO_PIN_14, GPIO_PIN_SET); // LCD_RST/PC14 + HAL_Delay(120); // max wait time for hardware reset is 120 milliseconds + // (experienced display flakiness using only 5ms wait before + // sending commands) + // identify the controller we will communicate with } -void display_init(void) -{ - // init peripherials - __HAL_RCC_GPIOE_CLK_ENABLE(); - __HAL_RCC_TIM1_CLK_ENABLE(); - __HAL_RCC_FMC_CLK_ENABLE(); - - GPIO_InitTypeDef GPIO_InitStructure; - - // LCD_PWM/PA7 (backlight control) - GPIO_InitStructure.Mode = GPIO_MODE_AF_PP; - GPIO_InitStructure.Pull = GPIO_NOPULL; - GPIO_InitStructure.Speed = GPIO_SPEED_FREQ_VERY_HIGH; - GPIO_InitStructure.Alternate = GPIO_AF1_TIM1; - GPIO_InitStructure.Pin = GPIO_PIN_7; - HAL_GPIO_Init(GPIOA, &GPIO_InitStructure); - - // enable PWM timer - TIM_HandleTypeDef TIM1_Handle; - TIM1_Handle.Instance = TIM1; - TIM1_Handle.Init.Period = LED_PWM_TIM_PERIOD - 1; - // TIM1/APB2 source frequency equals to SystemCoreClock in our configuration, we want 1 MHz - TIM1_Handle.Init.Prescaler = SystemCoreClock / 1000000 - 1; - TIM1_Handle.Init.ClockDivision = TIM_CLOCKDIVISION_DIV1; - TIM1_Handle.Init.CounterMode = TIM_COUNTERMODE_UP; - TIM1_Handle.Init.RepetitionCounter = 0; - HAL_TIM_PWM_Init(&TIM1_Handle); - - TIM_OC_InitTypeDef TIM_OC_InitStructure; - TIM_OC_InitStructure.Pulse = 0; - TIM_OC_InitStructure.OCMode = TIM_OCMODE_PWM2; - TIM_OC_InitStructure.OCPolarity = TIM_OCPOLARITY_HIGH; - TIM_OC_InitStructure.OCFastMode = TIM_OCFAST_DISABLE; - TIM_OC_InitStructure.OCNPolarity = TIM_OCNPOLARITY_HIGH; - TIM_OC_InitStructure.OCIdleState = TIM_OCIDLESTATE_SET; - TIM_OC_InitStructure.OCNIdleState = TIM_OCNIDLESTATE_SET; - HAL_TIM_PWM_ConfigChannel(&TIM1_Handle, &TIM_OC_InitStructure, TIM_CHANNEL_1); - - display_backlight(0); - - HAL_TIM_PWM_Start(&TIM1_Handle, TIM_CHANNEL_1); - HAL_TIMEx_PWMN_Start(&TIM1_Handle, TIM_CHANNEL_1); - - // LCD_RST/PC14 - GPIO_InitStructure.Mode = GPIO_MODE_OUTPUT_PP; - GPIO_InitStructure.Pull = GPIO_NOPULL; - GPIO_InitStructure.Speed = GPIO_SPEED_FREQ_LOW; - GPIO_InitStructure.Alternate = 0; - GPIO_InitStructure.Pin = GPIO_PIN_14; - HAL_GPIO_WritePin(GPIOC, GPIO_PIN_14, GPIO_PIN_RESET); // default to keeping display in reset - HAL_GPIO_Init(GPIOC, &GPIO_InitStructure); - - // LCD_FMARK/PD12 (tearing effect) - GPIO_InitStructure.Mode = GPIO_MODE_INPUT; - GPIO_InitStructure.Pull = GPIO_NOPULL; - GPIO_InitStructure.Speed = GPIO_SPEED_FREQ_VERY_HIGH; - GPIO_InitStructure.Alternate = 0; - GPIO_InitStructure.Pin = GPIO_PIN_12; - HAL_GPIO_Init(GPIOD, &GPIO_InitStructure); - - GPIO_InitStructure.Mode = GPIO_MODE_AF_PP; - GPIO_InitStructure.Pull = GPIO_NOPULL; - GPIO_InitStructure.Speed = GPIO_SPEED_FREQ_VERY_HIGH; - GPIO_InitStructure.Alternate = GPIO_AF12_FMC; - // LCD_CS/PD7 LCD_RS/PD11 LCD_RD/PD4 LCD_WR/PD5 - GPIO_InitStructure.Pin = GPIO_PIN_7 | GPIO_PIN_11 | GPIO_PIN_4 | GPIO_PIN_5; - HAL_GPIO_Init(GPIOD, &GPIO_InitStructure); - // LCD_D0/PD14 LCD_D1/PD15 LCD_D2/PD0 LCD_D3/PD1 - GPIO_InitStructure.Pin = GPIO_PIN_14 | GPIO_PIN_15 | GPIO_PIN_0 | GPIO_PIN_1; - HAL_GPIO_Init(GPIOD, &GPIO_InitStructure); - // LCD_D4/PE7 LCD_D5/PE8 LCD_D6/PE9 LCD_D7/PE10 - GPIO_InitStructure.Pin = GPIO_PIN_7 | GPIO_PIN_8 | GPIO_PIN_9 | GPIO_PIN_10; - HAL_GPIO_Init(GPIOE, &GPIO_InitStructure); - - // Reference UM1725 "Description of STM32F4 HAL and LL drivers", section 64.2.1 "How to use this driver" - SRAM_HandleTypeDef external_display_data_sram; - external_display_data_sram.Instance = FMC_NORSRAM_DEVICE; - external_display_data_sram.Init.NSBank = FMC_NORSRAM_BANK1; - external_display_data_sram.Init.DataAddressMux = FMC_DATA_ADDRESS_MUX_DISABLE; - external_display_data_sram.Init.MemoryType = FMC_MEMORY_TYPE_SRAM; - external_display_data_sram.Init.MemoryDataWidth = FMC_NORSRAM_MEM_BUS_WIDTH_8; - external_display_data_sram.Init.BurstAccessMode = FMC_BURST_ACCESS_MODE_DISABLE; - external_display_data_sram.Init.WaitSignalPolarity = FMC_WAIT_SIGNAL_POLARITY_LOW; - external_display_data_sram.Init.WrapMode = FMC_WRAP_MODE_DISABLE; - external_display_data_sram.Init.WaitSignalActive = FMC_WAIT_TIMING_BEFORE_WS; - external_display_data_sram.Init.WriteOperation = FMC_WRITE_OPERATION_ENABLE; - external_display_data_sram.Init.WaitSignal = FMC_WAIT_SIGNAL_DISABLE; - external_display_data_sram.Init.ExtendedMode = FMC_EXTENDED_MODE_DISABLE; - external_display_data_sram.Init.AsynchronousWait = FMC_ASYNCHRONOUS_WAIT_DISABLE; - external_display_data_sram.Init.WriteBurst = FMC_WRITE_BURST_DISABLE; - external_display_data_sram.Init.ContinuousClock = FMC_CONTINUOUS_CLOCK_SYNC_ONLY; - external_display_data_sram.Init.PageSize = FMC_PAGE_SIZE_NONE; - - // reference RM0090 section 37.5 Table 259, 37.5.4, Mode 1 SRAM, and 37.5.6 - FMC_NORSRAM_TimingTypeDef normal_mode_timing; - normal_mode_timing.AddressSetupTime = 4; - normal_mode_timing.AddressHoldTime = 1; - normal_mode_timing.DataSetupTime = 4; - normal_mode_timing.BusTurnAroundDuration = 0; - normal_mode_timing.CLKDivision = 2; - normal_mode_timing.DataLatency = 2; - normal_mode_timing.AccessMode = FMC_ACCESS_MODE_A; - - HAL_SRAM_Init(&external_display_data_sram, &normal_mode_timing, NULL); - - display_hardware_reset(); - - uint32_t id = display_identify(); - if (id == DISPLAY_ID_GC9307) { - CMD(0xFE); // Inter Register Enable1 - CMD(0xEF); // Inter Register Enable2 - CMD(0x35); DATA(0x00); // TEON: Tearing Effect Line On; V-blanking only - CMD(0x3A); DATA(0x55); // COLMOD: Interface Pixel format; 65K color: 16-bit/pixel (RGB 5-6-5 bits input) - // CMD(0xE8); DATA(0x12); DATA(0x00); // Frame Rate - CMD(0xC3); DATA(0x27); // Power Control 2 - CMD(0xC4); DATA(0x18); // Power Control 3 - CMD(0xC9); DATA(0x1F); // Power Control 4 - CMD(0xC5); DATA(0x0F); - CMD(0xC6); DATA(0x00); - CMD(0xC7); DATA(0x10); - CMD(0xC8); DATA(0x01); - CMD(0xFF); DATA(0x62); - CMD(0x99); DATA(0x3E); - CMD(0x9D); DATA(0x4B); - CMD(0x8E); DATA(0x0F); - // SET_GAMMA1 - CMD(0xF0); DATA(0x8F); DATA(0x1B); DATA(0x05); DATA(0x06); DATA(0x07); DATA(0x42); - // SET_GAMMA3 - CMD(0xF2); DATA(0x5C); DATA(0x1F); DATA(0x12); DATA(0x10); DATA(0x07); DATA(0x43); - // SET_GAMMA2 - CMD(0xF1); DATA(0x59); DATA(0xCF); DATA(0xCF); DATA(0x35); DATA(0x37); DATA(0x8F); - // SET_GAMMA4 - CMD(0xF3); DATA(0x58); DATA(0xCF); DATA(0xCF); DATA(0x35); DATA(0x37); DATA(0x8F); - } else - if (id == DISPLAY_ID_ST7789V) { - CMD(0x35); DATA(0x00); // TEON: Tearing Effect Line On; V-blanking only - CMD(0x3A); DATA(0x55); // COLMOD: Interface Pixel format; 65K color: 16-bit/pixel (RGB 5-6-5 bits input) - CMD(0xDF); DATA(0x5A); DATA(0x69); DATA(0x02); DATA(0x01); // CMD2EN: Commands in command table 2 can be executed when EXTC level is Low - CMD(0xC0); DATA(0x20); // LCMCTRL: LCM Control: XOR RGB setting - CMD(0xE4); DATA(0x1D); DATA(0x0A); DATA(0x11); // GATECTRL: Gate Control; NL = 240 gate lines, first scan line is gate 80.; gate scan direction 319 -> 0 - // the above config is the most important and definitely necessary - CMD(0xD0); DATA(0xA4); DATA(0xA1); // PWCTRL1: Power Control 1 - // gamma curve 1 - // CMD(0xE0); DATA(0x70); DATA(0x2C); DATA(0x2E); DATA(0x15); DATA(0x10); DATA(0x09); DATA(0x48); DATA(0x33); DATA(0x53); DATA(0x0B); DATA(0x19); DATA(0x18); DATA(0x20); DATA(0x25); - // gamma curve 2 - // CMD(0xE1); DATA(0x70); DATA(0x2C); DATA(0x2E); DATA(0x15); DATA(0x10); DATA(0x09); DATA(0x48); DATA(0x33); DATA(0x53); DATA(0x0B); DATA(0x19); DATA(0x18); DATA(0x20); DATA(0x25); - } else - if (id == DISPLAY_ID_ILI9341V) { - // most recent manual: https://www.newhavendisplay.com/app_notes/ILI9341.pdf - CMD(0x35); DATA(0x00); // TEON: Tearing Effect Line On; V-blanking only - CMD(0x3A); DATA(0x55); // COLMOD: Interface Pixel format; 65K color: 16-bit/pixel (RGB 5-6-5 bits input) - CMD(0xB6); DATA(0x0A); DATA(0xC2); DATA(0x27); DATA(0x00); // Display Function Control: gate scan direction 319 -> 0 - CMD(0xF6); DATA(0x09); DATA(0x30); DATA(0x00); // Interface Control: XOR BGR as ST7789V does - // the above config is the most important and definitely necessary - CMD(0xCF); DATA(0x00); DATA(0xC1); DATA(0x30); - CMD(0xED); DATA(0x64); DATA(0x03); DATA(0x12); DATA(0x81); - CMD(0xE8); DATA(0x85); DATA(0x10); DATA(0x7A); - CMD(0xF7); DATA(0x20); - CMD(0xEA); DATA(0x00); DATA(0x00); - CMD(0xC0); DATA(0x23); // power control VRH[5:0] - CMD(0xC1); DATA(0x12); // power control SAP[2:0] BT[3:0] - CMD(0xC5); DATA(0x60); DATA(0x44); // vcm control 1 - CMD(0xC7); DATA(0x8A); // vcm control 2 - CMD(0xB1); DATA(0x00); DATA(0x18); // framerate - CMD(0xF2); DATA(0x00); // 3 gamma func disable - // gamma curve 1 - CMD(0xE0); DATA(0x0F); DATA(0x2F); DATA(0x2C); DATA(0x0B); DATA(0x0F); DATA(0x09); DATA(0x56); DATA(0xD9); DATA(0x4A); DATA(0x0B); DATA(0x14); DATA(0x05); DATA(0x0C); DATA(0x06); DATA(0x00); - // gamma curve 2 - CMD(0xE1); DATA(0x00); DATA(0x10); DATA(0x13); DATA(0x04); DATA(0x10); DATA(0x06); DATA(0x25); DATA(0x26); DATA(0x3B); DATA(0x04); DATA(0x0B); DATA(0x0A); DATA(0x33); DATA(0x39); DATA(0x0F); - } - - display_clear(); - display_unsleep(); +void display_init(void) { + // init peripherials + __HAL_RCC_GPIOE_CLK_ENABLE(); + __HAL_RCC_TIM1_CLK_ENABLE(); + __HAL_RCC_FMC_CLK_ENABLE(); + + GPIO_InitTypeDef GPIO_InitStructure; + + // LCD_PWM/PA7 (backlight control) + GPIO_InitStructure.Mode = GPIO_MODE_AF_PP; + GPIO_InitStructure.Pull = GPIO_NOPULL; + GPIO_InitStructure.Speed = GPIO_SPEED_FREQ_VERY_HIGH; + GPIO_InitStructure.Alternate = GPIO_AF1_TIM1; + GPIO_InitStructure.Pin = GPIO_PIN_7; + HAL_GPIO_Init(GPIOA, &GPIO_InitStructure); + + // enable PWM timer + TIM_HandleTypeDef TIM1_Handle; + TIM1_Handle.Instance = TIM1; + TIM1_Handle.Init.Period = LED_PWM_TIM_PERIOD - 1; + // TIM1/APB2 source frequency equals to SystemCoreClock in our configuration, + // we want 1 MHz + TIM1_Handle.Init.Prescaler = SystemCoreClock / 1000000 - 1; + TIM1_Handle.Init.ClockDivision = TIM_CLOCKDIVISION_DIV1; + TIM1_Handle.Init.CounterMode = TIM_COUNTERMODE_UP; + TIM1_Handle.Init.RepetitionCounter = 0; + HAL_TIM_PWM_Init(&TIM1_Handle); + + TIM_OC_InitTypeDef TIM_OC_InitStructure; + TIM_OC_InitStructure.Pulse = 0; + TIM_OC_InitStructure.OCMode = TIM_OCMODE_PWM2; + TIM_OC_InitStructure.OCPolarity = TIM_OCPOLARITY_HIGH; + TIM_OC_InitStructure.OCFastMode = TIM_OCFAST_DISABLE; + TIM_OC_InitStructure.OCNPolarity = TIM_OCNPOLARITY_HIGH; + TIM_OC_InitStructure.OCIdleState = TIM_OCIDLESTATE_SET; + TIM_OC_InitStructure.OCNIdleState = TIM_OCNIDLESTATE_SET; + HAL_TIM_PWM_ConfigChannel(&TIM1_Handle, &TIM_OC_InitStructure, TIM_CHANNEL_1); + + display_backlight(0); + + HAL_TIM_PWM_Start(&TIM1_Handle, TIM_CHANNEL_1); + HAL_TIMEx_PWMN_Start(&TIM1_Handle, TIM_CHANNEL_1); + + // LCD_RST/PC14 + GPIO_InitStructure.Mode = GPIO_MODE_OUTPUT_PP; + GPIO_InitStructure.Pull = GPIO_NOPULL; + GPIO_InitStructure.Speed = GPIO_SPEED_FREQ_LOW; + GPIO_InitStructure.Alternate = 0; + GPIO_InitStructure.Pin = GPIO_PIN_14; + HAL_GPIO_WritePin(GPIOC, GPIO_PIN_14, + GPIO_PIN_RESET); // default to keeping display in reset + HAL_GPIO_Init(GPIOC, &GPIO_InitStructure); + + // LCD_FMARK/PD12 (tearing effect) + GPIO_InitStructure.Mode = GPIO_MODE_INPUT; + GPIO_InitStructure.Pull = GPIO_NOPULL; + GPIO_InitStructure.Speed = GPIO_SPEED_FREQ_VERY_HIGH; + GPIO_InitStructure.Alternate = 0; + GPIO_InitStructure.Pin = GPIO_PIN_12; + HAL_GPIO_Init(GPIOD, &GPIO_InitStructure); + + GPIO_InitStructure.Mode = GPIO_MODE_AF_PP; + GPIO_InitStructure.Pull = GPIO_NOPULL; + GPIO_InitStructure.Speed = GPIO_SPEED_FREQ_VERY_HIGH; + GPIO_InitStructure.Alternate = GPIO_AF12_FMC; + // LCD_CS/PD7 LCD_RS/PD11 LCD_RD/PD4 + // LCD_WR/PD5 + GPIO_InitStructure.Pin = GPIO_PIN_7 | GPIO_PIN_11 | GPIO_PIN_4 | GPIO_PIN_5; + HAL_GPIO_Init(GPIOD, &GPIO_InitStructure); + // LCD_D0/PD14 LCD_D1/PD15 LCD_D2/PD0 + // LCD_D3/PD1 + GPIO_InitStructure.Pin = GPIO_PIN_14 | GPIO_PIN_15 | GPIO_PIN_0 | GPIO_PIN_1; + HAL_GPIO_Init(GPIOD, &GPIO_InitStructure); + // LCD_D4/PE7 LCD_D5/PE8 LCD_D6/PE9 + // LCD_D7/PE10 + GPIO_InitStructure.Pin = GPIO_PIN_7 | GPIO_PIN_8 | GPIO_PIN_9 | GPIO_PIN_10; + HAL_GPIO_Init(GPIOE, &GPIO_InitStructure); + + // Reference UM1725 "Description of STM32F4 HAL and LL drivers", + // section 64.2.1 "How to use this driver" + SRAM_HandleTypeDef external_display_data_sram; + external_display_data_sram.Instance = FMC_NORSRAM_DEVICE; + external_display_data_sram.Init.NSBank = FMC_NORSRAM_BANK1; + external_display_data_sram.Init.DataAddressMux = FMC_DATA_ADDRESS_MUX_DISABLE; + external_display_data_sram.Init.MemoryType = FMC_MEMORY_TYPE_SRAM; + external_display_data_sram.Init.MemoryDataWidth = FMC_NORSRAM_MEM_BUS_WIDTH_8; + external_display_data_sram.Init.BurstAccessMode = + FMC_BURST_ACCESS_MODE_DISABLE; + external_display_data_sram.Init.WaitSignalPolarity = + FMC_WAIT_SIGNAL_POLARITY_LOW; + external_display_data_sram.Init.WrapMode = FMC_WRAP_MODE_DISABLE; + external_display_data_sram.Init.WaitSignalActive = FMC_WAIT_TIMING_BEFORE_WS; + external_display_data_sram.Init.WriteOperation = FMC_WRITE_OPERATION_ENABLE; + external_display_data_sram.Init.WaitSignal = FMC_WAIT_SIGNAL_DISABLE; + external_display_data_sram.Init.ExtendedMode = FMC_EXTENDED_MODE_DISABLE; + external_display_data_sram.Init.AsynchronousWait = + FMC_ASYNCHRONOUS_WAIT_DISABLE; + external_display_data_sram.Init.WriteBurst = FMC_WRITE_BURST_DISABLE; + external_display_data_sram.Init.ContinuousClock = + FMC_CONTINUOUS_CLOCK_SYNC_ONLY; + external_display_data_sram.Init.PageSize = FMC_PAGE_SIZE_NONE; + + // reference RM0090 section 37.5 Table 259, 37.5.4, Mode 1 SRAM, and 37.5.6 + FMC_NORSRAM_TimingTypeDef normal_mode_timing; + normal_mode_timing.AddressSetupTime = 4; + normal_mode_timing.AddressHoldTime = 1; + normal_mode_timing.DataSetupTime = 4; + normal_mode_timing.BusTurnAroundDuration = 0; + normal_mode_timing.CLKDivision = 2; + normal_mode_timing.DataLatency = 2; + normal_mode_timing.AccessMode = FMC_ACCESS_MODE_A; + + HAL_SRAM_Init(&external_display_data_sram, &normal_mode_timing, NULL); + + display_hardware_reset(); + + uint32_t id = display_identify(); + if (id == DISPLAY_ID_GC9307) { + CMD(0xFE); // Inter Register Enable1 + CMD(0xEF); // Inter Register Enable2 + CMD(0x35); + DATA(0x00); // TEON: Tearing Effect Line On; V-blanking only + CMD(0x3A); + DATA(0x55); // COLMOD: Interface Pixel format; 65K color: 16-bit/pixel (RGB + // 5-6-5 bits input) + // CMD(0xE8); DATA(0x12); DATA(0x00); // Frame Rate + CMD(0xC3); + DATA(0x27); // Power Control 2 + CMD(0xC4); + DATA(0x18); // Power Control 3 + CMD(0xC9); + DATA(0x1F); // Power Control 4 + CMD(0xC5); + DATA(0x0F); + CMD(0xC6); + DATA(0x00); + CMD(0xC7); + DATA(0x10); + CMD(0xC8); + DATA(0x01); + CMD(0xFF); + DATA(0x62); + CMD(0x99); + DATA(0x3E); + CMD(0x9D); + DATA(0x4B); + CMD(0x8E); + DATA(0x0F); + // SET_GAMMA1 + CMD(0xF0); + DATA(0x8F); + DATA(0x1B); + DATA(0x05); + DATA(0x06); + DATA(0x07); + DATA(0x42); + // SET_GAMMA3 + CMD(0xF2); + DATA(0x5C); + DATA(0x1F); + DATA(0x12); + DATA(0x10); + DATA(0x07); + DATA(0x43); + // SET_GAMMA2 + CMD(0xF1); + DATA(0x59); + DATA(0xCF); + DATA(0xCF); + DATA(0x35); + DATA(0x37); + DATA(0x8F); + // SET_GAMMA4 + CMD(0xF3); + DATA(0x58); + DATA(0xCF); + DATA(0xCF); + DATA(0x35); + DATA(0x37); + DATA(0x8F); + } else if (id == DISPLAY_ID_ST7789V) { + CMD(0x35); + DATA(0x00); // TEON: Tearing Effect Line On; V-blanking only + CMD(0x3A); + DATA(0x55); // COLMOD: Interface Pixel format; 65K color: 16-bit/pixel (RGB + // 5-6-5 bits input) + CMD(0xDF); + DATA(0x5A); + DATA(0x69); + DATA(0x02); + DATA(0x01); // CMD2EN: Commands in command table 2 can be executed when + // EXTC level is Low + CMD(0xC0); + DATA(0x20); // LCMCTRL: LCM Control: XOR RGB setting + CMD(0xE4); + DATA(0x1D); + DATA(0x0A); + DATA(0x11); // GATECTRL: Gate Control; NL = 240 gate lines, first scan line + // is gate 80.; gate scan direction 319 -> 0 + // the above config is the most important and definitely necessary + CMD(0xD0); + DATA(0xA4); + DATA(0xA1); // PWCTRL1: Power Control 1 + // gamma curve 1 + // CMD(0xE0); DATA(0x70); DATA(0x2C); DATA(0x2E); DATA(0x15); DATA(0x10); + // DATA(0x09); DATA(0x48); DATA(0x33); DATA(0x53); DATA(0x0B); DATA(0x19); + // DATA(0x18); DATA(0x20); DATA(0x25); gamma curve 2 CMD(0xE1); DATA(0x70); + // DATA(0x2C); DATA(0x2E); DATA(0x15); DATA(0x10); DATA(0x09); DATA(0x48); + // DATA(0x33); DATA(0x53); DATA(0x0B); DATA(0x19); DATA(0x18); DATA(0x20); + // DATA(0x25); + } else if (id == DISPLAY_ID_ILI9341V) { + // most recent manual: https://www.newhavendisplay.com/app_notes/ILI9341.pdf + CMD(0x35); + DATA(0x00); // TEON: Tearing Effect Line On; V-blanking only + CMD(0x3A); + DATA(0x55); // COLMOD: Interface Pixel format; 65K color: 16-bit/pixel (RGB + // 5-6-5 bits input) + CMD(0xB6); + DATA(0x0A); + DATA(0xC2); + DATA(0x27); + DATA(0x00); // Display Function Control: gate scan direction 319 -> 0 + CMD(0xF6); + DATA(0x09); + DATA(0x30); + DATA(0x00); // Interface Control: XOR BGR as ST7789V does + // the above config is the most important and definitely necessary + CMD(0xCF); + DATA(0x00); + DATA(0xC1); + DATA(0x30); + CMD(0xED); + DATA(0x64); + DATA(0x03); + DATA(0x12); + DATA(0x81); + CMD(0xE8); + DATA(0x85); + DATA(0x10); + DATA(0x7A); + CMD(0xF7); + DATA(0x20); + CMD(0xEA); + DATA(0x00); + DATA(0x00); + CMD(0xC0); + DATA(0x23); // power control VRH[5:0] + CMD(0xC1); + DATA(0x12); // power control SAP[2:0] BT[3:0] + CMD(0xC5); + DATA(0x60); + DATA(0x44); // vcm control 1 + CMD(0xC7); + DATA(0x8A); // vcm control 2 + CMD(0xB1); + DATA(0x00); + DATA(0x18); // framerate + CMD(0xF2); + DATA(0x00); // 3 gamma func disable + // gamma curve 1 + CMD(0xE0); + DATA(0x0F); + DATA(0x2F); + DATA(0x2C); + DATA(0x0B); + DATA(0x0F); + DATA(0x09); + DATA(0x56); + DATA(0xD9); + DATA(0x4A); + DATA(0x0B); + DATA(0x14); + DATA(0x05); + DATA(0x0C); + DATA(0x06); + DATA(0x00); + // gamma curve 2 + CMD(0xE1); + DATA(0x00); + DATA(0x10); + DATA(0x13); + DATA(0x04); + DATA(0x10); + DATA(0x06); + DATA(0x25); + DATA(0x26); + DATA(0x3B); + DATA(0x04); + DATA(0x0B); + DATA(0x0A); + DATA(0x33); + DATA(0x39); + DATA(0x0F); + } + + display_clear(); + display_unsleep(); } -void display_refresh(void) -{ - uint32_t id = display_identify(); - if (id && (id != DISPLAY_ID_GC9307)) { - // synchronize with the panel synchronization signal in order to avoid visual tearing effects - while (GPIO_PIN_RESET == HAL_GPIO_ReadPin(GPIOD, GPIO_PIN_12)) { } - while (GPIO_PIN_SET == HAL_GPIO_ReadPin(GPIOD, GPIO_PIN_12)) { } +void display_refresh(void) { + uint32_t id = display_identify(); + if (id && (id != DISPLAY_ID_GC9307)) { + // synchronize with the panel synchronization signal in order to avoid + // visual tearing effects + while (GPIO_PIN_RESET == HAL_GPIO_ReadPin(GPIOD, GPIO_PIN_12)) { } + while (GPIO_PIN_SET == HAL_GPIO_ReadPin(GPIOD, GPIO_PIN_12)) { + } + } } -void display_save(const char *prefix) -{ -} +void display_save(const char *prefix) {} diff --git a/embed/extmod/modtrezorui/display-unix.h b/embed/extmod/modtrezorui/display-unix.h index cef387b0c..1da6218ab 100644 --- a/embed/extmod/modtrezorui/display-unix.h +++ b/embed/extmod/modtrezorui/display-unix.h @@ -27,23 +27,23 @@ #if TREZOR_MODEL == T #ifdef TREZOR_EMULATOR_RASPI -#define WINDOW_WIDTH 480 -#define WINDOW_HEIGHT 320 -#define TOUCH_OFFSET_X 110 -#define TOUCH_OFFSET_Y 40 +#define WINDOW_WIDTH 480 +#define WINDOW_HEIGHT 320 +#define TOUCH_OFFSET_X 110 +#define TOUCH_OFFSET_Y 40 #else -#define WINDOW_WIDTH 400 -#define WINDOW_HEIGHT 600 -#define TOUCH_OFFSET_X 80 -#define TOUCH_OFFSET_Y 110 +#define WINDOW_WIDTH 400 +#define WINDOW_HEIGHT 600 +#define TOUCH_OFFSET_X 80 +#define TOUCH_OFFSET_Y 110 #endif #elif TREZOR_MODEL == 1 -#define WINDOW_WIDTH 200 -#define WINDOW_HEIGHT 340 -#define TOUCH_OFFSET_X 36 -#define TOUCH_OFFSET_Y 92 +#define WINDOW_WIDTH 200 +#define WINDOW_HEIGHT 340 +#define TOUCH_OFFSET_X 36 +#define TOUCH_OFFSET_Y 92 #else #error Unknown TREZOR Model @@ -57,162 +57,172 @@ int sdl_display_res_x = DISPLAY_RESX, sdl_display_res_y = DISPLAY_RESY; int sdl_touch_offset_x, sdl_touch_offset_y; static struct { - struct { - uint16_t x, y; - } start; - struct { - uint16_t x, y; - } end; - struct { - uint16_t x, y; - } pos; + struct { + uint16_t x, y; + } start; + struct { + uint16_t x, y; + } end; + struct { + uint16_t x, y; + } pos; } PIXELWINDOW; void PIXELDATA(uint16_t c) { #if TREZOR_MODEL == 1 - // set to white if highest bits of all R, G, B values are set to 1 - // bin(10000 100000 10000) = hex(0x8410) - // otherwise set to black - c = (c & 0x8410) ? 0xFFFF : 0x0000; + // set to white if highest bits of all R, G, B values are set to 1 + // bin(10000 100000 10000) = hex(0x8410) + // otherwise set to black + c = (c & 0x8410) ? 0xFFFF : 0x0000; #endif - if (!RENDERER) { - display_init(); - } - if (PIXELWINDOW.pos.x <= PIXELWINDOW.end.x && PIXELWINDOW.pos.y <= PIXELWINDOW.end.y) { - ((uint16_t *)BUFFER->pixels)[PIXELWINDOW.pos.x + PIXELWINDOW.pos.y * BUFFER->pitch / sizeof(uint16_t)] = c; - } - PIXELWINDOW.pos.x++; - if (PIXELWINDOW.pos.x > PIXELWINDOW.end.x) { - PIXELWINDOW.pos.x = PIXELWINDOW.start.x; - PIXELWINDOW.pos.y++; - } + if (!RENDERER) { + display_init(); + } + if (PIXELWINDOW.pos.x <= PIXELWINDOW.end.x && + PIXELWINDOW.pos.y <= PIXELWINDOW.end.y) { + ((uint16_t *) + BUFFER->pixels)[PIXELWINDOW.pos.x + PIXELWINDOW.pos.y * BUFFER->pitch / + sizeof(uint16_t)] = c; + } + PIXELWINDOW.pos.x++; + if (PIXELWINDOW.pos.x > PIXELWINDOW.end.x) { + PIXELWINDOW.pos.x = PIXELWINDOW.start.x; + PIXELWINDOW.pos.y++; + } } #else #define PIXELDATA(X) (void)(X) #endif -void display_init(void) -{ +void display_init(void) { #ifndef TREZOR_EMULATOR_NOUI - if (SDL_Init(SDL_INIT_VIDEO) != 0) { - printf("%s\n", SDL_GetError()); - ensure(secfalse, "SDL_Init error"); - } - atexit(SDL_Quit); - SDL_Window *win = SDL_CreateWindow("TREZOR Emulator", SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED, WINDOW_WIDTH, WINDOW_HEIGHT, + if (SDL_Init(SDL_INIT_VIDEO) != 0) { + printf("%s\n", SDL_GetError()); + ensure(secfalse, "SDL_Init error"); + } + atexit(SDL_Quit); + SDL_Window *win = + SDL_CreateWindow("TREZOR Emulator", SDL_WINDOWPOS_UNDEFINED, + SDL_WINDOWPOS_UNDEFINED, WINDOW_WIDTH, WINDOW_HEIGHT, #ifdef TREZOR_EMULATOR_RASPI - SDL_WINDOW_SHOWN | SDL_WINDOW_FULLSCREEN + SDL_WINDOW_SHOWN | SDL_WINDOW_FULLSCREEN #else - SDL_WINDOW_SHOWN | SDL_WINDOW_ALLOW_HIGHDPI + SDL_WINDOW_SHOWN | SDL_WINDOW_ALLOW_HIGHDPI #endif - ); - if (!win) { - printf("%s\n", SDL_GetError()); - ensure(secfalse, "SDL_CreateWindow error"); - } - RENDERER = SDL_CreateRenderer(win, -1, SDL_RENDERER_SOFTWARE); - if (!RENDERER) { - printf("%s\n", SDL_GetError()); - SDL_DestroyWindow(win); - ensure(secfalse, "SDL_CreateRenderer error"); - } - SDL_SetRenderDrawColor(RENDERER, 0, 0, 0, 255); - SDL_RenderClear(RENDERER); - BUFFER = SDL_CreateRGBSurface(0, MAX_DISPLAY_RESX, MAX_DISPLAY_RESY, 16, 0xF800, 0x07E0, 0x001F, 0x0000); - TEXTURE = SDL_CreateTexture(RENDERER, SDL_PIXELFORMAT_RGB565, SDL_TEXTUREACCESS_STREAMING, DISPLAY_RESX, DISPLAY_RESY); - SDL_SetTextureBlendMode(TEXTURE, SDL_BLENDMODE_BLEND); + ); + if (!win) { + printf("%s\n", SDL_GetError()); + ensure(secfalse, "SDL_CreateWindow error"); + } + RENDERER = SDL_CreateRenderer(win, -1, SDL_RENDERER_SOFTWARE); + if (!RENDERER) { + printf("%s\n", SDL_GetError()); + SDL_DestroyWindow(win); + ensure(secfalse, "SDL_CreateRenderer error"); + } + SDL_SetRenderDrawColor(RENDERER, 0, 0, 0, 255); + SDL_RenderClear(RENDERER); + BUFFER = SDL_CreateRGBSurface(0, MAX_DISPLAY_RESX, MAX_DISPLAY_RESY, 16, + 0xF800, 0x07E0, 0x001F, 0x0000); + TEXTURE = SDL_CreateTexture(RENDERER, SDL_PIXELFORMAT_RGB565, + SDL_TEXTUREACCESS_STREAMING, DISPLAY_RESX, + DISPLAY_RESY); + SDL_SetTextureBlendMode(TEXTURE, SDL_BLENDMODE_BLEND); #ifdef __APPLE__ - // macOS Mojave SDL black screen workaround - SDL_PumpEvents(); - SDL_SetWindowSize(win, WINDOW_WIDTH, WINDOW_HEIGHT); + // macOS Mojave SDL black screen workaround + SDL_PumpEvents(); + SDL_SetWindowSize(win, WINDOW_WIDTH, WINDOW_HEIGHT); #endif - // TODO: find better way how to embed/distribute background image + // TODO: find better way how to embed/distribute background image #ifdef TREZOR_EMULATOR_RASPI - BACKGROUND = IMG_LoadTexture(RENDERER, "../embed/unix/background_raspi.jpg"); + BACKGROUND = IMG_LoadTexture(RENDERER, "../embed/unix/background_raspi.jpg"); #else - BACKGROUND = IMG_LoadTexture(RENDERER, "../embed/unix/background_" XSTR(TREZOR_MODEL) ".jpg"); + BACKGROUND = IMG_LoadTexture( + RENDERER, "../embed/unix/background_" XSTR(TREZOR_MODEL) ".jpg"); #endif - if (BACKGROUND) { - SDL_SetTextureBlendMode(BACKGROUND, SDL_BLENDMODE_NONE); - sdl_touch_offset_x = TOUCH_OFFSET_X; - sdl_touch_offset_y = TOUCH_OFFSET_Y; - } else { - SDL_SetWindowSize(win, DISPLAY_RESX + 2 * EMULATOR_BORDER, DISPLAY_RESY + 2 * EMULATOR_BORDER); - sdl_touch_offset_x = EMULATOR_BORDER; - sdl_touch_offset_y = EMULATOR_BORDER; - } - DISPLAY_BACKLIGHT = 0; + if (BACKGROUND) { + SDL_SetTextureBlendMode(BACKGROUND, SDL_BLENDMODE_NONE); + sdl_touch_offset_x = TOUCH_OFFSET_X; + sdl_touch_offset_y = TOUCH_OFFSET_Y; + } else { + SDL_SetWindowSize(win, DISPLAY_RESX + 2 * EMULATOR_BORDER, + DISPLAY_RESY + 2 * EMULATOR_BORDER); + sdl_touch_offset_x = EMULATOR_BORDER; + sdl_touch_offset_y = EMULATOR_BORDER; + } + DISPLAY_BACKLIGHT = 0; #ifdef TREZOR_EMULATOR_RASPI - DISPLAY_ORIENTATION = 270; - SDL_ShowCursor(SDL_DISABLE); + DISPLAY_ORIENTATION = 270; + SDL_ShowCursor(SDL_DISABLE); #else - DISPLAY_ORIENTATION = 0; + DISPLAY_ORIENTATION = 0; #endif #endif } -static void display_set_window(uint16_t x0, uint16_t y0, uint16_t x1, uint16_t y1) -{ +static void display_set_window(uint16_t x0, uint16_t y0, uint16_t x1, + uint16_t y1) { #ifndef TREZOR_EMULATOR_NOUI - if (!RENDERER) { - display_init(); - } - PIXELWINDOW.start.x = x0; PIXELWINDOW.start.y = y0; - PIXELWINDOW.end.x = x1; PIXELWINDOW.end.y = y1; - PIXELWINDOW.pos.x = x0; PIXELWINDOW.pos.y = y0; + if (!RENDERER) { + display_init(); + } + PIXELWINDOW.start.x = x0; + PIXELWINDOW.start.y = y0; + PIXELWINDOW.end.x = x1; + PIXELWINDOW.end.y = y1; + PIXELWINDOW.pos.x = x0; + PIXELWINDOW.pos.y = y0; #endif } -void display_refresh(void) -{ +void display_refresh(void) { #ifndef TREZOR_EMULATOR_NOUI - if (!RENDERER) { - display_init(); - } - if (BACKGROUND) { - SDL_RenderCopy(RENDERER, BACKGROUND, NULL, NULL); - } else { - SDL_RenderClear(RENDERER); - } - SDL_UpdateTexture(TEXTURE, NULL, BUFFER->pixels, BUFFER->pitch); + if (!RENDERER) { + display_init(); + } + if (BACKGROUND) { + SDL_RenderCopy(RENDERER, BACKGROUND, NULL, NULL); + } else { + SDL_RenderClear(RENDERER); + } + SDL_UpdateTexture(TEXTURE, NULL, BUFFER->pixels, BUFFER->pitch); #define BACKLIGHT_NORMAL 150 - SDL_SetTextureAlphaMod(TEXTURE, MIN(255, 255 * DISPLAY_BACKLIGHT / BACKLIGHT_NORMAL)); - if (BACKGROUND) { - const SDL_Rect r = {TOUCH_OFFSET_X, TOUCH_OFFSET_Y, DISPLAY_RESX, DISPLAY_RESY}; - SDL_RenderCopyEx(RENDERER, TEXTURE, NULL, &r, DISPLAY_ORIENTATION, NULL, 0); - } else { - const SDL_Rect r = {EMULATOR_BORDER, EMULATOR_BORDER, DISPLAY_RESX, DISPLAY_RESY}; - SDL_RenderCopyEx(RENDERER, TEXTURE, NULL, &r, DISPLAY_ORIENTATION, NULL, 0); - } - SDL_RenderPresent(RENDERER); + SDL_SetTextureAlphaMod(TEXTURE, + MIN(255, 255 * DISPLAY_BACKLIGHT / BACKLIGHT_NORMAL)); + if (BACKGROUND) { + const SDL_Rect r = {TOUCH_OFFSET_X, TOUCH_OFFSET_Y, DISPLAY_RESX, + DISPLAY_RESY}; + SDL_RenderCopyEx(RENDERER, TEXTURE, NULL, &r, DISPLAY_ORIENTATION, NULL, 0); + } else { + const SDL_Rect r = {EMULATOR_BORDER, EMULATOR_BORDER, DISPLAY_RESX, + DISPLAY_RESY}; + SDL_RenderCopyEx(RENDERER, TEXTURE, NULL, &r, DISPLAY_ORIENTATION, NULL, 0); + } + SDL_RenderPresent(RENDERER); #endif } -static void display_set_orientation(int degrees) -{ - display_refresh(); -} +static void display_set_orientation(int degrees) { display_refresh(); } -static void display_set_backlight(int val) -{ - display_refresh(); -} +static void display_set_backlight(int val) { display_refresh(); } -void display_save(const char *prefix) -{ +void display_save(const char *prefix) { #ifndef TREZOR_EMULATOR_NOUI - if (!RENDERER) { - display_init(); - } - static uint32_t cnt = 0; - char fname[256]; - snprintf(fname, sizeof(fname), "%s%08d.png", prefix, cnt); - const SDL_Rect rect = {0, 0, DISPLAY_RESX, DISPLAY_RESY}; - SDL_Surface *crop = SDL_CreateRGBSurface(BUFFER->flags, rect.w, rect.h, BUFFER->format->BitsPerPixel, BUFFER->format->Rmask, BUFFER->format->Gmask, BUFFER->format->Bmask, BUFFER->format->Amask); - SDL_BlitSurface(BUFFER, &rect, crop, NULL); - IMG_SavePNG(crop, fname); - SDL_FreeSurface(crop); - fprintf(stderr, "Saved screenshot to %s\n", fname); - cnt++; + if (!RENDERER) { + display_init(); + } + static uint32_t cnt = 0; + char fname[256]; + snprintf(fname, sizeof(fname), "%s%08d.png", prefix, cnt); + const SDL_Rect rect = {0, 0, DISPLAY_RESX, DISPLAY_RESY}; + SDL_Surface *crop = SDL_CreateRGBSurface( + BUFFER->flags, rect.w, rect.h, BUFFER->format->BitsPerPixel, + BUFFER->format->Rmask, BUFFER->format->Gmask, BUFFER->format->Bmask, + BUFFER->format->Amask); + SDL_BlitSurface(BUFFER, &rect, crop, NULL); + IMG_SavePNG(crop, fname); + SDL_FreeSurface(crop); + fprintf(stderr, "Saved screenshot to %s\n", fname); + cnt++; #endif } diff --git a/embed/extmod/modtrezorui/display.c b/embed/extmod/modtrezorui/display.c index f04876b17..eba7ecfd2 100644 --- a/embed/extmod/modtrezorui/display.c +++ b/embed/extmod/modtrezorui/display.c @@ -17,8 +17,8 @@ * along with this program. If not, see . */ -#include "inflate.h" #include "font_bitmap.h" +#include "inflate.h" #ifdef TREZOR_FONT_NORMAL_ENABLE #include "font_roboto_regular_20.h" #endif @@ -37,17 +37,15 @@ #include "common.h" #include "display.h" -#include #include +#include #include "memzero.h" static int DISPLAY_BACKLIGHT = -1; static int DISPLAY_ORIENTATION = -1; -static struct { - int x, y; -} DISPLAY_OFFSET; +static struct { int x, y; } DISPLAY_OFFSET; #ifdef TREZOR_EMULATOR #include "display-unix.h" @@ -61,317 +59,334 @@ static struct { // common display functions -static inline uint16_t interpolate_color(uint16_t color0, uint16_t color1, uint8_t step) -{ - uint8_t cr, cg, cb; - cr = (((color0 & 0xF800) >> 11) * step + ((color1 & 0xF800) >> 11) * (15 - step)) / 15; - cg = (((color0 & 0x07E0) >> 5) * step + ((color1 & 0x07E0) >> 5) * (15 - step)) / 15; - cb = ((color0 & 0x001F) * step + (color1 & 0x001F) * (15 - step)) / 15; - return (cr << 11) | (cg << 5) | cb; +static inline uint16_t interpolate_color(uint16_t color0, uint16_t color1, + uint8_t step) { + uint8_t cr, cg, cb; + cr = (((color0 & 0xF800) >> 11) * step + + ((color1 & 0xF800) >> 11) * (15 - step)) / + 15; + cg = (((color0 & 0x07E0) >> 5) * step + + ((color1 & 0x07E0) >> 5) * (15 - step)) / + 15; + cb = ((color0 & 0x001F) * step + (color1 & 0x001F) * (15 - step)) / 15; + return (cr << 11) | (cg << 5) | cb; } -static inline void set_color_table(uint16_t colortable[16], uint16_t fgcolor, uint16_t bgcolor) -{ - for (int i = 0; i < 16; i++) { - colortable[i] = interpolate_color(fgcolor, bgcolor, i); - } +static inline void set_color_table(uint16_t colortable[16], uint16_t fgcolor, + uint16_t bgcolor) { + for (int i = 0; i < 16; i++) { + colortable[i] = interpolate_color(fgcolor, bgcolor, i); + } } -static inline void clamp_coords(int x, int y, int w, int h, int *x0, int *y0, int *x1, int *y1) -{ - *x0 = MAX(x, 0); - *y0 = MAX(y, 0); - *x1 = MIN(x + w - 1, DISPLAY_RESX - 1); - *y1 = MIN(y + h - 1, DISPLAY_RESY - 1); +static inline void clamp_coords(int x, int y, int w, int h, int *x0, int *y0, + int *x1, int *y1) { + *x0 = MAX(x, 0); + *y0 = MAX(y, 0); + *x1 = MIN(x + w - 1, DISPLAY_RESX - 1); + *y1 = MIN(y + h - 1, DISPLAY_RESY - 1); } -void display_clear(void) -{ - const int saved_orientation = DISPLAY_ORIENTATION; - display_orientation(0); // set MADCTL first so that we can set the window correctly next - display_set_window(0, 0, MAX_DISPLAY_RESX - 1, MAX_DISPLAY_RESY - 1); // address the complete frame memory - for (uint32_t i = 0; i < MAX_DISPLAY_RESX * MAX_DISPLAY_RESY; i++) { - PIXELDATA(0x0000); // 2 bytes per pixel because we're using RGB 5-6-5 format - } - display_set_window(0, 0, DISPLAY_RESX - 1, DISPLAY_RESY - 1); // go back to restricted window - display_orientation(saved_orientation); // if valid, go back to the saved orientation +void display_clear(void) { + const int saved_orientation = DISPLAY_ORIENTATION; + display_orientation( + 0); // set MADCTL first so that we can set the window correctly next + display_set_window( + 0, 0, MAX_DISPLAY_RESX - 1, + MAX_DISPLAY_RESY - 1); // address the complete frame memory + for (uint32_t i = 0; i < MAX_DISPLAY_RESX * MAX_DISPLAY_RESY; i++) { + PIXELDATA( + 0x0000); // 2 bytes per pixel because we're using RGB 5-6-5 format + } + display_set_window(0, 0, DISPLAY_RESX - 1, + DISPLAY_RESY - 1); // go back to restricted window + display_orientation( + saved_orientation); // if valid, go back to the saved orientation } -void display_bar(int x, int y, int w, int h, uint16_t c) -{ - x += DISPLAY_OFFSET.x; - y += DISPLAY_OFFSET.y; - int x0, y0, x1, y1; - clamp_coords(x, y, w, h, &x0, &y0, &x1, &y1); - display_set_window(x0, y0, x1, y1); - for (int i = 0; i < (x1 - x0 + 1) * (y1 - y0 + 1); i++) { - PIXELDATA(c); - } +void display_bar(int x, int y, int w, int h, uint16_t c) { + x += DISPLAY_OFFSET.x; + y += DISPLAY_OFFSET.y; + int x0, y0, x1, y1; + clamp_coords(x, y, w, h, &x0, &y0, &x1, &y1); + display_set_window(x0, y0, x1, y1); + for (int i = 0; i < (x1 - x0 + 1) * (y1 - y0 + 1); i++) { + PIXELDATA(c); + } } #define CORNER_RADIUS 16 static const uint8_t cornertable[CORNER_RADIUS * CORNER_RADIUS] = { - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 5, 9, 12, 14, 15, - 0, 0, 0, 0, 0, 0, 0, 0, 3, 9, 15, 15, 15, 15, 15, 15, - 0, 0, 0, 0, 0, 0, 0, 8, 15, 15, 15, 15, 15, 15, 15, 15, - 0, 0, 0, 0, 0, 3, 12, 15, 15, 15, 15, 15, 15, 15, 15, 15, - 0, 0, 0, 0, 3, 14, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, - 0, 0, 0, 3, 14, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, - 0, 0, 0, 12, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, - 0, 0, 8, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, - 0, 3, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, - 0, 9, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, - 1, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, - 5, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, - 9, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, - 12, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, - 14, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, - 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 5, 9, 12, 14, 15, 0, 0, 0, + 0, 0, 0, 0, 0, 3, 9, 15, 15, 15, 15, 15, 15, 0, 0, 0, 0, 0, 0, + 0, 8, 15, 15, 15, 15, 15, 15, 15, 15, 0, 0, 0, 0, 0, 3, 12, 15, 15, + 15, 15, 15, 15, 15, 15, 15, 0, 0, 0, 0, 3, 14, 15, 15, 15, 15, 15, 15, + 15, 15, 15, 15, 0, 0, 0, 3, 14, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, + 15, 0, 0, 0, 12, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 0, 0, + 8, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 0, 3, 15, 15, 15, + 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 0, 9, 15, 15, 15, 15, 15, 15, + 15, 15, 15, 15, 15, 15, 15, 15, 1, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, + 15, 15, 15, 15, 15, 5, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, + 15, 15, 9, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 12, + 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 14, 15, 15, 15, + 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, + 15, 15, 15, 15, 15, 15, 15, 15, 15, }; -void display_bar_radius(int x, int y, int w, int h, uint16_t c, uint16_t b, uint8_t r) -{ - if (r != 2 && r != 4 && r != 8 && r != 16) { - return; - } else { - r = 16 / r; - } - uint16_t colortable[16]; - set_color_table(colortable, c, b); - x += DISPLAY_OFFSET.x; - y += DISPLAY_OFFSET.y; - int x0, y0, x1, y1; - clamp_coords(x, y, w, h, &x0, &y0, &x1, &y1); - display_set_window(x0, y0, x1, y1); - for (int j = y0; j <= y1; j++) { - for (int i = x0; i <= x1; i++) { - int rx = i - x; - int ry = j - y; - if (rx < CORNER_RADIUS / r && ry < CORNER_RADIUS / r) { - uint8_t c = cornertable[rx * r + ry * r * CORNER_RADIUS]; - PIXELDATA(colortable[c]); - } else - if (rx < CORNER_RADIUS / r && ry >= h - CORNER_RADIUS / r) { - uint8_t c = cornertable[rx * r + (h - 1 - ry) * r * CORNER_RADIUS]; - PIXELDATA(colortable[c]); - } else - if (rx >= w - CORNER_RADIUS / r && ry < CORNER_RADIUS / r) { - uint8_t c = cornertable[(w - 1 - rx) * r + ry * r * CORNER_RADIUS]; - PIXELDATA(colortable[c]); - } else - if (rx >= w - CORNER_RADIUS / r && ry >= h - CORNER_RADIUS / r) { - uint8_t c = cornertable[(w - 1 - rx) * r + (h - 1 - ry) * r * CORNER_RADIUS]; - PIXELDATA(colortable[c]); - } else { - PIXELDATA(c); - } - } +void display_bar_radius(int x, int y, int w, int h, uint16_t c, uint16_t b, + uint8_t r) { + if (r != 2 && r != 4 && r != 8 && r != 16) { + return; + } else { + r = 16 / r; + } + uint16_t colortable[16]; + set_color_table(colortable, c, b); + x += DISPLAY_OFFSET.x; + y += DISPLAY_OFFSET.y; + int x0, y0, x1, y1; + clamp_coords(x, y, w, h, &x0, &y0, &x1, &y1); + display_set_window(x0, y0, x1, y1); + for (int j = y0; j <= y1; j++) { + for (int i = x0; i <= x1; i++) { + int rx = i - x; + int ry = j - y; + if (rx < CORNER_RADIUS / r && ry < CORNER_RADIUS / r) { + uint8_t c = cornertable[rx * r + ry * r * CORNER_RADIUS]; + PIXELDATA(colortable[c]); + } else if (rx < CORNER_RADIUS / r && ry >= h - CORNER_RADIUS / r) { + uint8_t c = cornertable[rx * r + (h - 1 - ry) * r * CORNER_RADIUS]; + PIXELDATA(colortable[c]); + } else if (rx >= w - CORNER_RADIUS / r && ry < CORNER_RADIUS / r) { + uint8_t c = cornertable[(w - 1 - rx) * r + ry * r * CORNER_RADIUS]; + PIXELDATA(colortable[c]); + } else if (rx >= w - CORNER_RADIUS / r && ry >= h - CORNER_RADIUS / r) { + uint8_t c = + cornertable[(w - 1 - rx) * r + (h - 1 - ry) * r * CORNER_RADIUS]; + PIXELDATA(colortable[c]); + } else { + PIXELDATA(c); + } } + } } #if TREZOR_MODEL == T -static void inflate_callback_image(uint8_t byte1, uint32_t pos, void *userdata) -{ - static uint8_t byte0; - if (pos % 2 == 0) { - byte0 = byte1; - return; - } - const int w = ((const int *)userdata)[0]; - const int x0 = ((const int *)userdata)[1]; - const int x1 = ((const int *)userdata)[2]; - const int y0 = ((const int *)userdata)[3]; - const int y1 = ((const int *)userdata)[4]; - const int px = (pos / 2) % w; - const int py = (pos / 2) / w; - if (px >= x0 && px <= x1 && py >= y0 && py <= y1) { - PIXELDATA((byte0 << 8) | byte1); - } +static void inflate_callback_image(uint8_t byte1, uint32_t pos, + void *userdata) { + static uint8_t byte0; + if (pos % 2 == 0) { + byte0 = byte1; + return; + } + const int w = ((const int *)userdata)[0]; + const int x0 = ((const int *)userdata)[1]; + const int x1 = ((const int *)userdata)[2]; + const int y0 = ((const int *)userdata)[3]; + const int y1 = ((const int *)userdata)[4]; + const int px = (pos / 2) % w; + const int py = (pos / 2) / w; + if (px >= x0 && px <= x1 && py >= y0 && py <= y1) { + PIXELDATA((byte0 << 8) | byte1); + } } #endif -void display_image(int x, int y, int w, int h, const void *data, int datalen) -{ +void display_image(int x, int y, int w, int h, const void *data, int datalen) { #if TREZOR_MODEL == T - x += DISPLAY_OFFSET.x; - y += DISPLAY_OFFSET.y; - int x0, y0, x1, y1; - clamp_coords(x, y, w, h, &x0, &y0, &x1, &y1); - display_set_window(x0, y0, x1, y1); - int userdata[5] = {w, x0 - x, x1 - x, y0 - y, y1 - y}; - sinf_inflate(data, datalen, inflate_callback_image, userdata); + x += DISPLAY_OFFSET.x; + y += DISPLAY_OFFSET.y; + int x0, y0, x1, y1; + clamp_coords(x, y, w, h, &x0, &y0, &x1, &y1); + display_set_window(x0, y0, x1, y1); + int userdata[5] = {w, x0 - x, x1 - x, y0 - y, y1 - y}; + sinf_inflate(data, datalen, inflate_callback_image, userdata); #endif } #if TREZOR_MODEL == T -static void inflate_callback_avatar(uint8_t byte1, uint32_t pos, void *userdata) -{ -#define AVATAR_BORDER_SIZE 4 -#define AVATAR_BORDER_LOW (AVATAR_IMAGE_SIZE / 2 - AVATAR_BORDER_SIZE) * (AVATAR_IMAGE_SIZE / 2 - AVATAR_BORDER_SIZE) -#define AVATAR_BORDER_HIGH (AVATAR_IMAGE_SIZE / 2) * (AVATAR_IMAGE_SIZE / 2) -#define AVATAR_ANTIALIAS 1 - static uint8_t byte0; - if (pos % 2 == 0) { - byte0 = byte1; - return; - } - const int w = ((const int *)userdata)[0]; - const int x0 = ((const int *)userdata)[1]; - const int x1 = ((const int *)userdata)[2]; - const int y0 = ((const int *)userdata)[3]; - const int y1 = ((const int *)userdata)[4]; - const int fgcolor = ((const int *)userdata)[5]; - const int bgcolor = ((const int *)userdata)[6]; - const int px = (pos / 2) % w; - const int py = (pos / 2) / w; - if (px >= x0 && px <= x1 && py >= y0 && py <= y1) { - int d = (px - w / 2) * (px - w / 2) + (py - w / 2) * (py - w / 2); - // inside border area - if (d < AVATAR_BORDER_LOW) { - PIXELDATA((byte0 << 8) | byte1); - } else +static void inflate_callback_avatar(uint8_t byte1, uint32_t pos, + void *userdata) { +#define AVATAR_BORDER_SIZE 4 +#define AVATAR_BORDER_LOW \ + (AVATAR_IMAGE_SIZE / 2 - AVATAR_BORDER_SIZE) * \ + (AVATAR_IMAGE_SIZE / 2 - AVATAR_BORDER_SIZE) +#define AVATAR_BORDER_HIGH (AVATAR_IMAGE_SIZE / 2) * (AVATAR_IMAGE_SIZE / 2) +#define AVATAR_ANTIALIAS 1 + static uint8_t byte0; + if (pos % 2 == 0) { + byte0 = byte1; + return; + } + const int w = ((const int *)userdata)[0]; + const int x0 = ((const int *)userdata)[1]; + const int x1 = ((const int *)userdata)[2]; + const int y0 = ((const int *)userdata)[3]; + const int y1 = ((const int *)userdata)[4]; + const int fgcolor = ((const int *)userdata)[5]; + const int bgcolor = ((const int *)userdata)[6]; + const int px = (pos / 2) % w; + const int py = (pos / 2) / w; + if (px >= x0 && px <= x1 && py >= y0 && py <= y1) { + int d = (px - w / 2) * (px - w / 2) + (py - w / 2) * (py - w / 2); + // inside border area + if (d < AVATAR_BORDER_LOW) { + PIXELDATA((byte0 << 8) | byte1); + } else // outside border area if (d > AVATAR_BORDER_HIGH) { - PIXELDATA(bgcolor); - // border area - } else { + PIXELDATA(bgcolor); + // border area + } else { #if AVATAR_ANTIALIAS - d = 31 * (d - AVATAR_BORDER_LOW) / (AVATAR_BORDER_HIGH - AVATAR_BORDER_LOW); - uint16_t c; - if (d >= 16) { - c = interpolate_color(bgcolor, fgcolor, d - 16); - } else { - c = interpolate_color(fgcolor, (byte0 << 8) | byte1 , d); - } - PIXELDATA(c); + d = 31 * (d - AVATAR_BORDER_LOW) / + (AVATAR_BORDER_HIGH - AVATAR_BORDER_LOW); + uint16_t c; + if (d >= 16) { + c = interpolate_color(bgcolor, fgcolor, d - 16); + } else { + c = interpolate_color(fgcolor, (byte0 << 8) | byte1, d); + } + PIXELDATA(c); #else - PIXELDATA(fgcolor); + PIXELDATA(fgcolor); #endif - } } + } } #endif -void display_avatar(int x, int y, const void *data, int datalen, uint16_t fgcolor, uint16_t bgcolor) -{ +void display_avatar(int x, int y, const void *data, int datalen, + uint16_t fgcolor, uint16_t bgcolor) { #if TREZOR_MODEL == T - x += DISPLAY_OFFSET.x; - y += DISPLAY_OFFSET.y; - int x0, y0, x1, y1; - clamp_coords(x, y, AVATAR_IMAGE_SIZE, AVATAR_IMAGE_SIZE, &x0, &y0, &x1, &y1); - display_set_window(x0, y0, x1, y1); - int userdata[7] = {AVATAR_IMAGE_SIZE, x0 - x, x1 - x, y0 - y, y1 - y, fgcolor, bgcolor}; - sinf_inflate(data, datalen, inflate_callback_avatar, userdata); + x += DISPLAY_OFFSET.x; + y += DISPLAY_OFFSET.y; + int x0, y0, x1, y1; + clamp_coords(x, y, AVATAR_IMAGE_SIZE, AVATAR_IMAGE_SIZE, &x0, &y0, &x1, &y1); + display_set_window(x0, y0, x1, y1); + int userdata[7] = {AVATAR_IMAGE_SIZE, x0 - x, x1 - x, y0 - y, y1 - y, + fgcolor, bgcolor}; + sinf_inflate(data, datalen, inflate_callback_avatar, userdata); #endif } -static void inflate_callback_icon(uint8_t byte, uint32_t pos, void *userdata) -{ - const uint16_t *colortable = (const uint16_t *)(((const int *)userdata) + 5); - const int w = ((const int *)userdata)[0]; - const int x0 = ((const int *)userdata)[1]; - const int x1 = ((const int *)userdata)[2]; - const int y0 = ((const int *)userdata)[3]; - const int y1 = ((const int *)userdata)[4]; - const int px = (pos * 2) % w; - const int py = (pos * 2) / w; - if (px >= x0 && px <= x1 && py >= y0 && py <= y1) { - PIXELDATA(colortable[byte >> 4]); - PIXELDATA(colortable[byte & 0x0F]); - } +static void inflate_callback_icon(uint8_t byte, uint32_t pos, void *userdata) { + const uint16_t *colortable = (const uint16_t *)(((const int *)userdata) + 5); + const int w = ((const int *)userdata)[0]; + const int x0 = ((const int *)userdata)[1]; + const int x1 = ((const int *)userdata)[2]; + const int y0 = ((const int *)userdata)[3]; + const int y1 = ((const int *)userdata)[4]; + const int px = (pos * 2) % w; + const int py = (pos * 2) / w; + if (px >= x0 && px <= x1 && py >= y0 && py <= y1) { + PIXELDATA(colortable[byte >> 4]); + PIXELDATA(colortable[byte & 0x0F]); + } } -void display_icon(int x, int y, int w, int h, const void *data, int datalen, uint16_t fgcolor, uint16_t bgcolor) -{ - x += DISPLAY_OFFSET.x; - y += DISPLAY_OFFSET.y; - x &= ~1; // cannot draw at odd coordinate - int x0, y0, x1, y1; - clamp_coords(x, y, w, h, &x0, &y0, &x1, &y1); - display_set_window(x0, y0, x1, y1); - int userdata[5 + 16 * sizeof(uint16_t) / sizeof(int)] = {w, x0 - x, x1 - x, y0 - y, y1 - y}; - set_color_table((uint16_t *)(userdata + 5), fgcolor, bgcolor); - sinf_inflate(data, datalen, inflate_callback_icon, userdata); +void display_icon(int x, int y, int w, int h, const void *data, int datalen, + uint16_t fgcolor, uint16_t bgcolor) { + x += DISPLAY_OFFSET.x; + y += DISPLAY_OFFSET.y; + x &= ~1; // cannot draw at odd coordinate + int x0, y0, x1, y1; + clamp_coords(x, y, w, h, &x0, &y0, &x1, &y1); + display_set_window(x0, y0, x1, y1); + int userdata[5 + 16 * sizeof(uint16_t) / sizeof(int)] = {w, x0 - x, x1 - x, + y0 - y, y1 - y}; + set_color_table((uint16_t *)(userdata + 5), fgcolor, bgcolor); + sinf_inflate(data, datalen, inflate_callback_icon, userdata); } #if TREZOR_MODEL == T #include "loader.h" -static void inflate_callback_loader(uint8_t byte, uint32_t pos, void *userdata) -{ - uint8_t *out = (uint8_t *)userdata; - out[pos] = byte; +static void inflate_callback_loader(uint8_t byte, uint32_t pos, + void *userdata) { + uint8_t *out = (uint8_t *)userdata; + out[pos] = byte; } #endif -void display_loader(uint16_t progress, int yoffset, uint16_t fgcolor, uint16_t bgcolor, const uint8_t *icon, uint32_t iconlen, uint16_t iconfgcolor) -{ +void display_loader(uint16_t progress, int yoffset, uint16_t fgcolor, + uint16_t bgcolor, const uint8_t *icon, uint32_t iconlen, + uint16_t iconfgcolor) { #if TREZOR_MODEL == T - uint16_t colortable[16], iconcolortable[16]; - set_color_table(colortable, fgcolor, bgcolor); - if (icon) { - set_color_table(iconcolortable, iconfgcolor, bgcolor); - } - if ((DISPLAY_RESY / 2 - img_loader_size + yoffset < 0) || - (DISPLAY_RESY / 2 + img_loader_size - 1 + yoffset >= DISPLAY_RESY)) { - return; - } - display_set_window(DISPLAY_RESX / 2 - img_loader_size, DISPLAY_RESY / 2 - img_loader_size + yoffset, DISPLAY_RESX / 2 + img_loader_size - 1, DISPLAY_RESY / 2 + img_loader_size - 1 + yoffset); - if (icon && memcmp(icon, "TOIg", 4) == 0 && LOADER_ICON_SIZE == *(uint16_t *)(icon + 4) && LOADER_ICON_SIZE == *(uint16_t *)(icon + 6) && iconlen == 12 + *(uint32_t *)(icon + 8)) { - uint8_t icondata[LOADER_ICON_SIZE * LOADER_ICON_SIZE / 2]; - sinf_inflate(icon + 12, iconlen - 12, inflate_callback_loader, icondata); - icon = icondata; - } else { - icon = NULL; - } - for (int y = 0; y < img_loader_size * 2; y++) { - for (int x = 0; x < img_loader_size * 2; x++) { - int mx = x, my = y; - uint16_t a; - if ((mx >= img_loader_size) && (my >= img_loader_size)) { - mx = img_loader_size * 2 - 1 - x; - my = img_loader_size * 2 - 1 - y; - a = 499 - (img_loader[my][mx] >> 8); - } else - if (mx >= img_loader_size) { - mx = img_loader_size * 2 - 1 - x; - a = img_loader[my][mx] >> 8; - } else - if (my >= img_loader_size) { - my = img_loader_size * 2 - 1 - y; - a = 500 + (img_loader[my][mx] >> 8); - } else { - a = 999 - (img_loader[my][mx] >> 8); - } - // inside of circle - draw glyph - #define LOADER_ICON_CORNER_CUT 2 - if (icon && mx + my > (((LOADER_ICON_SIZE / 2) + LOADER_ICON_CORNER_CUT) * 2) && mx >= img_loader_size - (LOADER_ICON_SIZE / 2) && my >= img_loader_size - (LOADER_ICON_SIZE / 2)) { - int i = (x - (img_loader_size - (LOADER_ICON_SIZE / 2))) + (y - (img_loader_size - (LOADER_ICON_SIZE / 2))) * LOADER_ICON_SIZE; - uint8_t c; - if (i % 2) { - c = icon[i / 2] & 0x0F; - } else { - c = (icon[i / 2] & 0xF0) >> 4; - } - PIXELDATA(iconcolortable[c]); - } else { - uint8_t c; - if (progress > a) { - c = (img_loader[my][mx] & 0x00F0) >> 4; - } else { - c = img_loader[my][mx] & 0x000F; - } - PIXELDATA(colortable[c]); - } + uint16_t colortable[16], iconcolortable[16]; + set_color_table(colortable, fgcolor, bgcolor); + if (icon) { + set_color_table(iconcolortable, iconfgcolor, bgcolor); + } + if ((DISPLAY_RESY / 2 - img_loader_size + yoffset < 0) || + (DISPLAY_RESY / 2 + img_loader_size - 1 + yoffset >= DISPLAY_RESY)) { + return; + } + display_set_window(DISPLAY_RESX / 2 - img_loader_size, + DISPLAY_RESY / 2 - img_loader_size + yoffset, + DISPLAY_RESX / 2 + img_loader_size - 1, + DISPLAY_RESY / 2 + img_loader_size - 1 + yoffset); + if (icon && memcmp(icon, "TOIg", 4) == 0 && + LOADER_ICON_SIZE == *(uint16_t *)(icon + 4) && + LOADER_ICON_SIZE == *(uint16_t *)(icon + 6) && + iconlen == 12 + *(uint32_t *)(icon + 8)) { + uint8_t icondata[LOADER_ICON_SIZE * LOADER_ICON_SIZE / 2]; + sinf_inflate(icon + 12, iconlen - 12, inflate_callback_loader, icondata); + icon = icondata; + } else { + icon = NULL; + } + for (int y = 0; y < img_loader_size * 2; y++) { + for (int x = 0; x < img_loader_size * 2; x++) { + int mx = x, my = y; + uint16_t a; + if ((mx >= img_loader_size) && (my >= img_loader_size)) { + mx = img_loader_size * 2 - 1 - x; + my = img_loader_size * 2 - 1 - y; + a = 499 - (img_loader[my][mx] >> 8); + } else if (mx >= img_loader_size) { + mx = img_loader_size * 2 - 1 - x; + a = img_loader[my][mx] >> 8; + } else if (my >= img_loader_size) { + my = img_loader_size * 2 - 1 - y; + a = 500 + (img_loader[my][mx] >> 8); + } else { + a = 999 - (img_loader[my][mx] >> 8); + } +// inside of circle - draw glyph +#define LOADER_ICON_CORNER_CUT 2 + if (icon && + mx + my > (((LOADER_ICON_SIZE / 2) + LOADER_ICON_CORNER_CUT) * 2) && + mx >= img_loader_size - (LOADER_ICON_SIZE / 2) && + my >= img_loader_size - (LOADER_ICON_SIZE / 2)) { + int i = + (x - (img_loader_size - (LOADER_ICON_SIZE / 2))) + + (y - (img_loader_size - (LOADER_ICON_SIZE / 2))) * LOADER_ICON_SIZE; + uint8_t c; + if (i % 2) { + c = icon[i / 2] & 0x0F; + } else { + c = (icon[i / 2] & 0xF0) >> 4; + } + PIXELDATA(iconcolortable[c]); + } else { + uint8_t c; + if (progress > a) { + c = (img_loader[my][mx] & 0x00F0) >> 4; + } else { + c = img_loader[my][mx] & 0x000F; } + PIXELDATA(colortable[c]); + } } + } #endif } @@ -380,81 +395,81 @@ void display_loader(uint16_t progress, int yoffset, uint16_t fgcolor, uint16_t b #define DISPLAY_PRINT_COLS (DISPLAY_RESX / 6) #define DISPLAY_PRINT_ROWS (DISPLAY_RESY / 8) static char display_print_buf[DISPLAY_PRINT_ROWS][DISPLAY_PRINT_COLS]; -static uint16_t display_print_fgcolor = COLOR_WHITE, display_print_bgcolor = COLOR_BLACK; +static uint16_t display_print_fgcolor = COLOR_WHITE, + display_print_bgcolor = COLOR_BLACK; // set colors for display_print function -void display_print_color(uint16_t fgcolor, uint16_t bgcolor) -{ - display_print_fgcolor = fgcolor; - display_print_bgcolor = bgcolor; +void display_print_color(uint16_t fgcolor, uint16_t bgcolor) { + display_print_fgcolor = fgcolor; + display_print_bgcolor = bgcolor; } // display text using bitmap font -void display_print(const char *text, int textlen) -{ - static uint8_t row = 0, col = 0; - - // determine text length if not provided - if (textlen < 0) { - textlen = strlen(text); +void display_print(const char *text, int textlen) { + static uint8_t row = 0, col = 0; + + // determine text length if not provided + if (textlen < 0) { + textlen = strlen(text); + } + + // print characters to internal buffer (display_print_buf) + for (int i = 0; i < textlen; i++) { + switch (text[i]) { + case '\r': + break; + case '\n': + row++; + col = 0; + break; + default: + display_print_buf[row][col] = text[i]; + col++; + break; } - // print characters to internal buffer (display_print_buf) - for (int i = 0; i < textlen; i++) { - - switch (text[i]) { - case '\r': - break; - case '\n': - row++; - col = 0; - break; - default: - display_print_buf[row][col] = text[i]; - col++; - break; - } - - if (col >= DISPLAY_PRINT_COLS) { - col = 0; - row++; - } - - if (row >= DISPLAY_PRINT_ROWS) { - for (int j = 0; j < DISPLAY_PRINT_ROWS - 1; j++) { - memcpy(display_print_buf[j], display_print_buf[j + 1], DISPLAY_PRINT_COLS); - } - memzero(display_print_buf[DISPLAY_PRINT_ROWS - 1], DISPLAY_PRINT_COLS); - row = DISPLAY_PRINT_ROWS - 1; - } - + if (col >= DISPLAY_PRINT_COLS) { + col = 0; + row++; } - // render buffer to display - display_set_window(0, 0, DISPLAY_RESX - 1, DISPLAY_RESY - 1); - for (int i = 0; i < DISPLAY_RESX * DISPLAY_RESY; i++) { - int x = (i % DISPLAY_RESX); - int y = (i / DISPLAY_RESX); - const int j = y % 8; y /= 8; - const int k = x % 6; x /= 6; - char c; - if (x < DISPLAY_PRINT_COLS && y < DISPLAY_PRINT_ROWS) { - c = display_print_buf[y][x] & 0x7F; - // char invert = display_print_buf[y][x] & 0x80; - } else { - c = ' '; - } - if (c < ' ') { - c = ' '; - } - const uint8_t *g = Font_Bitmap + (5 * (c - ' ')); - if (k < 5 && (g[k] & (1 << j))) { - PIXELDATA(display_print_fgcolor); - } else { - PIXELDATA(display_print_bgcolor); - } + if (row >= DISPLAY_PRINT_ROWS) { + for (int j = 0; j < DISPLAY_PRINT_ROWS - 1; j++) { + memcpy(display_print_buf[j], display_print_buf[j + 1], + DISPLAY_PRINT_COLS); + } + memzero(display_print_buf[DISPLAY_PRINT_ROWS - 1], DISPLAY_PRINT_COLS); + row = DISPLAY_PRINT_ROWS - 1; + } + } + + // render buffer to display + display_set_window(0, 0, DISPLAY_RESX - 1, DISPLAY_RESY - 1); + for (int i = 0; i < DISPLAY_RESX * DISPLAY_RESY; i++) { + int x = (i % DISPLAY_RESX); + int y = (i / DISPLAY_RESX); + const int j = y % 8; + y /= 8; + const int k = x % 6; + x /= 6; + char c; + if (x < DISPLAY_PRINT_COLS && y < DISPLAY_PRINT_ROWS) { + c = display_print_buf[y][x] & 0x7F; + // char invert = display_print_buf[y][x] & 0x80; + } else { + c = ' '; } - display_refresh(); + if (c < ' ') { + c = ' '; + } + const uint8_t *g = Font_Bitmap + (5 * (c - ' ')); + if (k < 5 && (g[k] & (1 << j))) { + PIXELDATA(display_print_fgcolor); + } else { + PIXELDATA(display_print_bgcolor); + } + } + display_refresh(); } #ifdef TREZOR_EMULATOR @@ -465,256 +480,244 @@ void display_print(const char *text, int textlen) #endif // variadic display_print -void display_printf(const char *fmt, ...) -{ - if (!strchr(fmt, '%')) { - display_print(fmt, strlen(fmt)); - } else { - va_list va; - va_start(va, fmt); - char buf[256]; - int len = mini_vsnprintf(buf, sizeof(buf), fmt, va); - display_print(buf, len); - va_end(va); - } +void display_printf(const char *fmt, ...) { + if (!strchr(fmt, '%')) { + display_print(fmt, strlen(fmt)); + } else { + va_list va; + va_start(va, fmt); + char buf[256]; + int len = mini_vsnprintf(buf, sizeof(buf), fmt, va); + display_print(buf, len); + va_end(va); + } } -#endif // TREZOR_PRINT_DISABLE +#endif // TREZOR_PRINT_DISABLE #if TREZOR_MODEL == T -static const uint8_t *get_glyph(int font, uint8_t c) -{ - if (c >= ' ' && c <= '~') { +static const uint8_t *get_glyph(int font, uint8_t c) { + if (c >= ' ' && c <= '~') { // do nothing - valid ASCII - } else - // UTF-8 handling: https://en.wikipedia.org/wiki/UTF-8#Description - if (c >= 0xC0) { - // bytes 11xxxxxx are first byte of UTF-8 characters - c = '_'; - } else { - // bytes 10xxxxxx are successive UTF-8 characters - return 0; - } - switch (font) { + } else + // UTF-8 handling: https://en.wikipedia.org/wiki/UTF-8#Description + if (c >= 0xC0) { + // bytes 11xxxxxx are first byte of UTF-8 characters + c = '_'; + } else { + // bytes 10xxxxxx are successive UTF-8 characters + return 0; + } + switch (font) { #ifdef TREZOR_FONT_NORMAL_ENABLE - case FONT_NORMAL: - return Font_Roboto_Regular_20[c - ' ']; + case FONT_NORMAL: + return Font_Roboto_Regular_20[c - ' ']; #endif #ifdef TREZOR_FONT_BOLD_ENABLE - case FONT_BOLD: - return Font_Roboto_Bold_20[c - ' ']; + case FONT_BOLD: + return Font_Roboto_Bold_20[c - ' ']; #endif #ifdef TREZOR_FONT_MONO_ENABLE - case FONT_MONO: - return Font_RobotoMono_Regular_20[c - ' ']; + case FONT_MONO: + return Font_RobotoMono_Regular_20[c - ' ']; #endif #ifdef TREZOR_FONT_MONO_BOLD_ENABLE - case FONT_MONO_BOLD: - return Font_RobotoMono_Bold_20[c - ' ']; + case FONT_MONO_BOLD: + return Font_RobotoMono_Bold_20[c - ' ']; #endif - } - return 0; + } + return 0; } #endif #if TREZOR_MODEL == T -static void display_text_render(int x, int y, const char *text, int textlen, int font, uint16_t fgcolor, uint16_t bgcolor) -{ - // determine text length if not provided - if (textlen < 0) { - textlen = strlen(text); - } - - uint16_t colortable[16]; - set_color_table(colortable, fgcolor, bgcolor); - - // render glyphs - for (int i = 0; i < textlen; i++) { - const uint8_t *g = get_glyph(font, (uint8_t)text[i]); - if (!g) continue; - const uint8_t w = g[0]; // width - const uint8_t h = g[1]; // height - const uint8_t adv = g[2]; // advance - const uint8_t bearX = g[3]; // bearingX - const uint8_t bearY = g[4]; // bearingY - if (w && h) { - const int sx = x + bearX; - const int sy = y - bearY; - int x0, y0, x1, y1; - clamp_coords(sx, sy, w, h, &x0, &y0, &x1, &y1); - display_set_window(x0, y0, x1, y1); - for (int j = y0; j <= y1; j++) { - for (int i = x0; i <= x1; i++) { - const int rx = i - sx; - const int ry = j - sy; - const int a = rx + ry * w; - #if FONT_BPP == 2 - const uint8_t c = ((g[5 + a / 4] >> (6 - (a % 4) * 2)) & 0x03) * 5; - #elif FONT_BPP == 4 - const uint8_t c = (g[5 + a / 2] >> (4 - (a % 2) * 4)) & 0x0F; - #else - #error Unsupported FONT_BPP value - #endif - PIXELDATA(colortable[c]); - } - } +static void display_text_render(int x, int y, const char *text, int textlen, + int font, uint16_t fgcolor, uint16_t bgcolor) { + // determine text length if not provided + if (textlen < 0) { + textlen = strlen(text); + } + + uint16_t colortable[16]; + set_color_table(colortable, fgcolor, bgcolor); + + // render glyphs + for (int i = 0; i < textlen; i++) { + const uint8_t *g = get_glyph(font, (uint8_t)text[i]); + if (!g) continue; + const uint8_t w = g[0]; // width + const uint8_t h = g[1]; // height + const uint8_t adv = g[2]; // advance + const uint8_t bearX = g[3]; // bearingX + const uint8_t bearY = g[4]; // bearingY + if (w && h) { + const int sx = x + bearX; + const int sy = y - bearY; + int x0, y0, x1, y1; + clamp_coords(sx, sy, w, h, &x0, &y0, &x1, &y1); + display_set_window(x0, y0, x1, y1); + for (int j = y0; j <= y1; j++) { + for (int i = x0; i <= x1; i++) { + const int rx = i - sx; + const int ry = j - sy; + const int a = rx + ry * w; +#if FONT_BPP == 2 + const uint8_t c = ((g[5 + a / 4] >> (6 - (a % 4) * 2)) & 0x03) * 5; +#elif FONT_BPP == 4 + const uint8_t c = (g[5 + a / 2] >> (4 - (a % 2) * 4)) & 0x0F; +#else +#error Unsupported FONT_BPP value +#endif + PIXELDATA(colortable[c]); } - x += adv; + } } + x += adv; + } } #endif -void display_text(int x, int y, const char *text, int textlen, int font, uint16_t fgcolor, uint16_t bgcolor) -{ +void display_text(int x, int y, const char *text, int textlen, int font, + uint16_t fgcolor, uint16_t bgcolor) { #if TREZOR_MODEL == T - x += DISPLAY_OFFSET.x; - y += DISPLAY_OFFSET.y; - display_text_render(x, y, text, textlen, font, fgcolor, bgcolor); + x += DISPLAY_OFFSET.x; + y += DISPLAY_OFFSET.y; + display_text_render(x, y, text, textlen, font, fgcolor, bgcolor); #endif } -void display_text_center(int x, int y, const char *text, int textlen, int font, uint16_t fgcolor, uint16_t bgcolor) -{ +void display_text_center(int x, int y, const char *text, int textlen, int font, + uint16_t fgcolor, uint16_t bgcolor) { #if TREZOR_MODEL == T - x += DISPLAY_OFFSET.x; - y += DISPLAY_OFFSET.y; - int w = display_text_width(text, textlen, font); - display_text_render(x - w / 2, y, text, textlen, font, fgcolor, bgcolor); + x += DISPLAY_OFFSET.x; + y += DISPLAY_OFFSET.y; + int w = display_text_width(text, textlen, font); + display_text_render(x - w / 2, y, text, textlen, font, fgcolor, bgcolor); #endif } -void display_text_right(int x, int y, const char *text, int textlen, int font, uint16_t fgcolor, uint16_t bgcolor) -{ +void display_text_right(int x, int y, const char *text, int textlen, int font, + uint16_t fgcolor, uint16_t bgcolor) { #if TREZOR_MODEL == T - x += DISPLAY_OFFSET.x; - y += DISPLAY_OFFSET.y; - int w = display_text_width(text, textlen, font); - display_text_render(x - w, y, text, textlen, font, fgcolor, bgcolor); + x += DISPLAY_OFFSET.x; + y += DISPLAY_OFFSET.y; + int w = display_text_width(text, textlen, font); + display_text_render(x - w, y, text, textlen, font, fgcolor, bgcolor); #endif } // compute the width of the text (in pixels) -int display_text_width(const char *text, int textlen, int font) -{ - int width = 0; +int display_text_width(const char *text, int textlen, int font) { + int width = 0; #if TREZOR_MODEL == T - // determine text length if not provided - if (textlen < 0) { - textlen = strlen(text); - } - for (int i = 0; i < textlen; i++) { - const uint8_t *g = get_glyph(font, (uint8_t)text[i]); - if (!g) continue; + // determine text length if not provided + if (textlen < 0) { + textlen = strlen(text); + } + for (int i = 0; i < textlen; i++) { + const uint8_t *g = get_glyph(font, (uint8_t)text[i]); + if (!g) continue; + const uint8_t adv = g[2]; // advance + width += adv; + /* + if (i != textlen - 1) { const uint8_t adv = g[2]; // advance width += adv; - /* - if (i != textlen - 1) { - const uint8_t adv = g[2]; // advance - width += adv; - } else { // last character - const uint8_t w = g[0]; // width - const uint8_t bearX = g[3]; // bearingX - width += (bearX + w); - } - */ + } else { // last character + const uint8_t w = g[0]; // width + const uint8_t bearX = g[3]; // bearingX + width += (bearX + w); } + */ + } #endif - return width; + return width; } #define QR_MAX_VERSION 9 -void display_qrcode(int x, int y, const char *data, int datalen, uint8_t scale) -{ - if (scale < 1 || scale > 10) return; - - uint8_t codedata[qrcodegen_BUFFER_LEN_FOR_VERSION(QR_MAX_VERSION)]; - uint8_t tempdata[qrcodegen_BUFFER_LEN_FOR_VERSION(QR_MAX_VERSION)]; - - int side = 0; - if (qrcodegen_encodeText( - data, - tempdata, - codedata, - qrcodegen_Ecc_MEDIUM, - qrcodegen_VERSION_MIN, - QR_MAX_VERSION, - qrcodegen_Mask_AUTO, - true)) { - side = qrcodegen_getSize(codedata); - } - - x += DISPLAY_OFFSET.x - (side + 2) * scale / 2; - y += DISPLAY_OFFSET.y - (side + 2) * scale / 2; - int x0, y0, x1, y1; - clamp_coords(x, y, (side + 2) * scale, (side + 2) * scale, &x0, &y0, &x1, &y1); - display_set_window(x0, y0, x1, y1); - for (int j = y0; j <= y1; j++) { - for (int i = x0; i <= x1; i++) { - int rx = (i - x) / scale - 1; - int ry = (j - y) / scale - 1; - // 1px border - if (rx < 0 || ry < 0 || rx >= side || ry >= side) { - PIXELDATA(0xFFFF); - continue; - } - if (qrcodegen_getModule(codedata, rx, ry)) { - PIXELDATA(0x0000); - } else { - PIXELDATA(0xFFFF); - } - } +void display_qrcode(int x, int y, const char *data, int datalen, + uint8_t scale) { + if (scale < 1 || scale > 10) return; + + uint8_t codedata[qrcodegen_BUFFER_LEN_FOR_VERSION(QR_MAX_VERSION)]; + uint8_t tempdata[qrcodegen_BUFFER_LEN_FOR_VERSION(QR_MAX_VERSION)]; + + int side = 0; + if (qrcodegen_encodeText(data, tempdata, codedata, qrcodegen_Ecc_MEDIUM, + qrcodegen_VERSION_MIN, QR_MAX_VERSION, + qrcodegen_Mask_AUTO, true)) { + side = qrcodegen_getSize(codedata); + } + + x += DISPLAY_OFFSET.x - (side + 2) * scale / 2; + y += DISPLAY_OFFSET.y - (side + 2) * scale / 2; + int x0, y0, x1, y1; + clamp_coords(x, y, (side + 2) * scale, (side + 2) * scale, &x0, &y0, &x1, + &y1); + display_set_window(x0, y0, x1, y1); + for (int j = y0; j <= y1; j++) { + for (int i = x0; i <= x1; i++) { + int rx = (i - x) / scale - 1; + int ry = (j - y) / scale - 1; + // 1px border + if (rx < 0 || ry < 0 || rx >= side || ry >= side) { + PIXELDATA(0xFFFF); + continue; + } + if (qrcodegen_getModule(codedata, rx, ry)) { + PIXELDATA(0x0000); + } else { + PIXELDATA(0xFFFF); + } } + } } -void display_offset(int set_xy[2], int *get_x, int *get_y) -{ - if (set_xy) { - DISPLAY_OFFSET.x = set_xy[0]; - DISPLAY_OFFSET.y = set_xy[1]; - } - *get_x = DISPLAY_OFFSET.x; - *get_y = DISPLAY_OFFSET.y; +void display_offset(int set_xy[2], int *get_x, int *get_y) { + if (set_xy) { + DISPLAY_OFFSET.x = set_xy[0]; + DISPLAY_OFFSET.y = set_xy[1]; + } + *get_x = DISPLAY_OFFSET.x; + *get_y = DISPLAY_OFFSET.y; } -int display_orientation(int degrees) -{ - if (degrees != DISPLAY_ORIENTATION) { +int display_orientation(int degrees) { + if (degrees != DISPLAY_ORIENTATION) { #if TREZOR_MODEL == T - if (degrees == 0 || degrees == 90 || degrees == 180 || degrees == 270) { + if (degrees == 0 || degrees == 90 || degrees == 180 || degrees == 270) { #elif TREZOR_MODEL == 1 - if (degrees == 0 || degrees == 180) { + if (degrees == 0 || degrees == 180) { #else #error Unknown TREZOR model #endif - DISPLAY_ORIENTATION = degrees; - display_set_orientation(degrees); - } + DISPLAY_ORIENTATION = degrees; + display_set_orientation(degrees); } - return DISPLAY_ORIENTATION; + } + return DISPLAY_ORIENTATION; } -int display_backlight(int val) -{ +int display_backlight(int val) { #if TREZOR_MODEL == 1 - val = 255; + val = 255; #endif - if (DISPLAY_BACKLIGHT != val && val >= 0 && val <= 255) { - DISPLAY_BACKLIGHT = val; - display_set_backlight(val); - } - return DISPLAY_BACKLIGHT; + if (DISPLAY_BACKLIGHT != val && val >= 0 && val <= 255) { + DISPLAY_BACKLIGHT = val; + display_set_backlight(val); + } + return DISPLAY_BACKLIGHT; } -void display_fade(int start, int end, int delay) -{ - for (int i = 0; i < 100; i++) { - display_backlight(start + i * (end - start) / 100); - hal_delay(delay / 100); - } - display_backlight(end); +void display_fade(int start, int end, int delay) { + for (int i = 0; i < 100; i++) { + display_backlight(start + i * (end - start) / 100); + hal_delay(delay / 100); + } + display_backlight(end); } diff --git a/embed/extmod/modtrezorui/display.h b/embed/extmod/modtrezorui/display.h index d11c7e121..5236be958 100644 --- a/embed/extmod/modtrezorui/display.h +++ b/embed/extmod/modtrezorui/display.h @@ -25,42 +25,42 @@ #if TREZOR_MODEL == T // ILI9341V, GC9307 and ST7789V drivers support 240px x 320px display resolution -#define MAX_DISPLAY_RESX 240 -#define MAX_DISPLAY_RESY 320 -#define DISPLAY_RESX 240 -#define DISPLAY_RESY 240 +#define MAX_DISPLAY_RESX 240 +#define MAX_DISPLAY_RESY 320 +#define DISPLAY_RESX 240 +#define DISPLAY_RESY 240 #elif TREZOR_MODEL == 1 -#define MAX_DISPLAY_RESX 128 -#define MAX_DISPLAY_RESY 64 -#define DISPLAY_RESX 128 -#define DISPLAY_RESY 64 +#define MAX_DISPLAY_RESX 128 +#define MAX_DISPLAY_RESY 64 +#define DISPLAY_RESX 128 +#define DISPLAY_RESY 64 #else #error Unknown TREZOR Model #endif -#define FONT_BPP 4 -#define FONT_SIZE 20 -#define AVATAR_IMAGE_SIZE 144 -#define LOADER_ICON_SIZE 64 +#define FONT_BPP 4 +#define FONT_SIZE 20 +#define AVATAR_IMAGE_SIZE 144 +#define LOADER_ICON_SIZE 64 -#define RGB16(R, G, B) ((R & 0xF8) << 8) | ((G & 0xFC) << 3) | ((B & 0xF8) >> 3) -#define COLOR_WHITE 0xFFFF -#define COLOR_BLACK 0x0000 +#define RGB16(R, G, B) ((R & 0xF8) << 8) | ((G & 0xFC) << 3) | ((B & 0xF8) >> 3) +#define COLOR_WHITE 0xFFFF +#define COLOR_BLACK 0x0000 #ifdef TREZOR_FONT_NORMAL_ENABLE -#define FONT_NORMAL (-1) +#define FONT_NORMAL (-1) #endif #ifdef TREZOR_FONT_BOLD_ENABLE -#define FONT_BOLD (-2) +#define FONT_BOLD (-2) #endif #ifdef TREZOR_FONT_MONO_ENABLE -#define FONT_MONO (-3) +#define FONT_MONO (-3) #endif #ifdef TREZOR_FONT_MONO_BOLD_ENABLE -#define FONT_MONO_BOLD (-4) +#define FONT_MONO_BOLD (-4) #endif // provided by port @@ -74,22 +74,31 @@ void display_save(const char *prefix); void display_clear(void); void display_bar(int x, int y, int w, int h, uint16_t c); -void display_bar_radius(int x, int y, int w, int h, uint16_t c, uint16_t b, uint8_t r); +void display_bar_radius(int x, int y, int w, int h, uint16_t c, uint16_t b, + uint8_t r); void display_image(int x, int y, int w, int h, const void *data, int datalen); -void display_avatar(int x, int y, const void *data, int datalen, uint16_t fgcolor, uint16_t bgcolor); -void display_icon(int x, int y, int w, int h, const void *data, int datalen, uint16_t fgcolor, uint16_t bgcolor); -void display_loader(uint16_t progress, int yoffset, uint16_t fgcolor, uint16_t bgcolor, const uint8_t *icon, uint32_t iconlen, uint16_t iconfgcolor); +void display_avatar(int x, int y, const void *data, int datalen, + uint16_t fgcolor, uint16_t bgcolor); +void display_icon(int x, int y, int w, int h, const void *data, int datalen, + uint16_t fgcolor, uint16_t bgcolor); +void display_loader(uint16_t progress, int yoffset, uint16_t fgcolor, + uint16_t bgcolor, const uint8_t *icon, uint32_t iconlen, + uint16_t iconfgcolor); #ifndef TREZOR_PRINT_DISABLE void display_print_color(uint16_t fgcolor, uint16_t bgcolor); void display_print(const char *text, int textlen); -void display_printf(const char *fmt, ...) __attribute__ ((__format__ (__printf__, 1, 2))); +void display_printf(const char *fmt, ...) + __attribute__((__format__(__printf__, 1, 2))); #endif -void display_text(int x, int y, const char *text, int textlen, int font, uint16_t fgcolor, uint16_t bgcolor); -void display_text_center(int x, int y, const char *text, int textlen, int font, uint16_t fgcolor, uint16_t bgcolor); -void display_text_right(int x, int y, const char *text, int textlen, int font, uint16_t fgcolor, uint16_t bgcolor); +void display_text(int x, int y, const char *text, int textlen, int font, + uint16_t fgcolor, uint16_t bgcolor); +void display_text_center(int x, int y, const char *text, int textlen, int font, + uint16_t fgcolor, uint16_t bgcolor); +void display_text_right(int x, int y, const char *text, int textlen, int font, + uint16_t fgcolor, uint16_t bgcolor); int display_text_width(const char *text, int textlen, int font); void display_qrcode(int x, int y, const char *data, int datalen, uint8_t scale); diff --git a/embed/extmod/modtrezorui/font_bitmap.c b/embed/extmod/modtrezorui/font_bitmap.c index 6534f2b8e..ab017f662 100644 --- a/embed/extmod/modtrezorui/font_bitmap.c +++ b/embed/extmod/modtrezorui/font_bitmap.c @@ -1,5 +1,7 @@ #include "font_bitmap.h" +// clang-format off + const uint8_t * const Font_Bitmap = (const uint8_t * const) "\x00\x00\x00\x00\x00" "\x00\x00\x5f\x00\x00" diff --git a/embed/extmod/modtrezorui/font_bitmap.h b/embed/extmod/modtrezorui/font_bitmap.h index 804bc55e8..e9b9dd841 100644 --- a/embed/extmod/modtrezorui/font_bitmap.h +++ b/embed/extmod/modtrezorui/font_bitmap.h @@ -1,3 +1,3 @@ #include -extern const uint8_t * const Font_Bitmap; +extern const uint8_t* const Font_Bitmap; diff --git a/embed/extmod/modtrezorui/inflate.c b/embed/extmod/modtrezorui/inflate.c index b68d8cbb8..8f14f6515 100644 --- a/embed/extmod/modtrezorui/inflate.c +++ b/embed/extmod/modtrezorui/inflate.c @@ -17,6 +17,8 @@ * along with this program. If not, see . */ +// clang-format off + /* * stream_inflate - tiny inflate library with output streaming * diff --git a/embed/extmod/modtrezorui/inflate.h b/embed/extmod/modtrezorui/inflate.h index 2490e6ffe..9bae372f4 100644 --- a/embed/extmod/modtrezorui/inflate.h +++ b/embed/extmod/modtrezorui/inflate.h @@ -22,6 +22,9 @@ #include -int sinf_inflate(const uint8_t *data, uint32_t datalen, void (*write_callback)(uint8_t byte, uint32_t pos, void *userdata), void *userdata); +int sinf_inflate(const uint8_t *data, uint32_t datalen, + void (*write_callback)(uint8_t byte, uint32_t pos, + void *userdata), + void *userdata); #endif diff --git a/embed/extmod/modtrezorui/loader.h b/embed/extmod/modtrezorui/loader.h index fcd2821c5..ac9e294cd 100644 --- a/embed/extmod/modtrezorui/loader.h +++ b/embed/extmod/modtrezorui/loader.h @@ -1,3 +1,4 @@ +// clang-format off static const int img_loader_size = 60; static const uint16_t img_loader[60][60] = { {31744,31488,30976,30720,30208,29952,29696,29184,28672,28416,27904,27648,27136,26624,26368,25856,25344,25088,24576,24064,23552,23040,22528,22016,21504,20992,20480,19968,19456,18944,18432,17920,17408,16640,16128,15616,14848,14336,13824,13056,12544,11776,11264,10496,9984,9216,8704,7936,7424,6656,5888,5376,4624,4128,3393,2641,2146,1378,626,114,}, diff --git a/embed/extmod/modtrezorui/modtrezorui-display.h b/embed/extmod/modtrezorui/modtrezorui-display.h index b571320f4..862cd1199 100644 --- a/embed/extmod/modtrezorui/modtrezorui-display.h +++ b/embed/extmod/modtrezorui/modtrezorui-display.h @@ -26,18 +26,20 @@ /// Provide access to device display. /// ''' typedef struct _mp_obj_Display_t { - mp_obj_base_t base; + mp_obj_base_t base; } mp_obj_Display_t; /// def __init__(self) -> None: /// ''' /// Initialize the display. /// ''' -STATIC mp_obj_t mod_trezorui_Display_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_kw, const mp_obj_t *args) { - mp_arg_check_num(n_args, n_kw, 0, 0, false); - mp_obj_Display_t *o = m_new_obj(mp_obj_Display_t); - o->base.type = type; - return MP_OBJ_FROM_PTR(o); +STATIC mp_obj_t mod_trezorui_Display_make_new(const mp_obj_type_t *type, + size_t n_args, size_t n_kw, + const mp_obj_t *args) { + mp_arg_check_num(n_args, n_kw, 0, 0, false); + mp_obj_Display_t *o = m_new_obj(mp_obj_Display_t); + o->base.type = type; + return MP_OBJ_FROM_PTR(o); } /// def clear(self) -> None: @@ -45,423 +47,481 @@ STATIC mp_obj_t mod_trezorui_Display_make_new(const mp_obj_type_t *type, size_t /// Clear display with black color. /// ''' STATIC mp_obj_t mod_trezorui_Display_clear(mp_obj_t self) { - display_clear(); - return mp_const_none; + display_clear(); + return mp_const_none; } -STATIC MP_DEFINE_CONST_FUN_OBJ_1(mod_trezorui_Display_clear_obj, mod_trezorui_Display_clear); +STATIC MP_DEFINE_CONST_FUN_OBJ_1(mod_trezorui_Display_clear_obj, + mod_trezorui_Display_clear); /// def refresh(self) -> None: /// ''' /// Refresh display (update screen). /// ''' STATIC mp_obj_t mod_trezorui_Display_refresh(mp_obj_t self) { - display_refresh(); - return mp_const_none; + display_refresh(); + return mp_const_none; } -STATIC MP_DEFINE_CONST_FUN_OBJ_1(mod_trezorui_Display_refresh_obj, mod_trezorui_Display_refresh); +STATIC MP_DEFINE_CONST_FUN_OBJ_1(mod_trezorui_Display_refresh_obj, + mod_trezorui_Display_refresh); /// def bar(self, x: int, y: int, w: int, h: int, color: int) -> None: /// ''' -/// Renders a bar at position (x,y = upper left corner) with width w and height h of color color. +/// Renders a bar at position (x,y = upper left corner) with width w and +/// height h of color color. /// ''' STATIC mp_obj_t mod_trezorui_Display_bar(size_t n_args, const mp_obj_t *args) { - mp_int_t x = mp_obj_get_int(args[1]); - mp_int_t y = mp_obj_get_int(args[2]); - mp_int_t w = mp_obj_get_int(args[3]); - mp_int_t h = mp_obj_get_int(args[4]); - uint16_t c = mp_obj_get_int(args[5]); - display_bar(x, y, w, h, c); - return mp_const_none; + mp_int_t x = mp_obj_get_int(args[1]); + mp_int_t y = mp_obj_get_int(args[2]); + mp_int_t w = mp_obj_get_int(args[3]); + mp_int_t h = mp_obj_get_int(args[4]); + uint16_t c = mp_obj_get_int(args[5]); + display_bar(x, y, w, h, c); + return mp_const_none; } -STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(mod_trezorui_Display_bar_obj, 6, 6, mod_trezorui_Display_bar); +STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(mod_trezorui_Display_bar_obj, 6, 6, + mod_trezorui_Display_bar); -/// def bar_radius(self, x: int, y: int, w: int, h: int, fgcolor: int, bgcolor: int = None, radius: int = None) -> None: -/// ''' -/// Renders a rounded bar at position (x,y = upper left corner) with width w and height h of color fgcolor. -/// Background is set to bgcolor and corners are drawn with radius radius. -/// ''' -STATIC mp_obj_t mod_trezorui_Display_bar_radius(size_t n_args, const mp_obj_t *args) { - mp_int_t x = mp_obj_get_int(args[1]); - mp_int_t y = mp_obj_get_int(args[2]); - mp_int_t w = mp_obj_get_int(args[3]); - mp_int_t h = mp_obj_get_int(args[4]); - uint16_t c = mp_obj_get_int(args[5]); - uint16_t b = mp_obj_get_int(args[6]); - uint8_t r = mp_obj_get_int(args[7]); - display_bar_radius(x, y, w, h, c, b, r); - return mp_const_none; +/// def bar_radius(self, x: int, y: int, w: int, h: int, fgcolor: int, bgcolor: +/// int = None, radius: int = None) -> None: +/// ''' +/// Renders a rounded bar at position (x,y = upper left corner) with width w +/// and height h of color fgcolor. Background is set to bgcolor and corners +/// are drawn with radius radius. +/// ''' +STATIC mp_obj_t mod_trezorui_Display_bar_radius(size_t n_args, + const mp_obj_t *args) { + mp_int_t x = mp_obj_get_int(args[1]); + mp_int_t y = mp_obj_get_int(args[2]); + mp_int_t w = mp_obj_get_int(args[3]); + mp_int_t h = mp_obj_get_int(args[4]); + uint16_t c = mp_obj_get_int(args[5]); + uint16_t b = mp_obj_get_int(args[6]); + uint8_t r = mp_obj_get_int(args[7]); + display_bar_radius(x, y, w, h, c, b, r); + return mp_const_none; } -STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(mod_trezorui_Display_bar_radius_obj, 8, 8, mod_trezorui_Display_bar_radius); +STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(mod_trezorui_Display_bar_radius_obj, + 8, 8, + mod_trezorui_Display_bar_radius); /// def image(self, x: int, y: int, image: bytes) -> None: /// ''' /// Renders an image at position (x,y). -/// The image needs to be in TREZOR Optimized Image Format (TOIF) - full-color mode. -/// ''' -STATIC mp_obj_t mod_trezorui_Display_image(size_t n_args, const mp_obj_t *args) { - mp_int_t x = mp_obj_get_int(args[1]); - mp_int_t y = mp_obj_get_int(args[2]); - mp_buffer_info_t image; - mp_get_buffer_raise(args[3], &image, MP_BUFFER_READ); - const uint8_t *data = image.buf; - if (image.len < 8 || memcmp(data, "TOIf", 4) != 0) { - mp_raise_ValueError("Invalid image format"); - } - mp_int_t w = *(uint16_t *)(data + 4); - mp_int_t h = *(uint16_t *)(data + 6); - mp_int_t datalen = *(uint32_t *)(data + 8); - if (datalen != image.len - 12) { - mp_raise_ValueError("Invalid size of data"); - } - display_image(x, y, w, h, data + 12, datalen); - return mp_const_none; +/// The image needs to be in TREZOR Optimized Image Format (TOIF) - +/// full-color mode. +/// ''' +STATIC mp_obj_t mod_trezorui_Display_image(size_t n_args, + const mp_obj_t *args) { + mp_int_t x = mp_obj_get_int(args[1]); + mp_int_t y = mp_obj_get_int(args[2]); + mp_buffer_info_t image; + mp_get_buffer_raise(args[3], &image, MP_BUFFER_READ); + const uint8_t *data = image.buf; + if (image.len < 8 || memcmp(data, "TOIf", 4) != 0) { + mp_raise_ValueError("Invalid image format"); + } + mp_int_t w = *(uint16_t *)(data + 4); + mp_int_t h = *(uint16_t *)(data + 6); + mp_int_t datalen = *(uint32_t *)(data + 8); + if (datalen != image.len - 12) { + mp_raise_ValueError("Invalid size of data"); + } + display_image(x, y, w, h, data + 12, datalen); + return mp_const_none; } -STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(mod_trezorui_Display_image_obj, 4, 4, mod_trezorui_Display_image); +STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(mod_trezorui_Display_image_obj, 4, 4, + mod_trezorui_Display_image); -/// def avatar(self, x: int, y: int, image: bytes, fgcolor: int, bgcolor: int) -> None: +/// def avatar(self, x: int, y: int, image: bytes, fgcolor: int, bgcolor: int) +/// -> None: /// ''' /// Renders an avatar at position (x,y). -/// The image needs to be in TREZOR Optimized Image Format (TOIF) - full-color mode. -/// Image needs to be of exactly AVATAR_IMAGE_SIZE x AVATAR_IMAGE_SIZE pixels size. -/// ''' -STATIC mp_obj_t mod_trezorui_Display_avatar(size_t n_args, const mp_obj_t *args) { - mp_int_t x = mp_obj_get_int(args[1]); - mp_int_t y = mp_obj_get_int(args[2]); - mp_buffer_info_t image; - mp_get_buffer_raise(args[3], &image, MP_BUFFER_READ); - const uint8_t *data = image.buf; - if (image.len < 8 || memcmp(data, "TOIf", 4) != 0) { - mp_raise_ValueError("Invalid image format"); - } - mp_int_t w = *(uint16_t *)(data + 4); - mp_int_t h = *(uint16_t *)(data + 6); - if (w != AVATAR_IMAGE_SIZE || h != AVATAR_IMAGE_SIZE) { - mp_raise_ValueError("Invalid image size"); - } - mp_int_t datalen = *(uint32_t *)(data + 8); - if (datalen != image.len - 12) { - mp_raise_ValueError("Invalid size of data"); - } - mp_int_t fgcolor = mp_obj_get_int(args[4]); - mp_int_t bgcolor = mp_obj_get_int(args[5]); - display_avatar(x, y, data + 12, datalen, fgcolor, bgcolor); - return mp_const_none; +/// The image needs to be in TREZOR Optimized Image Format (TOIF) - +/// full-color mode. Image needs to be of exactly AVATAR_IMAGE_SIZE x +/// AVATAR_IMAGE_SIZE pixels size. +/// ''' +STATIC mp_obj_t mod_trezorui_Display_avatar(size_t n_args, + const mp_obj_t *args) { + mp_int_t x = mp_obj_get_int(args[1]); + mp_int_t y = mp_obj_get_int(args[2]); + mp_buffer_info_t image; + mp_get_buffer_raise(args[3], &image, MP_BUFFER_READ); + const uint8_t *data = image.buf; + if (image.len < 8 || memcmp(data, "TOIf", 4) != 0) { + mp_raise_ValueError("Invalid image format"); + } + mp_int_t w = *(uint16_t *)(data + 4); + mp_int_t h = *(uint16_t *)(data + 6); + if (w != AVATAR_IMAGE_SIZE || h != AVATAR_IMAGE_SIZE) { + mp_raise_ValueError("Invalid image size"); + } + mp_int_t datalen = *(uint32_t *)(data + 8); + if (datalen != image.len - 12) { + mp_raise_ValueError("Invalid size of data"); + } + mp_int_t fgcolor = mp_obj_get_int(args[4]); + mp_int_t bgcolor = mp_obj_get_int(args[5]); + display_avatar(x, y, data + 12, datalen, fgcolor, bgcolor); + return mp_const_none; } -STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(mod_trezorui_Display_avatar_obj, 6, 6, mod_trezorui_Display_avatar); +STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(mod_trezorui_Display_avatar_obj, 6, + 6, mod_trezorui_Display_avatar); -/// def icon(self, x: int, y: int, icon: bytes, fgcolor: int, bgcolor: int) -> None: +/// def icon(self, x: int, y: int, icon: bytes, fgcolor: int, bgcolor: int) -> +/// None: /// ''' -/// Renders an icon at position (x,y), fgcolor is used as foreground color, bgcolor as background. -/// The icon needs to be in TREZOR Optimized Image Format (TOIF) - gray-scale mode. +/// Renders an icon at position (x,y), fgcolor is used as foreground color, +/// bgcolor as background. The icon needs to be in TREZOR Optimized Image +/// Format (TOIF) - gray-scale mode. /// ''' STATIC mp_obj_t mod_trezorui_Display_icon(size_t n_args, const mp_obj_t *args) { - mp_int_t x = mp_obj_get_int(args[1]); - mp_int_t y = mp_obj_get_int(args[2]); + mp_int_t x = mp_obj_get_int(args[1]); + mp_int_t y = mp_obj_get_int(args[2]); + mp_buffer_info_t icon; + mp_get_buffer_raise(args[3], &icon, MP_BUFFER_READ); + const uint8_t *data = icon.buf; + if (icon.len < 8 || memcmp(data, "TOIg", 4) != 0) { + mp_raise_ValueError("Invalid image format"); + } + mp_int_t w = *(uint16_t *)(data + 4); + mp_int_t h = *(uint16_t *)(data + 6); + mp_int_t datalen = *(uint32_t *)(data + 8); + if (datalen != icon.len - 12) { + mp_raise_ValueError("Invalid size of data"); + } + mp_int_t fgcolor = mp_obj_get_int(args[4]); + mp_int_t bgcolor = mp_obj_get_int(args[5]); + display_icon(x, y, w, h, data + 12, icon.len - 12, fgcolor, bgcolor); + return mp_const_none; +} + +STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(mod_trezorui_Display_icon_obj, 6, 6, + mod_trezorui_Display_icon); +/// def loader(self, progress: int, yoffset: int, fgcolor: int, bgcolor: int, +/// icon: bytes = None, iconfgcolor: int = None) -> None: +/// ''' +/// Renders a rotating loader graphic. +/// Progress determines its position (0-1000), fgcolor is used as foreground +/// color, bgcolor as background. When icon and iconfgcolor are provided, an +/// icon is drawn in the middle using the color specified in iconfgcolor. +/// Icon needs to be of exactly LOADER_ICON_SIZE x LOADER_ICON_SIZE pixels +/// size. +/// ''' +STATIC mp_obj_t mod_trezorui_Display_loader(size_t n_args, + const mp_obj_t *args) { + mp_int_t progress = mp_obj_get_int(args[1]); + mp_int_t yoffset = mp_obj_get_int(args[2]); + mp_int_t fgcolor = mp_obj_get_int(args[3]); + mp_int_t bgcolor = mp_obj_get_int(args[4]); + if (n_args > 5) { // icon provided mp_buffer_info_t icon; - mp_get_buffer_raise(args[3], &icon, MP_BUFFER_READ); + mp_get_buffer_raise(args[5], &icon, MP_BUFFER_READ); const uint8_t *data = icon.buf; if (icon.len < 8 || memcmp(data, "TOIg", 4) != 0) { - mp_raise_ValueError("Invalid image format"); + mp_raise_ValueError("Invalid image format"); } mp_int_t w = *(uint16_t *)(data + 4); mp_int_t h = *(uint16_t *)(data + 6); mp_int_t datalen = *(uint32_t *)(data + 8); + if (w != LOADER_ICON_SIZE || h != LOADER_ICON_SIZE) { + mp_raise_ValueError("Invalid icon size"); + } if (datalen != icon.len - 12) { - mp_raise_ValueError("Invalid size of data"); + mp_raise_ValueError("Invalid size of data"); } - mp_int_t fgcolor = mp_obj_get_int(args[4]); - mp_int_t bgcolor = mp_obj_get_int(args[5]); - display_icon(x, y, w, h, data + 12, icon.len - 12, fgcolor, bgcolor); - return mp_const_none; -} - -STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(mod_trezorui_Display_icon_obj, 6, 6, mod_trezorui_Display_icon); -/// def loader(self, progress: int, yoffset: int, fgcolor: int, bgcolor: int, icon: bytes = None, iconfgcolor: int = None) -> None: -/// ''' -/// Renders a rotating loader graphic. -/// Progress determines its position (0-1000), fgcolor is used as foreground color, bgcolor as background. -/// When icon and iconfgcolor are provided, an icon is drawn in the middle using the color specified in iconfgcolor. -/// Icon needs to be of exactly LOADER_ICON_SIZE x LOADER_ICON_SIZE pixels size. -/// ''' -STATIC mp_obj_t mod_trezorui_Display_loader(size_t n_args, const mp_obj_t *args) { - mp_int_t progress = mp_obj_get_int(args[1]); - mp_int_t yoffset = mp_obj_get_int(args[2]); - mp_int_t fgcolor = mp_obj_get_int(args[3]); - mp_int_t bgcolor = mp_obj_get_int(args[4]); - if (n_args > 5) { // icon provided - mp_buffer_info_t icon; - mp_get_buffer_raise(args[5], &icon, MP_BUFFER_READ); - const uint8_t *data = icon.buf; - if (icon.len < 8 || memcmp(data, "TOIg", 4) != 0) { - mp_raise_ValueError("Invalid image format"); - } - mp_int_t w = *(uint16_t *)(data + 4); - mp_int_t h = *(uint16_t *)(data + 6); - mp_int_t datalen = *(uint32_t *)(data + 8); - if (w != LOADER_ICON_SIZE || h != LOADER_ICON_SIZE) { - mp_raise_ValueError("Invalid icon size"); - } - if (datalen != icon.len - 12) { - mp_raise_ValueError("Invalid size of data"); - } - uint16_t iconfgcolor; - if (n_args > 6) { // icon color provided - iconfgcolor = mp_obj_get_int(args[6]); - } else { - iconfgcolor = ~bgcolor; // invert - } - display_loader(progress, yoffset, fgcolor, bgcolor, icon.buf, icon.len, iconfgcolor); + uint16_t iconfgcolor; + if (n_args > 6) { // icon color provided + iconfgcolor = mp_obj_get_int(args[6]); } else { - display_loader(progress, yoffset, fgcolor, bgcolor, NULL, 0, 0); + iconfgcolor = ~bgcolor; // invert } - return mp_const_none; + display_loader(progress, yoffset, fgcolor, bgcolor, icon.buf, icon.len, + iconfgcolor); + } else { + display_loader(progress, yoffset, fgcolor, bgcolor, NULL, 0, 0); + } + return mp_const_none; } -STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(mod_trezorui_Display_loader_obj, 5, 7, mod_trezorui_Display_loader); +STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(mod_trezorui_Display_loader_obj, 5, + 7, mod_trezorui_Display_loader); /// def print(self, text: str) -> None: /// ''' /// Renders text using 5x8 bitmap font (using special text mode). /// ''' STATIC mp_obj_t mod_trezorui_Display_print(mp_obj_t self, mp_obj_t text) { - mp_buffer_info_t buf; - mp_get_buffer_raise(text, &buf, MP_BUFFER_READ); - if (buf.len > 0) { - display_print(buf.buf, buf.len); - } - return mp_const_none; + mp_buffer_info_t buf; + mp_get_buffer_raise(text, &buf, MP_BUFFER_READ); + if (buf.len > 0) { + display_print(buf.buf, buf.len); + } + return mp_const_none; } -STATIC MP_DEFINE_CONST_FUN_OBJ_2(mod_trezorui_Display_print_obj, mod_trezorui_Display_print); +STATIC MP_DEFINE_CONST_FUN_OBJ_2(mod_trezorui_Display_print_obj, + mod_trezorui_Display_print); -/// def text(self, x: int, y: int, text: str, font: int, fgcolor: int, bgcolor: int, minwidth: int=None) -> int: +/// def text(self, x: int, y: int, text: str, font: int, fgcolor: int, bgcolor: +/// int, minwidth: int=None) -> int: /// ''' -/// Renders left-aligned text at position (x,y) where x is left position and y is baseline. -/// Font font is used for rendering, fgcolor is used as foreground color, bgcolor as background. -/// Fills at least minwidth pixels with bgcolor. -/// Returns width of rendered text in pixels. +/// Renders left-aligned text at position (x,y) where x is left position and +/// y is baseline. Font font is used for rendering, fgcolor is used as +/// foreground color, bgcolor as background. Fills at least minwidth pixels +/// with bgcolor. Returns width of rendered text in pixels. /// ''' STATIC mp_obj_t mod_trezorui_Display_text(size_t n_args, const mp_obj_t *args) { - mp_int_t x = mp_obj_get_int(args[1]); - mp_int_t y = mp_obj_get_int(args[2]); - mp_buffer_info_t text; - mp_get_buffer_raise(args[3], &text, MP_BUFFER_READ); - mp_int_t font = mp_obj_get_int(args[4]); - mp_int_t fgcolor = mp_obj_get_int(args[5]); - mp_int_t bgcolor = mp_obj_get_int(args[6]); - mp_int_t minwidth = (n_args > 7) ? mp_obj_get_int(args[7]) : 0; - // prefill start - int w = display_text_width(text.buf, text.len, font); - int barwidth = MAX(w, minwidth); - display_bar(x, y - 18, barwidth, 23, bgcolor); - // prefill end - display_text(x, y, text.buf, text.len, font, fgcolor, bgcolor); - return mp_obj_new_int(w); + mp_int_t x = mp_obj_get_int(args[1]); + mp_int_t y = mp_obj_get_int(args[2]); + mp_buffer_info_t text; + mp_get_buffer_raise(args[3], &text, MP_BUFFER_READ); + mp_int_t font = mp_obj_get_int(args[4]); + mp_int_t fgcolor = mp_obj_get_int(args[5]); + mp_int_t bgcolor = mp_obj_get_int(args[6]); + mp_int_t minwidth = (n_args > 7) ? mp_obj_get_int(args[7]) : 0; + // prefill start + int w = display_text_width(text.buf, text.len, font); + int barwidth = MAX(w, minwidth); + display_bar(x, y - 18, barwidth, 23, bgcolor); + // prefill end + display_text(x, y, text.buf, text.len, font, fgcolor, bgcolor); + return mp_obj_new_int(w); } -STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(mod_trezorui_Display_text_obj, 7, 8, mod_trezorui_Display_text); +STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(mod_trezorui_Display_text_obj, 7, 8, + mod_trezorui_Display_text); -/// def text_center(self, x: int, y: int, text: str, font: int, fgcolor: int, bgcolor: int, minwidth: int=None) -> int: -/// ''' -/// Renders text centered at position (x,y) where x is text center and y is baseline. -/// Font font is used for rendering, fgcolor is used as foreground color, bgcolor as background. -/// Fills at least minwidth pixels with bgcolor. -/// Returns width of rendered text in pixels. -/// ''' -STATIC mp_obj_t mod_trezorui_Display_text_center(size_t n_args, const mp_obj_t *args) { - mp_int_t x = mp_obj_get_int(args[1]); - mp_int_t y = mp_obj_get_int(args[2]); - mp_buffer_info_t text; - mp_get_buffer_raise(args[3], &text, MP_BUFFER_READ); - mp_int_t font = mp_obj_get_int(args[4]); - mp_int_t fgcolor = mp_obj_get_int(args[5]); - mp_int_t bgcolor = mp_obj_get_int(args[6]); - mp_int_t minwidth = (n_args > 7) ? mp_obj_get_int(args[7]) : 0; - // prefill start - int w = display_text_width(text.buf, text.len, font); - int barwidth = MAX(w, minwidth); - display_bar(x - barwidth / 2, y - 18, barwidth, 23, bgcolor); - // prefill end - display_text_center(x, y, text.buf, text.len, font, fgcolor, bgcolor); - return mp_obj_new_int(w); +/// def text_center(self, x: int, y: int, text: str, font: int, fgcolor: int, +/// bgcolor: int, minwidth: int=None) -> int: +/// ''' +/// Renders text centered at position (x,y) where x is text center and y is +/// baseline. Font font is used for rendering, fgcolor is used as foreground +/// color, bgcolor as background. Fills at least minwidth pixels with +/// bgcolor. Returns width of rendered text in pixels. +/// ''' +STATIC mp_obj_t mod_trezorui_Display_text_center(size_t n_args, + const mp_obj_t *args) { + mp_int_t x = mp_obj_get_int(args[1]); + mp_int_t y = mp_obj_get_int(args[2]); + mp_buffer_info_t text; + mp_get_buffer_raise(args[3], &text, MP_BUFFER_READ); + mp_int_t font = mp_obj_get_int(args[4]); + mp_int_t fgcolor = mp_obj_get_int(args[5]); + mp_int_t bgcolor = mp_obj_get_int(args[6]); + mp_int_t minwidth = (n_args > 7) ? mp_obj_get_int(args[7]) : 0; + // prefill start + int w = display_text_width(text.buf, text.len, font); + int barwidth = MAX(w, minwidth); + display_bar(x - barwidth / 2, y - 18, barwidth, 23, bgcolor); + // prefill end + display_text_center(x, y, text.buf, text.len, font, fgcolor, bgcolor); + return mp_obj_new_int(w); } -STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(mod_trezorui_Display_text_center_obj, 7, 8, mod_trezorui_Display_text_center); +STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(mod_trezorui_Display_text_center_obj, + 7, 8, + mod_trezorui_Display_text_center); -/// def text_right(self, x: int, y: int, text: str, font: int, fgcolor: int, bgcolor: int, minwidth: int=None) -> int: -/// ''' -/// Renders right-aligned text at position (x,y) where x is right position and y is baseline. -/// Font font is used for rendering, fgcolor is used as foreground color, bgcolor as background. -/// Fills at least minwidth pixels with bgcolor. -/// Returns width of rendered text in pixels. -/// ''' -STATIC mp_obj_t mod_trezorui_Display_text_right(size_t n_args, const mp_obj_t *args) { - mp_int_t x = mp_obj_get_int(args[1]); - mp_int_t y = mp_obj_get_int(args[2]); - mp_buffer_info_t text; - mp_get_buffer_raise(args[3], &text, MP_BUFFER_READ); - mp_int_t font = mp_obj_get_int(args[4]); - mp_int_t fgcolor = mp_obj_get_int(args[5]); - mp_int_t bgcolor = mp_obj_get_int(args[6]); - mp_int_t minwidth = (n_args > 7) ? mp_obj_get_int(args[7]) : 0; - // prefill start - int w = display_text_width(text.buf, text.len, font); - int barwidth = MAX(w, minwidth); - display_bar(x - barwidth, y - 18, barwidth, 23, bgcolor); - // prefill end - display_text_right(x, y, text.buf, text.len, font, fgcolor, bgcolor); - return mp_obj_new_int(w); +/// def text_right(self, x: int, y: int, text: str, font: int, fgcolor: int, +/// bgcolor: int, minwidth: int=None) -> int: +/// ''' +/// Renders right-aligned text at position (x,y) where x is right position +/// and y is baseline. Font font is used for rendering, fgcolor is used as +/// foreground color, bgcolor as background. Fills at least minwidth pixels +/// with bgcolor. Returns width of rendered text in pixels. +/// ''' +STATIC mp_obj_t mod_trezorui_Display_text_right(size_t n_args, + const mp_obj_t *args) { + mp_int_t x = mp_obj_get_int(args[1]); + mp_int_t y = mp_obj_get_int(args[2]); + mp_buffer_info_t text; + mp_get_buffer_raise(args[3], &text, MP_BUFFER_READ); + mp_int_t font = mp_obj_get_int(args[4]); + mp_int_t fgcolor = mp_obj_get_int(args[5]); + mp_int_t bgcolor = mp_obj_get_int(args[6]); + mp_int_t minwidth = (n_args > 7) ? mp_obj_get_int(args[7]) : 0; + // prefill start + int w = display_text_width(text.buf, text.len, font); + int barwidth = MAX(w, minwidth); + display_bar(x - barwidth, y - 18, barwidth, 23, bgcolor); + // prefill end + display_text_right(x, y, text.buf, text.len, font, fgcolor, bgcolor); + return mp_obj_new_int(w); } -STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(mod_trezorui_Display_text_right_obj, 7, 8, mod_trezorui_Display_text_right); +STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(mod_trezorui_Display_text_right_obj, + 7, 8, + mod_trezorui_Display_text_right); /// def text_width(self, text: str, font: int) -> int: /// ''' /// Returns a width of text in pixels. Font font is used for rendering. /// ''' -STATIC mp_obj_t mod_trezorui_Display_text_width(mp_obj_t self, mp_obj_t text, mp_obj_t font) { - mp_buffer_info_t txt; - mp_get_buffer_raise(text, &txt, MP_BUFFER_READ); - mp_int_t f = mp_obj_get_int(font); - int w = display_text_width(txt.buf, txt.len, f); - return mp_obj_new_int(w); +STATIC mp_obj_t mod_trezorui_Display_text_width(mp_obj_t self, mp_obj_t text, + mp_obj_t font) { + mp_buffer_info_t txt; + mp_get_buffer_raise(text, &txt, MP_BUFFER_READ); + mp_int_t f = mp_obj_get_int(font); + int w = display_text_width(txt.buf, txt.len, f); + return mp_obj_new_int(w); } -STATIC MP_DEFINE_CONST_FUN_OBJ_3(mod_trezorui_Display_text_width_obj, mod_trezorui_Display_text_width); +STATIC MP_DEFINE_CONST_FUN_OBJ_3(mod_trezorui_Display_text_width_obj, + mod_trezorui_Display_text_width); /// def qrcode(self, x: int, y: int, data: bytes, scale: int) -> None: /// ''' /// Renders data encoded as a QR code centered at position (x,y). /// Scale determines a zoom factor. /// ''' -STATIC mp_obj_t mod_trezorui_Display_qrcode(size_t n_args, const mp_obj_t *args) { - mp_int_t x = mp_obj_get_int(args[1]); - mp_int_t y = mp_obj_get_int(args[2]); - mp_int_t scale = mp_obj_get_int(args[4]); - if (scale < 1 || scale > 10) { - mp_raise_ValueError("Scale has to be between 1 and 10"); - } - mp_buffer_info_t data; - mp_get_buffer_raise(args[3], &data, MP_BUFFER_READ); - if (data.len > 0) { - display_qrcode(x, y, data.buf, data.len, scale); - } - return mp_const_none; +STATIC mp_obj_t mod_trezorui_Display_qrcode(size_t n_args, + const mp_obj_t *args) { + mp_int_t x = mp_obj_get_int(args[1]); + mp_int_t y = mp_obj_get_int(args[2]); + mp_int_t scale = mp_obj_get_int(args[4]); + if (scale < 1 || scale > 10) { + mp_raise_ValueError("Scale has to be between 1 and 10"); + } + mp_buffer_info_t data; + mp_get_buffer_raise(args[3], &data, MP_BUFFER_READ); + if (data.len > 0) { + display_qrcode(x, y, data.buf, data.len, scale); + } + return mp_const_none; } -STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(mod_trezorui_Display_qrcode_obj, 5, 5, mod_trezorui_Display_qrcode); +STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(mod_trezorui_Display_qrcode_obj, 5, + 5, mod_trezorui_Display_qrcode); /// def orientation(self, degrees: int = None) -> int: /// ''' /// Sets display orientation to 0, 90, 180 or 270 degrees. /// Everything needs to be redrawn again when this function is used. -/// Call without the degrees parameter to just perform the read of the value. -/// ''' -STATIC mp_obj_t mod_trezorui_Display_orientation(size_t n_args, const mp_obj_t *args) { - mp_int_t deg; - if (n_args > 1) { - deg = mp_obj_get_int(args[1]); - if (deg != 0 && deg != 90 && deg != 180 && deg != 270) { - mp_raise_ValueError("Value must be 0, 90, 180 or 270"); - } - deg = display_orientation(deg); - } else { - deg = display_orientation(-1); +/// Call without the degrees parameter to just perform the read of the +/// value. +/// ''' +STATIC mp_obj_t mod_trezorui_Display_orientation(size_t n_args, + const mp_obj_t *args) { + mp_int_t deg; + if (n_args > 1) { + deg = mp_obj_get_int(args[1]); + if (deg != 0 && deg != 90 && deg != 180 && deg != 270) { + mp_raise_ValueError("Value must be 0, 90, 180 or 270"); } - return MP_OBJ_NEW_SMALL_INT(deg); + deg = display_orientation(deg); + } else { + deg = display_orientation(-1); + } + return MP_OBJ_NEW_SMALL_INT(deg); } -STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(mod_trezorui_Display_orientation_obj, 1, 2, mod_trezorui_Display_orientation); +STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(mod_trezorui_Display_orientation_obj, + 1, 2, + mod_trezorui_Display_orientation); /// def backlight(self, val: int = None) -> int: /// ''' /// Sets backlight intensity to the value specified in val. /// Call without the val parameter to just perform the read of the value. /// ''' -STATIC mp_obj_t mod_trezorui_Display_backlight(size_t n_args, const mp_obj_t *args) { - mp_int_t val; - if (n_args > 1) { - val = mp_obj_get_int(args[1]); - if (val < 0 || val > 255) { - mp_raise_ValueError("Value must be between 0 and 255"); - } - val = display_backlight(val); - } else { - val = display_backlight(-1); +STATIC mp_obj_t mod_trezorui_Display_backlight(size_t n_args, + const mp_obj_t *args) { + mp_int_t val; + if (n_args > 1) { + val = mp_obj_get_int(args[1]); + if (val < 0 || val > 255) { + mp_raise_ValueError("Value must be between 0 and 255"); } - return MP_OBJ_NEW_SMALL_INT(val); + val = display_backlight(val); + } else { + val = display_backlight(-1); + } + return MP_OBJ_NEW_SMALL_INT(val); } -STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(mod_trezorui_Display_backlight_obj, 1, 2, mod_trezorui_Display_backlight); +STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(mod_trezorui_Display_backlight_obj, + 1, 2, + mod_trezorui_Display_backlight); /// def offset(self, xy: Tuple[int, int] = None) -> Tuple[int, int]: /// ''' /// Sets offset (x, y) for all subsequent drawing calls. /// Call without the xy parameter to just perform the read of the value. /// ''' -STATIC mp_obj_t mod_trezorui_Display_offset(size_t n_args, const mp_obj_t *args) { - int xy[2], x, y; - if (n_args > 1) { - size_t xy_cnt; - mp_obj_t *xy_obj; - if (MP_OBJ_IS_TYPE(args[1], &mp_type_tuple)) { - mp_obj_tuple_get(args[1], &xy_cnt, &xy_obj); - } else { - mp_raise_TypeError("Tuple expected"); - } - if (xy_cnt != 2) { - mp_raise_ValueError("Tuple of 2 values expected"); - } - xy[0] = mp_obj_get_int(xy_obj[0]); - xy[1] = mp_obj_get_int(xy_obj[1]); - display_offset(xy, &x, &y); +STATIC mp_obj_t mod_trezorui_Display_offset(size_t n_args, + const mp_obj_t *args) { + int xy[2], x, y; + if (n_args > 1) { + size_t xy_cnt; + mp_obj_t *xy_obj; + if (MP_OBJ_IS_TYPE(args[1], &mp_type_tuple)) { + mp_obj_tuple_get(args[1], &xy_cnt, &xy_obj); } else { - display_offset(0, &x, &y); + mp_raise_TypeError("Tuple expected"); + } + if (xy_cnt != 2) { + mp_raise_ValueError("Tuple of 2 values expected"); } - mp_obj_tuple_t *tuple = MP_OBJ_TO_PTR(mp_obj_new_tuple(2, NULL)); - tuple->items[0] = MP_OBJ_NEW_SMALL_INT(x); - tuple->items[1] = MP_OBJ_NEW_SMALL_INT(y); - return MP_OBJ_FROM_PTR(tuple); + xy[0] = mp_obj_get_int(xy_obj[0]); + xy[1] = mp_obj_get_int(xy_obj[1]); + display_offset(xy, &x, &y); + } else { + display_offset(0, &x, &y); + } + mp_obj_tuple_t *tuple = MP_OBJ_TO_PTR(mp_obj_new_tuple(2, NULL)); + tuple->items[0] = MP_OBJ_NEW_SMALL_INT(x); + tuple->items[1] = MP_OBJ_NEW_SMALL_INT(y); + return MP_OBJ_FROM_PTR(tuple); } -STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(mod_trezorui_Display_offset_obj, 1, 2, mod_trezorui_Display_offset); +STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(mod_trezorui_Display_offset_obj, 1, + 2, mod_trezorui_Display_offset); /// def save(self, prefix: str) -> None: /// ''' /// Saves current display contents to PNG file with given prefix. /// ''' STATIC mp_obj_t mod_trezorui_Display_save(mp_obj_t self, mp_obj_t prefix) { - mp_buffer_info_t pfx; - mp_get_buffer_raise(prefix, &pfx, MP_BUFFER_READ); - if (pfx.len > 0) { - display_save(pfx.buf); - } - return mp_const_none; + mp_buffer_info_t pfx; + mp_get_buffer_raise(prefix, &pfx, MP_BUFFER_READ); + if (pfx.len > 0) { + display_save(pfx.buf); + } + return mp_const_none; } -STATIC MP_DEFINE_CONST_FUN_OBJ_2(mod_trezorui_Display_save_obj, mod_trezorui_Display_save); +STATIC MP_DEFINE_CONST_FUN_OBJ_2(mod_trezorui_Display_save_obj, + mod_trezorui_Display_save); STATIC const mp_rom_map_elem_t mod_trezorui_Display_locals_dict_table[] = { - { MP_ROM_QSTR(MP_QSTR_clear), MP_ROM_PTR(&mod_trezorui_Display_clear_obj) }, - { MP_ROM_QSTR(MP_QSTR_refresh), MP_ROM_PTR(&mod_trezorui_Display_refresh_obj) }, - { MP_ROM_QSTR(MP_QSTR_bar), MP_ROM_PTR(&mod_trezorui_Display_bar_obj) }, - { MP_ROM_QSTR(MP_QSTR_bar_radius), MP_ROM_PTR(&mod_trezorui_Display_bar_radius_obj) }, - { MP_ROM_QSTR(MP_QSTR_image), MP_ROM_PTR(&mod_trezorui_Display_image_obj) }, - { MP_ROM_QSTR(MP_QSTR_avatar), MP_ROM_PTR(&mod_trezorui_Display_avatar_obj) }, - { MP_ROM_QSTR(MP_QSTR_icon), MP_ROM_PTR(&mod_trezorui_Display_icon_obj) }, - { MP_ROM_QSTR(MP_QSTR_loader), MP_ROM_PTR(&mod_trezorui_Display_loader_obj) }, - { MP_ROM_QSTR(MP_QSTR_print), MP_ROM_PTR(&mod_trezorui_Display_print_obj) }, - { MP_ROM_QSTR(MP_QSTR_text), MP_ROM_PTR(&mod_trezorui_Display_text_obj) }, - { MP_ROM_QSTR(MP_QSTR_text_center), MP_ROM_PTR(&mod_trezorui_Display_text_center_obj) }, - { MP_ROM_QSTR(MP_QSTR_text_right), MP_ROM_PTR(&mod_trezorui_Display_text_right_obj) }, - { MP_ROM_QSTR(MP_QSTR_text_width), MP_ROM_PTR(&mod_trezorui_Display_text_width_obj) }, - { MP_ROM_QSTR(MP_QSTR_qrcode), MP_ROM_PTR(&mod_trezorui_Display_qrcode_obj) }, - { MP_ROM_QSTR(MP_QSTR_orientation), MP_ROM_PTR(&mod_trezorui_Display_orientation_obj) }, - { MP_ROM_QSTR(MP_QSTR_backlight), MP_ROM_PTR(&mod_trezorui_Display_backlight_obj) }, - { MP_ROM_QSTR(MP_QSTR_offset), MP_ROM_PTR(&mod_trezorui_Display_offset_obj) }, - { MP_ROM_QSTR(MP_QSTR_save), MP_ROM_PTR(&mod_trezorui_Display_save_obj) }, - { MP_ROM_QSTR(MP_QSTR_WIDTH), MP_OBJ_NEW_SMALL_INT(DISPLAY_RESX) }, - { MP_ROM_QSTR(MP_QSTR_HEIGHT), MP_OBJ_NEW_SMALL_INT(DISPLAY_RESY) }, - { MP_ROM_QSTR(MP_QSTR_FONT_SIZE), MP_OBJ_NEW_SMALL_INT(FONT_SIZE) }, - { MP_ROM_QSTR(MP_QSTR_FONT_NORMAL), MP_OBJ_NEW_SMALL_INT(FONT_NORMAL) }, - { MP_ROM_QSTR(MP_QSTR_FONT_BOLD), MP_OBJ_NEW_SMALL_INT(FONT_BOLD) }, - { MP_ROM_QSTR(MP_QSTR_FONT_MONO), MP_OBJ_NEW_SMALL_INT(FONT_MONO) }, - { MP_ROM_QSTR(MP_QSTR_FONT_MONO_BOLD), MP_OBJ_NEW_SMALL_INT(FONT_MONO_BOLD) }, + {MP_ROM_QSTR(MP_QSTR_clear), MP_ROM_PTR(&mod_trezorui_Display_clear_obj)}, + {MP_ROM_QSTR(MP_QSTR_refresh), + MP_ROM_PTR(&mod_trezorui_Display_refresh_obj)}, + {MP_ROM_QSTR(MP_QSTR_bar), MP_ROM_PTR(&mod_trezorui_Display_bar_obj)}, + {MP_ROM_QSTR(MP_QSTR_bar_radius), + MP_ROM_PTR(&mod_trezorui_Display_bar_radius_obj)}, + {MP_ROM_QSTR(MP_QSTR_image), MP_ROM_PTR(&mod_trezorui_Display_image_obj)}, + {MP_ROM_QSTR(MP_QSTR_avatar), MP_ROM_PTR(&mod_trezorui_Display_avatar_obj)}, + {MP_ROM_QSTR(MP_QSTR_icon), MP_ROM_PTR(&mod_trezorui_Display_icon_obj)}, + {MP_ROM_QSTR(MP_QSTR_loader), MP_ROM_PTR(&mod_trezorui_Display_loader_obj)}, + {MP_ROM_QSTR(MP_QSTR_print), MP_ROM_PTR(&mod_trezorui_Display_print_obj)}, + {MP_ROM_QSTR(MP_QSTR_text), MP_ROM_PTR(&mod_trezorui_Display_text_obj)}, + {MP_ROM_QSTR(MP_QSTR_text_center), + MP_ROM_PTR(&mod_trezorui_Display_text_center_obj)}, + {MP_ROM_QSTR(MP_QSTR_text_right), + MP_ROM_PTR(&mod_trezorui_Display_text_right_obj)}, + {MP_ROM_QSTR(MP_QSTR_text_width), + MP_ROM_PTR(&mod_trezorui_Display_text_width_obj)}, + {MP_ROM_QSTR(MP_QSTR_qrcode), MP_ROM_PTR(&mod_trezorui_Display_qrcode_obj)}, + {MP_ROM_QSTR(MP_QSTR_orientation), + MP_ROM_PTR(&mod_trezorui_Display_orientation_obj)}, + {MP_ROM_QSTR(MP_QSTR_backlight), + MP_ROM_PTR(&mod_trezorui_Display_backlight_obj)}, + {MP_ROM_QSTR(MP_QSTR_offset), MP_ROM_PTR(&mod_trezorui_Display_offset_obj)}, + {MP_ROM_QSTR(MP_QSTR_save), MP_ROM_PTR(&mod_trezorui_Display_save_obj)}, + {MP_ROM_QSTR(MP_QSTR_WIDTH), MP_OBJ_NEW_SMALL_INT(DISPLAY_RESX)}, + {MP_ROM_QSTR(MP_QSTR_HEIGHT), MP_OBJ_NEW_SMALL_INT(DISPLAY_RESY)}, + {MP_ROM_QSTR(MP_QSTR_FONT_SIZE), MP_OBJ_NEW_SMALL_INT(FONT_SIZE)}, + {MP_ROM_QSTR(MP_QSTR_FONT_NORMAL), MP_OBJ_NEW_SMALL_INT(FONT_NORMAL)}, + {MP_ROM_QSTR(MP_QSTR_FONT_BOLD), MP_OBJ_NEW_SMALL_INT(FONT_BOLD)}, + {MP_ROM_QSTR(MP_QSTR_FONT_MONO), MP_OBJ_NEW_SMALL_INT(FONT_MONO)}, + {MP_ROM_QSTR(MP_QSTR_FONT_MONO_BOLD), MP_OBJ_NEW_SMALL_INT(FONT_MONO_BOLD)}, }; -STATIC MP_DEFINE_CONST_DICT(mod_trezorui_Display_locals_dict, mod_trezorui_Display_locals_dict_table); +STATIC MP_DEFINE_CONST_DICT(mod_trezorui_Display_locals_dict, + mod_trezorui_Display_locals_dict_table); STATIC const mp_obj_type_t mod_trezorui_Display_type = { - { &mp_type_type }, + {&mp_type_type}, .name = MP_QSTR_Display, .make_new = mod_trezorui_Display_make_new, - .locals_dict = (void*)&mod_trezorui_Display_locals_dict, + .locals_dict = (void *)&mod_trezorui_Display_locals_dict, }; diff --git a/embed/extmod/modtrezorui/modtrezorui.c b/embed/extmod/modtrezorui/modtrezorui.c index bf5cb2e3e..e31ba8495 100644 --- a/embed/extmod/modtrezorui/modtrezorui.c +++ b/embed/extmod/modtrezorui/modtrezorui.c @@ -17,9 +17,9 @@ * along with this program. If not, see . */ +#include #include #include -#include #include "py/runtime.h" @@ -28,15 +28,16 @@ #include "modtrezorui-display.h" STATIC const mp_rom_map_elem_t mp_module_trezorui_globals_table[] = { - { MP_ROM_QSTR(MP_QSTR___name__), MP_ROM_QSTR(MP_QSTR_trezorui) }, - { MP_ROM_QSTR(MP_QSTR_Display), MP_ROM_PTR(&mod_trezorui_Display_type) }, + {MP_ROM_QSTR(MP_QSTR___name__), MP_ROM_QSTR(MP_QSTR_trezorui)}, + {MP_ROM_QSTR(MP_QSTR_Display), MP_ROM_PTR(&mod_trezorui_Display_type)}, }; -STATIC MP_DEFINE_CONST_DICT(mp_module_trezorui_globals, mp_module_trezorui_globals_table); +STATIC MP_DEFINE_CONST_DICT(mp_module_trezorui_globals, + mp_module_trezorui_globals_table); const mp_obj_module_t mp_module_trezorui = { - .base = { &mp_type_module }, + .base = {&mp_type_module}, .globals = (mp_obj_dict_t*)&mp_module_trezorui_globals, }; -#endif // MICROPY_PY_TREZORUI +#endif // MICROPY_PY_TREZORUI diff --git a/embed/extmod/modtrezorutils/modtrezorutils.c b/embed/extmod/modtrezorutils/modtrezorutils.c index 3e254a65e..0f13a030a 100644 --- a/embed/extmod/modtrezorutils/modtrezorutils.c +++ b/embed/extmod/modtrezorutils/modtrezorutils.c @@ -36,25 +36,26 @@ /// expected to avoid any invalid memory access. /// ''' STATIC mp_obj_t mod_trezorutils_consteq(mp_obj_t sec, mp_obj_t pub) { - mp_buffer_info_t secbuf; - mp_get_buffer_raise(sec, &secbuf, MP_BUFFER_READ); - mp_buffer_info_t pubbuf; - mp_get_buffer_raise(pub, &pubbuf, MP_BUFFER_READ); - - size_t diff = secbuf.len - pubbuf.len; - for (size_t i = 0; i < pubbuf.len; i++) { - const uint8_t *s = (uint8_t *)secbuf.buf; - const uint8_t *p = (uint8_t *)pubbuf.buf; - diff |= s[i] - p[i]; - } - - if (diff == 0) { - return mp_const_true; - } else { - return mp_const_false; - } + mp_buffer_info_t secbuf; + mp_get_buffer_raise(sec, &secbuf, MP_BUFFER_READ); + mp_buffer_info_t pubbuf; + mp_get_buffer_raise(pub, &pubbuf, MP_BUFFER_READ); + + size_t diff = secbuf.len - pubbuf.len; + for (size_t i = 0; i < pubbuf.len; i++) { + const uint8_t *s = (uint8_t *)secbuf.buf; + const uint8_t *p = (uint8_t *)pubbuf.buf; + diff |= s[i] - p[i]; + } + + if (diff == 0) { + return mp_const_true; + } else { + return mp_const_false; + } } -STATIC MP_DEFINE_CONST_FUN_OBJ_2(mod_trezorutils_consteq_obj, mod_trezorutils_consteq); +STATIC MP_DEFINE_CONST_FUN_OBJ_2(mod_trezorutils_consteq_obj, + mod_trezorutils_consteq); /// def memcpy(dst: bytearray, dst_ofs: int, /// src: bytearray, src_ofs: int, @@ -65,42 +66,44 @@ STATIC MP_DEFINE_CONST_FUN_OBJ_2(mod_trezorutils_consteq_obj, mod_trezorutils_co /// copied bytes. /// ''' STATIC mp_obj_t mod_trezorutils_memcpy(size_t n_args, const mp_obj_t *args) { - mp_arg_check_num(n_args, 0, 5, 5, false); + mp_arg_check_num(n_args, 0, 5, 5, false); - mp_buffer_info_t dst; - mp_get_buffer_raise(args[0], &dst, MP_BUFFER_WRITE); - uint32_t dst_ofs = trezor_obj_get_uint(args[1]); + mp_buffer_info_t dst; + mp_get_buffer_raise(args[0], &dst, MP_BUFFER_WRITE); + uint32_t dst_ofs = trezor_obj_get_uint(args[1]); - mp_buffer_info_t src; - mp_get_buffer_raise(args[2], &src, MP_BUFFER_READ); - uint32_t src_ofs = trezor_obj_get_uint(args[3]); + mp_buffer_info_t src; + mp_get_buffer_raise(args[2], &src, MP_BUFFER_READ); + uint32_t src_ofs = trezor_obj_get_uint(args[3]); - uint32_t n = trezor_obj_get_uint(args[4]); + uint32_t n = trezor_obj_get_uint(args[4]); - size_t dst_rem = (dst_ofs < dst.len) ? dst.len - dst_ofs : 0; - size_t src_rem = (src_ofs < src.len) ? src.len - src_ofs : 0; - size_t ncpy = MIN(n, MIN(src_rem, dst_rem)); + size_t dst_rem = (dst_ofs < dst.len) ? dst.len - dst_ofs : 0; + size_t src_rem = (src_ofs < src.len) ? src.len - src_ofs : 0; + size_t ncpy = MIN(n, MIN(src_rem, dst_rem)); - memmove(((char*)dst.buf) + dst_ofs, ((const char*)src.buf) + src_ofs, ncpy); + memmove(((char *)dst.buf) + dst_ofs, ((const char *)src.buf) + src_ofs, ncpy); - return mp_obj_new_int(ncpy); + return mp_obj_new_int(ncpy); } -STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(mod_trezorutils_memcpy_obj, 5, 5, mod_trezorutils_memcpy); +STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(mod_trezorutils_memcpy_obj, 5, 5, + mod_trezorutils_memcpy); /// def halt(msg: str = None) -> None: /// ''' /// Halts execution. /// ''' STATIC mp_obj_t mod_trezorutils_halt(size_t n_args, const mp_obj_t *args) { - mp_buffer_info_t msg; - if (n_args > 0 && mp_get_buffer(args[0], &msg, MP_BUFFER_READ)) { - ensure(secfalse, msg.buf); - } else { - ensure(secfalse, "halt"); - } - return mp_const_none; + mp_buffer_info_t msg; + if (n_args > 0 && mp_get_buffer(args[0], &msg, MP_BUFFER_READ)) { + ensure(secfalse, msg.buf); + } else { + ensure(secfalse, "halt"); + } + return mp_const_none; } -STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(mod_trezorutils_halt_obj, 0, 1, mod_trezorutils_halt); +STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(mod_trezorutils_halt_obj, 0, 1, + mod_trezorutils_halt); /// def set_mode_unprivileged() -> None: /// ''' @@ -108,40 +111,43 @@ STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(mod_trezorutils_halt_obj, 0, 1, mod_t /// ''' STATIC mp_obj_t mod_trezorutils_set_mode_unprivileged(void) { #ifndef TREZOR_EMULATOR - __asm__ volatile("msr control, %0" :: "r" (0x1)); - __asm__ volatile("isb"); + __asm__ volatile("msr control, %0" ::"r"(0x1)); + __asm__ volatile("isb"); #endif - return mp_const_none; + return mp_const_none; } -STATIC MP_DEFINE_CONST_FUN_OBJ_0(mod_trezorutils_set_mode_unprivileged_obj, mod_trezorutils_set_mode_unprivileged); +STATIC MP_DEFINE_CONST_FUN_OBJ_0(mod_trezorutils_set_mode_unprivileged_obj, + mod_trezorutils_set_mode_unprivileged); -#define PASTER(s) MP_QSTR_ ## s +#define PASTER(s) MP_QSTR_##s #define MP_QSTR(s) PASTER(s) STATIC const mp_rom_map_elem_t mp_module_trezorutils_globals_table[] = { - { MP_ROM_QSTR(MP_QSTR___name__), MP_ROM_QSTR(MP_QSTR_trezorutils) }, - { MP_ROM_QSTR(MP_QSTR_consteq), MP_ROM_PTR(&mod_trezorutils_consteq_obj) }, - { MP_ROM_QSTR(MP_QSTR_memcpy), MP_ROM_PTR(&mod_trezorutils_memcpy_obj) }, - { MP_ROM_QSTR(MP_QSTR_halt), MP_ROM_PTR(&mod_trezorutils_halt_obj) }, - { MP_ROM_QSTR(MP_QSTR_set_mode_unprivileged), MP_ROM_PTR(&mod_trezorutils_set_mode_unprivileged_obj) }, + {MP_ROM_QSTR(MP_QSTR___name__), MP_ROM_QSTR(MP_QSTR_trezorutils)}, + {MP_ROM_QSTR(MP_QSTR_consteq), MP_ROM_PTR(&mod_trezorutils_consteq_obj)}, + {MP_ROM_QSTR(MP_QSTR_memcpy), MP_ROM_PTR(&mod_trezorutils_memcpy_obj)}, + {MP_ROM_QSTR(MP_QSTR_halt), MP_ROM_PTR(&mod_trezorutils_halt_obj)}, + {MP_ROM_QSTR(MP_QSTR_set_mode_unprivileged), + MP_ROM_PTR(&mod_trezorutils_set_mode_unprivileged_obj)}, // various built-in constants - { MP_ROM_QSTR(MP_QSTR_GITREV), MP_ROM_QSTR(MP_QSTR(GITREV)) }, - { MP_ROM_QSTR(MP_QSTR_VERSION_MAJOR), MP_OBJ_NEW_SMALL_INT(VERSION_MAJOR) }, - { MP_ROM_QSTR(MP_QSTR_VERSION_MINOR), MP_OBJ_NEW_SMALL_INT(VERSION_MINOR) }, - { MP_ROM_QSTR(MP_QSTR_VERSION_PATCH), MP_OBJ_NEW_SMALL_INT(VERSION_PATCH) }, - { MP_ROM_QSTR(MP_QSTR_MODEL), MP_ROM_QSTR(MP_QSTR(TREZOR_MODEL)) }, + {MP_ROM_QSTR(MP_QSTR_GITREV), MP_ROM_QSTR(MP_QSTR(GITREV))}, + {MP_ROM_QSTR(MP_QSTR_VERSION_MAJOR), MP_OBJ_NEW_SMALL_INT(VERSION_MAJOR)}, + {MP_ROM_QSTR(MP_QSTR_VERSION_MINOR), MP_OBJ_NEW_SMALL_INT(VERSION_MINOR)}, + {MP_ROM_QSTR(MP_QSTR_VERSION_PATCH), MP_OBJ_NEW_SMALL_INT(VERSION_PATCH)}, + {MP_ROM_QSTR(MP_QSTR_MODEL), MP_ROM_QSTR(MP_QSTR(TREZOR_MODEL))}, #ifdef TREZOR_EMULATOR - { MP_ROM_QSTR(MP_QSTR_EMULATOR), mp_const_true }, + {MP_ROM_QSTR(MP_QSTR_EMULATOR), mp_const_true}, #else - { MP_ROM_QSTR(MP_QSTR_EMULATOR), mp_const_false }, + {MP_ROM_QSTR(MP_QSTR_EMULATOR), mp_const_false}, #endif }; -STATIC MP_DEFINE_CONST_DICT(mp_module_trezorutils_globals, mp_module_trezorutils_globals_table); +STATIC MP_DEFINE_CONST_DICT(mp_module_trezorutils_globals, + mp_module_trezorutils_globals_table); const mp_obj_module_t mp_module_trezorutils = { - .base = { &mp_type_module }, - .globals = (mp_obj_dict_t*)&mp_module_trezorutils_globals, + .base = {&mp_type_module}, + .globals = (mp_obj_dict_t *)&mp_module_trezorutils_globals, }; -#endif // MICROPY_PY_TREZORUTILS +#endif // MICROPY_PY_TREZORUTILS diff --git a/embed/extmod/trezorobj.h b/embed/extmod/trezorobj.h index 76ff4d4c5..fbf220448 100644 --- a/embed/extmod/trezorobj.h +++ b/embed/extmod/trezorobj.h @@ -17,8 +17,8 @@ * along with this program. If not, see . */ -#include "py/runtime.h" #include "py/objint.h" +#include "py/runtime.h" #ifndef __TREZOROBJ_H__ #define __TREZOROBJ_H__ @@ -30,51 +30,49 @@ // Casts int object into mp_int_t, without any conversions. Raises if object is // not int or if it does not fit into mp_int_t representation. static inline mp_int_t trezor_obj_get_int(mp_obj_t obj) { - if (MP_OBJ_IS_SMALL_INT(obj)) { - mp_int_t i = MP_OBJ_SMALL_INT_VALUE(obj); - return i; - } - else if (MP_OBJ_IS_TYPE(obj, &mp_type_int)) { - mp_int_t i = 0; - mp_obj_int_t *self = MP_OBJ_TO_PTR(obj); - if (!mpz_as_int_checked(&self->mpz, &i)) { - mp_raise_msg(&mp_type_OverflowError, "value does not fit into signed int type"); - } - return i; - } - else { - mp_raise_TypeError("value is not int"); + if (MP_OBJ_IS_SMALL_INT(obj)) { + mp_int_t i = MP_OBJ_SMALL_INT_VALUE(obj); + return i; + } else if (MP_OBJ_IS_TYPE(obj, &mp_type_int)) { + mp_int_t i = 0; + mp_obj_int_t *self = MP_OBJ_TO_PTR(obj); + if (!mpz_as_int_checked(&self->mpz, &i)) { + mp_raise_msg(&mp_type_OverflowError, + "value does not fit into signed int type"); } + return i; + } else { + mp_raise_TypeError("value is not int"); + } } // Casts int object into mp_uint_t, without any conversions. Raises if object is // not int or if it does not fit into mp_uint_t representation (or is less than // 0). static inline mp_uint_t trezor_obj_get_uint(mp_obj_t obj) { - if (MP_OBJ_IS_SMALL_INT(obj)) { - mp_int_t i = MP_OBJ_SMALL_INT_VALUE(obj); - mp_uint_t u = i; - return u; - } - else if (MP_OBJ_IS_TYPE(obj, &mp_type_int)) { - mp_uint_t u = 0; - mp_obj_int_t *self = MP_OBJ_TO_PTR(obj); - if (!mpz_as_uint_checked(&self->mpz, &u)) { - mp_raise_msg(&mp_type_OverflowError, "value does not fit into unsigned int type"); - } - return u; - } - else { - mp_raise_TypeError("value is not int"); + if (MP_OBJ_IS_SMALL_INT(obj)) { + mp_int_t i = MP_OBJ_SMALL_INT_VALUE(obj); + mp_uint_t u = i; + return u; + } else if (MP_OBJ_IS_TYPE(obj, &mp_type_int)) { + mp_uint_t u = 0; + mp_obj_int_t *self = MP_OBJ_TO_PTR(obj); + if (!mpz_as_uint_checked(&self->mpz, &u)) { + mp_raise_msg(&mp_type_OverflowError, + "value does not fit into unsigned int type"); } + return u; + } else { + mp_raise_TypeError("value is not int"); + } } static inline uint8_t trezor_obj_get_uint8(mp_obj_t obj) { - mp_uint_t u = trezor_obj_get_uint(obj); - if (u > 0xFF) { - mp_raise_msg(&mp_type_OverflowError, "value does not fit into byte type"); - } - return u; + mp_uint_t u = trezor_obj_get_uint(obj); + if (u > 0xFF) { + mp_raise_msg(&mp_type_OverflowError, "value does not fit into byte type"); + } + return u; } #endif diff --git a/embed/firmware/bl_check.c b/embed/firmware/bl_check.c index 65daf9b11..43a915785 100644 --- a/embed/firmware/bl_check.c +++ b/embed/firmware/bl_check.c @@ -19,9 +19,9 @@ #include #include +#include "blake2s.h" #include "common.h" #include "flash.h" -#include "blake2s.h" // symbols from bootloader.bin => bootloader.o extern const uint32_t _binary_embed_firmware_bootloader_bin_start; @@ -31,56 +31,83 @@ extern const uint32_t _binary_embed_firmware_bootloader_bin_size; static secbool known_bootloader(const uint8_t *hash, int len) { if (len != 32) return secfalse; // bootloader-2.0.1.bin (padded with 0x00) - if (0 == memcmp(hash, "\x91\x37\x46\xd0\x2d\xa7\xc4\xbe\x1d\xae\xef\xb0\x9b\x4e\x31\x88\xed\x38\x23\x5e\x0e\x31\xa7\x8c\x01\xde\x4e\xcc\xc2\xd6\x36\xb3", 32)) return sectrue; + if (0 == memcmp(hash, +"\x91\x37\x46\xd0\x2d\xa7\xc4\xbe\x1d\xae\xef\xb0\x9b\x4e\x31\x88\xed\x38\x23\x5e\x0e\x31\xa7\x8c\x01\xde\x4e\xcc\xc2\xd6\x36\xb3", +32)) return sectrue; // bootloader-2.0.1.bin (padded with 0xff) - if (0 == memcmp(hash, "\x2f\xdb\xde\x94\x0a\xd8\x91\x1c\xbd\x07\xb0\xba\x06\x2c\x90\x84\x02\xec\x95\x19\xde\x52\x8d\x4b\xe9\xb9\xed\x30\x71\x91\xb4\xd3", 32)) return sectrue; + if (0 == memcmp(hash, +"\x2f\xdb\xde\x94\x0a\xd8\x91\x1c\xbd\x07\xb0\xba\x06\x2c\x90\x84\x02\xec\x95\x19\xde\x52\x8d\x4b\xe9\xb9\xed\x30\x71\x91\xb4\xd3", +32)) return sectrue; // bootloader-2.0.2.bin (padded with 0x00) - if (0 == memcmp(hash, "\x2e\xf7\x47\xf8\x49\x87\x1e\xc8\xc6\x01\x35\xd6\x32\xe5\x5a\xd1\x56\x18\xf8\x64\x87\xb7\xaa\x7c\x62\x0e\xc3\x0d\x25\x69\x4e\x18", 32)) return sectrue; + if (0 == memcmp(hash, +"\x2e\xf7\x47\xf8\x49\x87\x1e\xc8\xc6\x01\x35\xd6\x32\xe5\x5a\xd1\x56\x18\xf8\x64\x87\xb7\xaa\x7c\x62\x0e\xc3\x0d\x25\x69\x4e\x18", +32)) return sectrue; // bootloader-2.0.2.bin (padded with 0xff) - if (0 == memcmp(hash, "\xcc\x6b\x35\xc3\x8f\x29\x5c\xbd\x7d\x31\x69\xaf\xae\xf1\x61\x01\xef\xbe\x9f\x3b\x0a\xfd\xc5\x91\x70\x9b\xf5\xa0\xd5\xa4\xc5\xe0", 32)) return sectrue; + if (0 == memcmp(hash, +"\xcc\x6b\x35\xc3\x8f\x29\x5c\xbd\x7d\x31\x69\xaf\xae\xf1\x61\x01\xef\xbe\x9f\x3b\x0a\xfd\xc5\x91\x70\x9b\xf5\xa0\xd5\xa4\xc5\xe0", +32)) return sectrue; // bootloader-2.0.3.bin (padded with 0x00) - if (0 == memcmp(hash, "\xb1\x83\xd3\x31\xc7\xff\x3d\xcf\x54\x1e\x7e\x40\xf4\x9e\xc3\x53\x4c\xcc\xf3\x8c\x35\x39\x88\x81\x65\xc0\x5c\x25\xbd\xfc\xea\x14", 32)) return sectrue; + if (0 == memcmp(hash, +"\xb1\x83\xd3\x31\xc7\xff\x3d\xcf\x54\x1e\x7e\x40\xf4\x9e\xc3\x53\x4c\xcc\xf3\x8c\x35\x39\x88\x81\x65\xc0\x5c\x25\xbd\xfc\xea\x14", +32)) return sectrue; // bootloader-2.0.3.bin (padded with 0xff) - if (0 == memcmp(hash, "\xab\xdb\x7d\xe2\xef\x44\x66\xa7\xb7\x1f\x2b\x02\xf3\xe1\x40\xe7\xcd\xf2\x8e\xc0\xbb\x33\x04\xce\x0d\xa5\xca\x02\x57\xb6\xd4\x30", 32)) return sectrue; - return secfalse; + if (0 == memcmp(hash, +"\xab\xdb\x7d\xe2\xef\x44\x66\xa7\xb7\x1f\x2b\x02\xf3\xe1\x40\xe7\xcd\xf2\x8e\xc0\xbb\x33\x04\xce\x0d\xa5\xca\x02\x57\xb6\xd4\x30", +32)) return sectrue; return secfalse; } */ static secbool latest_bootloader(const uint8_t *hash, int len) { - if (len != 32) return secfalse; - // bootloader.bin (padded with 0x00) - if (0 == memcmp(hash, "\xb1\x83\xd3\x31\xc7\xff\x3d\xcf\x54\x1e\x7e\x40\xf4\x9e\xc3\x53\x4c\xcc\xf3\x8c\x35\x39\x88\x81\x65\xc0\x5c\x25\xbd\xfc\xea\x14", 32)) return sectrue; - // bootloader.bin (padded with 0xff) - if (0 == memcmp(hash, "\xab\xdb\x7d\xe2\xef\x44\x66\xa7\xb7\x1f\x2b\x02\xf3\xe1\x40\xe7\xcd\xf2\x8e\xc0\xbb\x33\x04\xce\x0d\xa5\xca\x02\x57\xb6\xd4\x30", 32)) return sectrue; - return secfalse; + if (len != 32) return secfalse; + // bootloader.bin (padded with 0x00) + if (0 == + memcmp(hash, + "\xb1\x83\xd3\x31\xc7\xff\x3d\xcf\x54\x1e\x7e\x40\xf4\x9e\xc3\x53" + "\x4c\xcc\xf3\x8c\x35\x39\x88\x81\x65\xc0\x5c\x25\xbd\xfc\xea\x14", + 32)) + return sectrue; + // bootloader.bin (padded with 0xff) + if (0 == + memcmp(hash, + "\xab\xdb\x7d\xe2\xef\x44\x66\xa7\xb7\x1f\x2b\x02\xf3\xe1\x40\xe7" + "\xcd\xf2\x8e\xc0\xbb\x33\x04\xce\x0d\xa5\xca\x02\x57\xb6\xd4\x30", + 32)) + return sectrue; + return secfalse; } -void check_and_replace_bootloader(void) -{ - // compute current bootloader hash - uint8_t hash[BLAKE2S_DIGEST_LENGTH]; - const uint32_t bl_len = 128 * 1024; - const void *bl_data = flash_get_address(FLASH_SECTOR_BOOTLOADER, 0, bl_len); - blake2s(bl_data, bl_len, hash, BLAKE2S_DIGEST_LENGTH); +void check_and_replace_bootloader(void) { + // compute current bootloader hash + uint8_t hash[BLAKE2S_DIGEST_LENGTH]; + const uint32_t bl_len = 128 * 1024; + const void *bl_data = flash_get_address(FLASH_SECTOR_BOOTLOADER, 0, bl_len); + blake2s(bl_data, bl_len, hash, BLAKE2S_DIGEST_LENGTH); - // don't whitelist the valid bootloaders for now - // ensure(known_bootloader(hash, BLAKE2S_DIGEST_LENGTH), "Unknown bootloader detected"); + // don't whitelist the valid bootloaders for now + // ensure(known_bootloader(hash, BLAKE2S_DIGEST_LENGTH), "Unknown bootloader + // detected"); - // do we have the latest bootloader? - if (sectrue == latest_bootloader(hash, BLAKE2S_DIGEST_LENGTH)) { - return; - } + // do we have the latest bootloader? + if (sectrue == latest_bootloader(hash, BLAKE2S_DIGEST_LENGTH)) { + return; + } - // replace bootloader with the latest one - const uint32_t *data = (const uint32_t *)&_binary_embed_firmware_bootloader_bin_start; - const uint32_t len = (const uint32_t)&_binary_embed_firmware_bootloader_bin_size; - ensure(flash_erase(FLASH_SECTOR_BOOTLOADER), NULL); - ensure(flash_unlock_write(), NULL); - for (int i = 0; i < len / sizeof(uint32_t); i++) { - ensure(flash_write_word(FLASH_SECTOR_BOOTLOADER, i * sizeof(uint32_t), data[i]), NULL); - } - for (int i = len / sizeof(uint32_t); i < 128 * 1024 / sizeof(uint32_t); i++) { - ensure(flash_write_word(FLASH_SECTOR_BOOTLOADER, i * sizeof(uint32_t), 0x00000000), NULL); - } - ensure(flash_lock_write(), NULL); + // replace bootloader with the latest one + const uint32_t *data = + (const uint32_t *)&_binary_embed_firmware_bootloader_bin_start; + const uint32_t len = + (const uint32_t)&_binary_embed_firmware_bootloader_bin_size; + ensure(flash_erase(FLASH_SECTOR_BOOTLOADER), NULL); + ensure(flash_unlock_write(), NULL); + for (int i = 0; i < len / sizeof(uint32_t); i++) { + ensure(flash_write_word(FLASH_SECTOR_BOOTLOADER, i * sizeof(uint32_t), + data[i]), + NULL); + } + for (int i = len / sizeof(uint32_t); i < 128 * 1024 / sizeof(uint32_t); i++) { + ensure(flash_write_word(FLASH_SECTOR_BOOTLOADER, i * sizeof(uint32_t), + 0x00000000), + NULL); + } + ensure(flash_lock_write(), NULL); } diff --git a/embed/firmware/main.c b/embed/firmware/main.c index e0b5f2caf..eb026b95d 100644 --- a/embed/firmware/main.c +++ b/embed/firmware/main.c @@ -21,18 +21,19 @@ #include #include -#include "py/nlr.h" +#include "lib/utils/pyexec.h" #include "py/compile.h" -#include "py/runtime.h" -#include "py/stackctrl.h" -#include "py/repl.h" #include "py/gc.h" #include "py/mperrno.h" -#include "lib/utils/pyexec.h" +#include "py/nlr.h" +#include "py/repl.h" +#include "py/runtime.h" +#include "py/stackctrl.h" #include "ports/stm32/gccollect.h" #include "ports/stm32/pendsv.h" +#include "bl_check.h" #include "common.h" #include "display.h" #include "flash.h" @@ -40,84 +41,82 @@ #include "rng.h" #include "sdcard.h" #include "touch.h" -#include "bl_check.h" -int main(void) -{ - // reinitialize HAL for Trezor One +int main(void) { + // reinitialize HAL for Trezor One #if TREZOR_MODEL == 1 - HAL_Init(); + HAL_Init(); #endif - collect_hw_entropy(); + collect_hw_entropy(); #if TREZOR_MODEL == T - check_and_replace_bootloader(); - // Enable MPU - mpu_config_firmware(); + check_and_replace_bootloader(); + // Enable MPU + mpu_config_firmware(); #endif - // Init peripherals - pendsv_init(); + // Init peripherals + pendsv_init(); #if TREZOR_MODEL == 1 - display_init(); - touch_init(); + display_init(); + touch_init(); #endif #if TREZOR_MODEL == T - sdcard_init(); - touch_init(); - touch_power_on(); + sdcard_init(); + touch_init(); + touch_power_on(); - display_clear(); + display_clear(); #endif - printf("CORE: Preparing stack\n"); - // Stack limit should be less than real stack size, so we have a chance - // to recover from limit hit. - mp_stack_set_top(&_estack); - mp_stack_set_limit((char*)&_estack - (char*)&_heap_end - 1024); - - // GC init - printf("CORE: Starting GC\n"); - gc_init(&_heap_start, &_heap_end); - - // Interpreter init - printf("CORE: Starting interpreter\n"); - mp_init(); - mp_obj_list_init(mp_sys_argv, 0); - mp_obj_list_init(mp_sys_path, 0); - mp_obj_list_append(mp_sys_path, MP_OBJ_NEW_QSTR(MP_QSTR_)); // current dir (or base dir of the script) - - // Execute the main script - printf("CORE: Executing main script\n"); - pyexec_frozen_module("main.py"); - - // Clean up - printf("CORE: Main script finished, cleaning up\n"); - mp_deinit(); - - return 0; + printf("CORE: Preparing stack\n"); + // Stack limit should be less than real stack size, so we have a chance + // to recover from limit hit. + mp_stack_set_top(&_estack); + mp_stack_set_limit((char *)&_estack - (char *)&_heap_end - 1024); + + // GC init + printf("CORE: Starting GC\n"); + gc_init(&_heap_start, &_heap_end); + + // Interpreter init + printf("CORE: Starting interpreter\n"); + mp_init(); + mp_obj_list_init(mp_sys_argv, 0); + mp_obj_list_init(mp_sys_path, 0); + mp_obj_list_append( + mp_sys_path, + MP_OBJ_NEW_QSTR(MP_QSTR_)); // current dir (or base dir of the script) + + // Execute the main script + printf("CORE: Executing main script\n"); + pyexec_frozen_module("main.py"); + + // Clean up + printf("CORE: Main script finished, cleaning up\n"); + mp_deinit(); + + return 0; } // MicroPython default exception handler void __attribute__((noreturn)) nlr_jump_fail(void *val) { - ensure(secfalse, "uncaught exception"); + ensure(secfalse, "uncaught exception"); } -void PendSV_Handler(void) { - pendsv_isr_handler(); -} +void PendSV_Handler(void) { pendsv_isr_handler(); } // MicroPython builtin stubs mp_import_stat_t mp_import_stat(const char *path) { - return MP_IMPORT_STAT_NO_EXIST; + return MP_IMPORT_STAT_NO_EXIST; } mp_obj_t mp_builtin_open(uint n_args, const mp_obj_t *args, mp_map_t *kwargs) { - return mp_const_none; + return mp_const_none; } MP_DEFINE_CONST_FUN_OBJ_KW(mp_builtin_open_obj, 1, mp_builtin_open); diff --git a/embed/firmware/modutime.c b/embed/firmware/modutime.c index 29ad0bc27..1cb795898 100644 --- a/embed/firmware/modutime.c +++ b/embed/firmware/modutime.c @@ -27,21 +27,21 @@ #include "extmod/utime_mphal.h" STATIC const mp_rom_map_elem_t time_module_globals_table[] = { - { MP_ROM_QSTR(MP_QSTR___name__), MP_ROM_QSTR(MP_QSTR_utime) }, + {MP_ROM_QSTR(MP_QSTR___name__), MP_ROM_QSTR(MP_QSTR_utime)}, - { MP_ROM_QSTR(MP_QSTR_sleep), MP_ROM_PTR(&mp_utime_sleep_obj) }, - { MP_ROM_QSTR(MP_QSTR_sleep_ms), MP_ROM_PTR(&mp_utime_sleep_ms_obj) }, - { MP_ROM_QSTR(MP_QSTR_sleep_us), MP_ROM_PTR(&mp_utime_sleep_us_obj) }, - { MP_ROM_QSTR(MP_QSTR_ticks_ms), MP_ROM_PTR(&mp_utime_ticks_ms_obj) }, - { MP_ROM_QSTR(MP_QSTR_ticks_us), MP_ROM_PTR(&mp_utime_ticks_us_obj) }, - { MP_ROM_QSTR(MP_QSTR_ticks_cpu), MP_ROM_PTR(&mp_utime_ticks_cpu_obj) }, - { MP_ROM_QSTR(MP_QSTR_ticks_add), MP_ROM_PTR(&mp_utime_ticks_add_obj) }, - { MP_ROM_QSTR(MP_QSTR_ticks_diff), MP_ROM_PTR(&mp_utime_ticks_diff_obj) }, + {MP_ROM_QSTR(MP_QSTR_sleep), MP_ROM_PTR(&mp_utime_sleep_obj)}, + {MP_ROM_QSTR(MP_QSTR_sleep_ms), MP_ROM_PTR(&mp_utime_sleep_ms_obj)}, + {MP_ROM_QSTR(MP_QSTR_sleep_us), MP_ROM_PTR(&mp_utime_sleep_us_obj)}, + {MP_ROM_QSTR(MP_QSTR_ticks_ms), MP_ROM_PTR(&mp_utime_ticks_ms_obj)}, + {MP_ROM_QSTR(MP_QSTR_ticks_us), MP_ROM_PTR(&mp_utime_ticks_us_obj)}, + {MP_ROM_QSTR(MP_QSTR_ticks_cpu), MP_ROM_PTR(&mp_utime_ticks_cpu_obj)}, + {MP_ROM_QSTR(MP_QSTR_ticks_add), MP_ROM_PTR(&mp_utime_ticks_add_obj)}, + {MP_ROM_QSTR(MP_QSTR_ticks_diff), MP_ROM_PTR(&mp_utime_ticks_diff_obj)}, }; STATIC MP_DEFINE_CONST_DICT(time_module_globals, time_module_globals_table); const mp_obj_module_t mp_module_utime = { - .base = { &mp_type_module }, + .base = {&mp_type_module}, .globals = (mp_obj_dict_t*)&time_module_globals, }; diff --git a/embed/firmware/mpconfigport.h b/embed/firmware/mpconfigport.h index fd2359d7d..f53734734 100644 --- a/embed/firmware/mpconfigport.h +++ b/embed/firmware/mpconfigport.h @@ -1,3 +1,5 @@ +// clang-format off + /* * This file is part of the MicroPython project, http://micropython.org/ * diff --git a/embed/firmware/mphalport.c b/embed/firmware/mphalport.c index e5b0268de..fb79803c0 100644 --- a/embed/firmware/mphalport.c +++ b/embed/firmware/mphalport.c @@ -17,27 +17,25 @@ * along with this program. If not, see . */ +#include "common.h" #include "py/mphal.h" #include "usb.h" -#include "common.h" static int vcp_iface_num = -1; int mp_hal_stdin_rx_chr(void) { - ensure(sectrue * (vcp_iface_num >= 0), "vcp stdio is not configured"); - uint8_t c = 0; - int r = usb_vcp_read_blocking(vcp_iface_num, &c, 1, -1); - (void)r; - return c; + ensure(sectrue * (vcp_iface_num >= 0), "vcp stdio is not configured"); + uint8_t c = 0; + int r = usb_vcp_read_blocking(vcp_iface_num, &c, 1, -1); + (void)r; + return c; } void mp_hal_stdout_tx_strn(const char *str, size_t len) { - if (vcp_iface_num >= 0) { - int r = usb_vcp_write_blocking(vcp_iface_num, (const uint8_t *)str, len, 0); - (void)r; - } + if (vcp_iface_num >= 0) { + int r = usb_vcp_write_blocking(vcp_iface_num, (const uint8_t *)str, len, 0); + (void)r; + } } -void mp_hal_set_vcp_iface(int iface_num) { - vcp_iface_num = iface_num; -} +void mp_hal_set_vcp_iface(int iface_num) { vcp_iface_num = iface_num; } diff --git a/embed/firmware/mphalport.h b/embed/firmware/mphalport.h index e128002cb..f91a9ce29 100644 --- a/embed/firmware/mphalport.h +++ b/embed/firmware/mphalport.h @@ -19,8 +19,6 @@ #include "lib/utils/interrupt_char.h" -static inline mp_uint_t mp_hal_ticks_cpu(void) { - return 0; -} +static inline mp_uint_t mp_hal_ticks_cpu(void) { return 0; } void mp_hal_set_vcp_iface(int iface_num); diff --git a/embed/firmware/nlrthumb.c b/embed/firmware/nlrthumb.c index fe8f622ec..2d4e00acd 100644 --- a/embed/firmware/nlrthumb.c +++ b/embed/firmware/nlrthumb.c @@ -1,3 +1,5 @@ +// clang-format off + /* * This file is part of the TREZOR project, https://trezor.io/ * diff --git a/embed/firmware/version.h b/embed/firmware/version.h index 20d3d7edb..0e57ccee0 100644 --- a/embed/firmware/version.h +++ b/embed/firmware/version.h @@ -1,9 +1,9 @@ -#define VERSION_MAJOR 2 -#define VERSION_MINOR 1 -#define VERSION_PATCH 0 -#define VERSION_BUILD 0 +#define VERSION_MAJOR 2 +#define VERSION_MINOR 1 +#define VERSION_PATCH 0 +#define VERSION_BUILD 0 -#define FIX_VERSION_MAJOR 2 -#define FIX_VERSION_MINOR 1 -#define FIX_VERSION_PATCH 0 -#define FIX_VERSION_BUILD 0 +#define FIX_VERSION_MAJOR 2 +#define FIX_VERSION_MINOR 1 +#define FIX_VERSION_PATCH 0 +#define FIX_VERSION_BUILD 0 diff --git a/embed/prodtest/main.c b/embed/prodtest/main.c index 448e64b88..a59b5e2d0 100644 --- a/embed/prodtest/main.c +++ b/embed/prodtest/main.c @@ -17,8 +17,8 @@ * along with this program. If not, see . */ -#include #include +#include #include #include STM32_HAL_H @@ -38,393 +38,400 @@ enum { VCP_IFACE = 0x00 }; -static void vcp_intr(void) -{ - display_clear(); - ensure(secfalse, "vcp_intr"); +static void vcp_intr(void) { + display_clear(); + ensure(secfalse, "vcp_intr"); } -static void vcp_puts(const char *s, size_t len) -{ - int r = usb_vcp_write_blocking(VCP_IFACE, (const uint8_t *) s, len, -1); - (void)r; +static void vcp_puts(const char *s, size_t len) { + int r = usb_vcp_write_blocking(VCP_IFACE, (const uint8_t *)s, len, -1); + (void)r; } -static char vcp_getchar(void) -{ - uint8_t c = 0; - int r = usb_vcp_read_blocking(VCP_IFACE, &c, 1, -1); - (void)r; - return (char)c; +static char vcp_getchar(void) { + uint8_t c = 0; + int r = usb_vcp_read_blocking(VCP_IFACE, &c, 1, -1); + (void)r; + return (char)c; } -static void vcp_readline(char *buf, size_t len) -{ - for (;;) { - char c = vcp_getchar(); - if (c == '\r') { - vcp_puts("\r\n", 2); - break; - } - if (c < 32 || c > 126) { // not printable - continue; - } - if (len > 1) { // leave space for \0 - *buf = c; - buf++; - len--; - vcp_puts(&c, 1); - } +static void vcp_readline(char *buf, size_t len) { + for (;;) { + char c = vcp_getchar(); + if (c == '\r') { + vcp_puts("\r\n", 2); + break; + } + if (c < 32 || c > 126) { // not printable + continue; } - if (len > 0) { - *buf = '\0'; + if (len > 1) { // leave space for \0 + *buf = c; + buf++; + len--; + vcp_puts(&c, 1); } + } + if (len > 0) { + *buf = '\0'; + } } -static void vcp_printf(const char *fmt, ...) -{ - static char buf[128]; - va_list va; - va_start(va, fmt); - int r = mini_vsnprintf(buf, sizeof(buf), fmt, va); - va_end(va); - vcp_puts(buf, r); - vcp_puts("\r\n", 2); +static void vcp_printf(const char *fmt, ...) { + static char buf[128]; + va_list va; + va_start(va, fmt); + int r = mini_vsnprintf(buf, sizeof(buf), fmt, va); + va_end(va); + vcp_puts(buf, r); + vcp_puts("\r\n", 2); } -static void usb_init_all(void) -{ - enum { - VCP_PACKET_LEN = 64, - VCP_BUFFER_LEN = 1024, - }; - - static const usb_dev_info_t dev_info = { - .device_class = 0xEF, // Composite Device Class - .device_subclass = 0x02, // Common Class - .device_protocol = 0x01, // Interface Association Descriptor - .vendor_id = 0x1209, - .product_id = 0x53C1, - .release_num = 0x0400, - .manufacturer = "SatoshiLabs", - .product = "TREZOR", - .serial_number = "000000000000", - .interface = "TREZOR Interface", - .usb21_enabled = secfalse, - .usb21_landing = secfalse, - }; - - static uint8_t tx_packet[VCP_PACKET_LEN]; - static uint8_t tx_buffer[VCP_BUFFER_LEN]; - static uint8_t rx_packet[VCP_PACKET_LEN]; - static uint8_t rx_buffer[VCP_BUFFER_LEN]; - - static const usb_vcp_info_t vcp_info = { - .tx_packet = tx_packet, - .tx_buffer = tx_buffer, - .rx_packet = rx_packet, - .rx_buffer = rx_buffer, - .tx_buffer_len = VCP_BUFFER_LEN, - .rx_buffer_len = VCP_BUFFER_LEN, - .rx_intr_fn = vcp_intr, - .rx_intr_byte = 3, // Ctrl-C - .iface_num = VCP_IFACE, - .data_iface_num = 0x01, - .ep_cmd = 0x82, - .ep_in = 0x81, - .ep_out = 0x01, - .polling_interval = 10, - .max_packet_len = VCP_PACKET_LEN, - }; - - usb_init(&dev_info); - ensure(usb_vcp_add(&vcp_info), "usb_vcp_add"); - usb_start(); +static void usb_init_all(void) { + enum { + VCP_PACKET_LEN = 64, + VCP_BUFFER_LEN = 1024, + }; + + static const usb_dev_info_t dev_info = { + .device_class = 0xEF, // Composite Device Class + .device_subclass = 0x02, // Common Class + .device_protocol = 0x01, // Interface Association Descriptor + .vendor_id = 0x1209, + .product_id = 0x53C1, + .release_num = 0x0400, + .manufacturer = "SatoshiLabs", + .product = "TREZOR", + .serial_number = "000000000000", + .interface = "TREZOR Interface", + .usb21_enabled = secfalse, + .usb21_landing = secfalse, + }; + + static uint8_t tx_packet[VCP_PACKET_LEN]; + static uint8_t tx_buffer[VCP_BUFFER_LEN]; + static uint8_t rx_packet[VCP_PACKET_LEN]; + static uint8_t rx_buffer[VCP_BUFFER_LEN]; + + static const usb_vcp_info_t vcp_info = { + .tx_packet = tx_packet, + .tx_buffer = tx_buffer, + .rx_packet = rx_packet, + .rx_buffer = rx_buffer, + .tx_buffer_len = VCP_BUFFER_LEN, + .rx_buffer_len = VCP_BUFFER_LEN, + .rx_intr_fn = vcp_intr, + .rx_intr_byte = 3, // Ctrl-C + .iface_num = VCP_IFACE, + .data_iface_num = 0x01, + .ep_cmd = 0x82, + .ep_in = 0x81, + .ep_out = 0x01, + .polling_interval = 10, + .max_packet_len = VCP_PACKET_LEN, + }; + + usb_init(&dev_info); + ensure(usb_vcp_add(&vcp_info), "usb_vcp_add"); + usb_start(); } -static void draw_border(int width, int padding) -{ - const int W = width, P = padding, RX = DISPLAY_RESX, RY = DISPLAY_RESY; - display_clear(); - display_bar(P, P, RX - 2 * P, RY - 2 * P, 0xFFFF); - display_bar(P + W, P + W, RX - 2 * (P + W), RY - 2 * (P + W), 0x0000); - display_refresh(); +static void draw_border(int width, int padding) { + const int W = width, P = padding, RX = DISPLAY_RESX, RY = DISPLAY_RESY; + display_clear(); + display_bar(P, P, RX - 2 * P, RY - 2 * P, 0xFFFF); + display_bar(P + W, P + W, RX - 2 * (P + W), RY - 2 * (P + W), 0x0000); + display_refresh(); } -static void test_border(void) -{ - draw_border(2, 0); - vcp_printf("OK"); +static void test_border(void) { + draw_border(2, 0); + vcp_printf("OK"); } -static void test_display(const char *colors) -{ - display_clear(); - - size_t l = strlen(colors); - size_t w = DISPLAY_RESX / l; - - for (size_t i = 0; i < l; i++) { - uint16_t c = 0x0000; // black - switch (colors[i]) { - case 'R': c = 0xF800; break; - case 'G': c = 0x07E0; break; - case 'B': c = 0x001F; break; - case 'W': c = 0xFFFF; break; - } - display_bar(i * w, 0, i * w + w, 240, c); +static void test_display(const char *colors) { + display_clear(); + + size_t l = strlen(colors); + size_t w = DISPLAY_RESX / l; + + for (size_t i = 0; i < l; i++) { + uint16_t c = 0x0000; // black + switch (colors[i]) { + case 'R': + c = 0xF800; + break; + case 'G': + c = 0x07E0; + break; + case 'B': + c = 0x001F; + break; + case 'W': + c = 0xFFFF; + break; } - display_refresh(); - vcp_printf("OK"); + display_bar(i * w, 0, i * w + w, 240, c); + } + display_refresh(); + vcp_printf("OK"); } -static secbool touch_click_timeout(uint32_t *touch, uint32_t timeout_ms) -{ - uint32_t deadline = HAL_GetTick() + timeout_ms; - uint32_t r = 0; - - while (touch_read()); - while ((touch_read() & TOUCH_START) == 0) { - if (HAL_GetTick() > deadline) return secfalse; - } - while (((r = touch_read()) & TOUCH_END) == 0) { - if (HAL_GetTick() > deadline) return secfalse; - } - while (touch_read()); - - *touch = r; - return sectrue; +static secbool touch_click_timeout(uint32_t *touch, uint32_t timeout_ms) { + uint32_t deadline = HAL_GetTick() + timeout_ms; + uint32_t r = 0; + + while (touch_read()) + ; + while ((touch_read() & TOUCH_START) == 0) { + if (HAL_GetTick() > deadline) return secfalse; + } + while (((r = touch_read()) & TOUCH_END) == 0) { + if (HAL_GetTick() > deadline) return secfalse; + } + while (touch_read()) + ; + + *touch = r; + return sectrue; } -static void test_touch(const char *args) -{ - int column = args[0] - '0'; - int timeout = args[1] - '0'; - - display_clear(); - switch (column) { - case 1: display_bar(0, 0, 120, 120, 0xFFFF); break; - case 2: display_bar(120, 0, 120, 120, 0xFFFF); break; - case 3: display_bar(120, 120, 120, 120, 0xFFFF); break; - default: display_bar(0, 120, 120, 120, 0xFFFF); break; - } - display_refresh(); - - touch_power_on(); - - uint32_t evt = 0; - if (touch_click_timeout(&evt, timeout * 1000)) { - uint16_t x = touch_unpack_x(evt); - uint16_t y = touch_unpack_y(evt); - vcp_printf("OK %d %d", x, y); - } else { - vcp_printf("ERROR TIMEOUT"); - } - display_clear(); - display_refresh(); - - touch_power_off(); +static void test_touch(const char *args) { + int column = args[0] - '0'; + int timeout = args[1] - '0'; + + display_clear(); + switch (column) { + case 1: + display_bar(0, 0, 120, 120, 0xFFFF); + break; + case 2: + display_bar(120, 0, 120, 120, 0xFFFF); + break; + case 3: + display_bar(120, 120, 120, 120, 0xFFFF); + break; + default: + display_bar(0, 120, 120, 120, 0xFFFF); + break; + } + display_refresh(); + + touch_power_on(); + + uint32_t evt = 0; + if (touch_click_timeout(&evt, timeout * 1000)) { + uint16_t x = touch_unpack_x(evt); + uint16_t y = touch_unpack_y(evt); + vcp_printf("OK %d %d", x, y); + } else { + vcp_printf("ERROR TIMEOUT"); + } + display_clear(); + display_refresh(); + + touch_power_off(); } -static void test_sensitivity(const char *args) -{ - int v = atoi(args); - - touch_power_on(); - touch_sensitivity(v & 0xFF); - - display_clear(); - display_refresh(); - - for (;;) { - uint32_t evt = touch_read(); - if (evt & TOUCH_START || evt & TOUCH_MOVE) { - int x = touch_unpack_x(evt); - int y = touch_unpack_y(evt); - display_clear(); - display_bar(x - 48, y - 48, 96, 96, 0xFFFF); - display_refresh(); - } else if (evt & TOUCH_END) { - display_clear(); - display_refresh(); - } +static void test_sensitivity(const char *args) { + int v = atoi(args); + + touch_power_on(); + touch_sensitivity(v & 0xFF); + + display_clear(); + display_refresh(); + + for (;;) { + uint32_t evt = touch_read(); + if (evt & TOUCH_START || evt & TOUCH_MOVE) { + int x = touch_unpack_x(evt); + int y = touch_unpack_y(evt); + display_clear(); + display_bar(x - 48, y - 48, 96, 96, 0xFFFF); + display_refresh(); + } else if (evt & TOUCH_END) { + display_clear(); + display_refresh(); } + } - touch_power_off(); + touch_power_off(); } -static void test_pwm(const char *args) -{ - int v = atoi(args); +static void test_pwm(const char *args) { + int v = atoi(args); - display_backlight(v); - display_refresh(); - vcp_printf("OK"); + display_backlight(v); + display_refresh(); + vcp_printf("OK"); } -static void test_sd(void) -{ +static void test_sd(void) { #define BLOCK_SIZE (32 * 1024) - static uint32_t buf1[BLOCK_SIZE / sizeof(uint32_t)]; - static uint32_t buf2[BLOCK_SIZE / sizeof(uint32_t)]; - - if (sectrue != sdcard_is_present()) { - vcp_printf("ERROR NOCARD"); - return; + static uint32_t buf1[BLOCK_SIZE / sizeof(uint32_t)]; + static uint32_t buf2[BLOCK_SIZE / sizeof(uint32_t)]; + + if (sectrue != sdcard_is_present()) { + vcp_printf("ERROR NOCARD"); + return; + } + + ensure(sdcard_power_on(), NULL); + if (sectrue != sdcard_read_blocks(buf1, 0, BLOCK_SIZE / SDCARD_BLOCK_SIZE)) { + vcp_printf("ERROR sdcard_read_blocks (0)"); + goto power_off; + } + for (int j = 1; j <= 2; j++) { + for (int i = 0; i < BLOCK_SIZE / sizeof(uint32_t); i++) { + buf1[i] ^= 0xFFFFFFFF; } - - ensure(sdcard_power_on(), NULL); - if (sectrue != sdcard_read_blocks(buf1, 0, BLOCK_SIZE / SDCARD_BLOCK_SIZE)) { - vcp_printf("ERROR sdcard_read_blocks (0)"); - goto power_off; + if (sectrue != + sdcard_write_blocks(buf1, 0, BLOCK_SIZE / SDCARD_BLOCK_SIZE)) { + vcp_printf("ERROR sdcard_write_blocks (%d)", j); + goto power_off; } - for (int j = 1; j <= 2; j++) { - for (int i = 0; i < BLOCK_SIZE / sizeof(uint32_t); i++) { - buf1[i] ^= 0xFFFFFFFF; - } - if (sectrue != sdcard_write_blocks(buf1, 0, BLOCK_SIZE / SDCARD_BLOCK_SIZE)) { - vcp_printf("ERROR sdcard_write_blocks (%d)", j); - goto power_off; - } - HAL_Delay(1000); - if (sectrue != sdcard_read_blocks(buf2, 0, BLOCK_SIZE / SDCARD_BLOCK_SIZE)) { - vcp_printf("ERROR sdcard_read_blocks (%d)", j); - goto power_off; - } - if (0 != memcmp(buf1, buf2, sizeof(buf1))) { - vcp_printf("ERROR DATA MISMATCH"); - goto power_off; - } + HAL_Delay(1000); + if (sectrue != + sdcard_read_blocks(buf2, 0, BLOCK_SIZE / SDCARD_BLOCK_SIZE)) { + vcp_printf("ERROR sdcard_read_blocks (%d)", j); + goto power_off; } - vcp_printf("OK"); + if (0 != memcmp(buf1, buf2, sizeof(buf1))) { + vcp_printf("ERROR DATA MISMATCH"); + goto power_off; + } + } + vcp_printf("OK"); power_off: - sdcard_power_off(); + sdcard_power_off(); } -static void test_wipe(void) -{ - // erase start of the firmware (metadata) -> invalidate FW - ensure(flash_unlock_write(), NULL); - for (int i = 0; i < 1024 / sizeof(uint32_t); i++) { - ensure(flash_write_word(FLASH_SECTOR_FIRMWARE_START, i * sizeof(uint32_t), 0x00000000), NULL); - } - ensure(flash_lock_write(), NULL); - display_clear(); - display_text_center(DISPLAY_RESX / 2, DISPLAY_RESY / 2 + 10, "WIPED", -1, FONT_BOLD, COLOR_WHITE, COLOR_BLACK); - display_refresh(); - vcp_printf("OK"); +static void test_wipe(void) { + // erase start of the firmware (metadata) -> invalidate FW + ensure(flash_unlock_write(), NULL); + for (int i = 0; i < 1024 / sizeof(uint32_t); i++) { + ensure(flash_write_word(FLASH_SECTOR_FIRMWARE_START, i * sizeof(uint32_t), + 0x00000000), + NULL); + } + ensure(flash_lock_write(), NULL); + display_clear(); + display_text_center(DISPLAY_RESX / 2, DISPLAY_RESY / 2 + 10, "WIPED", -1, + FONT_BOLD, COLOR_WHITE, COLOR_BLACK); + display_refresh(); + vcp_printf("OK"); } -static void test_sbu(const char *args) -{ - secbool sbu1 = sectrue * (args[0] == '1'); - secbool sbu2 = sectrue * (args[1] == '1'); - sbu_set(sbu1, sbu2); - vcp_printf("OK"); +static void test_sbu(const char *args) { + secbool sbu1 = sectrue * (args[0] == '1'); + secbool sbu2 = sectrue * (args[1] == '1'); + sbu_set(sbu1, sbu2); + vcp_printf("OK"); } -static void test_otp_read(void) -{ - uint8_t data[32]; - memzero(data, sizeof(data)); - ensure(flash_otp_read(FLASH_OTP_BLOCK_BATCH, 0, data, sizeof(data)), NULL); - - // strip trailing 0xFF - for (size_t i = 0; i < sizeof(data); i++) { - if (data[i] == 0xFF) { - data[i] = 0x00; - break; - } - } +static void test_otp_read(void) { + uint8_t data[32]; + memzero(data, sizeof(data)); + ensure(flash_otp_read(FLASH_OTP_BLOCK_BATCH, 0, data, sizeof(data)), NULL); - // use (null) for empty data - if (data[0] == 0x00) { - vcp_printf("OK (null)"); - } else { - vcp_printf("OK %s", (const char *) data); + // strip trailing 0xFF + for (size_t i = 0; i < sizeof(data); i++) { + if (data[i] == 0xFF) { + data[i] = 0x00; + break; } + } + + // use (null) for empty data + if (data[0] == 0x00) { + vcp_printf("OK (null)"); + } else { + vcp_printf("OK %s", (const char *)data); + } } -static void test_otp_write(const char *args) -{ - char data[32]; - memzero(data, sizeof(data)); - strncpy(data, args, sizeof(data) - 1); - ensure(flash_otp_write(FLASH_OTP_BLOCK_BATCH, 0, (const uint8_t *) data, sizeof(data)), NULL); - ensure(flash_otp_lock(FLASH_OTP_BLOCK_BATCH), NULL); - vcp_printf("OK"); +static void test_otp_write(const char *args) { + char data[32]; + memzero(data, sizeof(data)); + strncpy(data, args, sizeof(data) - 1); + ensure(flash_otp_write(FLASH_OTP_BLOCK_BATCH, 0, (const uint8_t *)data, + sizeof(data)), + NULL); + ensure(flash_otp_lock(FLASH_OTP_BLOCK_BATCH), NULL); + vcp_printf("OK"); } -static secbool startswith(const char *s, const char *prefix) -{ - return sectrue * (0 == strncmp(s, prefix, strlen(prefix))); +static secbool startswith(const char *s, const char *prefix) { + return sectrue * (0 == strncmp(s, prefix, strlen(prefix))); } #define BACKLIGHT_NORMAL 150 -int main(void) -{ - display_orientation(0); - sdcard_init(); - touch_init(); - sbu_init(); - usb_init_all(); - - display_clear(); - draw_border(1, 3); - - char dom[32]; - // format: TREZOR2-YYMMDD - if (sectrue == flash_otp_read(FLASH_OTP_BLOCK_BATCH, 0, (uint8_t *)dom, 32) && 0 == memcmp(dom, "TREZOR2-", 8) && dom[31] == 0) { - display_qrcode(DISPLAY_RESX / 2, DISPLAY_RESY / 2, dom, strlen(dom), 4); - display_text_center(DISPLAY_RESX / 2, DISPLAY_RESY - 30, dom + 8, -1, FONT_BOLD, COLOR_WHITE, COLOR_BLACK); - } +int main(void) { + display_orientation(0); + sdcard_init(); + touch_init(); + sbu_init(); + usb_init_all(); + + display_clear(); + draw_border(1, 3); - display_fade(0, BACKLIGHT_NORMAL, 1000); + char dom[32]; + // format: TREZOR2-YYMMDD + if (sectrue == flash_otp_read(FLASH_OTP_BLOCK_BATCH, 0, (uint8_t *)dom, 32) && + 0 == memcmp(dom, "TREZOR2-", 8) && dom[31] == 0) { + display_qrcode(DISPLAY_RESX / 2, DISPLAY_RESY / 2, dom, strlen(dom), 4); + display_text_center(DISPLAY_RESX / 2, DISPLAY_RESY - 30, dom + 8, -1, + FONT_BOLD, COLOR_WHITE, COLOR_BLACK); + } - char line[128]; + display_fade(0, BACKLIGHT_NORMAL, 1000); - for (;;) { - vcp_readline(line, sizeof(line)); + char line[128]; - if (startswith(line, "PING")) { - vcp_printf("OK"); + for (;;) { + vcp_readline(line, sizeof(line)); - } else if (startswith(line, "BORDER")) { - test_border(); + if (startswith(line, "PING")) { + vcp_printf("OK"); - } else if (startswith(line, "DISP ")) { - test_display(line + 5); + } else if (startswith(line, "BORDER")) { + test_border(); - } else if (startswith(line, "TOUCH ")) { - test_touch(line + 6); + } else if (startswith(line, "DISP ")) { + test_display(line + 5); - } else if (startswith(line, "SENS ")) { - test_sensitivity(line + 5); + } else if (startswith(line, "TOUCH ")) { + test_touch(line + 6); - } else if (startswith(line, "PWM ")) { - test_pwm(line + 4); + } else if (startswith(line, "SENS ")) { + test_sensitivity(line + 5); - } else if (startswith(line, "SD")) { - test_sd(); + } else if (startswith(line, "PWM ")) { + test_pwm(line + 4); - } else if (startswith(line, "SBU ")) { - test_sbu(line + 4); + } else if (startswith(line, "SD")) { + test_sd(); - } else if (startswith(line, "OTP READ")) { - test_otp_read(); + } else if (startswith(line, "SBU ")) { + test_sbu(line + 4); - } else if (startswith(line, "OTP WRITE ")) { - test_otp_write(line + 10); + } else if (startswith(line, "OTP READ")) { + test_otp_read(); - } else if (startswith(line, "WIPE")) { - test_wipe(); + } else if (startswith(line, "OTP WRITE ")) { + test_otp_write(line + 10); - } else { - vcp_printf("UNKNOWN"); - } + } else if (startswith(line, "WIPE")) { + test_wipe(); + + } else { + vcp_printf("UNKNOWN"); } + } - return 0; + return 0; } diff --git a/embed/reflash/main.c b/embed/reflash/main.c index 236f4779a..7b09abe0c 100644 --- a/embed/reflash/main.c +++ b/embed/reflash/main.c @@ -17,8 +17,8 @@ * along with this program. If not, see . */ -#include #include +#include #include #include STM32_HAL_H @@ -33,77 +33,74 @@ #include "secbool.h" #include "touch.h" -static void progress_callback(int pos, int len) -{ - display_printf("."); -} +static void progress_callback(int pos, int len) { display_printf("."); } -static void flash_from_sdcard(uint8_t sector, uint32_t source, uint32_t length) -{ - static uint32_t buf[SDCARD_BLOCK_SIZE / sizeof(uint32_t)]; +static void flash_from_sdcard(uint8_t sector, uint32_t source, + uint32_t length) { + static uint32_t buf[SDCARD_BLOCK_SIZE / sizeof(uint32_t)]; - ensure( - sectrue * (source % SDCARD_BLOCK_SIZE == 0), - "source not a multiple of block size"); - ensure( - sectrue * (length % SDCARD_BLOCK_SIZE == 0), - "length not a multiple of block size"); + ensure(sectrue * (source % SDCARD_BLOCK_SIZE == 0), + "source not a multiple of block size"); + ensure(sectrue * (length % SDCARD_BLOCK_SIZE == 0), + "length not a multiple of block size"); - for (uint32_t i = 0; i < length / SDCARD_BLOCK_SIZE; i++) { - display_printf("read %d\n", (unsigned int)(i + source / SDCARD_BLOCK_SIZE)); + for (uint32_t i = 0; i < length / SDCARD_BLOCK_SIZE; i++) { + display_printf("read %d\n", (unsigned int)(i + source / SDCARD_BLOCK_SIZE)); - ensure( - sdcard_read_blocks(buf, i + source / SDCARD_BLOCK_SIZE, 1), - "sdcard_read_blocks"); + ensure(sdcard_read_blocks(buf, i + source / SDCARD_BLOCK_SIZE, 1), + "sdcard_read_blocks"); - for (uint32_t j = 0; j < SDCARD_BLOCK_SIZE / sizeof(uint32_t); j++) { - ensure(flash_write_word(sector, i * SDCARD_BLOCK_SIZE + j * sizeof(uint32_t), buf[j]), NULL); - } + for (uint32_t j = 0; j < SDCARD_BLOCK_SIZE / sizeof(uint32_t); j++) { + ensure(flash_write_word( + sector, i * SDCARD_BLOCK_SIZE + j * sizeof(uint32_t), buf[j]), + NULL); } + } } -int main(void) -{ - sdcard_init(); - touch_init(); +int main(void) { + sdcard_init(); + touch_init(); - display_orientation(0); - display_clear(); - display_backlight(255); + display_orientation(0); + display_clear(); + display_backlight(255); - ensure( - sdcard_is_present(), - "sdcard_is_present"); + ensure(sdcard_is_present(), "sdcard_is_present"); - display_printf("updating boardloader + bootloader\n"); + display_printf("updating boardloader + bootloader\n"); - static const uint8_t sectors[] = { - FLASH_SECTOR_BOARDLOADER_START, - 1, - FLASH_SECTOR_BOARDLOADER_END, - FLASH_SECTOR_BOOTLOADER, - }; - display_printf("erasing sectors"); - ensure(flash_erase_sectors(sectors, sizeof(sectors), progress_callback), "flash_erase_sectors"); - display_printf("\n"); - display_printf("erased\n"); + static const uint8_t sectors[] = { + FLASH_SECTOR_BOARDLOADER_START, + 1, + FLASH_SECTOR_BOARDLOADER_END, + FLASH_SECTOR_BOOTLOADER, + }; + display_printf("erasing sectors"); + ensure(flash_erase_sectors(sectors, sizeof(sectors), progress_callback), + "flash_erase_sectors"); + display_printf("\n"); + display_printf("erased\n"); - ensure(flash_unlock_write(), NULL); + ensure(flash_unlock_write(), NULL); - ensure(sdcard_power_on(), NULL); + ensure(sdcard_power_on(), NULL); -#define BOARDLOADER_CHUNK_SIZE (16 * 1024) -#define BOARDLOADER_TOTAL_SIZE (3 * BOARDLOADER_CHUNK_SIZE) -#define BOOTLOADER_TOTAL_SIZE (128 * 1024) +#define BOARDLOADER_CHUNK_SIZE (16 * 1024) +#define BOARDLOADER_TOTAL_SIZE (3 * BOARDLOADER_CHUNK_SIZE) +#define BOOTLOADER_TOTAL_SIZE (128 * 1024) - flash_from_sdcard(FLASH_SECTOR_BOARDLOADER_START, 0 * BOARDLOADER_CHUNK_SIZE, BOARDLOADER_CHUNK_SIZE); - flash_from_sdcard(1, 1 * BOARDLOADER_CHUNK_SIZE, BOARDLOADER_CHUNK_SIZE); - flash_from_sdcard(FLASH_SECTOR_BOARDLOADER_END, 2 * BOARDLOADER_CHUNK_SIZE, BOARDLOADER_CHUNK_SIZE); - flash_from_sdcard(FLASH_SECTOR_BOOTLOADER, BOARDLOADER_TOTAL_SIZE, BOOTLOADER_TOTAL_SIZE); + flash_from_sdcard(FLASH_SECTOR_BOARDLOADER_START, 0 * BOARDLOADER_CHUNK_SIZE, + BOARDLOADER_CHUNK_SIZE); + flash_from_sdcard(1, 1 * BOARDLOADER_CHUNK_SIZE, BOARDLOADER_CHUNK_SIZE); + flash_from_sdcard(FLASH_SECTOR_BOARDLOADER_END, 2 * BOARDLOADER_CHUNK_SIZE, + BOARDLOADER_CHUNK_SIZE); + flash_from_sdcard(FLASH_SECTOR_BOOTLOADER, BOARDLOADER_TOTAL_SIZE, + BOOTLOADER_TOTAL_SIZE); - display_printf("done\n"); - sdcard_power_off(); - ensure(flash_lock_write(), NULL); + display_printf("done\n"); + sdcard_power_off(); + ensure(flash_lock_write(), NULL); - return 0; + return 0; } diff --git a/embed/reflash/version.h b/embed/reflash/version.h index 952adcfbc..f5eeee876 100644 --- a/embed/reflash/version.h +++ b/embed/reflash/version.h @@ -1,9 +1,9 @@ -#define VERSION_MAJOR 0 -#define VERSION_MINOR 1 -#define VERSION_PATCH 0 -#define VERSION_BUILD 0 +#define VERSION_MAJOR 0 +#define VERSION_MINOR 1 +#define VERSION_PATCH 0 +#define VERSION_BUILD 0 -#define FIX_VERSION_MAJOR 0 -#define FIX_VERSION_MINOR 1 -#define FIX_VERSION_PATCH 0 -#define FIX_VERSION_BUILD 0 +#define FIX_VERSION_MAJOR 0 +#define FIX_VERSION_MINOR 1 +#define FIX_VERSION_PATCH 0 +#define FIX_VERSION_BUILD 0 diff --git a/embed/trezorhal/common.c b/embed/trezorhal/common.c index d0dc28f8d..0fba1d0f5 100644 --- a/embed/trezorhal/common.c +++ b/embed/trezorhal/common.c @@ -23,9 +23,9 @@ #include "common.h" #include "display.h" -#include "rng.h" -#include "rand.h" #include "flash.h" +#include "rand.h" +#include "rng.h" #include "stm32f4xx_ll_utils.h" @@ -34,144 +34,154 @@ extern void shutdown(void); #define COLOR_FATAL_ERROR RGB16(0x7F, 0x00, 0x00) -void __attribute__((noreturn)) __fatal_error(const char *expr, const char *msg, const char *file, int line, const char *func) { - display_orientation(0); - display_backlight(255); - display_print_color(COLOR_WHITE, COLOR_FATAL_ERROR); - display_printf("\nFATAL ERROR:\n"); - if (expr) { - display_printf("expr: %s\n", expr); - } - if (msg) { - display_printf("msg : %s\n", msg); - } - if (file) { - display_printf("file: %s:%d\n", file, line); - } - if (func) { - display_printf("func: %s\n", func); - } +void __attribute__((noreturn)) +__fatal_error(const char *expr, const char *msg, const char *file, int line, + const char *func) { + display_orientation(0); + display_backlight(255); + display_print_color(COLOR_WHITE, COLOR_FATAL_ERROR); + display_printf("\nFATAL ERROR:\n"); + if (expr) { + display_printf("expr: %s\n", expr); + } + if (msg) { + display_printf("msg : %s\n", msg); + } + if (file) { + display_printf("file: %s:%d\n", file, line); + } + if (func) { + display_printf("func: %s\n", func); + } #ifdef GITREV - display_printf("rev : %s\n", XSTR(GITREV)); + display_printf("rev : %s\n", XSTR(GITREV)); #endif - display_printf("\nPlease contact TREZOR support.\n"); - shutdown(); - for (;;); + display_printf("\nPlease contact TREZOR support.\n"); + shutdown(); + for (;;) + ; } -void __attribute__((noreturn)) error_shutdown(const char *line1, const char *line2, const char *line3, const char *line4) -{ - display_orientation(0); +void __attribute__((noreturn)) +error_shutdown(const char *line1, const char *line2, const char *line3, + const char *line4) { + display_orientation(0); #ifdef TREZOR_FONT_NORMAL_ENABLE - display_clear(); - display_bar(0, 0, DISPLAY_RESX, DISPLAY_RESY, COLOR_FATAL_ERROR); - int y = 32; - if (line1) { - display_text(8, y, line1, -1, FONT_NORMAL, COLOR_WHITE, COLOR_FATAL_ERROR); - y += 32; - } - if (line2) { - display_text(8, y, line2, -1, FONT_NORMAL, COLOR_WHITE, COLOR_FATAL_ERROR); - y += 32; - } - if (line3) { - display_text(8, y, line3, -1, FONT_NORMAL, COLOR_WHITE, COLOR_FATAL_ERROR); - y += 32; - } - if (line4) { - display_text(8, y, line4, -1, FONT_NORMAL, COLOR_WHITE, COLOR_FATAL_ERROR); - y += 32; - } + display_clear(); + display_bar(0, 0, DISPLAY_RESX, DISPLAY_RESY, COLOR_FATAL_ERROR); + int y = 32; + if (line1) { + display_text(8, y, line1, -1, FONT_NORMAL, COLOR_WHITE, COLOR_FATAL_ERROR); y += 32; - display_text(8, y, "Please unplug the device.", -1, FONT_NORMAL, COLOR_WHITE, COLOR_FATAL_ERROR); + } + if (line2) { + display_text(8, y, line2, -1, FONT_NORMAL, COLOR_WHITE, COLOR_FATAL_ERROR); + y += 32; + } + if (line3) { + display_text(8, y, line3, -1, FONT_NORMAL, COLOR_WHITE, COLOR_FATAL_ERROR); + y += 32; + } + if (line4) { + display_text(8, y, line4, -1, FONT_NORMAL, COLOR_WHITE, COLOR_FATAL_ERROR); + y += 32; + } + y += 32; + display_text(8, y, "Please unplug the device.", -1, FONT_NORMAL, COLOR_WHITE, + COLOR_FATAL_ERROR); #else - display_print_color(COLOR_WHITE, COLOR_FATAL_ERROR); - if (line1) { - display_printf("%s\n", line1); - } - if (line2) { - display_printf("%s\n", line2); - } - if (line3) { - display_printf("%s\n", line3); - } - if (line4) { - display_printf("%s\n", line4); - } - display_printf("\nPlease unplug the device.\n"); + display_print_color(COLOR_WHITE, COLOR_FATAL_ERROR); + if (line1) { + display_printf("%s\n", line1); + } + if (line2) { + display_printf("%s\n", line2); + } + if (line3) { + display_printf("%s\n", line3); + } + if (line4) { + display_printf("%s\n", line4); + } + display_printf("\nPlease unplug the device.\n"); #endif - display_backlight(255); - shutdown(); - for (;;); + display_backlight(255); + shutdown(); + for (;;) + ; } #ifndef NDEBUG -void __assert_func(const char *file, int line, const char *func, const char *expr) { - __fatal_error(expr, "assert failed", file, line, func); +void __assert_func(const char *file, int line, const char *func, + const char *expr) { + __fatal_error(expr, "assert failed", file, line, func); } #endif -void hal_delay(uint32_t ms) -{ - HAL_Delay(ms); -} +void hal_delay(uint32_t ms) { HAL_Delay(ms); } -void delay_random(void) -{ - int wait = rng_get() & 0xff; - volatile int i = 0; - volatile int j = wait; - while (i < wait) { - if (i + j != wait) { - shutdown(); - } - ++i; - --j; - } - // Double-check loop completion. - if (i != wait || j != 0) { - shutdown(); +void delay_random(void) { + int wait = rng_get() & 0xff; + volatile int i = 0; + volatile int j = wait; + while (i < wait) { + if (i + j != wait) { + shutdown(); } + ++i; + --j; + } + // Double-check loop completion. + if (i != wait || j != 0) { + shutdown(); + } } // reference RM0090 section 35.12.1 Figure 413 -#define USB_OTG_HS_DATA_FIFO_RAM (USB_OTG_HS_PERIPH_BASE + 0x20000U) +#define USB_OTG_HS_DATA_FIFO_RAM (USB_OTG_HS_PERIPH_BASE + 0x20000U) #define USB_OTG_HS_DATA_FIFO_SIZE (4096U) -void clear_otg_hs_memory(void) -{ - // use the HAL version due to section 2.1.6 of STM32F42xx Errata sheet - __HAL_RCC_USB_OTG_HS_CLK_ENABLE(); // enable USB_OTG_HS peripheral clock so that the peripheral memory is accessible - memset_reg((volatile void *) USB_OTG_HS_DATA_FIFO_RAM, (volatile void *) (USB_OTG_HS_DATA_FIFO_RAM + USB_OTG_HS_DATA_FIFO_SIZE), 0); - __HAL_RCC_USB_OTG_HS_CLK_DISABLE(); // disable USB OTG_HS peripheral clock as the peripheral is not needed right now +void clear_otg_hs_memory(void) { + // use the HAL version due to section 2.1.6 of STM32F42xx Errata sheet + __HAL_RCC_USB_OTG_HS_CLK_ENABLE(); // enable USB_OTG_HS peripheral clock so + // that the peripheral memory is + // accessible + memset_reg( + (volatile void *)USB_OTG_HS_DATA_FIFO_RAM, + (volatile void *)(USB_OTG_HS_DATA_FIFO_RAM + USB_OTG_HS_DATA_FIFO_SIZE), + 0); + __HAL_RCC_USB_OTG_HS_CLK_DISABLE(); // disable USB OTG_HS peripheral clock as + // the peripheral is not needed right now } uint32_t __stack_chk_guard = 0; -void __attribute__((noreturn)) __stack_chk_fail(void) -{ - ensure(secfalse, "Stack smashing detected"); +void __attribute__((noreturn)) __stack_chk_fail(void) { + ensure(secfalse, "Stack smashing detected"); } uint8_t HW_ENTROPY_DATA[HW_ENTROPY_LEN]; -void collect_hw_entropy(void) -{ - // collect entropy from UUID - uint32_t w = LL_GetUID_Word0(); - memcpy(HW_ENTROPY_DATA, &w, 4); - w = LL_GetUID_Word1(); - memcpy(HW_ENTROPY_DATA + 4, &w, 4); - w = LL_GetUID_Word2(); - memcpy(HW_ENTROPY_DATA + 8, &w, 4); - - // set entropy in the OTP randomness block - if (secfalse == flash_otp_is_locked(FLASH_OTP_BLOCK_RANDOMNESS)) { - uint8_t entropy[FLASH_OTP_BLOCK_SIZE]; - random_buffer(entropy, FLASH_OTP_BLOCK_SIZE); - ensure(flash_otp_write(FLASH_OTP_BLOCK_RANDOMNESS, 0, entropy, FLASH_OTP_BLOCK_SIZE), NULL); - ensure(flash_otp_lock(FLASH_OTP_BLOCK_RANDOMNESS), NULL); - } - // collect entropy from OTP randomness block - ensure(flash_otp_read(FLASH_OTP_BLOCK_RANDOMNESS, 0, HW_ENTROPY_DATA + 12, FLASH_OTP_BLOCK_SIZE), NULL); +void collect_hw_entropy(void) { + // collect entropy from UUID + uint32_t w = LL_GetUID_Word0(); + memcpy(HW_ENTROPY_DATA, &w, 4); + w = LL_GetUID_Word1(); + memcpy(HW_ENTROPY_DATA + 4, &w, 4); + w = LL_GetUID_Word2(); + memcpy(HW_ENTROPY_DATA + 8, &w, 4); + + // set entropy in the OTP randomness block + if (secfalse == flash_otp_is_locked(FLASH_OTP_BLOCK_RANDOMNESS)) { + uint8_t entropy[FLASH_OTP_BLOCK_SIZE]; + random_buffer(entropy, FLASH_OTP_BLOCK_SIZE); + ensure(flash_otp_write(FLASH_OTP_BLOCK_RANDOMNESS, 0, entropy, + FLASH_OTP_BLOCK_SIZE), + NULL); + ensure(flash_otp_lock(FLASH_OTP_BLOCK_RANDOMNESS), NULL); + } + // collect entropy from OTP randomness block + ensure(flash_otp_read(FLASH_OTP_BLOCK_RANDOMNESS, 0, HW_ENTROPY_DATA + 12, + FLASH_OTP_BLOCK_SIZE), + NULL); } diff --git a/embed/trezorhal/common.h b/embed/trezorhal/common.h index 3fac1dec6..2954580bd 100644 --- a/embed/trezorhal/common.h +++ b/embed/trezorhal/common.h @@ -27,19 +27,41 @@ #define STR(s) #s #ifndef MIN_8bits -#define MIN_8bits(a, b) ({ typeof(a) _a = (a); typeof(b) _b = (b); _a < _b ? (_a & 0xFF) : (_b & 0xFF); }) +#define MIN_8bits(a, b) \ + ({ \ + typeof(a) _a = (a); \ + typeof(b) _b = (b); \ + _a < _b ? (_a & 0xFF) : (_b & 0xFF); \ + }) #endif #ifndef MIN -#define MIN(a, b) ({ typeof(a) _a = (a); typeof(b) _b = (b); _a < _b ? _a : _b; }) +#define MIN(a, b) \ + ({ \ + typeof(a) _a = (a); \ + typeof(b) _b = (b); \ + _a < _b ? _a : _b; \ + }) #endif #ifndef MAX -#define MAX(a, b) ({ typeof(a) _a = (a); typeof(b) _b = (b); _a > _b ? _a : _b; }) +#define MAX(a, b) \ + ({ \ + typeof(a) _a = (a); \ + typeof(b) _b = (b); \ + _a > _b ? _a : _b; \ + }) #endif -void __attribute__((noreturn)) __fatal_error(const char *expr, const char *msg, const char *file, int line, const char *func); -void __attribute__((noreturn)) error_shutdown(const char *line1, const char *line2, const char *line3, const char *line4); +void __attribute__((noreturn)) +__fatal_error(const char *expr, const char *msg, const char *file, int line, + const char *func); +void __attribute__((noreturn)) +error_shutdown(const char *line1, const char *line2, const char *line3, + const char *line4); -#define ensure(expr, msg) (((expr) == sectrue) ? (void)0 : __fatal_error(#expr, msg, __FILE__, __LINE__, __func__)) +#define ensure(expr, msg) \ + (((expr) == sectrue) \ + ? (void)0 \ + : __fatal_error(#expr, msg, __FILE__, __LINE__, __func__)) void hal_delay(uint32_t ms); diff --git a/embed/trezorhal/flash.c b/embed/trezorhal/flash.c index b91c2c8f9..b722aa3ed 100644 --- a/embed/trezorhal/flash.c +++ b/embed/trezorhal/flash.c @@ -27,34 +27,34 @@ // see docs/memory.md for more information static const uint32_t FLASH_SECTOR_TABLE[FLASH_SECTOR_COUNT + 1] = { - [ 0] = 0x08000000, // - 0x08003FFF | 16 KiB - [ 1] = 0x08004000, // - 0x08007FFF | 16 KiB - [ 2] = 0x08008000, // - 0x0800BFFF | 16 KiB - [ 3] = 0x0800C000, // - 0x0800FFFF | 16 KiB - [ 4] = 0x08010000, // - 0x0801FFFF | 64 KiB - [ 5] = 0x08020000, // - 0x0803FFFF | 128 KiB - [ 6] = 0x08040000, // - 0x0805FFFF | 128 KiB - [ 7] = 0x08060000, // - 0x0807FFFF | 128 KiB - [ 8] = 0x08080000, // - 0x0809FFFF | 128 KiB - [ 9] = 0x080A0000, // - 0x080BFFFF | 128 KiB - [10] = 0x080C0000, // - 0x080DFFFF | 128 KiB - [11] = 0x080E0000, // - 0x080FFFFF | 128 KiB - [12] = 0x08100000, // - 0x08103FFF | 16 KiB - [13] = 0x08104000, // - 0x08107FFF | 16 KiB - [14] = 0x08108000, // - 0x0810BFFF | 16 KiB - [15] = 0x0810C000, // - 0x0810FFFF | 16 KiB - [16] = 0x08110000, // - 0x0811FFFF | 64 KiB - [17] = 0x08120000, // - 0x0813FFFF | 128 KiB - [18] = 0x08140000, // - 0x0815FFFF | 128 KiB - [19] = 0x08160000, // - 0x0817FFFF | 128 KiB - [20] = 0x08180000, // - 0x0819FFFF | 128 KiB - [21] = 0x081A0000, // - 0x081BFFFF | 128 KiB - [22] = 0x081C0000, // - 0x081DFFFF | 128 KiB - [23] = 0x081E0000, // - 0x081FFFFF | 128 KiB - [24] = 0x08200000, // last element - not a valid sector + [0] = 0x08000000, // - 0x08003FFF | 16 KiB + [1] = 0x08004000, // - 0x08007FFF | 16 KiB + [2] = 0x08008000, // - 0x0800BFFF | 16 KiB + [3] = 0x0800C000, // - 0x0800FFFF | 16 KiB + [4] = 0x08010000, // - 0x0801FFFF | 64 KiB + [5] = 0x08020000, // - 0x0803FFFF | 128 KiB + [6] = 0x08040000, // - 0x0805FFFF | 128 KiB + [7] = 0x08060000, // - 0x0807FFFF | 128 KiB + [8] = 0x08080000, // - 0x0809FFFF | 128 KiB + [9] = 0x080A0000, // - 0x080BFFFF | 128 KiB + [10] = 0x080C0000, // - 0x080DFFFF | 128 KiB + [11] = 0x080E0000, // - 0x080FFFFF | 128 KiB + [12] = 0x08100000, // - 0x08103FFF | 16 KiB + [13] = 0x08104000, // - 0x08107FFF | 16 KiB + [14] = 0x08108000, // - 0x0810BFFF | 16 KiB + [15] = 0x0810C000, // - 0x0810FFFF | 16 KiB + [16] = 0x08110000, // - 0x0811FFFF | 64 KiB + [17] = 0x08120000, // - 0x0813FFFF | 128 KiB + [18] = 0x08140000, // - 0x0815FFFF | 128 KiB + [19] = 0x08160000, // - 0x0817FFFF | 128 KiB + [20] = 0x08180000, // - 0x0819FFFF | 128 KiB + [21] = 0x081A0000, // - 0x081BFFFF | 128 KiB + [22] = 0x081C0000, // - 0x081DFFFF | 128 KiB + [23] = 0x081E0000, // - 0x081FFFFF | 128 KiB + [24] = 0x08200000, // last element - not a valid sector }; -const uint8_t FIRMWARE_SECTORS [FIRMWARE_SECTORS_COUNT] = { +const uint8_t FIRMWARE_SECTORS[FIRMWARE_SECTORS_COUNT] = { FLASH_SECTOR_FIRMWARE_START, 7, 8, @@ -75,147 +75,146 @@ const uint8_t STORAGE_SECTORS[STORAGE_SECTORS_COUNT] = { FLASH_SECTOR_STORAGE_2, }; -void flash_init(void) -{ -} +void flash_init(void) {} -secbool flash_unlock_write(void) -{ - HAL_FLASH_Unlock(); - FLASH->SR |= FLASH_STATUS_ALL_FLAGS; // clear all status flags - return sectrue; +secbool flash_unlock_write(void) { + HAL_FLASH_Unlock(); + FLASH->SR |= FLASH_STATUS_ALL_FLAGS; // clear all status flags + return sectrue; } -secbool flash_lock_write(void) -{ - HAL_FLASH_Lock(); - return sectrue; +secbool flash_lock_write(void) { + HAL_FLASH_Lock(); + return sectrue; } -const void *flash_get_address(uint8_t sector, uint32_t offset, uint32_t size) -{ - if (sector >= FLASH_SECTOR_COUNT) { - return NULL; - } - const uint32_t addr = FLASH_SECTOR_TABLE[sector] + offset; - const uint32_t next = FLASH_SECTOR_TABLE[sector + 1]; - if (addr + size > next) { - return NULL; - } - return (const void *)addr; +const void *flash_get_address(uint8_t sector, uint32_t offset, uint32_t size) { + if (sector >= FLASH_SECTOR_COUNT) { + return NULL; + } + const uint32_t addr = FLASH_SECTOR_TABLE[sector] + offset; + const uint32_t next = FLASH_SECTOR_TABLE[sector + 1]; + if (addr + size > next) { + return NULL; + } + return (const void *)addr; } -secbool flash_erase_sectors(const uint8_t *sectors, int len, void (*progress)(int pos, int len)) -{ - ensure(flash_unlock_write(), NULL); - FLASH_EraseInitTypeDef EraseInitStruct; - EraseInitStruct.TypeErase = FLASH_TYPEERASE_SECTORS; - EraseInitStruct.VoltageRange = FLASH_VOLTAGE_RANGE_3; - EraseInitStruct.NbSectors = 1; - if (progress) { - progress(0, len); - } - for (int i = 0; i < len; i++) { - EraseInitStruct.Sector = sectors[i]; - uint32_t SectorError; - if (HAL_FLASHEx_Erase(&EraseInitStruct, &SectorError) != HAL_OK) { - ensure(flash_lock_write(), NULL); - return secfalse; - } - // check whether the sector was really deleted (contains only 0xFF) - const uint32_t addr_start = FLASH_SECTOR_TABLE[sectors[i]], addr_end = FLASH_SECTOR_TABLE[sectors[i] + 1]; - for (uint32_t addr = addr_start; addr < addr_end; addr += 4) { - if (*((const uint32_t *)addr) != 0xFFFFFFFF) { - ensure(flash_lock_write(), NULL); - return secfalse; - } - } - if (progress) { - progress(i + 1, len); - } - } - ensure(flash_lock_write(), NULL); - return sectrue; -} - -secbool flash_write_byte(uint8_t sector, uint32_t offset, uint8_t data) -{ - uint32_t address = (uint32_t)flash_get_address(sector, offset, 1); - if (address == 0) { +secbool flash_erase_sectors(const uint8_t *sectors, int len, + void (*progress)(int pos, int len)) { + ensure(flash_unlock_write(), NULL); + FLASH_EraseInitTypeDef EraseInitStruct; + EraseInitStruct.TypeErase = FLASH_TYPEERASE_SECTORS; + EraseInitStruct.VoltageRange = FLASH_VOLTAGE_RANGE_3; + EraseInitStruct.NbSectors = 1; + if (progress) { + progress(0, len); + } + for (int i = 0; i < len; i++) { + EraseInitStruct.Sector = sectors[i]; + uint32_t SectorError; + if (HAL_FLASHEx_Erase(&EraseInitStruct, &SectorError) != HAL_OK) { + ensure(flash_lock_write(), NULL); + return secfalse; + } + // check whether the sector was really deleted (contains only 0xFF) + const uint32_t addr_start = FLASH_SECTOR_TABLE[sectors[i]], + addr_end = FLASH_SECTOR_TABLE[sectors[i] + 1]; + for (uint32_t addr = addr_start; addr < addr_end; addr += 4) { + if (*((const uint32_t *)addr) != 0xFFFFFFFF) { + ensure(flash_lock_write(), NULL); return secfalse; + } } - if (data != (data & *((const uint8_t *)address))) { - return secfalse; - } - if (HAL_OK != HAL_FLASH_Program(FLASH_TYPEPROGRAM_BYTE, address, data)) { - return secfalse; - } - if (data != *((const uint8_t *)address)) { - return secfalse; + if (progress) { + progress(i + 1, len); } - return sectrue; + } + ensure(flash_lock_write(), NULL); + return sectrue; } -secbool flash_write_word(uint8_t sector, uint32_t offset, uint32_t data) -{ - uint32_t address = (uint32_t)flash_get_address(sector, offset, 4); - if (address == 0) { - return secfalse; - } - if (offset % sizeof(uint32_t)) { // we write only at 4-byte boundary - return secfalse; - } - if (data != (data & *((const uint32_t *)address))) { - return secfalse; - } - if (HAL_OK != HAL_FLASH_Program(FLASH_TYPEPROGRAM_WORD, address, data)) { - return secfalse; - } - if (data != *((const uint32_t *)address)) { - return secfalse; - } - return sectrue; +secbool flash_write_byte(uint8_t sector, uint32_t offset, uint8_t data) { + uint32_t address = (uint32_t)flash_get_address(sector, offset, 1); + if (address == 0) { + return secfalse; + } + if (data != (data & *((const uint8_t *)address))) { + return secfalse; + } + if (HAL_OK != HAL_FLASH_Program(FLASH_TYPEPROGRAM_BYTE, address, data)) { + return secfalse; + } + if (data != *((const uint8_t *)address)) { + return secfalse; + } + return sectrue; } -#define FLASH_OTP_LOCK_BASE 0x1FFF7A00U +secbool flash_write_word(uint8_t sector, uint32_t offset, uint32_t data) { + uint32_t address = (uint32_t)flash_get_address(sector, offset, 4); + if (address == 0) { + return secfalse; + } + if (offset % sizeof(uint32_t)) { // we write only at 4-byte boundary + return secfalse; + } + if (data != (data & *((const uint32_t *)address))) { + return secfalse; + } + if (HAL_OK != HAL_FLASH_Program(FLASH_TYPEPROGRAM_WORD, address, data)) { + return secfalse; + } + if (data != *((const uint32_t *)address)) { + return secfalse; + } + return sectrue; +} -secbool flash_otp_read(uint8_t block, uint8_t offset, uint8_t *data, uint8_t datalen) -{ - if (block >= FLASH_OTP_NUM_BLOCKS || offset + datalen > FLASH_OTP_BLOCK_SIZE) { - return secfalse; - } - for (uint8_t i = 0; i < datalen; i++) { - data[i] = *(__IO uint8_t *)(FLASH_OTP_BASE + block * FLASH_OTP_BLOCK_SIZE + offset + i); - } - return sectrue; +#define FLASH_OTP_LOCK_BASE 0x1FFF7A00U + +secbool flash_otp_read(uint8_t block, uint8_t offset, uint8_t *data, + uint8_t datalen) { + if (block >= FLASH_OTP_NUM_BLOCKS || + offset + datalen > FLASH_OTP_BLOCK_SIZE) { + return secfalse; + } + for (uint8_t i = 0; i < datalen; i++) { + data[i] = *(__IO uint8_t *)(FLASH_OTP_BASE + block * FLASH_OTP_BLOCK_SIZE + + offset + i); + } + return sectrue; } -secbool flash_otp_write(uint8_t block, uint8_t offset, const uint8_t *data, uint8_t datalen) -{ - if (block >= FLASH_OTP_NUM_BLOCKS || offset + datalen > FLASH_OTP_BLOCK_SIZE) { - return secfalse; - } - ensure(flash_unlock_write(), NULL); - for (uint8_t i = 0; i < datalen; i++) { - uint32_t address = FLASH_OTP_BASE + block * FLASH_OTP_BLOCK_SIZE + offset + i; - ensure(sectrue * (HAL_OK == HAL_FLASH_Program(FLASH_TYPEPROGRAM_BYTE, address, data[i])), NULL); - } - ensure(flash_lock_write(), NULL); - return sectrue; +secbool flash_otp_write(uint8_t block, uint8_t offset, const uint8_t *data, + uint8_t datalen) { + if (block >= FLASH_OTP_NUM_BLOCKS || + offset + datalen > FLASH_OTP_BLOCK_SIZE) { + return secfalse; + } + ensure(flash_unlock_write(), NULL); + for (uint8_t i = 0; i < datalen; i++) { + uint32_t address = + FLASH_OTP_BASE + block * FLASH_OTP_BLOCK_SIZE + offset + i; + ensure(sectrue * (HAL_OK == HAL_FLASH_Program(FLASH_TYPEPROGRAM_BYTE, + address, data[i])), + NULL); + } + ensure(flash_lock_write(), NULL); + return sectrue; } -secbool flash_otp_lock(uint8_t block) -{ - if (block >= FLASH_OTP_NUM_BLOCKS) { - return secfalse; - } - ensure(flash_unlock_write(), NULL); - HAL_StatusTypeDef ret = HAL_FLASH_Program(FLASH_TYPEPROGRAM_BYTE, FLASH_OTP_LOCK_BASE + block, 0x00); - ensure(flash_lock_write(), NULL); - return sectrue * (ret == HAL_OK); +secbool flash_otp_lock(uint8_t block) { + if (block >= FLASH_OTP_NUM_BLOCKS) { + return secfalse; + } + ensure(flash_unlock_write(), NULL); + HAL_StatusTypeDef ret = HAL_FLASH_Program(FLASH_TYPEPROGRAM_BYTE, + FLASH_OTP_LOCK_BASE + block, 0x00); + ensure(flash_lock_write(), NULL); + return sectrue * (ret == HAL_OK); } -secbool flash_otp_is_locked(uint8_t block) -{ - return sectrue * (0x00 == *(__IO uint8_t *)(FLASH_OTP_LOCK_BASE + block)); +secbool flash_otp_is_locked(uint8_t block) { + return sectrue * (0x00 == *(__IO uint8_t *)(FLASH_OTP_LOCK_BASE + block)); } diff --git a/embed/trezorhal/flash.h b/embed/trezorhal/flash.h index 285a1e76f..a2e9459b5 100644 --- a/embed/trezorhal/flash.h +++ b/embed/trezorhal/flash.h @@ -28,51 +28,54 @@ #define FLASH_SECTOR_COUNT 24 -#define FLASH_SECTOR_BOARDLOADER_START 0 +#define FLASH_SECTOR_BOARDLOADER_START 0 // 1 -#define FLASH_SECTOR_BOARDLOADER_END 2 +#define FLASH_SECTOR_BOARDLOADER_END 2 // 3 -#define FLASH_SECTOR_STORAGE_1 4 +#define FLASH_SECTOR_STORAGE_1 4 -#define FLASH_SECTOR_BOOTLOADER 5 +#define FLASH_SECTOR_BOOTLOADER 5 -#define FLASH_SECTOR_FIRMWARE_START 6 +#define FLASH_SECTOR_FIRMWARE_START 6 // 7 // 8 // 9 // 10 -#define FLASH_SECTOR_FIRMWARE_END 11 +#define FLASH_SECTOR_FIRMWARE_END 11 -#define FLASH_SECTOR_UNUSED_START 12 +#define FLASH_SECTOR_UNUSED_START 12 // 13 // 14 -#define FLASH_SECTOR_UNUSED_END 15 +#define FLASH_SECTOR_UNUSED_END 15 -#define FLASH_SECTOR_STORAGE_2 16 +#define FLASH_SECTOR_STORAGE_2 16 -#define FLASH_SECTOR_FIRMWARE_EXTRA_START 17 +#define FLASH_SECTOR_FIRMWARE_EXTRA_START 17 // 18 // 19 // 20 // 21 // 22 -#define FLASH_SECTOR_FIRMWARE_EXTRA_END 23 +#define FLASH_SECTOR_FIRMWARE_EXTRA_END 23 -#define BOOTLOADER_SECTORS_COUNT (1) -#define STORAGE_SECTORS_COUNT (2) -#define FIRMWARE_SECTORS_COUNT (6 + 7) +#define BOOTLOADER_SECTORS_COUNT (1) +#define STORAGE_SECTORS_COUNT (2) +#define FIRMWARE_SECTORS_COUNT (6 + 7) extern const uint8_t STORAGE_SECTORS[STORAGE_SECTORS_COUNT]; extern const uint8_t FIRMWARE_SECTORS[FIRMWARE_SECTORS_COUNT]; -// note: FLASH_SR_RDERR is STM32F42xxx and STM32F43xxx specific (STM32F427) (reference RM0090 section 3.7.5) +// note: FLASH_SR_RDERR is STM32F42xxx and STM32F43xxx specific (STM32F427) +// (reference RM0090 section 3.7.5) #ifndef STM32F427xx #define FLASH_SR_RDERR 0 #endif -#define FLASH_STATUS_ALL_FLAGS (FLASH_SR_RDERR | FLASH_SR_PGSERR | FLASH_SR_PGPERR | FLASH_SR_PGAERR | FLASH_SR_WRPERR | FLASH_SR_SOP | FLASH_SR_EOP) +#define FLASH_STATUS_ALL_FLAGS \ + (FLASH_SR_RDERR | FLASH_SR_PGSERR | FLASH_SR_PGPERR | FLASH_SR_PGAERR | \ + FLASH_SR_WRPERR | FLASH_SR_SOP | FLASH_SR_EOP) void flash_init(void); @@ -81,23 +84,28 @@ secbool __wur flash_lock_write(void); const void *flash_get_address(uint8_t sector, uint32_t offset, uint32_t size); -secbool __wur flash_erase_sectors(const uint8_t *sectors, int len, void (*progress)(int pos, int len)); -static inline secbool flash_erase(uint8_t sector) { return flash_erase_sectors(§or, 1, NULL); } +secbool __wur flash_erase_sectors(const uint8_t *sectors, int len, + void (*progress)(int pos, int len)); +static inline secbool flash_erase(uint8_t sector) { + return flash_erase_sectors(§or, 1, NULL); +} secbool __wur flash_write_byte(uint8_t sector, uint32_t offset, uint8_t data); secbool __wur flash_write_word(uint8_t sector, uint32_t offset, uint32_t data); -#define FLASH_OTP_NUM_BLOCKS 16 -#define FLASH_OTP_BLOCK_SIZE 32 +#define FLASH_OTP_NUM_BLOCKS 16 +#define FLASH_OTP_BLOCK_SIZE 32 // OTP blocks allocation -#define FLASH_OTP_BLOCK_BATCH 0 -#define FLASH_OTP_BLOCK_BOOTLOADER_VERSION 1 -#define FLASH_OTP_BLOCK_VENDOR_KEYS_LOCK 2 -#define FLASH_OTP_BLOCK_RANDOMNESS 3 - -secbool __wur flash_otp_read(uint8_t block, uint8_t offset, uint8_t *data, uint8_t datalen); -secbool __wur flash_otp_write(uint8_t block, uint8_t offset, const uint8_t *data, uint8_t datalen); +#define FLASH_OTP_BLOCK_BATCH 0 +#define FLASH_OTP_BLOCK_BOOTLOADER_VERSION 1 +#define FLASH_OTP_BLOCK_VENDOR_KEYS_LOCK 2 +#define FLASH_OTP_BLOCK_RANDOMNESS 3 + +secbool __wur flash_otp_read(uint8_t block, uint8_t offset, uint8_t *data, + uint8_t datalen); +secbool __wur flash_otp_write(uint8_t block, uint8_t offset, + const uint8_t *data, uint8_t datalen); secbool __wur flash_otp_lock(uint8_t block); secbool __wur flash_otp_is_locked(uint8_t block); -#endif // TREZORHAL_FLASH_H +#endif // TREZORHAL_FLASH_H diff --git a/embed/trezorhal/image.c b/embed/trezorhal/image.c index 6ff3a26fc..b08e98674 100644 --- a/embed/trezorhal/image.c +++ b/embed/trezorhal/image.c @@ -26,180 +26,199 @@ #include "flash.h" #include "image.h" -static secbool compute_pubkey(uint8_t sig_m, uint8_t sig_n, const uint8_t * const *pub, uint8_t sigmask, ed25519_public_key res) -{ - if (0 == sig_m || 0 == sig_n) return secfalse; - if (sig_m > sig_n) return secfalse; - - // discard bits higher than sig_n - sigmask &= ((1 << sig_n) - 1); - - // remove if number of set bits in sigmask is not equal to sig_m - if (__builtin_popcount(sigmask) != sig_m) return secfalse; - - ed25519_public_key keys[sig_m]; - int j = 0; - for (int i = 0; i < sig_n; i++) { - if ((1 << i) & sigmask) { - memcpy(keys[j], pub[i], 32); - j++; - } +static secbool compute_pubkey(uint8_t sig_m, uint8_t sig_n, + const uint8_t *const *pub, uint8_t sigmask, + ed25519_public_key res) { + if (0 == sig_m || 0 == sig_n) return secfalse; + if (sig_m > sig_n) return secfalse; + + // discard bits higher than sig_n + sigmask &= ((1 << sig_n) - 1); + + // remove if number of set bits in sigmask is not equal to sig_m + if (__builtin_popcount(sigmask) != sig_m) return secfalse; + + ed25519_public_key keys[sig_m]; + int j = 0; + for (int i = 0; i < sig_n; i++) { + if ((1 << i) & sigmask) { + memcpy(keys[j], pub[i], 32); + j++; } + } - return sectrue * (0 == ed25519_cosi_combine_publickeys(res, keys, sig_m)); + return sectrue * (0 == ed25519_cosi_combine_publickeys(res, keys, sig_m)); } -secbool load_image_header(const uint8_t * const data, const uint32_t magic, const uint32_t maxsize, uint8_t key_m, uint8_t key_n, const uint8_t * const *keys, image_header * const hdr) -{ - memcpy(&hdr->magic, data, 4); - if (hdr->magic != magic) return secfalse; +secbool load_image_header(const uint8_t *const data, const uint32_t magic, + const uint32_t maxsize, uint8_t key_m, uint8_t key_n, + const uint8_t *const *keys, image_header *const hdr) { + memcpy(&hdr->magic, data, 4); + if (hdr->magic != magic) return secfalse; - memcpy(&hdr->hdrlen, data + 4, 4); - if (hdr->hdrlen != IMAGE_HEADER_SIZE) return secfalse; + memcpy(&hdr->hdrlen, data + 4, 4); + if (hdr->hdrlen != IMAGE_HEADER_SIZE) return secfalse; - memcpy(&hdr->expiry, data + 8, 4); - // TODO: expiry mechanism needs to be ironed out before production or those - // devices won't accept expiring bootloaders (due to boardloader write protection). - if (hdr->expiry != 0) return secfalse; + memcpy(&hdr->expiry, data + 8, 4); + // TODO: expiry mechanism needs to be ironed out before production or those + // devices won't accept expiring bootloaders (due to boardloader write + // protection). + if (hdr->expiry != 0) return secfalse; - memcpy(&hdr->codelen, data + 12, 4); - if (hdr->codelen > (maxsize - hdr->hdrlen)) return secfalse; - if ((hdr->hdrlen + hdr->codelen) < 4 * 1024) return secfalse; - if ((hdr->hdrlen + hdr->codelen) % 512 != 0) return secfalse; + memcpy(&hdr->codelen, data + 12, 4); + if (hdr->codelen > (maxsize - hdr->hdrlen)) return secfalse; + if ((hdr->hdrlen + hdr->codelen) < 4 * 1024) return secfalse; + if ((hdr->hdrlen + hdr->codelen) % 512 != 0) return secfalse; - memcpy(&hdr->version, data + 16, 4); - memcpy(&hdr->fix_version, data + 20, 4); + memcpy(&hdr->version, data + 16, 4); + memcpy(&hdr->fix_version, data + 20, 4); - memcpy(hdr->hashes, data + 32, 512); + memcpy(hdr->hashes, data + 32, 512); - memcpy(&hdr->sigmask, data + IMAGE_HEADER_SIZE - IMAGE_SIG_SIZE, 1); + memcpy(&hdr->sigmask, data + IMAGE_HEADER_SIZE - IMAGE_SIG_SIZE, 1); - memcpy(hdr->sig, data + IMAGE_HEADER_SIZE - IMAGE_SIG_SIZE + 1, IMAGE_SIG_SIZE - 1); + memcpy(hdr->sig, data + IMAGE_HEADER_SIZE - IMAGE_SIG_SIZE + 1, + IMAGE_SIG_SIZE - 1); - // check header signature + // check header signature - BLAKE2S_CTX ctx; - blake2s_Init(&ctx, BLAKE2S_DIGEST_LENGTH); - blake2s_Update(&ctx, data, IMAGE_HEADER_SIZE - IMAGE_SIG_SIZE); - for (int i = 0; i < IMAGE_SIG_SIZE; i++) { - blake2s_Update(&ctx, (const uint8_t *)"\x00", 1); - } - blake2s_Final(&ctx, hdr->fingerprint, BLAKE2S_DIGEST_LENGTH); + BLAKE2S_CTX ctx; + blake2s_Init(&ctx, BLAKE2S_DIGEST_LENGTH); + blake2s_Update(&ctx, data, IMAGE_HEADER_SIZE - IMAGE_SIG_SIZE); + for (int i = 0; i < IMAGE_SIG_SIZE; i++) { + blake2s_Update(&ctx, (const uint8_t *)"\x00", 1); + } + blake2s_Final(&ctx, hdr->fingerprint, BLAKE2S_DIGEST_LENGTH); - ed25519_public_key pub; - if (sectrue != compute_pubkey(key_m, key_n, keys, hdr->sigmask, pub)) return secfalse; + ed25519_public_key pub; + if (sectrue != compute_pubkey(key_m, key_n, keys, hdr->sigmask, pub)) + return secfalse; - return sectrue * (0 == ed25519_sign_open(hdr->fingerprint, BLAKE2S_DIGEST_LENGTH, pub, *(const ed25519_signature *)hdr->sig)); + return sectrue * + (0 == ed25519_sign_open(hdr->fingerprint, BLAKE2S_DIGEST_LENGTH, pub, + *(const ed25519_signature *)hdr->sig)); } -secbool load_vendor_header(const uint8_t * const data, uint8_t key_m, uint8_t key_n, const uint8_t * const *keys, vendor_header * const vhdr) -{ - memcpy(&vhdr->magic, data, 4); - if (vhdr->magic != 0x565A5254) return secfalse; // TRZV +secbool load_vendor_header(const uint8_t *const data, uint8_t key_m, + uint8_t key_n, const uint8_t *const *keys, + vendor_header *const vhdr) { + memcpy(&vhdr->magic, data, 4); + if (vhdr->magic != 0x565A5254) return secfalse; // TRZV - memcpy(&vhdr->hdrlen, data + 4, 4); - if (vhdr->hdrlen > 64 * 1024) return secfalse; + memcpy(&vhdr->hdrlen, data + 4, 4); + if (vhdr->hdrlen > 64 * 1024) return secfalse; - memcpy(&vhdr->expiry, data + 8, 4); - if (vhdr->expiry != 0) return secfalse; + memcpy(&vhdr->expiry, data + 8, 4); + if (vhdr->expiry != 0) return secfalse; - memcpy(&vhdr->version, data + 12, 2); + memcpy(&vhdr->version, data + 12, 2); - memcpy(&vhdr->vsig_m, data + 14, 1); - memcpy(&vhdr->vsig_n, data + 15, 1); - memcpy(&vhdr->vtrust, data + 16, 2); + memcpy(&vhdr->vsig_m, data + 14, 1); + memcpy(&vhdr->vsig_n, data + 15, 1); + memcpy(&vhdr->vtrust, data + 16, 2); - if (vhdr->vsig_n > MAX_VENDOR_PUBLIC_KEYS) { - return secfalse; - } + if (vhdr->vsig_n > MAX_VENDOR_PUBLIC_KEYS) { + return secfalse; + } - for (int i = 0; i < vhdr->vsig_n; i++) { - vhdr->vpub[i] = data + 32 + i * 32; - } - for (int i = vhdr->vsig_n; i < MAX_VENDOR_PUBLIC_KEYS; i++) { - vhdr->vpub[i] = 0; - } + for (int i = 0; i < vhdr->vsig_n; i++) { + vhdr->vpub[i] = data + 32 + i * 32; + } + for (int i = vhdr->vsig_n; i < MAX_VENDOR_PUBLIC_KEYS; i++) { + vhdr->vpub[i] = 0; + } - memcpy(&vhdr->vstr_len, data + 32 + vhdr->vsig_n * 32, 1); + memcpy(&vhdr->vstr_len, data + 32 + vhdr->vsig_n * 32, 1); - vhdr->vstr = (const char *)(data + 32 + vhdr->vsig_n * 32 + 1); + vhdr->vstr = (const char *)(data + 32 + vhdr->vsig_n * 32 + 1); - vhdr->vimg = data + 32 + vhdr->vsig_n * 32 + 1 + vhdr->vstr_len; - // align to 4 bytes - vhdr->vimg += (-(uintptr_t)vhdr->vimg) & 3; + vhdr->vimg = data + 32 + vhdr->vsig_n * 32 + 1 + vhdr->vstr_len; + // align to 4 bytes + vhdr->vimg += (-(uintptr_t)vhdr->vimg) & 3; - memcpy(&vhdr->sigmask, data + vhdr->hdrlen - IMAGE_SIG_SIZE, 1); + memcpy(&vhdr->sigmask, data + vhdr->hdrlen - IMAGE_SIG_SIZE, 1); - memcpy(vhdr->sig, data + vhdr->hdrlen - IMAGE_SIG_SIZE + 1, IMAGE_SIG_SIZE - 1); + memcpy(vhdr->sig, data + vhdr->hdrlen - IMAGE_SIG_SIZE + 1, + IMAGE_SIG_SIZE - 1); - // check header signature + // check header signature - uint8_t hash[BLAKE2S_DIGEST_LENGTH]; - BLAKE2S_CTX ctx; - blake2s_Init(&ctx, BLAKE2S_DIGEST_LENGTH); - blake2s_Update(&ctx, data, vhdr->hdrlen - IMAGE_SIG_SIZE); - for (int i = 0; i < IMAGE_SIG_SIZE; i++) { - blake2s_Update(&ctx, (const uint8_t *)"\x00", 1); - } - blake2s_Final(&ctx, hash, BLAKE2S_DIGEST_LENGTH); + uint8_t hash[BLAKE2S_DIGEST_LENGTH]; + BLAKE2S_CTX ctx; + blake2s_Init(&ctx, BLAKE2S_DIGEST_LENGTH); + blake2s_Update(&ctx, data, vhdr->hdrlen - IMAGE_SIG_SIZE); + for (int i = 0; i < IMAGE_SIG_SIZE; i++) { + blake2s_Update(&ctx, (const uint8_t *)"\x00", 1); + } + blake2s_Final(&ctx, hash, BLAKE2S_DIGEST_LENGTH); - ed25519_public_key pub; - if (sectrue != compute_pubkey(key_m, key_n, keys, vhdr->sigmask, pub)) return secfalse; + ed25519_public_key pub; + if (sectrue != compute_pubkey(key_m, key_n, keys, vhdr->sigmask, pub)) + return secfalse; - return sectrue * (0 == ed25519_sign_open(hash, BLAKE2S_DIGEST_LENGTH, pub, *(const ed25519_signature *)vhdr->sig)); + return sectrue * + (0 == ed25519_sign_open(hash, BLAKE2S_DIGEST_LENGTH, pub, + *(const ed25519_signature *)vhdr->sig)); } -void vendor_keys_hash(const vendor_header * const vhdr, uint8_t *hash) -{ - BLAKE2S_CTX ctx; - blake2s_Init(&ctx, BLAKE2S_DIGEST_LENGTH); - blake2s_Update(&ctx, &(vhdr->vsig_m), sizeof(vhdr->vsig_m)); - blake2s_Update(&ctx, &(vhdr->vsig_n), sizeof(vhdr->vsig_n)); - for (int i = 0; i < MAX_VENDOR_PUBLIC_KEYS; i++) { - if (vhdr->vpub[i] != 0) { - blake2s_Update(&ctx, vhdr->vpub[i], 32); - } else { - blake2s_Update(&ctx, "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00", 32); - } +void vendor_keys_hash(const vendor_header *const vhdr, uint8_t *hash) { + BLAKE2S_CTX ctx; + blake2s_Init(&ctx, BLAKE2S_DIGEST_LENGTH); + blake2s_Update(&ctx, &(vhdr->vsig_m), sizeof(vhdr->vsig_m)); + blake2s_Update(&ctx, &(vhdr->vsig_n), sizeof(vhdr->vsig_n)); + for (int i = 0; i < MAX_VENDOR_PUBLIC_KEYS; i++) { + if (vhdr->vpub[i] != 0) { + blake2s_Update(&ctx, vhdr->vpub[i], 32); + } else { + blake2s_Update( + &ctx, + "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00", + 32); } - blake2s_Final(&ctx, hash, BLAKE2S_DIGEST_LENGTH); + } + blake2s_Final(&ctx, hash, BLAKE2S_DIGEST_LENGTH); } -secbool check_single_hash(const uint8_t * const hash, const uint8_t * const data, int len) -{ - uint8_t h[BLAKE2S_DIGEST_LENGTH]; - blake2s(data, len, h, BLAKE2S_DIGEST_LENGTH); - return sectrue * (0 == memcmp(h, hash, BLAKE2S_DIGEST_LENGTH)); +secbool check_single_hash(const uint8_t *const hash, const uint8_t *const data, + int len) { + uint8_t h[BLAKE2S_DIGEST_LENGTH]; + blake2s(data, len, h, BLAKE2S_DIGEST_LENGTH); + return sectrue * (0 == memcmp(h, hash, BLAKE2S_DIGEST_LENGTH)); } -secbool check_image_contents(const image_header * const hdr, uint32_t firstskip, const uint8_t *sectors, int blocks) -{ - if (0 == sectors || blocks < 1) { - return secfalse; +secbool check_image_contents(const image_header *const hdr, uint32_t firstskip, + const uint8_t *sectors, int blocks) { + if (0 == sectors || blocks < 1) { + return secfalse; + } + const void *data = + flash_get_address(sectors[0], firstskip, IMAGE_CHUNK_SIZE - firstskip); + if (!data) { + return secfalse; + } + int remaining = hdr->codelen; + if (sectrue != + check_single_hash(hdr->hashes, data, + MIN(remaining, IMAGE_CHUNK_SIZE - firstskip))) { + return secfalse; + } + int block = 1; + remaining -= IMAGE_CHUNK_SIZE - firstskip; + while (remaining > 0) { + if (block >= blocks) { + return secfalse; } - const void *data = flash_get_address(sectors[0], firstskip, IMAGE_CHUNK_SIZE - firstskip); + data = flash_get_address(sectors[block], 0, IMAGE_CHUNK_SIZE); if (!data) { - return secfalse; - } - int remaining = hdr->codelen; - if (sectrue != check_single_hash(hdr->hashes, data, MIN(remaining, IMAGE_CHUNK_SIZE - firstskip))) { - return secfalse; + return secfalse; } - int block = 1; - remaining -= IMAGE_CHUNK_SIZE - firstskip; - while (remaining > 0) { - if (block >= blocks) { - return secfalse; - } - data = flash_get_address(sectors[block], 0, IMAGE_CHUNK_SIZE); - if (!data) { - return secfalse; - } - if (sectrue != check_single_hash(hdr->hashes + block * 32, data, MIN(remaining, IMAGE_CHUNK_SIZE))) { - return secfalse; - } - block++; - remaining -= IMAGE_CHUNK_SIZE; + if (sectrue != check_single_hash(hdr->hashes + block * 32, data, + MIN(remaining, IMAGE_CHUNK_SIZE))) { + return secfalse; } - return sectrue; + block++; + remaining -= IMAGE_CHUNK_SIZE; + } + return sectrue; } diff --git a/embed/trezorhal/image.h b/embed/trezorhal/image.h index 7eef84531..3fd8c2224 100644 --- a/embed/trezorhal/image.h +++ b/embed/trezorhal/image.h @@ -23,68 +23,76 @@ #include #include "secbool.h" -#define BOARDLOADER_START 0x08000000 -#define BOOTLOADER_START 0x08020000 -#define FIRMWARE_START 0x08040000 +#define BOARDLOADER_START 0x08000000 +#define BOOTLOADER_START 0x08020000 +#define FIRMWARE_START 0x08040000 -#define IMAGE_HEADER_SIZE 0x400 -#define IMAGE_SIG_SIZE 65 -#define IMAGE_CHUNK_SIZE (128 * 1024) +#define IMAGE_HEADER_SIZE 0x400 +#define IMAGE_SIG_SIZE 65 +#define IMAGE_CHUNK_SIZE (128 * 1024) -#define BOOTLOADER_IMAGE_MAGIC 0x425A5254 // TRZB +#define BOOTLOADER_IMAGE_MAGIC 0x425A5254 // TRZB #define BOOTLOADER_IMAGE_MAXSIZE (BOOTLOADER_SECTORS_COUNT * IMAGE_CHUNK_SIZE) -#define FIRMWARE_IMAGE_MAGIC 0x465A5254 // TRZF -#define FIRMWARE_IMAGE_MAXSIZE (FIRMWARE_SECTORS_COUNT * IMAGE_CHUNK_SIZE) +#define FIRMWARE_IMAGE_MAGIC 0x465A5254 // TRZF +#define FIRMWARE_IMAGE_MAXSIZE (FIRMWARE_SECTORS_COUNT * IMAGE_CHUNK_SIZE) typedef struct { - uint32_t magic; - uint32_t hdrlen; - uint32_t expiry; - uint32_t codelen; - uint32_t version; - uint32_t fix_version; - // uint8_t reserved[8]; - uint8_t hashes[512]; - // uint8_t reserved[415]; - uint8_t sigmask; - uint8_t sig[64]; - uint8_t fingerprint[32]; + uint32_t magic; + uint32_t hdrlen; + uint32_t expiry; + uint32_t codelen; + uint32_t version; + uint32_t fix_version; + // uint8_t reserved[8]; + uint8_t hashes[512]; + // uint8_t reserved[415]; + uint8_t sigmask; + uint8_t sig[64]; + uint8_t fingerprint[32]; } image_header; #define MAX_VENDOR_PUBLIC_KEYS 8 -#define VTRUST_WAIT 0x000F -#define VTRUST_RED 0x0010 -#define VTRUST_CLICK 0x0020 -#define VTRUST_STRING 0x0040 -#define VTRUST_ALL (VTRUST_WAIT | VTRUST_RED | VTRUST_CLICK | VTRUST_STRING) +#define VTRUST_WAIT 0x000F +#define VTRUST_RED 0x0010 +#define VTRUST_CLICK 0x0020 +#define VTRUST_STRING 0x0040 +#define VTRUST_ALL (VTRUST_WAIT | VTRUST_RED | VTRUST_CLICK | VTRUST_STRING) typedef struct { - uint32_t magic; - uint32_t hdrlen; - uint32_t expiry; - uint16_t version; - uint8_t vsig_m; - uint8_t vsig_n; - uint16_t vtrust; - // uint8_t reserved[14]; - const uint8_t *vpub[MAX_VENDOR_PUBLIC_KEYS]; - uint8_t vstr_len; - const char *vstr; - const uint8_t *vimg; - uint8_t sigmask; - uint8_t sig[64]; + uint32_t magic; + uint32_t hdrlen; + uint32_t expiry; + uint16_t version; + uint8_t vsig_m; + uint8_t vsig_n; + uint16_t vtrust; + // uint8_t reserved[14]; + const uint8_t *vpub[MAX_VENDOR_PUBLIC_KEYS]; + uint8_t vstr_len; + const char *vstr; + const uint8_t *vimg; + uint8_t sigmask; + uint8_t sig[64]; } vendor_header; -secbool __wur load_image_header(const uint8_t * const data, const uint32_t magic, const uint32_t maxsize, uint8_t key_m, uint8_t key_n, const uint8_t * const *keys, image_header * const hdr); +secbool __wur load_image_header(const uint8_t *const data, const uint32_t magic, + const uint32_t maxsize, uint8_t key_m, + uint8_t key_n, const uint8_t *const *keys, + image_header *const hdr); -secbool __wur load_vendor_header(const uint8_t * const data, uint8_t key_m, uint8_t key_n, const uint8_t * const *keys, vendor_header * const vhdr); +secbool __wur load_vendor_header(const uint8_t *const data, uint8_t key_m, + uint8_t key_n, const uint8_t *const *keys, + vendor_header *const vhdr); -void vendor_keys_hash(const vendor_header * const vhdr, uint8_t *hash); +void vendor_keys_hash(const vendor_header *const vhdr, uint8_t *hash); -secbool __wur check_single_hash(const uint8_t * const hash, const uint8_t * const data, int len); +secbool __wur check_single_hash(const uint8_t *const hash, + const uint8_t *const data, int len); -secbool __wur check_image_contents(const image_header * const hdr, uint32_t firstskip, const uint8_t *sectors, int blocks); +secbool __wur check_image_contents(const image_header *const hdr, + uint32_t firstskip, const uint8_t *sectors, + int blocks); #endif diff --git a/embed/trezorhal/lowlevel.c b/embed/trezorhal/lowlevel.c index d74bb09e9..998593a19 100644 --- a/embed/trezorhal/lowlevel.c +++ b/embed/trezorhal/lowlevel.c @@ -19,151 +19,165 @@ #include STM32_HAL_H -#include "flash.h" #include "lowlevel.h" +#include "flash.h" -#pragma GCC optimize("no-stack-protector") // applies to all functions in this file +#pragma GCC optimize( \ + "no-stack-protector") // applies to all functions in this file #if PRODUCTION - #define WANT_RDP_LEVEL (OB_RDP_LEVEL_2) - #define WANT_WRP_SECTORS (OB_WRP_SECTOR_0 | OB_WRP_SECTOR_1 | OB_WRP_SECTOR_2) +#define WANT_RDP_LEVEL (OB_RDP_LEVEL_2) +#define WANT_WRP_SECTORS (OB_WRP_SECTOR_0 | OB_WRP_SECTOR_1 | OB_WRP_SECTOR_2) #else - #define WANT_RDP_LEVEL (OB_RDP_LEVEL_0) - #define WANT_WRP_SECTORS (0) +#define WANT_RDP_LEVEL (OB_RDP_LEVEL_0) +#define WANT_WRP_SECTORS (0) #endif // BOR LEVEL 3: Reset level threshold is around 2.5 V #define WANT_BOR_LEVEL (OB_BOR_LEVEL3) -// reference RM0090 section 3.9.10; SPRMOD is 0 meaning PCROP disabled.; DB1M is 0 because we use 2MB dual-bank; BFB2 is 0 allowing boot from flash; -#define FLASH_OPTCR_VALUE ( (((~WANT_WRP_SECTORS) << FLASH_OPTCR_nWRP_Pos) & FLASH_OPTCR_nWRP_Msk) | \ - (WANT_RDP_LEVEL << FLASH_OPTCR_RDP_Pos) | FLASH_OPTCR_nRST_STDBY | FLASH_OPTCR_nRST_STOP | FLASH_OPTCR_WDG_SW | WANT_BOR_LEVEL ) +// reference RM0090 section 3.9.10; SPRMOD is 0 meaning PCROP disabled.; DB1M is +// 0 because we use 2MB dual-bank; BFB2 is 0 allowing boot from flash; +#define FLASH_OPTCR_VALUE \ + ((((~WANT_WRP_SECTORS) << FLASH_OPTCR_nWRP_Pos) & FLASH_OPTCR_nWRP_Msk) | \ + (WANT_RDP_LEVEL << FLASH_OPTCR_RDP_Pos) | FLASH_OPTCR_nRST_STDBY | \ + FLASH_OPTCR_nRST_STOP | FLASH_OPTCR_WDG_SW | WANT_BOR_LEVEL) // reference RM0090 section 3.7.1 table 16 -#define OPTION_BYTES_RDP_USER_VALUE ((uint16_t) ((WANT_RDP_LEVEL << FLASH_OPTCR_RDP_Pos) | FLASH_OPTCR_nRST_STDBY | FLASH_OPTCR_nRST_STOP | FLASH_OPTCR_WDG_SW | WANT_BOR_LEVEL)) -#define OPTION_BYTES_BANK1_WRP_VALUE ((uint16_t) ((~WANT_WRP_SECTORS) & 0xFFFU)) -#define OPTION_BYTES_BANK2_WRP_VALUE ((uint16_t) 0xFFFU) - -// reference RM0090 section 3.7.1 table 16. use 16 bit pointers because the top 48 bits are all reserved. -#define OPTION_BYTES_RDP_USER (*(volatile uint16_t * const) 0x1FFFC000U) -#define OPTION_BYTES_BANK1_WRP (*(volatile uint16_t * const) 0x1FFFC008U) -#define OPTION_BYTES_BANK2_WRP (*(volatile uint16_t * const) 0x1FFEC008U) - -uint32_t flash_wait_and_clear_status_flags(void) -{ - while(FLASH->SR & FLASH_SR_BSY); // wait for all previous flash operations to complete - const uint32_t result = FLASH->SR & FLASH_STATUS_ALL_FLAGS; // get the current status flags - FLASH->SR |= FLASH_STATUS_ALL_FLAGS; // clear all status flags - return result; +#define OPTION_BYTES_RDP_USER_VALUE \ + ((uint16_t)((WANT_RDP_LEVEL << FLASH_OPTCR_RDP_Pos) | \ + FLASH_OPTCR_nRST_STDBY | FLASH_OPTCR_nRST_STOP | \ + FLASH_OPTCR_WDG_SW | WANT_BOR_LEVEL)) +#define OPTION_BYTES_BANK1_WRP_VALUE ((uint16_t)((~WANT_WRP_SECTORS) & 0xFFFU)) +#define OPTION_BYTES_BANK2_WRP_VALUE ((uint16_t)0xFFFU) + +// reference RM0090 section 3.7.1 table 16. use 16 bit pointers because the top +// 48 bits are all reserved. +#define OPTION_BYTES_RDP_USER (*(volatile uint16_t* const)0x1FFFC000U) +#define OPTION_BYTES_BANK1_WRP (*(volatile uint16_t* const)0x1FFFC008U) +#define OPTION_BYTES_BANK2_WRP (*(volatile uint16_t* const)0x1FFEC008U) + +uint32_t flash_wait_and_clear_status_flags(void) { + while (FLASH->SR & FLASH_SR_BSY) + ; // wait for all previous flash operations to complete + const uint32_t result = + FLASH->SR & FLASH_STATUS_ALL_FLAGS; // get the current status flags + FLASH->SR |= FLASH_STATUS_ALL_FLAGS; // clear all status flags + return result; } -secbool flash_check_option_bytes(void) -{ - flash_wait_and_clear_status_flags(); - // check values stored in flash interface registers - if ((FLASH->OPTCR & ~3) != FLASH_OPTCR_VALUE) { // ignore bits 0 and 1 because they are control bits - return secfalse; - } - if (FLASH->OPTCR1 != FLASH_OPTCR1_nWRP) { - return secfalse; - } - // check values stored in flash memory - if ((OPTION_BYTES_RDP_USER & ~3) != OPTION_BYTES_RDP_USER_VALUE) { // bits 0 and 1 are unused - return secfalse; - } - if ((OPTION_BYTES_BANK1_WRP & 0xCFFFU) != OPTION_BYTES_BANK1_WRP_VALUE) { // bits 12 and 13 are unused - return secfalse; - } - if ((OPTION_BYTES_BANK2_WRP & 0xFFFU) != OPTION_BYTES_BANK2_WRP_VALUE) { // bits 12, 13, 14, and 15 are unused - return secfalse; - } - return sectrue; +secbool flash_check_option_bytes(void) { + flash_wait_and_clear_status_flags(); + // check values stored in flash interface registers + if ((FLASH->OPTCR & ~3) != + FLASH_OPTCR_VALUE) { // ignore bits 0 and 1 because they are control bits + return secfalse; + } + if (FLASH->OPTCR1 != FLASH_OPTCR1_nWRP) { + return secfalse; + } + // check values stored in flash memory + if ((OPTION_BYTES_RDP_USER & ~3) != + OPTION_BYTES_RDP_USER_VALUE) { // bits 0 and 1 are unused + return secfalse; + } + if ((OPTION_BYTES_BANK1_WRP & 0xCFFFU) != + OPTION_BYTES_BANK1_WRP_VALUE) { // bits 12 and 13 are unused + return secfalse; + } + if ((OPTION_BYTES_BANK2_WRP & 0xFFFU) != + OPTION_BYTES_BANK2_WRP_VALUE) { // bits 12, 13, 14, and 15 are unused + return secfalse; + } + return sectrue; } -void flash_lock_option_bytes(void) -{ - FLASH->OPTCR |= FLASH_OPTCR_OPTLOCK; // lock the option bytes +void flash_lock_option_bytes(void) { + FLASH->OPTCR |= FLASH_OPTCR_OPTLOCK; // lock the option bytes } -void flash_unlock_option_bytes(void) -{ - if ((FLASH->OPTCR & FLASH_OPTCR_OPTLOCK) == 0) { - return; // already unlocked - } - // reference RM0090 section 3.7.2 - // write the special sequence to unlock - FLASH->OPTKEYR = FLASH_OPT_KEY1; - FLASH->OPTKEYR = FLASH_OPT_KEY2; - while (FLASH->OPTCR & FLASH_OPTCR_OPTLOCK); // wait until the flash option control register is unlocked +void flash_unlock_option_bytes(void) { + if ((FLASH->OPTCR & FLASH_OPTCR_OPTLOCK) == 0) { + return; // already unlocked + } + // reference RM0090 section 3.7.2 + // write the special sequence to unlock + FLASH->OPTKEYR = FLASH_OPT_KEY1; + FLASH->OPTKEYR = FLASH_OPT_KEY2; + while (FLASH->OPTCR & FLASH_OPTCR_OPTLOCK) + ; // wait until the flash option control register is unlocked } -uint32_t flash_set_option_bytes(void) -{ - // reference RM0090 section 3.7.2 - flash_wait_and_clear_status_flags(); - flash_unlock_option_bytes(); - flash_wait_and_clear_status_flags(); - FLASH->OPTCR1 = FLASH_OPTCR1_nWRP; // no write protection on any sectors in bank 2 - FLASH->OPTCR = FLASH_OPTCR_VALUE; // WARNING: dev board safe unless you compile for PRODUCTION or change this value!!! - FLASH->OPTCR |= FLASH_OPTCR_OPTSTRT; // begin committing changes to flash - const uint32_t result = flash_wait_and_clear_status_flags(); // wait until changes are committed - flash_lock_option_bytes(); - return result; +uint32_t flash_set_option_bytes(void) { + // reference RM0090 section 3.7.2 + flash_wait_and_clear_status_flags(); + flash_unlock_option_bytes(); + flash_wait_and_clear_status_flags(); + FLASH->OPTCR1 = + FLASH_OPTCR1_nWRP; // no write protection on any sectors in bank 2 + FLASH->OPTCR = + FLASH_OPTCR_VALUE; // WARNING: dev board safe unless you compile for + // PRODUCTION or change this value!!! + FLASH->OPTCR |= FLASH_OPTCR_OPTSTRT; // begin committing changes to flash + const uint32_t result = + flash_wait_and_clear_status_flags(); // wait until changes are committed + flash_lock_option_bytes(); + return result; } -secbool flash_configure_option_bytes(void) -{ - if (sectrue == flash_check_option_bytes()) { - return sectrue; // we DID NOT have to change the option bytes - } +secbool flash_configure_option_bytes(void) { + if (sectrue == flash_check_option_bytes()) { + return sectrue; // we DID NOT have to change the option bytes + } - do { - flash_set_option_bytes(); - } while(sectrue != flash_check_option_bytes()); + do { + flash_set_option_bytes(); + } while (sectrue != flash_check_option_bytes()); - return secfalse; // notify that we DID have to change the option bytes + return secfalse; // notify that we DID have to change the option bytes } -void periph_init(void) -{ - // STM32F4xx HAL library initialization: - // - configure the Flash prefetch, instruction and data caches - // - configure the Systick to generate an interrupt each 1 msec - // - set NVIC Group Priority to 4 - // - global MSP (MCU Support Package) initialization - HAL_Init(); - - // Enable GPIO clocks - __HAL_RCC_GPIOA_CLK_ENABLE(); - __HAL_RCC_GPIOB_CLK_ENABLE(); - __HAL_RCC_GPIOC_CLK_ENABLE(); - __HAL_RCC_GPIOD_CLK_ENABLE(); - - // enable the PVD (programmable voltage detector). - // select the "2.7V" threshold (level 5). - // this detector will be active regardless of the - // flash option byte BOR setting. - __HAL_RCC_PWR_CLK_ENABLE(); - PWR_PVDTypeDef pvd_config; - pvd_config.PVDLevel = PWR_PVDLEVEL_5; - pvd_config.Mode = PWR_PVD_MODE_IT_RISING_FALLING; - HAL_PWR_ConfigPVD(&pvd_config); - HAL_PWR_EnablePVD(); - NVIC_EnableIRQ(PVD_IRQn); +void periph_init(void) { + // STM32F4xx HAL library initialization: + // - configure the Flash prefetch, instruction and data caches + // - configure the Systick to generate an interrupt each 1 msec + // - set NVIC Group Priority to 4 + // - global MSP (MCU Support Package) initialization + HAL_Init(); + + // Enable GPIO clocks + __HAL_RCC_GPIOA_CLK_ENABLE(); + __HAL_RCC_GPIOB_CLK_ENABLE(); + __HAL_RCC_GPIOC_CLK_ENABLE(); + __HAL_RCC_GPIOD_CLK_ENABLE(); + + // enable the PVD (programmable voltage detector). + // select the "2.7V" threshold (level 5). + // this detector will be active regardless of the + // flash option byte BOR setting. + __HAL_RCC_PWR_CLK_ENABLE(); + PWR_PVDTypeDef pvd_config; + pvd_config.PVDLevel = PWR_PVDLEVEL_5; + pvd_config.Mode = PWR_PVD_MODE_IT_RISING_FALLING; + HAL_PWR_ConfigPVD(&pvd_config); + HAL_PWR_EnablePVD(); + NVIC_EnableIRQ(PVD_IRQn); } -secbool reset_flags_check(void) -{ +secbool reset_flags_check(void) { #if PRODUCTION - // this is effective enough that it makes development painful, so only use it for production. - // check the reset flags to assure that we arrive here due to a regular full power-on event, - // and not as a result of a lesser reset. - if ((RCC->CSR & (RCC_CSR_LPWRRSTF | RCC_CSR_WWDGRSTF | RCC_CSR_IWDGRSTF | RCC_CSR_SFTRSTF | RCC_CSR_PORRSTF | RCC_CSR_PINRSTF | RCC_CSR_BORRSTF)) != (RCC_CSR_PORRSTF | RCC_CSR_PINRSTF | RCC_CSR_BORRSTF)) { - return secfalse; - } + // this is effective enough that it makes development painful, so only use it + // for production. check the reset flags to assure that we arrive here due to + // a regular full power-on event, and not as a result of a lesser reset. + if ((RCC->CSR & (RCC_CSR_LPWRRSTF | RCC_CSR_WWDGRSTF | RCC_CSR_IWDGRSTF | + RCC_CSR_SFTRSTF | RCC_CSR_PORRSTF | RCC_CSR_PINRSTF | + RCC_CSR_BORRSTF)) != + (RCC_CSR_PORRSTF | RCC_CSR_PINRSTF | RCC_CSR_BORRSTF)) { + return secfalse; + } #endif - RCC->CSR |= RCC_CSR_RMVF; // clear the reset flags + RCC->CSR |= RCC_CSR_RMVF; // clear the reset flags - return sectrue; + return sectrue; } diff --git a/embed/trezorhal/lowlevel.h b/embed/trezorhal/lowlevel.h index e9665e7d1..f9bac6a4f 100644 --- a/embed/trezorhal/lowlevel.h +++ b/embed/trezorhal/lowlevel.h @@ -31,4 +31,4 @@ secbool flash_configure_option_bytes(void); void periph_init(void); secbool reset_flags_check(void); -#endif // __TREZORHAL_LOWLEVEL_H__ +#endif // __TREZORHAL_LOWLEVEL_H__ diff --git a/embed/trezorhal/mini_printf.c b/embed/trezorhal/mini_printf.c index 69a5848e4..eb340c91a 100644 --- a/embed/trezorhal/mini_printf.c +++ b/embed/trezorhal/mini_printf.c @@ -1,3 +1,5 @@ +// clang-format off + /* * The Minimal snprintf() implementation * diff --git a/embed/trezorhal/mini_printf.h b/embed/trezorhal/mini_printf.h index 92f982ed1..b3a21eab1 100644 --- a/embed/trezorhal/mini_printf.h +++ b/embed/trezorhal/mini_printf.h @@ -1,3 +1,5 @@ +// clang-format off + /* * The Minimal snprintf() implementation * diff --git a/embed/trezorhal/mpu.c b/embed/trezorhal/mpu.c index 03effbb85..55d6372fe 100644 --- a/embed/trezorhal/mpu.c +++ b/embed/trezorhal/mpu.c @@ -21,126 +21,151 @@ #include "stm32f4xx_ll_cortex.h" // http://infocenter.arm.com/help/topic/com.arm.doc.dui0552a/BABDJJGF.html -#define MPU_RASR_ATTR_FLASH (MPU_RASR_C_Msk) -#define MPU_RASR_ATTR_SRAM (MPU_RASR_C_Msk | MPU_RASR_S_Msk) +#define MPU_RASR_ATTR_FLASH (MPU_RASR_C_Msk) +#define MPU_RASR_ATTR_SRAM (MPU_RASR_C_Msk | MPU_RASR_S_Msk) #define MPU_RASR_ATTR_PERIPH (MPU_RASR_B_Msk | MPU_RASR_S_Msk) #define MPU_SUBREGION_DISABLE(X) ((X) << MPU_RASR_SRD_Pos) -void mpu_config_off(void) -{ - // Disable MPU - HAL_MPU_Disable(); +void mpu_config_off(void) { + // Disable MPU + HAL_MPU_Disable(); } -void mpu_config_bootloader(void) -{ - // Disable MPU - HAL_MPU_Disable(); - - // Note: later entries overwrite previous ones - - // Everything (0x00000000 - 0xFFFFFFFF, 4 GiB, read-write) - MPU->RNR = MPU_REGION_NUMBER0; - MPU->RBAR = 0; - MPU->RASR = MPU_RASR_ENABLE_Msk | MPU_RASR_ATTR_FLASH | LL_MPU_REGION_SIZE_4GB | LL_MPU_REGION_FULL_ACCESS; - - // Flash (0x0800C000 - 0x0800FFFF, 16 KiB, no access) - MPU->RNR = MPU_REGION_NUMBER1; - MPU->RBAR = FLASH_BASE + 0xC000; - MPU->RASR = MPU_RASR_ENABLE_Msk | MPU_RASR_ATTR_FLASH | LL_MPU_REGION_SIZE_16KB | LL_MPU_REGION_NO_ACCESS; - - // Flash (0x0810C000 - 0x0810FFFF, 16 KiB, no access) - MPU->RNR = MPU_REGION_NUMBER2; - MPU->RBAR = FLASH_BASE + 0x10C000; - MPU->RASR = MPU_RASR_ENABLE_Msk | MPU_RASR_ATTR_FLASH | LL_MPU_REGION_SIZE_16KB | LL_MPU_REGION_NO_ACCESS; - - // SRAM (0x20000000 - 0x2002FFFF, 192 KiB = 256 KiB except 2/8 at end, read-write, execute never) - MPU->RNR = MPU_REGION_NUMBER3; - MPU->RBAR = SRAM_BASE; - MPU->RASR = MPU_RASR_ENABLE_Msk | MPU_RASR_ATTR_SRAM | LL_MPU_REGION_SIZE_256KB | LL_MPU_REGION_FULL_ACCESS | MPU_RASR_XN_Msk | MPU_SUBREGION_DISABLE(0xC0); - - // Peripherals (0x40000000 - 0x5FFFFFFF, read-write, execute never) - // External RAM (0x60000000 - 0x7FFFFFFF, read-write, execute never) - MPU->RNR = MPU_REGION_NUMBER4; - MPU->RBAR = PERIPH_BASE; - MPU->RASR = MPU_RASR_ENABLE_Msk | MPU_RASR_ATTR_PERIPH | LL_MPU_REGION_SIZE_1GB | LL_MPU_REGION_FULL_ACCESS | MPU_RASR_XN_Msk; +void mpu_config_bootloader(void) { + // Disable MPU + HAL_MPU_Disable(); + + // Note: later entries overwrite previous ones + + // Everything (0x00000000 - 0xFFFFFFFF, 4 GiB, read-write) + MPU->RNR = MPU_REGION_NUMBER0; + MPU->RBAR = 0; + MPU->RASR = MPU_RASR_ENABLE_Msk | MPU_RASR_ATTR_FLASH | + LL_MPU_REGION_SIZE_4GB | LL_MPU_REGION_FULL_ACCESS; + + // Flash (0x0800C000 - 0x0800FFFF, 16 KiB, no access) + MPU->RNR = MPU_REGION_NUMBER1; + MPU->RBAR = FLASH_BASE + 0xC000; + MPU->RASR = MPU_RASR_ENABLE_Msk | MPU_RASR_ATTR_FLASH | + LL_MPU_REGION_SIZE_16KB | LL_MPU_REGION_NO_ACCESS; + + // Flash (0x0810C000 - 0x0810FFFF, 16 KiB, no access) + MPU->RNR = MPU_REGION_NUMBER2; + MPU->RBAR = FLASH_BASE + 0x10C000; + MPU->RASR = MPU_RASR_ENABLE_Msk | MPU_RASR_ATTR_FLASH | + LL_MPU_REGION_SIZE_16KB | LL_MPU_REGION_NO_ACCESS; + + // SRAM (0x20000000 - 0x2002FFFF, 192 KiB = 256 KiB except 2/8 at end, + // read-write, execute never) + MPU->RNR = MPU_REGION_NUMBER3; + MPU->RBAR = SRAM_BASE; + MPU->RASR = MPU_RASR_ENABLE_Msk | MPU_RASR_ATTR_SRAM | + LL_MPU_REGION_SIZE_256KB | LL_MPU_REGION_FULL_ACCESS | + MPU_RASR_XN_Msk | MPU_SUBREGION_DISABLE(0xC0); + + // Peripherals (0x40000000 - 0x5FFFFFFF, read-write, execute never) + // External RAM (0x60000000 - 0x7FFFFFFF, read-write, execute never) + MPU->RNR = MPU_REGION_NUMBER4; + MPU->RBAR = PERIPH_BASE; + MPU->RASR = MPU_RASR_ENABLE_Msk | MPU_RASR_ATTR_PERIPH | + LL_MPU_REGION_SIZE_1GB | LL_MPU_REGION_FULL_ACCESS | + MPU_RASR_XN_Msk; #ifdef STM32F427xx - // CCMRAM (0x10000000 - 0x1000FFFF, read-write, execute never) - MPU->RNR = MPU_REGION_NUMBER5; - MPU->RBAR = CCMDATARAM_BASE; - MPU->RASR = MPU_RASR_ENABLE_Msk | MPU_RASR_ATTR_SRAM | LL_MPU_REGION_SIZE_64KB | LL_MPU_REGION_FULL_ACCESS | MPU_RASR_XN_Msk; + // CCMRAM (0x10000000 - 0x1000FFFF, read-write, execute never) + MPU->RNR = MPU_REGION_NUMBER5; + MPU->RBAR = CCMDATARAM_BASE; + MPU->RASR = MPU_RASR_ENABLE_Msk | MPU_RASR_ATTR_SRAM | + LL_MPU_REGION_SIZE_64KB | LL_MPU_REGION_FULL_ACCESS | + MPU_RASR_XN_Msk; #elif STM32F405xx - // no CCMRAM + // no CCMRAM #else #error Unsupported MCU #endif - // Enable MPU - HAL_MPU_Enable(LL_MPU_CTRL_HARDFAULT_NMI); + // Enable MPU + HAL_MPU_Enable(LL_MPU_CTRL_HARDFAULT_NMI); } - -void mpu_config_firmware(void) -{ - // Disable MPU - HAL_MPU_Disable(); - - // Note: later entries overwrite previous ones - -/* - // Boardloader (0x08000000 - 0x0800FFFF, 64 KiB, read-only, execute never) - MPU->RBAR = FLASH_BASE | MPU_REGION_NUMBER0; - MPU->RASR = MPU_RASR_ENABLE_Msk | MPU_RASR_ATTR_FLASH | LL_MPU_REGION_SIZE_64KB | LL_MPU_REGION_PRIV_RO_URO | MPU_RASR_XN_Msk; -*/ - - // Bootloader (0x08020000 - 0x0803FFFF, 64 KiB, read-only) - MPU->RNR = MPU_REGION_NUMBER0; - MPU->RBAR = FLASH_BASE + 0x20000; - MPU->RASR = MPU_RASR_ENABLE_Msk | MPU_RASR_ATTR_FLASH | LL_MPU_REGION_SIZE_64KB | LL_MPU_REGION_PRIV_RO_URO; - - // Storage#1 (0x08010000 - 0x0801FFFF, 64 KiB, read-write, execute never) - MPU->RNR = MPU_REGION_NUMBER1; - MPU->RBAR = FLASH_BASE + 0x10000; - MPU->RASR = MPU_RASR_ENABLE_Msk | MPU_RASR_ATTR_FLASH | LL_MPU_REGION_SIZE_64KB | LL_MPU_REGION_FULL_ACCESS | MPU_RASR_XN_Msk; - // Storage#2 (0x08110000 - 0x0811FFFF, 64 KiB, read-write, execute never) - MPU->RNR = MPU_REGION_NUMBER2; - MPU->RBAR = FLASH_BASE + 0x110000; - MPU->RASR = MPU_RASR_ENABLE_Msk | MPU_RASR_ATTR_FLASH | LL_MPU_REGION_SIZE_64KB | LL_MPU_REGION_FULL_ACCESS | MPU_RASR_XN_Msk; - - // Firmware (0x08040000 - 0x080FFFFF, 6 * 128 KiB = 1024 KiB except 2/8 at start = 768 KiB, read-only) - MPU->RNR = MPU_REGION_NUMBER3; - MPU->RBAR = FLASH_BASE; - MPU->RASR = MPU_RASR_ENABLE_Msk | MPU_RASR_ATTR_FLASH | LL_MPU_REGION_SIZE_1MB | LL_MPU_REGION_PRIV_RO_URO | MPU_SUBREGION_DISABLE(0x03); - - // Firmware extra (0x08120000 - 0x081FFFFF, 7 * 128 KiB = 1024 KiB except 1/8 at start = 896 KiB, read-only) - MPU->RNR = MPU_REGION_NUMBER4; - MPU->RBAR = FLASH_BASE + 0x100000; - MPU->RASR = MPU_RASR_ENABLE_Msk | MPU_RASR_ATTR_FLASH | LL_MPU_REGION_SIZE_1MB | LL_MPU_REGION_PRIV_RO_URO | MPU_SUBREGION_DISABLE(0x01); - - // SRAM (0x20000000 - 0x2002FFFF, 192 KiB = 256 KiB except 2/8 at end, read-write, execute never) - MPU->RNR = MPU_REGION_NUMBER5; - MPU->RBAR = SRAM_BASE; - MPU->RASR = MPU_RASR_ENABLE_Msk | MPU_RASR_ATTR_SRAM | LL_MPU_REGION_SIZE_256KB | LL_MPU_REGION_FULL_ACCESS | MPU_RASR_XN_Msk | MPU_SUBREGION_DISABLE(0xC0); - - // Peripherals (0x40000000 - 0x5FFFFFFF, read-write, execute never) - // External RAM (0x60000000 - 0x7FFFFFFF, read-write, execute never) - MPU->RNR = MPU_REGION_NUMBER6; - MPU->RBAR = PERIPH_BASE; - MPU->RASR = MPU_RASR_ENABLE_Msk | MPU_RASR_ATTR_PERIPH | LL_MPU_REGION_SIZE_1GB | LL_MPU_REGION_FULL_ACCESS | MPU_RASR_XN_Msk; +void mpu_config_firmware(void) { + // Disable MPU + HAL_MPU_Disable(); + + // Note: later entries overwrite previous ones + + /* + // Boardloader (0x08000000 - 0x0800FFFF, 64 KiB, read-only, execute never) + MPU->RBAR = FLASH_BASE | MPU_REGION_NUMBER0; + MPU->RASR = MPU_RASR_ENABLE_Msk | MPU_RASR_ATTR_FLASH | + LL_MPU_REGION_SIZE_64KB | LL_MPU_REGION_PRIV_RO_URO | MPU_RASR_XN_Msk; + */ + + // Bootloader (0x08020000 - 0x0803FFFF, 64 KiB, read-only) + MPU->RNR = MPU_REGION_NUMBER0; + MPU->RBAR = FLASH_BASE + 0x20000; + MPU->RASR = MPU_RASR_ENABLE_Msk | MPU_RASR_ATTR_FLASH | + LL_MPU_REGION_SIZE_64KB | LL_MPU_REGION_PRIV_RO_URO; + + // Storage#1 (0x08010000 - 0x0801FFFF, 64 KiB, read-write, execute never) + MPU->RNR = MPU_REGION_NUMBER1; + MPU->RBAR = FLASH_BASE + 0x10000; + MPU->RASR = MPU_RASR_ENABLE_Msk | MPU_RASR_ATTR_FLASH | + LL_MPU_REGION_SIZE_64KB | LL_MPU_REGION_FULL_ACCESS | + MPU_RASR_XN_Msk; + // Storage#2 (0x08110000 - 0x0811FFFF, 64 KiB, read-write, execute never) + MPU->RNR = MPU_REGION_NUMBER2; + MPU->RBAR = FLASH_BASE + 0x110000; + MPU->RASR = MPU_RASR_ENABLE_Msk | MPU_RASR_ATTR_FLASH | + LL_MPU_REGION_SIZE_64KB | LL_MPU_REGION_FULL_ACCESS | + MPU_RASR_XN_Msk; + + // Firmware (0x08040000 - 0x080FFFFF, 6 * 128 KiB = 1024 KiB except 2/8 at + // start = 768 KiB, read-only) + MPU->RNR = MPU_REGION_NUMBER3; + MPU->RBAR = FLASH_BASE; + MPU->RASR = MPU_RASR_ENABLE_Msk | MPU_RASR_ATTR_FLASH | + LL_MPU_REGION_SIZE_1MB | LL_MPU_REGION_PRIV_RO_URO | + MPU_SUBREGION_DISABLE(0x03); + + // Firmware extra (0x08120000 - 0x081FFFFF, 7 * 128 KiB = 1024 KiB except 1/8 + // at start = 896 KiB, read-only) + MPU->RNR = MPU_REGION_NUMBER4; + MPU->RBAR = FLASH_BASE + 0x100000; + MPU->RASR = MPU_RASR_ENABLE_Msk | MPU_RASR_ATTR_FLASH | + LL_MPU_REGION_SIZE_1MB | LL_MPU_REGION_PRIV_RO_URO | + MPU_SUBREGION_DISABLE(0x01); + + // SRAM (0x20000000 - 0x2002FFFF, 192 KiB = 256 KiB except 2/8 at end, + // read-write, execute never) + MPU->RNR = MPU_REGION_NUMBER5; + MPU->RBAR = SRAM_BASE; + MPU->RASR = MPU_RASR_ENABLE_Msk | MPU_RASR_ATTR_SRAM | + LL_MPU_REGION_SIZE_256KB | LL_MPU_REGION_FULL_ACCESS | + MPU_RASR_XN_Msk | MPU_SUBREGION_DISABLE(0xC0); + + // Peripherals (0x40000000 - 0x5FFFFFFF, read-write, execute never) + // External RAM (0x60000000 - 0x7FFFFFFF, read-write, execute never) + MPU->RNR = MPU_REGION_NUMBER6; + MPU->RBAR = PERIPH_BASE; + MPU->RASR = MPU_RASR_ENABLE_Msk | MPU_RASR_ATTR_PERIPH | + LL_MPU_REGION_SIZE_1GB | LL_MPU_REGION_FULL_ACCESS | + MPU_RASR_XN_Msk; #ifdef STM32F427xx - // CCMRAM (0x10000000 - 0x1000FFFF, read-write, execute never) - MPU->RNR = MPU_REGION_NUMBER7; - MPU->RBAR = CCMDATARAM_BASE; - MPU->RASR = MPU_RASR_ENABLE_Msk | MPU_RASR_ATTR_SRAM | LL_MPU_REGION_SIZE_64KB | LL_MPU_REGION_FULL_ACCESS | MPU_RASR_XN_Msk; + // CCMRAM (0x10000000 - 0x1000FFFF, read-write, execute never) + MPU->RNR = MPU_REGION_NUMBER7; + MPU->RBAR = CCMDATARAM_BASE; + MPU->RASR = MPU_RASR_ENABLE_Msk | MPU_RASR_ATTR_SRAM | + LL_MPU_REGION_SIZE_64KB | LL_MPU_REGION_FULL_ACCESS | + MPU_RASR_XN_Msk; #elif STM32F405xx - // no CCMRAM + // no CCMRAM #else #error Unsupported MCU #endif - // Enable MPU - HAL_MPU_Enable(LL_MPU_CTRL_HARDFAULT_NMI); + // Enable MPU + HAL_MPU_Enable(LL_MPU_CTRL_HARDFAULT_NMI); } diff --git a/embed/trezorhal/rng.c b/embed/trezorhal/rng.c index f01c695f7..136b17d34 100644 --- a/embed/trezorhal/rng.c +++ b/embed/trezorhal/rng.c @@ -21,36 +21,38 @@ #include "rng.h" -#pragma GCC optimize("no-stack-protector") // applies to all functions in this file +#pragma GCC optimize( \ + "no-stack-protector") // applies to all functions in this file -void rng_init(void) -{ - // enable TRNG peripheral clock - // use the HAL version due to section 2.1.6 of STM32F42xx Errata sheet - // "Delay after an RCC peripheral clock enabling" - __HAL_RCC_RNG_CLK_ENABLE(); - RNG->CR = RNG_CR_RNGEN; // enable TRNG +void rng_init(void) { + // enable TRNG peripheral clock + // use the HAL version due to section 2.1.6 of STM32F42xx Errata sheet + // "Delay after an RCC peripheral clock enabling" + __HAL_RCC_RNG_CLK_ENABLE(); + RNG->CR = RNG_CR_RNGEN; // enable TRNG } -uint32_t rng_read(const uint32_t previous, const uint32_t compare_previous) -{ - uint32_t temp = previous; - do { - while ((RNG->SR & (RNG_SR_SECS | RNG_SR_CECS | RNG_SR_DRDY)) != RNG_SR_DRDY); // wait until TRNG is ready - temp = RNG->DR; // read the data from the TRNG - } while (compare_previous && (temp == previous)); // RM0090 section 24.3.1 FIPS continuous random number generator test - return temp; +uint32_t rng_read(const uint32_t previous, const uint32_t compare_previous) { + uint32_t temp = previous; + do { + while ((RNG->SR & (RNG_SR_SECS | RNG_SR_CECS | RNG_SR_DRDY)) != RNG_SR_DRDY) + ; // wait until TRNG is ready + temp = RNG->DR; // read the data from the TRNG + } while (compare_previous && + (temp == previous)); // RM0090 section 24.3.1 FIPS continuous random + // number generator test + return temp; } -uint32_t rng_get(void) -{ - // reason for keeping history: RM0090 section 24.3.1 FIPS continuous random number generator test - static uint32_t previous = 0, current = 0; - if (previous == current) { - previous = rng_read(previous, 0); - } else { - previous = current; - } - current = rng_read(previous, 1); - return current; +uint32_t rng_get(void) { + // reason for keeping history: RM0090 section 24.3.1 FIPS continuous random + // number generator test + static uint32_t previous = 0, current = 0; + if (previous == current) { + previous = rng_read(previous, 0); + } else { + previous = current; + } + current = rng_read(previous, 1); + return current; } diff --git a/embed/trezorhal/sbu.c b/embed/trezorhal/sbu.c index 4caf201eb..4eb71f3e5 100644 --- a/embed/trezorhal/sbu.c +++ b/embed/trezorhal/sbu.c @@ -22,20 +22,22 @@ #include "sbu.h" void sbu_init(void) { - GPIO_InitTypeDef GPIO_InitStructure; + GPIO_InitTypeDef GPIO_InitStructure; - // SBU1/PA2 SBU2/PA3 - GPIO_InitStructure.Pin = GPIO_PIN_2 | GPIO_PIN_3; - GPIO_InitStructure.Mode = GPIO_MODE_OUTPUT_PP; - GPIO_InitStructure.Pull = GPIO_NOPULL; - GPIO_InitStructure.Speed = GPIO_SPEED_FREQ_VERY_HIGH; - HAL_GPIO_Init(GPIOA, &GPIO_InitStructure); + // SBU1/PA2 SBU2/PA3 + GPIO_InitStructure.Pin = GPIO_PIN_2 | GPIO_PIN_3; + GPIO_InitStructure.Mode = GPIO_MODE_OUTPUT_PP; + GPIO_InitStructure.Pull = GPIO_NOPULL; + GPIO_InitStructure.Speed = GPIO_SPEED_FREQ_VERY_HIGH; + HAL_GPIO_Init(GPIOA, &GPIO_InitStructure); - HAL_GPIO_WritePin(GPIOA, GPIO_PIN_2, GPIO_PIN_RESET); - HAL_GPIO_WritePin(GPIOA, GPIO_PIN_3, GPIO_PIN_RESET); + HAL_GPIO_WritePin(GPIOA, GPIO_PIN_2, GPIO_PIN_RESET); + HAL_GPIO_WritePin(GPIOA, GPIO_PIN_3, GPIO_PIN_RESET); } void sbu_set(secbool sbu1, secbool sbu2) { - HAL_GPIO_WritePin(GPIOA, GPIO_PIN_2, sbu1 == sectrue ? GPIO_PIN_SET : GPIO_PIN_RESET); - HAL_GPIO_WritePin(GPIOA, GPIO_PIN_3, sbu2 == sectrue ? GPIO_PIN_SET : GPIO_PIN_RESET); + HAL_GPIO_WritePin(GPIOA, GPIO_PIN_2, + sbu1 == sectrue ? GPIO_PIN_SET : GPIO_PIN_RESET); + HAL_GPIO_WritePin(GPIOA, GPIO_PIN_3, + sbu2 == sectrue ? GPIO_PIN_SET : GPIO_PIN_RESET); } diff --git a/embed/trezorhal/sdcard.c b/embed/trezorhal/sdcard.c index 8bb7b362f..53ebff0ce 100644 --- a/embed/trezorhal/sdcard.c +++ b/embed/trezorhal/sdcard.c @@ -52,198 +52,202 @@ static SD_HandleTypeDef sd_handle; static inline void sdcard_default_pin_state(void) { - HAL_GPIO_WritePin(GPIOC, GPIO_PIN_0, GPIO_PIN_SET); // SD_ON/PC0 - HAL_GPIO_WritePin(GPIOC, GPIO_PIN_8, GPIO_PIN_RESET); // SD_DAT0/PC8 - HAL_GPIO_WritePin(GPIOC, GPIO_PIN_9, GPIO_PIN_RESET); // SD_DAT1/PC9 - HAL_GPIO_WritePin(GPIOC, GPIO_PIN_10, GPIO_PIN_RESET); // SD_DAT2/PC10 - HAL_GPIO_WritePin(GPIOC, GPIO_PIN_11, GPIO_PIN_RESET); // SD_DAT3/PC11 - HAL_GPIO_WritePin(GPIOC, GPIO_PIN_12, GPIO_PIN_RESET); // SD_CLK/PC12 - HAL_GPIO_WritePin(GPIOD, GPIO_PIN_2, GPIO_PIN_RESET); // SD_CMD/PD2 - - GPIO_InitTypeDef GPIO_InitStructure; - - // configure the SD card circuitry on/off pin - GPIO_InitStructure.Mode = GPIO_MODE_OUTPUT_PP; - GPIO_InitStructure.Pull = GPIO_NOPULL; - GPIO_InitStructure.Speed = GPIO_SPEED_FREQ_LOW; - GPIO_InitStructure.Pin = GPIO_PIN_0; - HAL_GPIO_Init(GPIOC, &GPIO_InitStructure); - - // configure SD GPIO - GPIO_InitStructure.Mode = GPIO_MODE_OUTPUT_PP; - GPIO_InitStructure.Pull = GPIO_NOPULL; - GPIO_InitStructure.Speed = GPIO_SPEED_FREQ_LOW; - GPIO_InitStructure.Pin = GPIO_PIN_8 | GPIO_PIN_9 | GPIO_PIN_10 | GPIO_PIN_11 | GPIO_PIN_12; - HAL_GPIO_Init(GPIOC, &GPIO_InitStructure); - GPIO_InitStructure.Pin = GPIO_PIN_2; - HAL_GPIO_Init(GPIOD, &GPIO_InitStructure); - - // configure the SD card detect pin - GPIO_InitStructure.Mode = GPIO_MODE_INPUT; - GPIO_InitStructure.Pull = GPIO_PULLUP; - GPIO_InitStructure.Speed = GPIO_SPEED_FREQ_LOW; - GPIO_InitStructure.Pin = GPIO_PIN_13; - HAL_GPIO_Init(GPIOC, &GPIO_InitStructure); + HAL_GPIO_WritePin(GPIOC, GPIO_PIN_0, GPIO_PIN_SET); // SD_ON/PC0 + HAL_GPIO_WritePin(GPIOC, GPIO_PIN_8, GPIO_PIN_RESET); // SD_DAT0/PC8 + HAL_GPIO_WritePin(GPIOC, GPIO_PIN_9, GPIO_PIN_RESET); // SD_DAT1/PC9 + HAL_GPIO_WritePin(GPIOC, GPIO_PIN_10, GPIO_PIN_RESET); // SD_DAT2/PC10 + HAL_GPIO_WritePin(GPIOC, GPIO_PIN_11, GPIO_PIN_RESET); // SD_DAT3/PC11 + HAL_GPIO_WritePin(GPIOC, GPIO_PIN_12, GPIO_PIN_RESET); // SD_CLK/PC12 + HAL_GPIO_WritePin(GPIOD, GPIO_PIN_2, GPIO_PIN_RESET); // SD_CMD/PD2 + + GPIO_InitTypeDef GPIO_InitStructure; + + // configure the SD card circuitry on/off pin + GPIO_InitStructure.Mode = GPIO_MODE_OUTPUT_PP; + GPIO_InitStructure.Pull = GPIO_NOPULL; + GPIO_InitStructure.Speed = GPIO_SPEED_FREQ_LOW; + GPIO_InitStructure.Pin = GPIO_PIN_0; + HAL_GPIO_Init(GPIOC, &GPIO_InitStructure); + + // configure SD GPIO + GPIO_InitStructure.Mode = GPIO_MODE_OUTPUT_PP; + GPIO_InitStructure.Pull = GPIO_NOPULL; + GPIO_InitStructure.Speed = GPIO_SPEED_FREQ_LOW; + GPIO_InitStructure.Pin = + GPIO_PIN_8 | GPIO_PIN_9 | GPIO_PIN_10 | GPIO_PIN_11 | GPIO_PIN_12; + HAL_GPIO_Init(GPIOC, &GPIO_InitStructure); + GPIO_InitStructure.Pin = GPIO_PIN_2; + HAL_GPIO_Init(GPIOD, &GPIO_InitStructure); + + // configure the SD card detect pin + GPIO_InitStructure.Mode = GPIO_MODE_INPUT; + GPIO_InitStructure.Pull = GPIO_PULLUP; + GPIO_InitStructure.Speed = GPIO_SPEED_FREQ_LOW; + GPIO_InitStructure.Pin = GPIO_PIN_13; + HAL_GPIO_Init(GPIOC, &GPIO_InitStructure); } static inline void sdcard_active_pin_state(void) { - HAL_GPIO_WritePin(GPIOC, GPIO_PIN_0, GPIO_PIN_RESET); // SD_ON/PC0 - HAL_Delay(10); // we need to wait until the circuit fully kicks-in - - GPIO_InitTypeDef GPIO_InitStructure; - - // configure SD GPIO - GPIO_InitStructure.Mode = GPIO_MODE_AF_PP; - GPIO_InitStructure.Pull = GPIO_PULLUP; - GPIO_InitStructure.Speed = GPIO_SPEED_FREQ_VERY_HIGH; - GPIO_InitStructure.Alternate = GPIO_AF12_SDIO; - GPIO_InitStructure.Pin = GPIO_PIN_8 | GPIO_PIN_9 | GPIO_PIN_10 | GPIO_PIN_11 | GPIO_PIN_12; - HAL_GPIO_Init(GPIOC, &GPIO_InitStructure); - GPIO_InitStructure.Pin = GPIO_PIN_2; - HAL_GPIO_Init(GPIOD, &GPIO_InitStructure); + HAL_GPIO_WritePin(GPIOC, GPIO_PIN_0, GPIO_PIN_RESET); // SD_ON/PC0 + HAL_Delay(10); // we need to wait until the circuit fully kicks-in + + GPIO_InitTypeDef GPIO_InitStructure; + + // configure SD GPIO + GPIO_InitStructure.Mode = GPIO_MODE_AF_PP; + GPIO_InitStructure.Pull = GPIO_PULLUP; + GPIO_InitStructure.Speed = GPIO_SPEED_FREQ_VERY_HIGH; + GPIO_InitStructure.Alternate = GPIO_AF12_SDIO; + GPIO_InitStructure.Pin = + GPIO_PIN_8 | GPIO_PIN_9 | GPIO_PIN_10 | GPIO_PIN_11 | GPIO_PIN_12; + HAL_GPIO_Init(GPIOC, &GPIO_InitStructure); + GPIO_InitStructure.Pin = GPIO_PIN_2; + HAL_GPIO_Init(GPIOD, &GPIO_InitStructure); } -void sdcard_init(void) { - sdcard_default_pin_state(); -} +void sdcard_init(void) { sdcard_default_pin_state(); } void HAL_SD_MspInit(SD_HandleTypeDef *hsd) { - // enable SDIO clock - __HAL_RCC_SDIO_CLK_ENABLE(); - // GPIO have already been initialised by sdcard_init + // enable SDIO clock + __HAL_RCC_SDIO_CLK_ENABLE(); + // GPIO have already been initialised by sdcard_init } -void HAL_SD_MspDeInit(SD_HandleTypeDef *hsd) { - __HAL_RCC_SDIO_CLK_DISABLE(); -} +void HAL_SD_MspDeInit(SD_HandleTypeDef *hsd) { __HAL_RCC_SDIO_CLK_DISABLE(); } secbool sdcard_power_on(void) { - if (sectrue != sdcard_is_present()) { - return secfalse; - } - if (sd_handle.Instance) { - return sectrue; + if (sectrue != sdcard_is_present()) { + return secfalse; + } + if (sd_handle.Instance) { + return sectrue; + } + // turn on SD card circuitry + sdcard_active_pin_state(); + HAL_Delay(50); + + // SD device interface configuration + sd_handle.Instance = SDIO; + sd_handle.Init.ClockEdge = SDIO_CLOCK_EDGE_RISING; + sd_handle.Init.ClockBypass = SDIO_CLOCK_BYPASS_DISABLE; + sd_handle.Init.ClockPowerSave = SDIO_CLOCK_POWER_SAVE_ENABLE; + sd_handle.Init.BusWide = SDIO_BUS_WIDE_1B; + sd_handle.Init.HardwareFlowControl = SDIO_HARDWARE_FLOW_CONTROL_DISABLE; + sd_handle.Init.ClockDiv = SDIO_TRANSFER_CLK_DIV; + + // init the SD interface, with retry if it's not ready yet + for (int retry = 10; HAL_SD_Init(&sd_handle) != HAL_OK; retry--) { + if (retry == 0) { + goto error; } - // turn on SD card circuitry - sdcard_active_pin_state(); HAL_Delay(50); + } - // SD device interface configuration - sd_handle.Instance = SDIO; - sd_handle.Init.ClockEdge = SDIO_CLOCK_EDGE_RISING; - sd_handle.Init.ClockBypass = SDIO_CLOCK_BYPASS_DISABLE; - sd_handle.Init.ClockPowerSave = SDIO_CLOCK_POWER_SAVE_ENABLE; - sd_handle.Init.BusWide = SDIO_BUS_WIDE_1B; - sd_handle.Init.HardwareFlowControl = SDIO_HARDWARE_FLOW_CONTROL_DISABLE; - sd_handle.Init.ClockDiv = SDIO_TRANSFER_CLK_DIV; - - // init the SD interface, with retry if it's not ready yet - for (int retry = 10; HAL_SD_Init(&sd_handle) != HAL_OK; retry--) { - if (retry == 0) { - goto error; - } - HAL_Delay(50); - } + // configure the SD bus width for wide operation + if (HAL_SD_ConfigWideBusOperation(&sd_handle, SDIO_BUS_WIDE_4B) != HAL_OK) { + HAL_SD_DeInit(&sd_handle); + goto error; + } - // configure the SD bus width for wide operation - if (HAL_SD_ConfigWideBusOperation(&sd_handle, SDIO_BUS_WIDE_4B) != HAL_OK) { - HAL_SD_DeInit(&sd_handle); - goto error; - } - - return sectrue; + return sectrue; error: - sdcard_power_off(); - return secfalse; + sdcard_power_off(); + return secfalse; } void sdcard_power_off(void) { - if (sd_handle.Instance) { - HAL_SD_DeInit(&sd_handle); - sd_handle.Instance = NULL; - } - // turn off SD card circuitry - HAL_Delay(50); - sdcard_default_pin_state(); - HAL_Delay(100); + if (sd_handle.Instance) { + HAL_SD_DeInit(&sd_handle); + sd_handle.Instance = NULL; + } + // turn off SD card circuitry + HAL_Delay(50); + sdcard_default_pin_state(); + HAL_Delay(100); } secbool sdcard_is_present(void) { - return sectrue * (GPIO_PIN_RESET == HAL_GPIO_ReadPin(GPIOC, GPIO_PIN_13)); + return sectrue * (GPIO_PIN_RESET == HAL_GPIO_ReadPin(GPIOC, GPIO_PIN_13)); } uint64_t sdcard_get_capacity_in_bytes(void) { - if (sd_handle.Instance == NULL) { - return 0; - } - HAL_SD_CardInfoTypeDef cardinfo; - HAL_SD_GetCardInfo(&sd_handle, &cardinfo); - return (uint64_t)cardinfo.LogBlockNbr * (uint64_t)cardinfo.LogBlockSize; + if (sd_handle.Instance == NULL) { + return 0; + } + HAL_SD_CardInfoTypeDef cardinfo; + HAL_SD_GetCardInfo(&sd_handle, &cardinfo); + return (uint64_t)cardinfo.LogBlockNbr * (uint64_t)cardinfo.LogBlockSize; } -static HAL_StatusTypeDef sdcard_wait_finished(SD_HandleTypeDef *sd, uint32_t timeout) { - // Wait for HAL driver to be ready (eg for DMA to finish) - uint32_t start = HAL_GetTick(); - while (sd->State == HAL_SD_STATE_BUSY) { - if (HAL_GetTick() - start >= timeout) { - return HAL_TIMEOUT; - } +static HAL_StatusTypeDef sdcard_wait_finished(SD_HandleTypeDef *sd, + uint32_t timeout) { + // Wait for HAL driver to be ready (eg for DMA to finish) + uint32_t start = HAL_GetTick(); + while (sd->State == HAL_SD_STATE_BUSY) { + if (HAL_GetTick() - start >= timeout) { + return HAL_TIMEOUT; } - // Wait for SD card to complete the operation - for (;;) { - HAL_SD_CardStateTypeDef state = HAL_SD_GetCardState(sd); - if (state == HAL_SD_CARD_TRANSFER) { - return HAL_OK; - } - if (!(state == HAL_SD_CARD_SENDING || state == HAL_SD_CARD_RECEIVING || state == HAL_SD_CARD_PROGRAMMING)) { - return HAL_ERROR; - } - if (HAL_GetTick() - start >= timeout) { - return HAL_TIMEOUT; - } + } + // Wait for SD card to complete the operation + for (;;) { + HAL_SD_CardStateTypeDef state = HAL_SD_GetCardState(sd); + if (state == HAL_SD_CARD_TRANSFER) { + return HAL_OK; } - return HAL_OK; + if (!(state == HAL_SD_CARD_SENDING || state == HAL_SD_CARD_RECEIVING || + state == HAL_SD_CARD_PROGRAMMING)) { + return HAL_ERROR; + } + if (HAL_GetTick() - start >= timeout) { + return HAL_TIMEOUT; + } + } + return HAL_OK; } -secbool sdcard_read_blocks(uint32_t *dest, uint32_t block_num, uint32_t num_blocks) { - // check that SD card is initialised - if (sd_handle.Instance == NULL) { - return secfalse; - } +secbool sdcard_read_blocks(uint32_t *dest, uint32_t block_num, + uint32_t num_blocks) { + // check that SD card is initialised + if (sd_handle.Instance == NULL) { + return secfalse; + } - // check that dest pointer is aligned on a 4-byte boundary - if (((uint32_t)dest & 3) != 0) { - return secfalse; - } + // check that dest pointer is aligned on a 4-byte boundary + if (((uint32_t)dest & 3) != 0) { + return secfalse; + } - HAL_StatusTypeDef err = HAL_OK; + HAL_StatusTypeDef err = HAL_OK; - err = HAL_SD_ReadBlocks(&sd_handle, (uint8_t *)dest, block_num, num_blocks, 60000); - if (err == HAL_OK) { - err = sdcard_wait_finished(&sd_handle, 60000); - } + err = HAL_SD_ReadBlocks(&sd_handle, (uint8_t *)dest, block_num, num_blocks, + 60000); + if (err == HAL_OK) { + err = sdcard_wait_finished(&sd_handle, 60000); + } - return sectrue * (err == HAL_OK); + return sectrue * (err == HAL_OK); } -secbool sdcard_write_blocks(const uint32_t *src, uint32_t block_num, uint32_t num_blocks) { - // check that SD card is initialised - if (sd_handle.Instance == NULL) { - return secfalse; - } +secbool sdcard_write_blocks(const uint32_t *src, uint32_t block_num, + uint32_t num_blocks) { + // check that SD card is initialised + if (sd_handle.Instance == NULL) { + return secfalse; + } - // check that src pointer is aligned on a 4-byte boundary - if (((uint32_t)src & 3) != 0) { - return secfalse; - } + // check that src pointer is aligned on a 4-byte boundary + if (((uint32_t)src & 3) != 0) { + return secfalse; + } - HAL_StatusTypeDef err = HAL_OK; + HAL_StatusTypeDef err = HAL_OK; - err = HAL_SD_WriteBlocks(&sd_handle, (uint8_t *)src, block_num, num_blocks, 60000); - if (err == HAL_OK) { - err = sdcard_wait_finished(&sd_handle, 60000); - } + err = HAL_SD_WriteBlocks(&sd_handle, (uint8_t *)src, block_num, num_blocks, + 60000); + if (err == HAL_OK) { + err = sdcard_wait_finished(&sd_handle, 60000); + } - return sectrue * (err == HAL_OK); + return sectrue * (err == HAL_OK); } diff --git a/embed/trezorhal/sdcard.h b/embed/trezorhal/sdcard.h index 2e16d78d4..955289ff1 100644 --- a/embed/trezorhal/sdcard.h +++ b/embed/trezorhal/sdcard.h @@ -56,7 +56,9 @@ secbool __wur sdcard_power_on(void); void sdcard_power_off(void); secbool __wur sdcard_is_present(void); uint64_t sdcard_get_capacity_in_bytes(void); -secbool __wur sdcard_read_blocks(uint32_t *dest, uint32_t block_num, uint32_t num_blocks); -secbool __wur sdcard_write_blocks(const uint32_t *src, uint32_t block_num, uint32_t num_blocks); +secbool __wur sdcard_read_blocks(uint32_t *dest, uint32_t block_num, + uint32_t num_blocks); +secbool __wur sdcard_write_blocks(const uint32_t *src, uint32_t block_num, + uint32_t num_blocks); #endif diff --git a/embed/trezorhal/secbool.h b/embed/trezorhal/secbool.h index 76dfb38dc..65860dd76 100644 --- a/embed/trezorhal/secbool.h +++ b/embed/trezorhal/secbool.h @@ -23,11 +23,11 @@ #include typedef uint32_t secbool; -#define sectrue 0xAAAAAAAAU +#define sectrue 0xAAAAAAAAU #define secfalse 0x00000000U #ifndef __wur -#define __wur __attribute__ ((warn_unused_result)) +#define __wur __attribute__((warn_unused_result)) #endif #endif diff --git a/embed/trezorhal/stm32.c b/embed/trezorhal/stm32.c index 5c74fd350..02a64afe2 100644 --- a/embed/trezorhal/stm32.c +++ b/embed/trezorhal/stm32.c @@ -21,7 +21,8 @@ #include "rng.h" -const uint8_t AHBPrescTable[16] = {0, 0, 0, 0, 0, 0, 0, 0, 1, 2, 3, 4, 6, 7, 8, 9}; +const uint8_t AHBPrescTable[16] = {0, 0, 0, 0, 0, 0, 0, 0, + 1, 2, 3, 4, 6, 7, 8, 9}; const uint8_t APBPrescTable[8] = {0, 0, 0, 0, 1, 2, 3, 4}; #ifdef STM32F427xx @@ -34,56 +35,69 @@ const uint8_t APBPrescTable[8] = {0, 0, 0, 0, 1, 2, 3, 4}; uint32_t SystemCoreClock = CORE_CLOCK_MHZ * 1000000U; -#pragma GCC optimize("no-stack-protector") // applies to all functions in this file +#pragma GCC optimize( \ + "no-stack-protector") // applies to all functions in this file -void SystemInit(void) -{ - // set flash wait states for an increasing HCLK frequency -- reference RM0090 section 3.5.1 - FLASH->ACR = FLASH_ACR_LATENCY_5WS; - // wait until the new wait state config takes effect -- per section 3.5.1 guidance - while ((FLASH->ACR & FLASH_ACR_LATENCY) != FLASH_ACR_LATENCY_5WS); - // configure main PLL; assumes HSE is 8 MHz; this should evaluate to 0x27402a04 -- reference RM0090 section 7.3.2 - RCC->PLLCFGR = (RCC_PLLCFGR_RST_VALUE & ~RCC_PLLCFGR_PLLQ & ~RCC_PLLCFGR_PLLSRC & ~RCC_PLLCFGR_PLLP & ~RCC_PLLCFGR_PLLN & ~RCC_PLLCFGR_PLLM) - | (7U << RCC_PLLCFGR_PLLQ_Pos) // Q = 7 - | RCC_PLLCFGR_PLLSRC_HSE // PLLSRC = HSE - | (0U << RCC_PLLCFGR_PLLP_Pos) // P = 2 (two bits, 00 means PLLP = 2) - | (CORE_CLOCK_MHZ << RCC_PLLCFGR_PLLN_Pos) // N = CORE_CLOCK_MHZ - | (4U << RCC_PLLCFGR_PLLM_Pos); // M = 4 - // enable spread spectrum clock for main PLL - RCC->SSCGR = RCC_SSCGR_SSCGEN | (44 << RCC_SSCGR_INCSTEP_Pos) | (250 << RCC_SSCGR_MODPER_Pos); - // enable clock security system, HSE clock, and main PLL - RCC->CR |= RCC_CR_CSSON | RCC_CR_HSEON | RCC_CR_PLLON; - // wait until PLL and HSE ready - while((RCC->CR & (RCC_CR_PLLRDY | RCC_CR_HSERDY)) != (RCC_CR_PLLRDY | RCC_CR_HSERDY)); - // APB2=2, APB1=4, AHB=1, system clock = main PLL - const uint32_t cfgr = RCC_CFGR_PPRE2_DIV2 | RCC_CFGR_PPRE1_DIV4 | RCC_CFGR_HPRE_DIV1 | RCC_CFGR_SW_PLL; - RCC->CFGR = cfgr; - // wait until PLL is system clock and also verify that the pre-scalers were set - while(RCC->CFGR != (RCC_CFGR_SWS_PLL | cfgr)); - // turn off the HSI as it is now unused (it will be turned on again automatically if a clock security failure occurs) - RCC->CR &= ~RCC_CR_HSION; - // wait until ths HSI is off - while((RCC->CR & RCC_CR_HSION) == RCC_CR_HSION); - // init the TRNG peripheral - rng_init(); - // set CP10 and CP11 to enable full access to the fpu coprocessor; ARMv7-M Architecture Reference Manual section B3.2.20 - SCB->CPACR |= ((3U << 22) | (3U << 20)); +void SystemInit(void) { + // set flash wait states for an increasing HCLK frequency -- reference RM0090 + // section 3.5.1 + FLASH->ACR = FLASH_ACR_LATENCY_5WS; + // wait until the new wait state config takes effect -- per section 3.5.1 + // guidance + while ((FLASH->ACR & FLASH_ACR_LATENCY) != FLASH_ACR_LATENCY_5WS) + ; + // configure main PLL; assumes HSE is 8 MHz; this should evaluate to + // 0x27402a04 -- reference RM0090 section 7.3.2 + RCC->PLLCFGR = + (RCC_PLLCFGR_RST_VALUE & ~RCC_PLLCFGR_PLLQ & ~RCC_PLLCFGR_PLLSRC & + ~RCC_PLLCFGR_PLLP & ~RCC_PLLCFGR_PLLN & ~RCC_PLLCFGR_PLLM) | + (7U << RCC_PLLCFGR_PLLQ_Pos) // Q = 7 + | RCC_PLLCFGR_PLLSRC_HSE // PLLSRC = HSE + | (0U << RCC_PLLCFGR_PLLP_Pos) // P = 2 (two bits, 00 means PLLP = 2) + | (CORE_CLOCK_MHZ << RCC_PLLCFGR_PLLN_Pos) // N = CORE_CLOCK_MHZ + | (4U << RCC_PLLCFGR_PLLM_Pos); // M = 4 + // enable spread spectrum clock for main PLL + RCC->SSCGR = RCC_SSCGR_SSCGEN | (44 << RCC_SSCGR_INCSTEP_Pos) | + (250 << RCC_SSCGR_MODPER_Pos); + // enable clock security system, HSE clock, and main PLL + RCC->CR |= RCC_CR_CSSON | RCC_CR_HSEON | RCC_CR_PLLON; + // wait until PLL and HSE ready + while ((RCC->CR & (RCC_CR_PLLRDY | RCC_CR_HSERDY)) != + (RCC_CR_PLLRDY | RCC_CR_HSERDY)) + ; + // APB2=2, APB1=4, AHB=1, system clock = main PLL + const uint32_t cfgr = RCC_CFGR_PPRE2_DIV2 | RCC_CFGR_PPRE1_DIV4 | + RCC_CFGR_HPRE_DIV1 | RCC_CFGR_SW_PLL; + RCC->CFGR = cfgr; + // wait until PLL is system clock and also verify that the pre-scalers were + // set + while (RCC->CFGR != (RCC_CFGR_SWS_PLL | cfgr)) + ; + // turn off the HSI as it is now unused (it will be turned on again + // automatically if a clock security failure occurs) + RCC->CR &= ~RCC_CR_HSION; + // wait until ths HSI is off + while ((RCC->CR & RCC_CR_HSION) == RCC_CR_HSION) + ; + // init the TRNG peripheral + rng_init(); + // set CP10 and CP11 to enable full access to the fpu coprocessor; ARMv7-M + // Architecture Reference Manual section B3.2.20 + SCB->CPACR |= ((3U << 22) | (3U << 20)); } extern volatile uint32_t uwTick; -void SysTick_Handler(void) -{ - // this is a millisecond tick counter that wraps after approximately - // 49.71 days = (0xffffffff / (24 * 60 * 60 * 1000)) - uwTick++; +void SysTick_Handler(void) { + // this is a millisecond tick counter that wraps after approximately + // 49.71 days = (0xffffffff / (24 * 60 * 60 * 1000)) + uwTick++; } // from util.s extern void shutdown(void); -void PVD_IRQHandler(void) -{ - TIM1->CCR1 = 0; // turn off display backlight - shutdown(); +void PVD_IRQHandler(void) { + TIM1->CCR1 = 0; // turn off display backlight + shutdown(); } diff --git a/embed/trezorhal/stm32f4xx_hal_conf.h b/embed/trezorhal/stm32f4xx_hal_conf.h index 0626d195d..2882f8a16 100644 --- a/embed/trezorhal/stm32f4xx_hal_conf.h +++ b/embed/trezorhal/stm32f4xx_hal_conf.h @@ -1,3 +1,5 @@ +// clang-format off + /** ****************************************************************************** * @file stm32f4xx_hal_conf.h diff --git a/embed/trezorhal/systick.c b/embed/trezorhal/systick.c index eac2bd12c..d995e740b 100644 --- a/embed/trezorhal/systick.c +++ b/embed/trezorhal/systick.c @@ -1,3 +1,5 @@ +// clang-format off + /* * This file is part of the TREZOR project, https://trezor.io/ * diff --git a/embed/trezorhal/touch.c b/embed/trezorhal/touch.c index c1ff33e99..6077d9bd5 100644 --- a/embed/trezorhal/touch.c +++ b/embed/trezorhal/touch.c @@ -28,17 +28,20 @@ #error Unknown TREZOR Model #endif -uint32_t touch_click(void) -{ - uint32_t r = 0; - // flush touch events if any - while (touch_read()) { } - // wait for TOUCH_START - while ((touch_read() & TOUCH_START) == 0) { } - // wait for TOUCH_END - while (((r = touch_read()) & TOUCH_END) == 0) { } - // flush touch events if any - while (touch_read()) { } - // return last touch coordinate - return r; +uint32_t touch_click(void) { + uint32_t r = 0; + // flush touch events if any + while (touch_read()) { + } + // wait for TOUCH_START + while ((touch_read() & TOUCH_START) == 0) { + } + // wait for TOUCH_END + while (((r = touch_read()) & TOUCH_END) == 0) { + } + // flush touch events if any + while (touch_read()) { + } + // return last touch coordinate + return r; } diff --git a/embed/trezorhal/touch.h b/embed/trezorhal/touch.h index 4e18ac43c..e975af141 100644 --- a/embed/trezorhal/touch.h +++ b/embed/trezorhal/touch.h @@ -22,9 +22,9 @@ #include -#define TOUCH_START (1U << 24) -#define TOUCH_MOVE (1U << 25) -#define TOUCH_END (1U << 26) +#define TOUCH_START (1U << 24) +#define TOUCH_MOVE (1U << 25) +#define TOUCH_END (1U << 26) void touch_init(void); void touch_power_on(void); @@ -33,8 +33,14 @@ void touch_sensitivity(uint8_t value); uint32_t touch_read(void); uint32_t touch_click(void); uint32_t touch_is_detected(void); -static inline uint16_t touch_unpack_x(uint32_t evt) { return (evt >> 12) & 0xFFF; } -static inline uint16_t touch_unpack_y(uint32_t evt) { return (evt >> 0) & 0xFFF; } -static inline uint32_t touch_pack_xy(uint16_t x, uint16_t y) { return ((x & 0xFFF) << 12) | (y & 0xFFF); } +static inline uint16_t touch_unpack_x(uint32_t evt) { + return (evt >> 12) & 0xFFF; +} +static inline uint16_t touch_unpack_y(uint32_t evt) { + return (evt >> 0) & 0xFFF; +} +static inline uint32_t touch_pack_xy(uint16_t x, uint16_t y) { + return ((x & 0xFFF) << 12) | (y & 0xFFF); +} #endif diff --git a/embed/trezorhal/touch_1.h b/embed/trezorhal/touch_1.h index 402e963e2..2f66c7bf5 100644 --- a/embed/trezorhal/touch_1.h +++ b/embed/trezorhal/touch_1.h @@ -1,55 +1,54 @@ -#define BTN_PIN_LEFT GPIO_PIN_5 -#define BTN_PIN_RIGHT GPIO_PIN_2 +#define BTN_PIN_LEFT GPIO_PIN_5 +#define BTN_PIN_RIGHT GPIO_PIN_2 -#define DISPLAY_RESX 128 -#define DISPLAY_RESY 64 -#define BTN_LEFT_COORDS touch_pack_xy(0, DISPLAY_RESY - 1) -#define BTN_RIGHT_COORDS touch_pack_xy(DISPLAY_RESX - 1, DISPLAY_RESY - 1) +#define DISPLAY_RESX 128 +#define DISPLAY_RESY 64 +#define BTN_LEFT_COORDS touch_pack_xy(0, DISPLAY_RESY - 1) +#define BTN_RIGHT_COORDS touch_pack_xy(DISPLAY_RESX - 1, DISPLAY_RESY - 1) void touch_init(void) { - __HAL_RCC_GPIOC_CLK_ENABLE(); + __HAL_RCC_GPIOC_CLK_ENABLE(); - GPIO_InitTypeDef GPIO_InitStructure; + GPIO_InitTypeDef GPIO_InitStructure; - // PC4 capacitive touch panel module (CTPM) interrupt (INT) input - GPIO_InitStructure.Mode = GPIO_MODE_INPUT; - GPIO_InitStructure.Pull = GPIO_PULLUP; - GPIO_InitStructure.Speed = GPIO_SPEED_FREQ_LOW; - GPIO_InitStructure.Pin = BTN_PIN_LEFT | BTN_PIN_RIGHT; - HAL_GPIO_Init(GPIOC, &GPIO_InitStructure); + // PC4 capacitive touch panel module (CTPM) interrupt (INT) input + GPIO_InitStructure.Mode = GPIO_MODE_INPUT; + GPIO_InitStructure.Pull = GPIO_PULLUP; + GPIO_InitStructure.Speed = GPIO_SPEED_FREQ_LOW; + GPIO_InitStructure.Pin = BTN_PIN_LEFT | BTN_PIN_RIGHT; + HAL_GPIO_Init(GPIOC, &GPIO_InitStructure); } -void touch_power_on(void) { } +void touch_power_on(void) {} -void touch_power_off(void) { } +void touch_power_off(void) {} void touch_sensitivity(uint8_t value) { (void)value; } -uint32_t touch_read(void) -{ - static char last_left = 0, last_right = 0; - char left = (GPIO_PIN_RESET == HAL_GPIO_ReadPin(GPIOC, BTN_PIN_LEFT)); - char right = (GPIO_PIN_RESET == HAL_GPIO_ReadPin(GPIOC, BTN_PIN_RIGHT)); - if (last_left != left) { - last_left = left; - if (left) { - return TOUCH_START | BTN_LEFT_COORDS; - } else { - return TOUCH_END | BTN_LEFT_COORDS; - } +uint32_t touch_read(void) { + static char last_left = 0, last_right = 0; + char left = (GPIO_PIN_RESET == HAL_GPIO_ReadPin(GPIOC, BTN_PIN_LEFT)); + char right = (GPIO_PIN_RESET == HAL_GPIO_ReadPin(GPIOC, BTN_PIN_RIGHT)); + if (last_left != left) { + last_left = left; + if (left) { + return TOUCH_START | BTN_LEFT_COORDS; + } else { + return TOUCH_END | BTN_LEFT_COORDS; } - if (last_right != right) { - last_right = right; - if (right) { - return TOUCH_START | BTN_RIGHT_COORDS; - } else { - return TOUCH_END | BTN_RIGHT_COORDS; - } + } + if (last_right != right) { + last_right = right; + if (right) { + return TOUCH_START | BTN_RIGHT_COORDS; + } else { + return TOUCH_END | BTN_RIGHT_COORDS; } - return 0; + } + return 0; } -uint32_t touch_is_detected(void) -{ - return (GPIO_PIN_RESET == HAL_GPIO_ReadPin(GPIOC, BTN_PIN_LEFT)) || (GPIO_PIN_RESET == HAL_GPIO_ReadPin(GPIOC, BTN_PIN_RIGHT)); +uint32_t touch_is_detected(void) { + return (GPIO_PIN_RESET == HAL_GPIO_ReadPin(GPIOC, BTN_PIN_LEFT)) || + (GPIO_PIN_RESET == HAL_GPIO_ReadPin(GPIOC, BTN_PIN_RIGHT)); } diff --git a/embed/trezorhal/touch_t.h b/embed/trezorhal/touch_t.h index c8cd35a0f..4283b542f 100644 --- a/embed/trezorhal/touch_t.h +++ b/embed/trezorhal/touch_t.h @@ -3,13 +3,14 @@ #include "common.h" #include "secbool.h" -#define TOUCH_ADDRESS (0x38U << 1) // the HAL requires the 7-bit address to be shifted by one bit -#define TOUCH_PACKET_SIZE 7U -#define EVENT_PRESS_DOWN 0x00U -#define EVENT_CONTACT 0x80U -#define EVENT_LIFT_UP 0x40U -#define EVENT_NO_EVENT 0xC0U -#define GESTURE_NO_GESTURE 0x00U +#define TOUCH_ADDRESS \ + (0x38U << 1) // the HAL requires the 7-bit address to be shifted by one bit +#define TOUCH_PACKET_SIZE 7U +#define EVENT_PRESS_DOWN 0x00U +#define EVENT_CONTACT 0x80U +#define EVENT_LIFT_UP 0x40U +#define EVENT_NO_EVENT 0xC0U +#define GESTURE_NO_GESTURE 0x00U #define X_POS_MSB (touch_data[3] & 0x0FU) #define X_POS_LSB (touch_data[4]) #define Y_POS_MSB (touch_data[5] & 0x0FU) @@ -18,180 +19,202 @@ static I2C_HandleTypeDef i2c_handle; static void touch_default_pin_state(void) { - // set power off and other pins as per section 3.5 of FT6236 datasheet - HAL_GPIO_WritePin(GPIOB, GPIO_PIN_10, GPIO_PIN_SET); // CTP_ON/PB10 (active low) i.e.- CTPM power off when set/high/log 1 - HAL_GPIO_WritePin(GPIOB, GPIO_PIN_6, GPIO_PIN_RESET); // CTP_I2C_SCL/PB6 - HAL_GPIO_WritePin(GPIOB, GPIO_PIN_7, GPIO_PIN_RESET); // CTP_I2C_SDA/PB7 - HAL_GPIO_WritePin(GPIOC, GPIO_PIN_4, GPIO_PIN_RESET); // CTP_INT/PC4 normally an input, but drive low as an output while powered off - HAL_GPIO_WritePin(GPIOC, GPIO_PIN_5, GPIO_PIN_RESET); // CTP_REST/PC5 (active low) i.e.- CTPM held in reset until released - - // set above pins to OUTPUT / NOPULL - GPIO_InitTypeDef GPIO_InitStructure; - - GPIO_InitStructure.Mode = GPIO_MODE_OUTPUT_PP; - GPIO_InitStructure.Pull = GPIO_NOPULL; - GPIO_InitStructure.Speed = GPIO_SPEED_FREQ_LOW; - GPIO_InitStructure.Pin = GPIO_PIN_10 | GPIO_PIN_6 | GPIO_PIN_7; - HAL_GPIO_Init(GPIOB, &GPIO_InitStructure); - GPIO_InitStructure.Pin = GPIO_PIN_4 | GPIO_PIN_5; - HAL_GPIO_Init(GPIOC, &GPIO_InitStructure); - - // in-case power was on, or CTPM was active make sure to wait long enough - // for these changes to take effect. a reset needs to be low for - // a minimum of 5ms. also wait for power circuitry to stabilize (if it changed). - HAL_Delay(100); // 100ms (being conservative) + // set power off and other pins as per section 3.5 of FT6236 datasheet + HAL_GPIO_WritePin(GPIOB, GPIO_PIN_10, + GPIO_PIN_SET); // CTP_ON/PB10 (active low) i.e.- CTPM power + // off when set/high/log 1 + HAL_GPIO_WritePin(GPIOB, GPIO_PIN_6, GPIO_PIN_RESET); // CTP_I2C_SCL/PB6 + HAL_GPIO_WritePin(GPIOB, GPIO_PIN_7, GPIO_PIN_RESET); // CTP_I2C_SDA/PB7 + HAL_GPIO_WritePin( + GPIOC, GPIO_PIN_4, + GPIO_PIN_RESET); // CTP_INT/PC4 normally an input, but drive low as an + // output while powered off + HAL_GPIO_WritePin(GPIOC, GPIO_PIN_5, + GPIO_PIN_RESET); // CTP_REST/PC5 (active low) i.e.- CTPM + // held in reset until released + + // set above pins to OUTPUT / NOPULL + GPIO_InitTypeDef GPIO_InitStructure; + + GPIO_InitStructure.Mode = GPIO_MODE_OUTPUT_PP; + GPIO_InitStructure.Pull = GPIO_NOPULL; + GPIO_InitStructure.Speed = GPIO_SPEED_FREQ_LOW; + GPIO_InitStructure.Pin = GPIO_PIN_10 | GPIO_PIN_6 | GPIO_PIN_7; + HAL_GPIO_Init(GPIOB, &GPIO_InitStructure); + GPIO_InitStructure.Pin = GPIO_PIN_4 | GPIO_PIN_5; + HAL_GPIO_Init(GPIOC, &GPIO_InitStructure); + + // in-case power was on, or CTPM was active make sure to wait long enough + // for these changes to take effect. a reset needs to be low for + // a minimum of 5ms. also wait for power circuitry to stabilize (if it + // changed). + HAL_Delay(100); // 100ms (being conservative) } static void touch_active_pin_state(void) { - HAL_GPIO_WritePin(GPIOB, GPIO_PIN_10, GPIO_PIN_RESET); // CTP_ON/PB10 - HAL_Delay(10); // we need to wait until the circuit fully kicks-in - - GPIO_InitTypeDef GPIO_InitStructure; - - // configure CTP I2C SCL and SDA GPIO lines (PB6 & PB7) - GPIO_InitStructure.Mode = GPIO_MODE_AF_OD; - GPIO_InitStructure.Pull = GPIO_NOPULL; - GPIO_InitStructure.Speed = GPIO_SPEED_FREQ_LOW; // I2C is a KHz bus and low speed is still good into the low MHz - GPIO_InitStructure.Alternate = GPIO_AF4_I2C1; - GPIO_InitStructure.Pin = GPIO_PIN_6 | GPIO_PIN_7; - HAL_GPIO_Init(GPIOB, &GPIO_InitStructure); - - // PC4 capacitive touch panel module (CTPM) interrupt (INT) input - GPIO_InitStructure.Mode = GPIO_MODE_INPUT; - GPIO_InitStructure.Pull = GPIO_PULLUP; - GPIO_InitStructure.Speed = GPIO_SPEED_FREQ_LOW; - GPIO_InitStructure.Pin = GPIO_PIN_4; - HAL_GPIO_Init(GPIOC, &GPIO_InitStructure); - - HAL_GPIO_WritePin(GPIOC, GPIO_PIN_5, GPIO_PIN_SET); // release CTPM reset - HAL_Delay(310); // "Time of starting to report point after resetting" min is 300ms, giving an extra 10ms + HAL_GPIO_WritePin(GPIOB, GPIO_PIN_10, GPIO_PIN_RESET); // CTP_ON/PB10 + HAL_Delay(10); // we need to wait until the circuit fully kicks-in + + GPIO_InitTypeDef GPIO_InitStructure; + + // configure CTP I2C SCL and SDA GPIO lines (PB6 & PB7) + GPIO_InitStructure.Mode = GPIO_MODE_AF_OD; + GPIO_InitStructure.Pull = GPIO_NOPULL; + GPIO_InitStructure.Speed = + GPIO_SPEED_FREQ_LOW; // I2C is a KHz bus and low speed is still good into + // the low MHz + GPIO_InitStructure.Alternate = GPIO_AF4_I2C1; + GPIO_InitStructure.Pin = GPIO_PIN_6 | GPIO_PIN_7; + HAL_GPIO_Init(GPIOB, &GPIO_InitStructure); + + // PC4 capacitive touch panel module (CTPM) interrupt (INT) input + GPIO_InitStructure.Mode = GPIO_MODE_INPUT; + GPIO_InitStructure.Pull = GPIO_PULLUP; + GPIO_InitStructure.Speed = GPIO_SPEED_FREQ_LOW; + GPIO_InitStructure.Pin = GPIO_PIN_4; + HAL_GPIO_Init(GPIOC, &GPIO_InitStructure); + + HAL_GPIO_WritePin(GPIOC, GPIO_PIN_5, GPIO_PIN_SET); // release CTPM reset + HAL_Delay(310); // "Time of starting to report point after resetting" min is + // 300ms, giving an extra 10ms } -void touch_init(void) { - touch_default_pin_state(); -} +void touch_init(void) { touch_default_pin_state(); } void HAL_I2C_MspInit(I2C_HandleTypeDef *hi2c) { - // enable I2C clock - __HAL_RCC_I2C1_CLK_ENABLE(); - // GPIO have already been initialised by touch_init + // enable I2C clock + __HAL_RCC_I2C1_CLK_ENABLE(); + // GPIO have already been initialised by touch_init } void HAL_I2C_MspDeInit(I2C_HandleTypeDef *hi2c) { - __HAL_RCC_I2C1_CLK_DISABLE(); + __HAL_RCC_I2C1_CLK_DISABLE(); } void touch_power_on(void) { - if (i2c_handle.Instance) { - return; - } - - // turn on CTP circuitry - touch_active_pin_state(); - HAL_Delay(50); - - // I2C device interface configuration - i2c_handle.Instance = I2C1; - i2c_handle.Init.ClockSpeed = 400000; - i2c_handle.Init.DutyCycle = I2C_DUTYCYCLE_16_9; - i2c_handle.Init.OwnAddress1 = 0xFE; // master - i2c_handle.Init.AddressingMode = I2C_ADDRESSINGMODE_7BIT; - i2c_handle.Init.DualAddressMode = I2C_DUALADDRESS_DISABLE; - i2c_handle.Init.OwnAddress2 = 0; - i2c_handle.Init.GeneralCallMode = I2C_GENERALCALL_DISABLE; - i2c_handle.Init.NoStretchMode = I2C_NOSTRETCH_DISABLE; - - if (HAL_OK != HAL_I2C_Init(&i2c_handle)) { - ensure(secfalse, NULL); - return; - } - - // set register 0xA4 G_MODE to interrupt polling mode (0x00). basically, CTPM keeps this input line (to PC4) low while a finger is on the screen. - uint8_t touch_panel_config[] = {0xA4, 0x00}; - ensure(sectrue * (HAL_OK == HAL_I2C_Master_Transmit(&i2c_handle, TOUCH_ADDRESS, touch_panel_config, sizeof(touch_panel_config), 10)), NULL); - - touch_sensitivity(0x06); + if (i2c_handle.Instance) { + return; + } + + // turn on CTP circuitry + touch_active_pin_state(); + HAL_Delay(50); + + // I2C device interface configuration + i2c_handle.Instance = I2C1; + i2c_handle.Init.ClockSpeed = 400000; + i2c_handle.Init.DutyCycle = I2C_DUTYCYCLE_16_9; + i2c_handle.Init.OwnAddress1 = 0xFE; // master + i2c_handle.Init.AddressingMode = I2C_ADDRESSINGMODE_7BIT; + i2c_handle.Init.DualAddressMode = I2C_DUALADDRESS_DISABLE; + i2c_handle.Init.OwnAddress2 = 0; + i2c_handle.Init.GeneralCallMode = I2C_GENERALCALL_DISABLE; + i2c_handle.Init.NoStretchMode = I2C_NOSTRETCH_DISABLE; + + if (HAL_OK != HAL_I2C_Init(&i2c_handle)) { + ensure(secfalse, NULL); + return; + } + + // set register 0xA4 G_MODE to interrupt polling mode (0x00). basically, CTPM + // keeps this input line (to PC4) low while a finger is on the screen. + uint8_t touch_panel_config[] = {0xA4, 0x00}; + ensure( + sectrue * (HAL_OK == HAL_I2C_Master_Transmit( + &i2c_handle, TOUCH_ADDRESS, touch_panel_config, + sizeof(touch_panel_config), 10)), + NULL); + + touch_sensitivity(0x06); } void touch_power_off(void) { - if (i2c_handle.Instance) { - HAL_I2C_DeInit(&i2c_handle); - i2c_handle.Instance = NULL; - } - // turn off CTP circuitry - HAL_Delay(50); - touch_default_pin_state(); + if (i2c_handle.Instance) { + HAL_I2C_DeInit(&i2c_handle); + i2c_handle.Instance = NULL; + } + // turn off CTP circuitry + HAL_Delay(50); + touch_default_pin_state(); } void touch_sensitivity(uint8_t value) { - // set panel threshold (TH_GROUP) - default value is 0x12 - uint8_t touch_panel_threshold[] = {0x80, value}; - ensure(sectrue * (HAL_OK == HAL_I2C_Master_Transmit(&i2c_handle, TOUCH_ADDRESS, touch_panel_threshold, sizeof(touch_panel_threshold), 10)), NULL); + // set panel threshold (TH_GROUP) - default value is 0x12 + uint8_t touch_panel_threshold[] = {0x80, value}; + ensure(sectrue * + (HAL_OK == HAL_I2C_Master_Transmit( + &i2c_handle, TOUCH_ADDRESS, touch_panel_threshold, + sizeof(touch_panel_threshold), 10)), + NULL); } -uint32_t touch_is_detected(void) -{ - // check the interrupt line coming in from the CTPM. - // the line goes low when a touch event is actively detected. - // reference section 1.2 of "Application Note for FT6x06 CTPM". - // we configure the touch controller to use "interrupt polling mode". - return GPIO_PIN_RESET == HAL_GPIO_ReadPin(GPIOC, GPIO_PIN_4); +uint32_t touch_is_detected(void) { + // check the interrupt line coming in from the CTPM. + // the line goes low when a touch event is actively detected. + // reference section 1.2 of "Application Note for FT6x06 CTPM". + // we configure the touch controller to use "interrupt polling mode". + return GPIO_PIN_RESET == HAL_GPIO_ReadPin(GPIOC, GPIO_PIN_4); } -uint32_t touch_read(void) -{ - static uint8_t touch_data[TOUCH_PACKET_SIZE], previous_touch_data[TOUCH_PACKET_SIZE]; - static uint32_t xy; - static int touching; - - int last_packet = 0; - if (!touch_is_detected()) { - // only poll when the touch interrupt is active. - // when it's inactive, we might need to read one last data packet to get to - // the TOUCH_END event, which clears the `touching` flag. - if (touching) { - last_packet = 1; - } else { - return 0; - } - } - - uint8_t outgoing[] = {0x00}; // start reading from address 0x00 - if (HAL_OK != HAL_I2C_Master_Transmit(&i2c_handle, TOUCH_ADDRESS, outgoing, sizeof(outgoing), 1)) { - return 0; - } - - if (HAL_OK != HAL_I2C_Master_Receive(&i2c_handle, TOUCH_ADDRESS, touch_data, TOUCH_PACKET_SIZE, 1)) { - return 0; // read failure - } - - if (0 == memcmp(previous_touch_data, touch_data, TOUCH_PACKET_SIZE)) { - return 0; // polled and got the same event again +uint32_t touch_read(void) { + static uint8_t touch_data[TOUCH_PACKET_SIZE], + previous_touch_data[TOUCH_PACKET_SIZE]; + static uint32_t xy; + static int touching; + + int last_packet = 0; + if (!touch_is_detected()) { + // only poll when the touch interrupt is active. + // when it's inactive, we might need to read one last data packet to get to + // the TOUCH_END event, which clears the `touching` flag. + if (touching) { + last_packet = 1; } else { - memcpy(previous_touch_data, touch_data, TOUCH_PACKET_SIZE); + return 0; } + } - const uint32_t number_of_touch_points = touch_data[2] & 0x0F; // valid values are 0, 1, 2 (invalid 0xF before first touch) (tested with FT6206) - const uint32_t event_flag = touch_data[3] & 0xC0; - if (touch_data[1] == GESTURE_NO_GESTURE) { - xy = touch_pack_xy((X_POS_MSB << 8) | X_POS_LSB, (Y_POS_MSB << 8) | Y_POS_LSB); - if ((number_of_touch_points == 1) && (event_flag == EVENT_PRESS_DOWN)) { - touching = 1; - return TOUCH_START | xy; - } else if ((number_of_touch_points == 1) && (event_flag == EVENT_CONTACT)) { - return TOUCH_MOVE | xy; - } else if ((number_of_touch_points == 0) && (event_flag == EVENT_LIFT_UP)) { - touching = 0; - return TOUCH_END | xy; - } + uint8_t outgoing[] = {0x00}; // start reading from address 0x00 + if (HAL_OK != HAL_I2C_Master_Transmit(&i2c_handle, TOUCH_ADDRESS, outgoing, + sizeof(outgoing), 1)) { + return 0; + } + + if (HAL_OK != HAL_I2C_Master_Receive(&i2c_handle, TOUCH_ADDRESS, touch_data, + TOUCH_PACKET_SIZE, 1)) { + return 0; // read failure + } + + if (0 == memcmp(previous_touch_data, touch_data, TOUCH_PACKET_SIZE)) { + return 0; // polled and got the same event again + } else { + memcpy(previous_touch_data, touch_data, TOUCH_PACKET_SIZE); + } + + const uint32_t number_of_touch_points = + touch_data[2] & 0x0F; // valid values are 0, 1, 2 (invalid 0xF before + // first touch) (tested with FT6206) + const uint32_t event_flag = touch_data[3] & 0xC0; + if (touch_data[1] == GESTURE_NO_GESTURE) { + xy = touch_pack_xy((X_POS_MSB << 8) | X_POS_LSB, + (Y_POS_MSB << 8) | Y_POS_LSB); + if ((number_of_touch_points == 1) && (event_flag == EVENT_PRESS_DOWN)) { + touching = 1; + return TOUCH_START | xy; + } else if ((number_of_touch_points == 1) && (event_flag == EVENT_CONTACT)) { + return TOUCH_MOVE | xy; + } else if ((number_of_touch_points == 0) && (event_flag == EVENT_LIFT_UP)) { + touching = 0; + return TOUCH_END | xy; } + } - if (last_packet) { - // interrupt line is inactive, we didn't read valid touch data, and as far as - // we know, we never sent a TOUCH_END event. - touching = 0; - return TOUCH_END | xy; - } + if (last_packet) { + // interrupt line is inactive, we didn't read valid touch data, and as far + // as we know, we never sent a TOUCH_END event. + touching = 0; + return TOUCH_END | xy; + } - return 0; + return 0; } diff --git a/embed/trezorhal/usb.c b/embed/trezorhal/usb.c index 03ac2cd5b..2b3466e6e 100644 --- a/embed/trezorhal/usb.c +++ b/embed/trezorhal/usb.c @@ -19,35 +19,41 @@ #include STM32_HAL_H -#include "common.h" #include "usb.h" +#include "common.h" #include "usbd_core.h" -#define USB_MAX_CONFIG_DESC_SIZE 256 -#define USB_MAX_STR_SIZE 62 -#define USB_MAX_STR_DESC_SIZE (USB_MAX_STR_SIZE * 2 + 2) +#define USB_MAX_CONFIG_DESC_SIZE 256 +#define USB_MAX_STR_SIZE 62 +#define USB_MAX_STR_DESC_SIZE (USB_MAX_STR_SIZE * 2 + 2) #if defined(USE_USB_FS) -#define USB_PHY_ID USB_PHY_FS_ID +#define USB_PHY_ID USB_PHY_FS_ID #elif defined(USE_USB_HS) && defined(USE_USB_HS_IN_FS) -#define USB_PHY_ID USB_PHY_HS_ID +#define USB_PHY_ID USB_PHY_HS_ID #else #error Unable to determine proper USB_PHY_ID to use #endif -#define USB_WINUSB_VENDOR_CODE '!' // arbitrary, but must be equivalent to the last character in extra string -#define USB_WINUSB_EXTRA_STRING 'M', 0x00, 'S', 0x00, 'F', 0x00, 'T', 0x00, '1', 0x00, '0', 0x00, '0', 0x00, USB_WINUSB_VENDOR_CODE , 0x00 // MSFT100! -#define USB_WINUSB_EXTRA_STRING_INDEX 0xEE -#define USB_WINUSB_REQ_GET_COMPATIBLE_ID_FEATURE_DESCRIPTOR 0x04 -#define USB_WINUSB_REQ_GET_EXTENDED_PROPERTIES_OS_FEATURE_DESCRIPTOR 0x05 +#define USB_WINUSB_VENDOR_CODE \ + '!' // arbitrary, but must be equivalent to the last character in extra + // string +#define USB_WINUSB_EXTRA_STRING \ + 'M', 0x00, 'S', 0x00, 'F', 0x00, 'T', 0x00, '1', 0x00, '0', 0x00, '0', 0x00, \ + USB_WINUSB_VENDOR_CODE, 0x00 // MSFT100! +#define USB_WINUSB_EXTRA_STRING_INDEX 0xEE +#define USB_WINUSB_REQ_GET_COMPATIBLE_ID_FEATURE_DESCRIPTOR 0x04 +#define USB_WINUSB_REQ_GET_EXTENDED_PROPERTIES_OS_FEATURE_DESCRIPTOR 0x05 #define UNCONST(X) ((uint8_t *)(X)) static usb_device_descriptor_t usb_dev_desc; // Config descriptor -static uint8_t usb_config_buf[USB_MAX_CONFIG_DESC_SIZE] __attribute__((aligned(4))); -static usb_config_descriptor_t *usb_config_desc = (usb_config_descriptor_t *)(usb_config_buf); +static uint8_t usb_config_buf[USB_MAX_CONFIG_DESC_SIZE] + __attribute__((aligned(4))); +static usb_config_descriptor_t *usb_config_desc = + (usb_config_descriptor_t *)(usb_config_buf); static usb_interface_descriptor_t *usb_next_iface_desc; // String descriptor @@ -64,114 +70,127 @@ static secbool usb21_enabled = secfalse; static secbool usb21_landing = secfalse; static secbool __wur check_desc_str(const char *s) { - if (NULL == s) return secfalse; - if (strlen(s) > USB_MAX_STR_SIZE) return secfalse; - return sectrue; + if (NULL == s) return secfalse; + if (strlen(s) > USB_MAX_STR_SIZE) return secfalse; + return sectrue; } void usb_init(const usb_dev_info_t *dev_info) { - - // enable/disable USB 2.1 features - usb21_enabled = dev_info->usb21_enabled; - usb21_landing = dev_info->usb21_landing; - - // Device descriptor - usb_dev_desc.bLength = sizeof(usb_device_descriptor_t); - usb_dev_desc.bDescriptorType = USB_DESC_TYPE_DEVICE; - usb_dev_desc.bcdUSB = (sectrue == usb21_enabled) ? 0x0210 : 0x0200; // USB 2.1 or USB 2.0 - usb_dev_desc.bDeviceClass = dev_info->device_class; - usb_dev_desc.bDeviceSubClass = dev_info->device_subclass; - usb_dev_desc.bDeviceProtocol = dev_info->device_protocol; - usb_dev_desc.bMaxPacketSize0 = USB_MAX_EP0_SIZE; - usb_dev_desc.idVendor = dev_info->vendor_id; - usb_dev_desc.idProduct = dev_info->product_id; - usb_dev_desc.bcdDevice = dev_info->release_num; - usb_dev_desc.iManufacturer = USBD_IDX_MFC_STR; // Index of manufacturer string - usb_dev_desc.iProduct = USBD_IDX_PRODUCT_STR; // Index of product string - usb_dev_desc.iSerialNumber = USBD_IDX_SERIAL_STR; // Index of serial number string - usb_dev_desc.bNumConfigurations = 1; - - // String table - ensure(check_desc_str(dev_info->manufacturer), NULL); - ensure(check_desc_str(dev_info->product), NULL); - ensure(check_desc_str(dev_info->serial_number), NULL); - ensure(check_desc_str(dev_info->interface), NULL); - - usb_str_table.manufacturer = dev_info->manufacturer; - usb_str_table.product = dev_info->product; - usb_str_table.serial_number = dev_info->serial_number; - usb_str_table.interface = dev_info->interface; - - // Configuration descriptor - usb_config_desc->bLength = sizeof(usb_config_descriptor_t); - usb_config_desc->bDescriptorType = USB_DESC_TYPE_CONFIGURATION; - usb_config_desc->wTotalLength = sizeof(usb_config_descriptor_t); // will be updated later via usb_desc_add_iface() - usb_config_desc->bNumInterfaces = 0; // will be updated later via usb_desc_add_iface() - usb_config_desc->bConfigurationValue = 0x01; - usb_config_desc->iConfiguration = 0; - usb_config_desc->bmAttributes = 0x80; // 0x80 = bus powered; 0xC0 = self powered - usb_config_desc->bMaxPower = 0x32; // Maximum Power Consumption in 2mA units - - // Pointer to interface descriptor data - usb_next_iface_desc = (usb_interface_descriptor_t *)(usb_config_buf + usb_config_desc->wTotalLength); - - ensure(sectrue * (USBD_OK == USBD_Init(&usb_dev_handle, (USBD_DescriptorsTypeDef*)&usb_descriptors, USB_PHY_ID)), NULL); - ensure(sectrue * (USBD_OK == USBD_RegisterClass(&usb_dev_handle, (USBD_ClassTypeDef*)&usb_class)), NULL); + // enable/disable USB 2.1 features + usb21_enabled = dev_info->usb21_enabled; + usb21_landing = dev_info->usb21_landing; + + // Device descriptor + usb_dev_desc.bLength = sizeof(usb_device_descriptor_t); + usb_dev_desc.bDescriptorType = USB_DESC_TYPE_DEVICE; + usb_dev_desc.bcdUSB = + (sectrue == usb21_enabled) ? 0x0210 : 0x0200; // USB 2.1 or USB 2.0 + usb_dev_desc.bDeviceClass = dev_info->device_class; + usb_dev_desc.bDeviceSubClass = dev_info->device_subclass; + usb_dev_desc.bDeviceProtocol = dev_info->device_protocol; + usb_dev_desc.bMaxPacketSize0 = USB_MAX_EP0_SIZE; + usb_dev_desc.idVendor = dev_info->vendor_id; + usb_dev_desc.idProduct = dev_info->product_id; + usb_dev_desc.bcdDevice = dev_info->release_num; + usb_dev_desc.iManufacturer = + USBD_IDX_MFC_STR; // Index of manufacturer string + usb_dev_desc.iProduct = USBD_IDX_PRODUCT_STR; // Index of product string + usb_dev_desc.iSerialNumber = + USBD_IDX_SERIAL_STR; // Index of serial number string + usb_dev_desc.bNumConfigurations = 1; + + // String table + ensure(check_desc_str(dev_info->manufacturer), NULL); + ensure(check_desc_str(dev_info->product), NULL); + ensure(check_desc_str(dev_info->serial_number), NULL); + ensure(check_desc_str(dev_info->interface), NULL); + + usb_str_table.manufacturer = dev_info->manufacturer; + usb_str_table.product = dev_info->product; + usb_str_table.serial_number = dev_info->serial_number; + usb_str_table.interface = dev_info->interface; + + // Configuration descriptor + usb_config_desc->bLength = sizeof(usb_config_descriptor_t); + usb_config_desc->bDescriptorType = USB_DESC_TYPE_CONFIGURATION; + usb_config_desc->wTotalLength = + sizeof(usb_config_descriptor_t); // will be updated later via + // usb_desc_add_iface() + usb_config_desc->bNumInterfaces = + 0; // will be updated later via usb_desc_add_iface() + usb_config_desc->bConfigurationValue = 0x01; + usb_config_desc->iConfiguration = 0; + usb_config_desc->bmAttributes = + 0x80; // 0x80 = bus powered; 0xC0 = self powered + usb_config_desc->bMaxPower = 0x32; // Maximum Power Consumption in 2mA units + + // Pointer to interface descriptor data + usb_next_iface_desc = + (usb_interface_descriptor_t *)(usb_config_buf + + usb_config_desc->wTotalLength); + + ensure(sectrue * + (USBD_OK == USBD_Init(&usb_dev_handle, + (USBD_DescriptorsTypeDef *)&usb_descriptors, + USB_PHY_ID)), + NULL); + ensure(sectrue * + (USBD_OK == USBD_RegisterClass(&usb_dev_handle, + (USBD_ClassTypeDef *)&usb_class)), + NULL); } void usb_deinit(void) { - USBD_DeInit(&usb_dev_handle); - for (int i = 0; i < USBD_MAX_NUM_INTERFACES; i++) { - usb_ifaces[i].type = USB_IFACE_TYPE_DISABLED; - } + USBD_DeInit(&usb_dev_handle); + for (int i = 0; i < USBD_MAX_NUM_INTERFACES; i++) { + usb_ifaces[i].type = USB_IFACE_TYPE_DISABLED; + } } -void usb_start(void) { - USBD_Start(&usb_dev_handle); -} +void usb_start(void) { USBD_Start(&usb_dev_handle); } -void usb_stop(void) { - USBD_Stop(&usb_dev_handle); -} +void usb_stop(void) { USBD_Stop(&usb_dev_handle); } /* * Utility functions for USB interfaces */ static usb_iface_t *usb_get_iface(uint8_t iface_num) { - if (iface_num < USBD_MAX_NUM_INTERFACES) { - return &usb_ifaces[iface_num]; - } else { - return NULL; // Invalid interface number - } + if (iface_num < USBD_MAX_NUM_INTERFACES) { + return &usb_ifaces[iface_num]; + } else { + return NULL; // Invalid interface number + } } static void *usb_desc_alloc_iface(size_t desc_len) { - if (usb_config_desc->wTotalLength + desc_len < USB_MAX_CONFIG_DESC_SIZE) { - return usb_next_iface_desc; - } else { - return NULL; // Not enough space in the descriptor - } + if (usb_config_desc->wTotalLength + desc_len < USB_MAX_CONFIG_DESC_SIZE) { + return usb_next_iface_desc; + } else { + return NULL; // Not enough space in the descriptor + } } static void usb_desc_add_iface(size_t desc_len) { - usb_config_desc->bNumInterfaces++; - usb_config_desc->wTotalLength += desc_len; - usb_next_iface_desc = (usb_interface_descriptor_t *)(usb_config_buf + usb_config_desc->wTotalLength); + usb_config_desc->bNumInterfaces++; + usb_config_desc->wTotalLength += desc_len; + usb_next_iface_desc = + (usb_interface_descriptor_t *)(usb_config_buf + + usb_config_desc->wTotalLength); } static uint8_t usb_ep_set_nak(USBD_HandleTypeDef *dev, uint8_t ep_num) { - PCD_HandleTypeDef *hpcd = dev->pData; - USB_OTG_GlobalTypeDef *USBx = hpcd->Instance; - USBx_OUTEP(ep_num)->DOEPCTL |= USB_OTG_DOEPCTL_SNAK; - return USBD_OK; + PCD_HandleTypeDef *hpcd = dev->pData; + USB_OTG_GlobalTypeDef *USBx = hpcd->Instance; + USBx_OUTEP(ep_num)->DOEPCTL |= USB_OTG_DOEPCTL_SNAK; + return USBD_OK; } static uint8_t usb_ep_clear_nak(USBD_HandleTypeDef *dev, uint8_t ep_num) { - PCD_HandleTypeDef *hpcd = dev->pData; - USB_OTG_GlobalTypeDef *USBx = hpcd->Instance; - USBx_OUTEP(ep_num)->DOEPCTL |= USB_OTG_DOEPCTL_CNAK; - return USBD_OK; + PCD_HandleTypeDef *hpcd = dev->pData; + USB_OTG_GlobalTypeDef *USBx = hpcd->Instance; + USBx_OUTEP(ep_num)->DOEPCTL |= USB_OTG_DOEPCTL_CNAK; + return USBD_OK; } /* @@ -186,84 +205,93 @@ static uint8_t usb_ep_clear_nak(USBD_HandleTypeDef *dev, uint8_t ep_num) { * USB configuration (device & string descriptors) */ -static uint8_t *usb_get_dev_descriptor(USBD_SpeedTypeDef speed, uint16_t *length) { - *length = sizeof(usb_dev_desc); - return (uint8_t *)(&usb_dev_desc); +static uint8_t *usb_get_dev_descriptor(USBD_SpeedTypeDef speed, + uint16_t *length) { + *length = sizeof(usb_dev_desc); + return (uint8_t *)(&usb_dev_desc); } -static uint8_t *usb_get_langid_str_descriptor(USBD_SpeedTypeDef speed, uint16_t *length) { - static const usb_langid_descriptor_t usb_langid_str_desc = { - .bLength = USB_LEN_LANGID_STR_DESC, - .bDescriptorType = USB_DESC_TYPE_STRING, - .wData = USB_LANGID_ENGLISH_US, - }; - *length = sizeof(usb_langid_str_desc); - return UNCONST(&usb_langid_str_desc); +static uint8_t *usb_get_langid_str_descriptor(USBD_SpeedTypeDef speed, + uint16_t *length) { + static const usb_langid_descriptor_t usb_langid_str_desc = { + .bLength = USB_LEN_LANGID_STR_DESC, + .bDescriptorType = USB_DESC_TYPE_STRING, + .wData = USB_LANGID_ENGLISH_US, + }; + *length = sizeof(usb_langid_str_desc); + return UNCONST(&usb_langid_str_desc); } -static uint8_t *usb_get_manufacturer_str_descriptor(USBD_SpeedTypeDef speed, uint16_t *length) { - USBD_GetString((uint8_t *)usb_str_table.manufacturer, usb_str_buf, length); - return usb_str_buf; +static uint8_t *usb_get_manufacturer_str_descriptor(USBD_SpeedTypeDef speed, + uint16_t *length) { + USBD_GetString((uint8_t *)usb_str_table.manufacturer, usb_str_buf, length); + return usb_str_buf; } -static uint8_t *usb_get_product_str_descriptor(USBD_SpeedTypeDef speed, uint16_t *length) { - USBD_GetString((uint8_t *)usb_str_table.product, usb_str_buf, length); - return usb_str_buf; +static uint8_t *usb_get_product_str_descriptor(USBD_SpeedTypeDef speed, + uint16_t *length) { + USBD_GetString((uint8_t *)usb_str_table.product, usb_str_buf, length); + return usb_str_buf; } -static uint8_t *usb_get_serial_str_descriptor(USBD_SpeedTypeDef speed, uint16_t *length) { - USBD_GetString((uint8_t *)usb_str_table.serial_number, usb_str_buf, length); - return usb_str_buf; +static uint8_t *usb_get_serial_str_descriptor(USBD_SpeedTypeDef speed, + uint16_t *length) { + USBD_GetString((uint8_t *)usb_str_table.serial_number, usb_str_buf, length); + return usb_str_buf; } -static uint8_t *usb_get_configuration_str_descriptor(USBD_SpeedTypeDef speed, uint16_t *length) { - USBD_GetString((uint8_t *)"", usb_str_buf, length); - return usb_str_buf; +static uint8_t *usb_get_configuration_str_descriptor(USBD_SpeedTypeDef speed, + uint16_t *length) { + USBD_GetString((uint8_t *)"", usb_str_buf, length); + return usb_str_buf; } -static uint8_t *usb_get_interface_str_descriptor(USBD_SpeedTypeDef speed, uint16_t *length) { - USBD_GetString((uint8_t *)usb_str_table.interface, usb_str_buf, length); - return usb_str_buf; +static uint8_t *usb_get_interface_str_descriptor(USBD_SpeedTypeDef speed, + uint16_t *length) { + USBD_GetString((uint8_t *)usb_str_table.interface, usb_str_buf, length); + return usb_str_buf; } -static uint8_t *usb_get_bos_descriptor(USBD_SpeedTypeDef speed, uint16_t *length) { - if (sectrue == usb21_enabled) { - static uint8_t bos[] = { - // usb_bos_descriptor { - 0x05, // uint8_t bLength - USB_DESC_TYPE_BOS, // uint8_t bDescriptorType - 0x1d, 0x0, // uint16_t wTotalLength - 0x01, // uint8_t bNumDeviceCaps - // } - // usb_device_capability_descriptor { - 0x18, // uint8_t bLength - USB_DESC_TYPE_DEVICE_CAPABILITY, // uint8_t bDescriptorType - USB_DEVICE_CAPABILITY_PLATFORM, // uint8_t bDevCapabilityType - 0x00, // uint8_t bReserved - 0x38, 0xb6, 0x08, 0x34, 0xa9, 0x09, 0xa0, 0x47, 0x8b, 0xfd, 0xa0, 0x76, 0x88, 0x15, 0xb6, 0x65, // uint128_t platformCompatibilityUUID - 0x00, 0x01, // uint16_t bcdVersion - USB_WEBUSB_VENDOR_CODE, // uint8_t bVendorCode - USB_WEBUSB_LANDING_PAGE, // uint8_t iLandingPage - // } - }; - bos[28] = (sectrue == usb21_landing) ? USB_WEBUSB_LANDING_PAGE : 0; - *length = sizeof(bos); - return UNCONST(bos); - } else { - *length = 0; - return NULL; - } +static uint8_t *usb_get_bos_descriptor(USBD_SpeedTypeDef speed, + uint16_t *length) { + if (sectrue == usb21_enabled) { + static uint8_t bos[] = { + // usb_bos_descriptor { + 0x05, // uint8_t bLength + USB_DESC_TYPE_BOS, // uint8_t bDescriptorType + 0x1d, 0x0, // uint16_t wTotalLength + 0x01, // uint8_t bNumDeviceCaps + // } + // usb_device_capability_descriptor { + 0x18, // uint8_t bLength + USB_DESC_TYPE_DEVICE_CAPABILITY, // uint8_t bDescriptorType + USB_DEVICE_CAPABILITY_PLATFORM, // uint8_t bDevCapabilityType + 0x00, // uint8_t bReserved + 0x38, 0xb6, 0x08, 0x34, 0xa9, 0x09, 0xa0, 0x47, 0x8b, 0xfd, 0xa0, 0x76, + 0x88, 0x15, 0xb6, 0x65, // uint128_t platformCompatibilityUUID + 0x00, 0x01, // uint16_t bcdVersion + USB_WEBUSB_VENDOR_CODE, // uint8_t bVendorCode + USB_WEBUSB_LANDING_PAGE, // uint8_t iLandingPage + // } + }; + bos[28] = (sectrue == usb21_landing) ? USB_WEBUSB_LANDING_PAGE : 0; + *length = sizeof(bos); + return UNCONST(bos); + } else { + *length = 0; + return NULL; + } } static const USBD_DescriptorsTypeDef usb_descriptors = { - .GetDeviceDescriptor = usb_get_dev_descriptor, - .GetLangIDStrDescriptor = usb_get_langid_str_descriptor, - .GetManufacturerStrDescriptor = usb_get_manufacturer_str_descriptor, - .GetProductStrDescriptor = usb_get_product_str_descriptor, - .GetSerialStrDescriptor = usb_get_serial_str_descriptor, + .GetDeviceDescriptor = usb_get_dev_descriptor, + .GetLangIDStrDescriptor = usb_get_langid_str_descriptor, + .GetManufacturerStrDescriptor = usb_get_manufacturer_str_descriptor, + .GetProductStrDescriptor = usb_get_product_str_descriptor, + .GetSerialStrDescriptor = usb_get_serial_str_descriptor, .GetConfigurationStrDescriptor = usb_get_configuration_str_descriptor, - .GetInterfaceStrDescriptor = usb_get_interface_str_descriptor, - .GetBOSDescriptor = usb_get_bos_descriptor, + .GetInterfaceStrDescriptor = usb_get_interface_str_descriptor, + .GetBOSDescriptor = usb_get_bos_descriptor, }; /* @@ -271,233 +299,267 @@ static const USBD_DescriptorsTypeDef usb_descriptors = { */ static uint8_t usb_class_init(USBD_HandleTypeDef *dev, uint8_t cfg_idx) { - for (int i = 0; i < USBD_MAX_NUM_INTERFACES; i++) { - switch (usb_ifaces[i].type) { - case USB_IFACE_TYPE_HID: - usb_hid_class_init(dev, &usb_ifaces[i].hid, cfg_idx); - break; - case USB_IFACE_TYPE_VCP: - usb_vcp_class_init(dev, &usb_ifaces[i].vcp, cfg_idx); - break; - case USB_IFACE_TYPE_WEBUSB: - usb_webusb_class_init(dev, &usb_ifaces[i].webusb, cfg_idx); - break; - default: - break; - } + for (int i = 0; i < USBD_MAX_NUM_INTERFACES; i++) { + switch (usb_ifaces[i].type) { + case USB_IFACE_TYPE_HID: + usb_hid_class_init(dev, &usb_ifaces[i].hid, cfg_idx); + break; + case USB_IFACE_TYPE_VCP: + usb_vcp_class_init(dev, &usb_ifaces[i].vcp, cfg_idx); + break; + case USB_IFACE_TYPE_WEBUSB: + usb_webusb_class_init(dev, &usb_ifaces[i].webusb, cfg_idx); + break; + default: + break; } - return USBD_OK; + } + return USBD_OK; } static uint8_t usb_class_deinit(USBD_HandleTypeDef *dev, uint8_t cfg_idx) { - for (int i = 0; i < USBD_MAX_NUM_INTERFACES; i++) { - switch (usb_ifaces[i].type) { - case USB_IFACE_TYPE_HID: - usb_hid_class_deinit(dev, &usb_ifaces[i].hid, cfg_idx); - break; - case USB_IFACE_TYPE_VCP: - usb_vcp_class_deinit(dev, &usb_ifaces[i].vcp, cfg_idx); - break; - case USB_IFACE_TYPE_WEBUSB: - usb_webusb_class_deinit(dev, &usb_ifaces[i].webusb, cfg_idx); - break; - default: - break; - } + for (int i = 0; i < USBD_MAX_NUM_INTERFACES; i++) { + switch (usb_ifaces[i].type) { + case USB_IFACE_TYPE_HID: + usb_hid_class_deinit(dev, &usb_ifaces[i].hid, cfg_idx); + break; + case USB_IFACE_TYPE_VCP: + usb_vcp_class_deinit(dev, &usb_ifaces[i].vcp, cfg_idx); + break; + case USB_IFACE_TYPE_WEBUSB: + usb_webusb_class_deinit(dev, &usb_ifaces[i].webusb, cfg_idx); + break; + default: + break; } - return USBD_OK; + } + return USBD_OK; } -#define USB_WEBUSB_REQ_GET_URL 0x02 -#define USB_WEBUSB_DESCRIPTOR_TYPE_URL 0x03 -#define USB_WEBUSB_URL_SCHEME_HTTP 0 -#define USB_WEBUSB_URL_SCHEME_HTTPS 1 - -static uint8_t usb_class_setup(USBD_HandleTypeDef *dev, USBD_SetupReqTypedef *req) { - delay_random(); - if (((req->bmRequest & USB_REQ_TYPE_MASK) != USB_REQ_TYPE_CLASS) && - ((req->bmRequest & USB_REQ_TYPE_MASK) != USB_REQ_TYPE_STANDARD) && - ((req->bmRequest & USB_REQ_TYPE_MASK) != USB_REQ_TYPE_VENDOR)) { - return USBD_OK; - } - - if ((req->bmRequest & USB_REQ_TYPE_MASK) == USB_REQ_TYPE_VENDOR) { - if ((req->bmRequest & USB_REQ_RECIPIENT_MASK) == USB_REQ_RECIPIENT_DEVICE) { - if (sectrue == usb21_enabled && req->bRequest == USB_WEBUSB_VENDOR_CODE) { - if (req->wIndex == USB_WEBUSB_REQ_GET_URL && req->wValue == USB_WEBUSB_LANDING_PAGE) { - static const char webusb_url[] = { - 3 + 15, // uint8_t bLength - USB_WEBUSB_DESCRIPTOR_TYPE_URL, // uint8_t bDescriptorType - USB_WEBUSB_URL_SCHEME_HTTPS, // uint8_t bScheme - 't', 'r', 'e', 'z', 'o', 'r', '.', 'i', 'o', '/', 's', 't', 'a', 'r', 't', // char URL[] - }; - USBD_CtlSendData(dev, UNCONST(webusb_url), MIN_8bits(req->wLength, sizeof(webusb_url))); - return USBD_OK; - } else { - USBD_CtlError(dev, req); - return USBD_FAIL; - } - } - else - if (sectrue == usb21_enabled && req->bRequest == USB_WINUSB_VENDOR_CODE) { - if (req->wIndex == USB_WINUSB_REQ_GET_COMPATIBLE_ID_FEATURE_DESCRIPTOR) { - static const uint8_t winusb_wcid[] = { - // header - 0x28, 0x00, 0x00, 0x00, // dwLength - 0x00, 0x01, // bcdVersion - 0x04, 0x00, // wIndex - 0x01, // bNumSections - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // reserved - // functions - 0x00, // bInterfaceNumber - HACK: we present only interface 0 as WinUSB - 0x01, // reserved - 'W', 'I', 'N', 'U', 'S', 'B', 0x00, 0x00, // compatibleId - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // subCompatibleId - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // reserved - }; - USBD_CtlSendData(dev, UNCONST(winusb_wcid), MIN_8bits(req->wLength, sizeof(winusb_wcid))); - return USBD_OK; - } else { - USBD_CtlError(dev, req); - return USBD_FAIL; - } - } - } - if ((req->bmRequest & USB_REQ_RECIPIENT_MASK) == USB_REQ_RECIPIENT_INTERFACE) { - if (sectrue == usb21_enabled && req->bRequest == USB_WINUSB_VENDOR_CODE) { - if (req->wIndex == USB_WINUSB_REQ_GET_EXTENDED_PROPERTIES_OS_FEATURE_DESCRIPTOR && - (req->wValue & 0xFF) == 0) { // reply only if interface is 0 - static const uint8_t winusb_guid[] = { - // header - 0x92, 0x00, 0x00, 0x00, // dwLength - 0x00, 0x01, // bcdVersion - 0x05, 0x00, // wIndex - 0x01, 0x00, // wNumFeatures - // features - 0x88, 0x00, 0x00, 0x00, // dwLength - 0x07, 0x00, 0x00, 0x00, // dwPropertyDataType - 0x2A, 0x00, // wNameLength - 'D', 0x00, 'e', 0x00, 'v', 0x00, 'i', 0x00, 'c', 0x00, 'e', 0x00, 'I', 0x00, 'n', 0x00, 't', 0x00, 'e', 0x00, 'r', 0x00, 'f', 0x00, 'a', 0x00, 'c', 0x00, 'e', 0x00, 'G', 0x00, 'U', 0x00, 'I', 0x00, 'D', 0x00, 's', 0x00, 0x00, 0x00, // .name - 0x50, 0x00, 0x00, 0x00, // dwPropertyDataLength - '{', 0x00, 'c', 0x00, '6', 0x00, 'c', 0x00, '3', 0x00, '7', 0x00, '4', 0x00, 'a', 0x00, '6', 0x00, '-', 0x00, '2', 0x00, '2', 0x00, '8', 0x00, '5', 0x00, '-', 0x00, '4', 0x00, 'c', 0x00, 'b', 0x00, '8', 0x00, '-', 0x00, 'a', 0x00, 'b', 0x00, '4', 0x00, '3', 0x00, '-', 0x00, '1', 0x00, '7', 0x00, '6', 0x00, '4', 0x00, '7', 0x00, 'c', 0x00, 'e', 0x00, 'a', 0x00, '5', 0x00, '0', 0x00, '3', 0x00, 'd', 0x00, '}', 0x00, 0x00, 0x00, 0x00, 0x00, // propertyData - }; - USBD_CtlSendData(dev, UNCONST(winusb_guid), MIN_8bits(req->wLength, sizeof(winusb_guid))); - return USBD_OK; - } else { - USBD_CtlError(dev, req); - return USBD_FAIL; - } - } +#define USB_WEBUSB_REQ_GET_URL 0x02 +#define USB_WEBUSB_DESCRIPTOR_TYPE_URL 0x03 +#define USB_WEBUSB_URL_SCHEME_HTTP 0 +#define USB_WEBUSB_URL_SCHEME_HTTPS 1 + +static uint8_t usb_class_setup(USBD_HandleTypeDef *dev, + USBD_SetupReqTypedef *req) { + delay_random(); + if (((req->bmRequest & USB_REQ_TYPE_MASK) != USB_REQ_TYPE_CLASS) && + ((req->bmRequest & USB_REQ_TYPE_MASK) != USB_REQ_TYPE_STANDARD) && + ((req->bmRequest & USB_REQ_TYPE_MASK) != USB_REQ_TYPE_VENDOR)) { + return USBD_OK; + } + + if ((req->bmRequest & USB_REQ_TYPE_MASK) == USB_REQ_TYPE_VENDOR) { + if ((req->bmRequest & USB_REQ_RECIPIENT_MASK) == USB_REQ_RECIPIENT_DEVICE) { + if (sectrue == usb21_enabled && req->bRequest == USB_WEBUSB_VENDOR_CODE) { + if (req->wIndex == USB_WEBUSB_REQ_GET_URL && + req->wValue == USB_WEBUSB_LANDING_PAGE) { + static const char webusb_url[] = { + 3 + 15, // uint8_t bLength + USB_WEBUSB_DESCRIPTOR_TYPE_URL, // uint8_t bDescriptorType + USB_WEBUSB_URL_SCHEME_HTTPS, // uint8_t bScheme + 't', + 'r', + 'e', + 'z', + 'o', + 'r', + '.', + 'i', + 'o', + '/', + 's', + 't', + 'a', + 'r', + 't', // char URL[] + }; + USBD_CtlSendData(dev, UNCONST(webusb_url), + MIN_8bits(req->wLength, sizeof(webusb_url))); + return USBD_OK; + } else { + USBD_CtlError(dev, req); + return USBD_FAIL; } - } else - if ((req->bmRequest & USB_REQ_RECIPIENT_MASK) == USB_REQ_RECIPIENT_INTERFACE) { - if (req->wIndex >= USBD_MAX_NUM_INTERFACES) { - USBD_CtlError(dev, req); - return USBD_FAIL; + } else if (sectrue == usb21_enabled && + req->bRequest == USB_WINUSB_VENDOR_CODE) { + if (req->wIndex == + USB_WINUSB_REQ_GET_COMPATIBLE_ID_FEATURE_DESCRIPTOR) { + static const uint8_t winusb_wcid[] = { + // header + 0x28, 0x00, 0x00, 0x00, // dwLength + 0x00, 0x01, // bcdVersion + 0x04, 0x00, // wIndex + 0x01, // bNumSections + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // reserved + // functions + 0x00, // bInterfaceNumber - HACK: we present only interface 0 as + // WinUSB + 0x01, // reserved + 'W', 'I', 'N', 'U', 'S', 'B', 0x00, 0x00, // compatibleId + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, // subCompatibleId + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // reserved + }; + USBD_CtlSendData(dev, UNCONST(winusb_wcid), + MIN_8bits(req->wLength, sizeof(winusb_wcid))); + return USBD_OK; + } else { + USBD_CtlError(dev, req); + return USBD_FAIL; } - switch (usb_ifaces[req->wIndex].type) { - case USB_IFACE_TYPE_HID: - return usb_hid_class_setup(dev, &usb_ifaces[req->wIndex].hid, req); - case USB_IFACE_TYPE_VCP: - return usb_vcp_class_setup(dev, &usb_ifaces[req->wIndex].vcp, req); - case USB_IFACE_TYPE_WEBUSB: - return usb_webusb_class_setup(dev, &usb_ifaces[req->wIndex].webusb, req); - default: - USBD_CtlError(dev, req); - return USBD_FAIL; + } + } + if ((req->bmRequest & USB_REQ_RECIPIENT_MASK) == + USB_REQ_RECIPIENT_INTERFACE) { + if (sectrue == usb21_enabled && req->bRequest == USB_WINUSB_VENDOR_CODE) { + if (req->wIndex == + USB_WINUSB_REQ_GET_EXTENDED_PROPERTIES_OS_FEATURE_DESCRIPTOR && + (req->wValue & 0xFF) == 0) { // reply only if interface is 0 + static const uint8_t winusb_guid[] = { + // header + 0x92, 0x00, 0x00, 0x00, // dwLength + 0x00, 0x01, // bcdVersion + 0x05, 0x00, // wIndex + 0x01, 0x00, // wNumFeatures + // features + 0x88, 0x00, 0x00, 0x00, // dwLength + 0x07, 0x00, 0x00, 0x00, // dwPropertyDataType + 0x2A, 0x00, // wNameLength + 'D', 0x00, 'e', 0x00, 'v', 0x00, 'i', 0x00, 'c', 0x00, 'e', 0x00, + 'I', 0x00, 'n', 0x00, 't', 0x00, 'e', 0x00, 'r', 0x00, 'f', 0x00, + 'a', 0x00, 'c', 0x00, 'e', 0x00, 'G', 0x00, 'U', 0x00, 'I', 0x00, + 'D', 0x00, 's', 0x00, 0x00, 0x00, // .name + 0x50, 0x00, 0x00, 0x00, // dwPropertyDataLength + '{', 0x00, 'c', 0x00, '6', 0x00, 'c', 0x00, '3', 0x00, '7', 0x00, + '4', 0x00, 'a', 0x00, '6', 0x00, '-', 0x00, '2', 0x00, '2', 0x00, + '8', 0x00, '5', 0x00, '-', 0x00, '4', 0x00, 'c', 0x00, 'b', 0x00, + '8', 0x00, '-', 0x00, 'a', 0x00, 'b', 0x00, '4', 0x00, '3', 0x00, + '-', 0x00, '1', 0x00, '7', 0x00, '6', 0x00, '4', 0x00, '7', 0x00, + 'c', 0x00, 'e', 0x00, 'a', 0x00, '5', 0x00, '0', 0x00, '3', 0x00, + 'd', 0x00, '}', 0x00, 0x00, 0x00, 0x00, 0x00, // propertyData + }; + USBD_CtlSendData(dev, UNCONST(winusb_guid), + MIN_8bits(req->wLength, sizeof(winusb_guid))); + return USBD_OK; + } else { + USBD_CtlError(dev, req); + return USBD_FAIL; } + } } - return USBD_OK; + } else if ((req->bmRequest & USB_REQ_RECIPIENT_MASK) == + USB_REQ_RECIPIENT_INTERFACE) { + if (req->wIndex >= USBD_MAX_NUM_INTERFACES) { + USBD_CtlError(dev, req); + return USBD_FAIL; + } + switch (usb_ifaces[req->wIndex].type) { + case USB_IFACE_TYPE_HID: + return usb_hid_class_setup(dev, &usb_ifaces[req->wIndex].hid, req); + case USB_IFACE_TYPE_VCP: + return usb_vcp_class_setup(dev, &usb_ifaces[req->wIndex].vcp, req); + case USB_IFACE_TYPE_WEBUSB: + return usb_webusb_class_setup(dev, &usb_ifaces[req->wIndex].webusb, + req); + default: + USBD_CtlError(dev, req); + return USBD_FAIL; + } + } + return USBD_OK; } static uint8_t usb_class_data_in(USBD_HandleTypeDef *dev, uint8_t ep_num) { - delay_random(); - for (int i = 0; i < USBD_MAX_NUM_INTERFACES; i++) { - switch (usb_ifaces[i].type) { - case USB_IFACE_TYPE_HID: - usb_hid_class_data_in(dev, &usb_ifaces[i].hid, ep_num); - break; - case USB_IFACE_TYPE_VCP: - usb_vcp_class_data_in(dev, &usb_ifaces[i].vcp, ep_num); - break; - case USB_IFACE_TYPE_WEBUSB: - usb_webusb_class_data_in(dev, &usb_ifaces[i].webusb, ep_num); - break; - default: - break; - } + delay_random(); + for (int i = 0; i < USBD_MAX_NUM_INTERFACES; i++) { + switch (usb_ifaces[i].type) { + case USB_IFACE_TYPE_HID: + usb_hid_class_data_in(dev, &usb_ifaces[i].hid, ep_num); + break; + case USB_IFACE_TYPE_VCP: + usb_vcp_class_data_in(dev, &usb_ifaces[i].vcp, ep_num); + break; + case USB_IFACE_TYPE_WEBUSB: + usb_webusb_class_data_in(dev, &usb_ifaces[i].webusb, ep_num); + break; + default: + break; } - return USBD_OK; + } + return USBD_OK; } static uint8_t usb_class_data_out(USBD_HandleTypeDef *dev, uint8_t ep_num) { - delay_random(); - for (int i = 0; i < USBD_MAX_NUM_INTERFACES; i++) { - switch (usb_ifaces[i].type) { - case USB_IFACE_TYPE_HID: - usb_hid_class_data_out(dev, &usb_ifaces[i].hid, ep_num); - break; - case USB_IFACE_TYPE_VCP: - usb_vcp_class_data_out(dev, &usb_ifaces[i].vcp, ep_num); - break; - case USB_IFACE_TYPE_WEBUSB: - usb_webusb_class_data_out(dev, &usb_ifaces[i].webusb, ep_num); - break; - default: - break; - } + delay_random(); + for (int i = 0; i < USBD_MAX_NUM_INTERFACES; i++) { + switch (usb_ifaces[i].type) { + case USB_IFACE_TYPE_HID: + usb_hid_class_data_out(dev, &usb_ifaces[i].hid, ep_num); + break; + case USB_IFACE_TYPE_VCP: + usb_vcp_class_data_out(dev, &usb_ifaces[i].vcp, ep_num); + break; + case USB_IFACE_TYPE_WEBUSB: + usb_webusb_class_data_out(dev, &usb_ifaces[i].webusb, ep_num); + break; + default: + break; } - return USBD_OK; + } + return USBD_OK; } static uint8_t usb_class_sof(USBD_HandleTypeDef *dev) { - delay_random(); - for (int i = 0; i < USBD_MAX_NUM_INTERFACES; i++) { - switch (usb_ifaces[i].type) { - case USB_IFACE_TYPE_VCP: - usb_vcp_class_sof(dev, &usb_ifaces[i].vcp); - break; - default: - break; - } + delay_random(); + for (int i = 0; i < USBD_MAX_NUM_INTERFACES; i++) { + switch (usb_ifaces[i].type) { + case USB_IFACE_TYPE_VCP: + usb_vcp_class_sof(dev, &usb_ifaces[i].vcp); + break; + default: + break; } - return USBD_OK; + } + return USBD_OK; } static uint8_t *usb_class_get_cfg_desc(uint16_t *length) { - *length = usb_config_desc->wTotalLength; - return usb_config_buf; + *length = usb_config_desc->wTotalLength; + return usb_config_buf; } -static uint8_t *usb_class_get_usrstr_desc(USBD_HandleTypeDef *dev, uint8_t index, uint16_t *length) { - if (sectrue == usb21_enabled && index == USB_WINUSB_EXTRA_STRING_INDEX) { - static const uint8_t winusb_string_descriptor[] = { - 0x12, // bLength - USB_DESC_TYPE_STRING, // bDescriptorType - USB_WINUSB_EXTRA_STRING // wData - }; - *length = sizeof(winusb_string_descriptor); - return UNCONST(winusb_string_descriptor); - } else { - *length = 0; - return NULL; - } +static uint8_t *usb_class_get_usrstr_desc(USBD_HandleTypeDef *dev, + uint8_t index, uint16_t *length) { + if (sectrue == usb21_enabled && index == USB_WINUSB_EXTRA_STRING_INDEX) { + static const uint8_t winusb_string_descriptor[] = { + 0x12, // bLength + USB_DESC_TYPE_STRING, // bDescriptorType + USB_WINUSB_EXTRA_STRING // wData + }; + *length = sizeof(winusb_string_descriptor); + return UNCONST(winusb_string_descriptor); + } else { + *length = 0; + return NULL; + } } static const USBD_ClassTypeDef usb_class = { - .Init = usb_class_init, - .DeInit = usb_class_deinit, - .Setup = usb_class_setup, - .EP0_TxSent = NULL, - .EP0_RxReady = NULL, - .DataIn = usb_class_data_in, - .DataOut = usb_class_data_out, - .SOF = usb_class_sof, - .IsoINIncomplete = NULL, - .IsoOUTIncomplete = NULL, - .GetHSConfigDescriptor = usb_class_get_cfg_desc, - .GetFSConfigDescriptor = usb_class_get_cfg_desc, + .Init = usb_class_init, + .DeInit = usb_class_deinit, + .Setup = usb_class_setup, + .EP0_TxSent = NULL, + .EP0_RxReady = NULL, + .DataIn = usb_class_data_in, + .DataOut = usb_class_data_out, + .SOF = usb_class_sof, + .IsoINIncomplete = NULL, + .IsoOUTIncomplete = NULL, + .GetHSConfigDescriptor = usb_class_get_cfg_desc, + .GetFSConfigDescriptor = usb_class_get_cfg_desc, .GetOtherSpeedConfigDescriptor = usb_class_get_cfg_desc, - .GetDeviceQualifierDescriptor = NULL, - .GetUsrStrDescriptor = usb_class_get_usrstr_desc, + .GetDeviceQualifierDescriptor = NULL, + .GetUsrStrDescriptor = usb_class_get_usrstr_desc, }; diff --git a/embed/trezorhal/usb.h b/embed/trezorhal/usb.h index 35fcc9258..efb40ea75 100644 --- a/embed/trezorhal/usb.h +++ b/embed/trezorhal/usb.h @@ -23,107 +23,107 @@ #include #include "secbool.h" -#define USB_EP_DIR_MASK 0x80 -#define USB_EP_DIR_OUT 0x00 -#define USB_EP_DIR_IN 0x80 +#define USB_EP_DIR_MASK 0x80 +#define USB_EP_DIR_OUT 0x00 +#define USB_EP_DIR_IN 0x80 typedef struct __attribute__((packed)) { - uint8_t bLength; - uint8_t bDescriptorType; - uint16_t bcdUSB; - uint8_t bDeviceClass; - uint8_t bDeviceSubClass; - uint8_t bDeviceProtocol; - uint8_t bMaxPacketSize0; - uint16_t idVendor; - uint16_t idProduct; - uint16_t bcdDevice; - uint8_t iManufacturer; - uint8_t iProduct; - uint8_t iSerialNumber; - uint8_t bNumConfigurations; + uint8_t bLength; + uint8_t bDescriptorType; + uint16_t bcdUSB; + uint8_t bDeviceClass; + uint8_t bDeviceSubClass; + uint8_t bDeviceProtocol; + uint8_t bMaxPacketSize0; + uint16_t idVendor; + uint16_t idProduct; + uint16_t bcdDevice; + uint8_t iManufacturer; + uint8_t iProduct; + uint8_t iSerialNumber; + uint8_t bNumConfigurations; } usb_device_descriptor_t; typedef struct __attribute__((packed)) { - uint8_t bLength; - uint8_t bDescriptorType; - uint16_t wData; + uint8_t bLength; + uint8_t bDescriptorType; + uint16_t wData; } usb_langid_descriptor_t; typedef struct __attribute__((packed)) { - uint8_t bLength; - uint8_t bDescriptorType; - uint16_t wTotalLength; - uint8_t bNumInterfaces; - uint8_t bConfigurationValue; - uint8_t iConfiguration; - uint8_t bmAttributes; - uint8_t bMaxPower; + uint8_t bLength; + uint8_t bDescriptorType; + uint16_t wTotalLength; + uint8_t bNumInterfaces; + uint8_t bConfigurationValue; + uint8_t iConfiguration; + uint8_t bmAttributes; + uint8_t bMaxPower; } usb_config_descriptor_t; typedef struct __attribute__((packed)) { - uint8_t bLength; - uint8_t bDescriptorType; - uint8_t bInterfaceNumber; - uint8_t bAlternateSetting; - uint8_t bNumEndpoints; - uint8_t bInterfaceClass; - uint8_t bInterfaceSubClass; - uint8_t bInterfaceProtocol; - uint8_t iInterface; + uint8_t bLength; + uint8_t bDescriptorType; + uint8_t bInterfaceNumber; + uint8_t bAlternateSetting; + uint8_t bNumEndpoints; + uint8_t bInterfaceClass; + uint8_t bInterfaceSubClass; + uint8_t bInterfaceProtocol; + uint8_t iInterface; } usb_interface_descriptor_t; typedef struct __attribute__((packed)) { - uint8_t bLength; - uint8_t bDescriptorType; - uint8_t bFirstInterface; - uint8_t bInterfaceCount; - uint8_t bFunctionClass; - uint8_t bFunctionSubClass; - uint8_t bFunctionProtocol; - uint8_t iFunction; + uint8_t bLength; + uint8_t bDescriptorType; + uint8_t bFirstInterface; + uint8_t bInterfaceCount; + uint8_t bFunctionClass; + uint8_t bFunctionSubClass; + uint8_t bFunctionProtocol; + uint8_t iFunction; } usb_interface_assoc_descriptor_t; typedef struct __attribute__((packed)) { - uint8_t bLength; - uint8_t bDescriptorType; - uint8_t bEndpointAddress; - uint8_t bmAttributes; - uint16_t wMaxPacketSize; - uint8_t bInterval; + uint8_t bLength; + uint8_t bDescriptorType; + uint8_t bEndpointAddress; + uint8_t bmAttributes; + uint16_t wMaxPacketSize; + uint8_t bInterval; } usb_endpoint_descriptor_t; typedef enum { - USB_LANGID_ENGLISH_US = 0x409, + USB_LANGID_ENGLISH_US = 0x409, } usb_language_id_t; typedef struct { - const char *manufacturer; - const char *product; - const char *serial_number; - const char *interface; + const char *manufacturer; + const char *product; + const char *serial_number; + const char *interface; } usb_dev_string_table_t; typedef struct { - uint8_t device_class; - uint8_t device_subclass; - uint8_t device_protocol; - uint16_t vendor_id; - uint16_t product_id; - uint16_t release_num; - const char *manufacturer; - const char *product; - const char *serial_number; - const char *interface; - secbool usb21_enabled; - secbool usb21_landing; + uint8_t device_class; + uint8_t device_subclass; + uint8_t device_protocol; + uint16_t vendor_id; + uint16_t product_id; + uint16_t release_num; + const char *manufacturer; + const char *product; + const char *serial_number; + const char *interface; + secbool usb21_enabled; + secbool usb21_landing; } usb_dev_info_t; typedef enum { - USB_IFACE_TYPE_DISABLED = 0, - USB_IFACE_TYPE_VCP = 1, - USB_IFACE_TYPE_HID = 2, - USB_IFACE_TYPE_WEBUSB = 3, + USB_IFACE_TYPE_DISABLED = 0, + USB_IFACE_TYPE_VCP = 1, + USB_IFACE_TYPE_HID = 2, + USB_IFACE_TYPE_WEBUSB = 3, } usb_iface_type_t; #include "usb_hid-defs.h" @@ -131,12 +131,12 @@ typedef enum { #include "usb_webusb-defs.h" typedef struct { - union { - usb_hid_state_t hid; - usb_vcp_state_t vcp; - usb_webusb_state_t webusb; - }; - usb_iface_type_t type; + union { + usb_hid_state_t hid; + usb_vcp_state_t vcp; + usb_webusb_state_t webusb; + }; + usb_iface_type_t type; } usb_iface_t; void usb_init(const usb_dev_info_t *dev_info); diff --git a/embed/trezorhal/usb_hid-defs.h b/embed/trezorhal/usb_hid-defs.h index f1626c3ea..fa1c037d2 100644 --- a/embed/trezorhal/usb_hid-defs.h +++ b/embed/trezorhal/usb_hid-defs.h @@ -18,36 +18,36 @@ */ typedef struct __attribute__((packed)) { - uint8_t bLength; - uint8_t bDescriptorType; - uint16_t bcdHID; - uint8_t bCountryCode; - uint8_t bNumDescriptors; - uint8_t bReportDescriptorType; - uint16_t wReportDescriptorLength; + uint8_t bLength; + uint8_t bDescriptorType; + uint16_t bcdHID; + uint8_t bCountryCode; + uint8_t bNumDescriptors; + uint8_t bReportDescriptorType; + uint16_t wReportDescriptorLength; } usb_hid_descriptor_t; typedef struct __attribute__((packed)) { - usb_interface_descriptor_t iface; - usb_hid_descriptor_t hid; - usb_endpoint_descriptor_t ep_in; - usb_endpoint_descriptor_t ep_out; + usb_interface_descriptor_t iface; + usb_hid_descriptor_t hid; + usb_endpoint_descriptor_t ep_in; + usb_endpoint_descriptor_t ep_out; } usb_hid_descriptor_block_t; /* usb_hid_info_t contains all information for setting up a HID interface. All * passed pointers need to live at least until the interface is disabled * (usb_stop is called). */ typedef struct { - const uint8_t *report_desc; // With length of report_desc_len bytes - uint8_t *rx_buffer; // With length of max_packet_len bytes - uint8_t iface_num; // Address of this HID interface - uint8_t ep_in; // Address of IN endpoint (with the highest bit set) - uint8_t ep_out; // Address of OUT endpoint - uint8_t subclass; // usb_iface_subclass_t - uint8_t protocol; // usb_iface_protocol_t - uint8_t polling_interval; // In units of 1ms - uint8_t max_packet_len; // Length of the biggest report and of rx_buffer - uint8_t report_desc_len; // Length of report_desc + const uint8_t *report_desc; // With length of report_desc_len bytes + uint8_t *rx_buffer; // With length of max_packet_len bytes + uint8_t iface_num; // Address of this HID interface + uint8_t ep_in; // Address of IN endpoint (with the highest bit set) + uint8_t ep_out; // Address of OUT endpoint + uint8_t subclass; // usb_iface_subclass_t + uint8_t protocol; // usb_iface_protocol_t + uint8_t polling_interval; // In units of 1ms + uint8_t max_packet_len; // Length of the biggest report and of rx_buffer + uint8_t report_desc_len; // Length of report_desc } usb_hid_info_t; /* usb_hid_state_t encapsulates all state used by enabled HID interface. It @@ -55,19 +55,19 @@ typedef struct { * usb_hid_class_init. See usb_hid_info_t for details of the configuration * fields. */ typedef struct { - const usb_hid_descriptor_block_t *desc_block; - const uint8_t *report_desc; - uint8_t *rx_buffer; - uint8_t ep_in; - uint8_t ep_out; - uint8_t max_packet_len; - uint8_t report_desc_len; + const usb_hid_descriptor_block_t *desc_block; + const uint8_t *report_desc; + uint8_t *rx_buffer; + uint8_t ep_in; + uint8_t ep_out; + uint8_t max_packet_len; + uint8_t report_desc_len; - uint8_t protocol; // For SET_PROTOCOL/GET_PROTOCOL setup reqs - uint8_t idle_rate; // For SET_IDLE/GET_IDLE setup reqs - uint8_t alt_setting; // For SET_INTERFACE/GET_INTERFACE setup reqs - uint8_t last_read_len; // Length of data read into rx_buffer - uint8_t ep_in_is_idle; // Set to 1 after IN endpoint gets idle + uint8_t protocol; // For SET_PROTOCOL/GET_PROTOCOL setup reqs + uint8_t idle_rate; // For SET_IDLE/GET_IDLE setup reqs + uint8_t alt_setting; // For SET_INTERFACE/GET_INTERFACE setup reqs + uint8_t last_read_len; // Length of data read into rx_buffer + uint8_t ep_in_is_idle; // Set to 1 after IN endpoint gets idle } usb_hid_state_t; secbool __wur usb_hid_add(const usb_hid_info_t *hid_info); @@ -77,5 +77,7 @@ int __wur usb_hid_read(uint8_t iface_num, uint8_t *buf, uint32_t len); int __wur usb_hid_write(uint8_t iface_num, const uint8_t *buf, uint32_t len); int __wur usb_hid_read_select(uint32_t timeout); -int __wur usb_hid_read_blocking(uint8_t iface_num, uint8_t *buf, uint32_t len, int timeout); -int __wur usb_hid_write_blocking(uint8_t iface_num, const uint8_t *buf, uint32_t len, int timeout); +int __wur usb_hid_read_blocking(uint8_t iface_num, uint8_t *buf, uint32_t len, + int timeout); +int __wur usb_hid_write_blocking(uint8_t iface_num, const uint8_t *buf, + uint32_t len, int timeout); diff --git a/embed/trezorhal/usb_hid-impl.h b/embed/trezorhal/usb_hid-impl.h index 7b20c9bee..9ad47839e 100644 --- a/embed/trezorhal/usb_hid-impl.h +++ b/embed/trezorhal/usb_hid-impl.h @@ -17,330 +17,340 @@ * along with this program. If not, see . */ -#define USB_CLASS_HID 0x03 +#define USB_CLASS_HID 0x03 -#define USB_DESC_TYPE_HID 0x21 -#define USB_DESC_TYPE_REPORT 0x22 +#define USB_DESC_TYPE_HID 0x21 +#define USB_DESC_TYPE_REPORT 0x22 -#define USB_HID_REQ_SET_PROTOCOL 0x0B -#define USB_HID_REQ_GET_PROTOCOL 0x03 -#define USB_HID_REQ_SET_IDLE 0x0A -#define USB_HID_REQ_GET_IDLE 0x02 +#define USB_HID_REQ_SET_PROTOCOL 0x0B +#define USB_HID_REQ_GET_PROTOCOL 0x03 +#define USB_HID_REQ_SET_IDLE 0x0A +#define USB_HID_REQ_GET_IDLE 0x02 /* usb_hid_add adds and configures new USB HID interface according to * configuration options passed in `info`. */ secbool usb_hid_add(const usb_hid_info_t *info) { - - usb_iface_t *iface = usb_get_iface(info->iface_num); - - if (iface == NULL) { - return secfalse; // Invalid interface number - } - if (iface->type != USB_IFACE_TYPE_DISABLED) { - return secfalse; // Interface is already enabled - } - - usb_hid_descriptor_block_t *d = usb_desc_alloc_iface(sizeof(usb_hid_descriptor_block_t)); - - if (d == NULL) { - return secfalse; // Not enough space in the configuration descriptor - } - - if ((info->ep_in & USB_EP_DIR_MASK) != USB_EP_DIR_IN) { - return secfalse; // IN EP is invalid - } - if ((info->ep_out & USB_EP_DIR_MASK) != USB_EP_DIR_OUT) { - return secfalse; // OUT EP is invalid - } - if (info->rx_buffer == NULL) { - return secfalse; - } - if (info->report_desc == NULL) { - return secfalse; - } - - // Interface descriptor - d->iface.bLength = sizeof(usb_interface_descriptor_t); - d->iface.bDescriptorType = USB_DESC_TYPE_INTERFACE; - d->iface.bInterfaceNumber = info->iface_num; - d->iface.bAlternateSetting = 0; - d->iface.bNumEndpoints = 2; - d->iface.bInterfaceClass = USB_CLASS_HID; - d->iface.bInterfaceSubClass = info->subclass; - d->iface.bInterfaceProtocol = info->protocol; - d->iface.iInterface = USBD_IDX_INTERFACE_STR; - - // HID descriptor - d->hid.bLength = sizeof(usb_hid_descriptor_t); - d->hid.bDescriptorType = USB_DESC_TYPE_HID; - d->hid.bcdHID = 0x0111; // HID Class Spec release number (1.11) - d->hid.bCountryCode = 0; // Hardware target country - d->hid.bNumDescriptors = 1; // Number of HID class descriptors - d->hid.bReportDescriptorType = USB_DESC_TYPE_REPORT; - d->hid.wReportDescriptorLength = info->report_desc_len; - - // IN endpoint (sending) - d->ep_in.bLength = sizeof(usb_endpoint_descriptor_t); - d->ep_in.bDescriptorType = USB_DESC_TYPE_ENDPOINT; - d->ep_in.bEndpointAddress = info->ep_in; - d->ep_in.bmAttributes = USBD_EP_TYPE_INTR; - d->ep_in.wMaxPacketSize = info->max_packet_len; - d->ep_in.bInterval = info->polling_interval; - - // OUT endpoint (receiving) - d->ep_out.bLength = sizeof(usb_endpoint_descriptor_t); - d->ep_out.bDescriptorType = USB_DESC_TYPE_ENDPOINT; - d->ep_out.bEndpointAddress = info->ep_out; - d->ep_out.bmAttributes = USBD_EP_TYPE_INTR; - d->ep_out.wMaxPacketSize = info->max_packet_len; - d->ep_out.bInterval = info->polling_interval; - - // Config descriptor - usb_desc_add_iface(sizeof(usb_hid_descriptor_block_t)); - - // Interface state - iface->type = USB_IFACE_TYPE_HID; - iface->hid.desc_block = d; - iface->hid.report_desc = info->report_desc; - iface->hid.rx_buffer = info->rx_buffer; - iface->hid.ep_in = info->ep_in; - iface->hid.ep_out = info->ep_out; - iface->hid.max_packet_len = info->max_packet_len; - iface->hid.report_desc_len = info->report_desc_len; - iface->hid.protocol = 0; - iface->hid.idle_rate = 0; - iface->hid.alt_setting = 0; - iface->hid.last_read_len = 0; - iface->hid.ep_in_is_idle = 1; - - return sectrue; + usb_iface_t *iface = usb_get_iface(info->iface_num); + + if (iface == NULL) { + return secfalse; // Invalid interface number + } + if (iface->type != USB_IFACE_TYPE_DISABLED) { + return secfalse; // Interface is already enabled + } + + usb_hid_descriptor_block_t *d = + usb_desc_alloc_iface(sizeof(usb_hid_descriptor_block_t)); + + if (d == NULL) { + return secfalse; // Not enough space in the configuration descriptor + } + + if ((info->ep_in & USB_EP_DIR_MASK) != USB_EP_DIR_IN) { + return secfalse; // IN EP is invalid + } + if ((info->ep_out & USB_EP_DIR_MASK) != USB_EP_DIR_OUT) { + return secfalse; // OUT EP is invalid + } + if (info->rx_buffer == NULL) { + return secfalse; + } + if (info->report_desc == NULL) { + return secfalse; + } + + // Interface descriptor + d->iface.bLength = sizeof(usb_interface_descriptor_t); + d->iface.bDescriptorType = USB_DESC_TYPE_INTERFACE; + d->iface.bInterfaceNumber = info->iface_num; + d->iface.bAlternateSetting = 0; + d->iface.bNumEndpoints = 2; + d->iface.bInterfaceClass = USB_CLASS_HID; + d->iface.bInterfaceSubClass = info->subclass; + d->iface.bInterfaceProtocol = info->protocol; + d->iface.iInterface = USBD_IDX_INTERFACE_STR; + + // HID descriptor + d->hid.bLength = sizeof(usb_hid_descriptor_t); + d->hid.bDescriptorType = USB_DESC_TYPE_HID; + d->hid.bcdHID = 0x0111; // HID Class Spec release number (1.11) + d->hid.bCountryCode = 0; // Hardware target country + d->hid.bNumDescriptors = 1; // Number of HID class descriptors + d->hid.bReportDescriptorType = USB_DESC_TYPE_REPORT; + d->hid.wReportDescriptorLength = info->report_desc_len; + + // IN endpoint (sending) + d->ep_in.bLength = sizeof(usb_endpoint_descriptor_t); + d->ep_in.bDescriptorType = USB_DESC_TYPE_ENDPOINT; + d->ep_in.bEndpointAddress = info->ep_in; + d->ep_in.bmAttributes = USBD_EP_TYPE_INTR; + d->ep_in.wMaxPacketSize = info->max_packet_len; + d->ep_in.bInterval = info->polling_interval; + + // OUT endpoint (receiving) + d->ep_out.bLength = sizeof(usb_endpoint_descriptor_t); + d->ep_out.bDescriptorType = USB_DESC_TYPE_ENDPOINT; + d->ep_out.bEndpointAddress = info->ep_out; + d->ep_out.bmAttributes = USBD_EP_TYPE_INTR; + d->ep_out.wMaxPacketSize = info->max_packet_len; + d->ep_out.bInterval = info->polling_interval; + + // Config descriptor + usb_desc_add_iface(sizeof(usb_hid_descriptor_block_t)); + + // Interface state + iface->type = USB_IFACE_TYPE_HID; + iface->hid.desc_block = d; + iface->hid.report_desc = info->report_desc; + iface->hid.rx_buffer = info->rx_buffer; + iface->hid.ep_in = info->ep_in; + iface->hid.ep_out = info->ep_out; + iface->hid.max_packet_len = info->max_packet_len; + iface->hid.report_desc_len = info->report_desc_len; + iface->hid.protocol = 0; + iface->hid.idle_rate = 0; + iface->hid.alt_setting = 0; + iface->hid.last_read_len = 0; + iface->hid.ep_in_is_idle = 1; + + return sectrue; } secbool usb_hid_can_read(uint8_t iface_num) { - usb_iface_t *iface = usb_get_iface(iface_num); - if (iface == NULL) { - return secfalse; // Invalid interface number - } - if (iface->type != USB_IFACE_TYPE_HID) { - return secfalse; // Invalid interface type - } - if (iface->hid.last_read_len == 0) { - return secfalse; // Nothing in the receiving buffer - } - if (usb_dev_handle.dev_state != USBD_STATE_CONFIGURED) { - return secfalse; // Device is not configured - } - return sectrue; + usb_iface_t *iface = usb_get_iface(iface_num); + if (iface == NULL) { + return secfalse; // Invalid interface number + } + if (iface->type != USB_IFACE_TYPE_HID) { + return secfalse; // Invalid interface type + } + if (iface->hid.last_read_len == 0) { + return secfalse; // Nothing in the receiving buffer + } + if (usb_dev_handle.dev_state != USBD_STATE_CONFIGURED) { + return secfalse; // Device is not configured + } + return sectrue; } secbool usb_hid_can_write(uint8_t iface_num) { - usb_iface_t *iface = usb_get_iface(iface_num); - if (iface == NULL) { - return secfalse; // Invalid interface number - } - if (iface->type != USB_IFACE_TYPE_HID) { - return secfalse; // Invalid interface type - } - if (iface->hid.ep_in_is_idle == 0) { - return secfalse; // Last transmission is not over yet - } - if (usb_dev_handle.dev_state != USBD_STATE_CONFIGURED) { - return secfalse; // Device is not configured - } - return sectrue; + usb_iface_t *iface = usb_get_iface(iface_num); + if (iface == NULL) { + return secfalse; // Invalid interface number + } + if (iface->type != USB_IFACE_TYPE_HID) { + return secfalse; // Invalid interface type + } + if (iface->hid.ep_in_is_idle == 0) { + return secfalse; // Last transmission is not over yet + } + if (usb_dev_handle.dev_state != USBD_STATE_CONFIGURED) { + return secfalse; // Device is not configured + } + return sectrue; } int usb_hid_read(uint8_t iface_num, uint8_t *buf, uint32_t len) { - usb_iface_t *iface = usb_get_iface(iface_num); - if (iface == NULL) { - return -1; // Invalid interface number - } - if (iface->type != USB_IFACE_TYPE_HID) { - return -2; // Invalid interface type - } - usb_hid_state_t *state = &iface->hid; - - // Copy maximum possible amount of data and truncate the buffer length - if (len < state->last_read_len) { - return 0; // Not enough data in the read buffer - } - len = state->last_read_len; - state->last_read_len = 0; - memcpy(buf, state->rx_buffer, len); - - // Clear NAK to indicate we are ready to read more data - usb_ep_clear_nak(&usb_dev_handle, state->ep_out); - - return len; + usb_iface_t *iface = usb_get_iface(iface_num); + if (iface == NULL) { + return -1; // Invalid interface number + } + if (iface->type != USB_IFACE_TYPE_HID) { + return -2; // Invalid interface type + } + usb_hid_state_t *state = &iface->hid; + + // Copy maximum possible amount of data and truncate the buffer length + if (len < state->last_read_len) { + return 0; // Not enough data in the read buffer + } + len = state->last_read_len; + state->last_read_len = 0; + memcpy(buf, state->rx_buffer, len); + + // Clear NAK to indicate we are ready to read more data + usb_ep_clear_nak(&usb_dev_handle, state->ep_out); + + return len; } int usb_hid_write(uint8_t iface_num, const uint8_t *buf, uint32_t len) { - usb_iface_t *iface = usb_get_iface(iface_num); - if (iface == NULL) { - return -1; // Invalid interface number - } - if (iface->type != USB_IFACE_TYPE_HID) { - return -2; // Invalid interface type - } - usb_hid_state_t *state = &iface->hid; - - state->ep_in_is_idle = 0; - USBD_LL_Transmit(&usb_dev_handle, state->ep_in, UNCONST(buf), (uint16_t)len); - - return len; + usb_iface_t *iface = usb_get_iface(iface_num); + if (iface == NULL) { + return -1; // Invalid interface number + } + if (iface->type != USB_IFACE_TYPE_HID) { + return -2; // Invalid interface type + } + usb_hid_state_t *state = &iface->hid; + + state->ep_in_is_idle = 0; + USBD_LL_Transmit(&usb_dev_handle, state->ep_in, UNCONST(buf), (uint16_t)len); + + return len; } int usb_hid_read_select(uint32_t timeout) { - const uint32_t start = HAL_GetTick(); - for (;;) { - for (int i = 0; i < USBD_MAX_NUM_INTERFACES; i++) { - if (sectrue == usb_hid_can_read(i)) { - return i; - } - } - if (HAL_GetTick() - start >= timeout) { - break; - } - __WFI(); // Enter sleep mode, waiting for interrupt + const uint32_t start = HAL_GetTick(); + for (;;) { + for (int i = 0; i < USBD_MAX_NUM_INTERFACES; i++) { + if (sectrue == usb_hid_can_read(i)) { + return i; + } + } + if (HAL_GetTick() - start >= timeout) { + break; } - return -1; // Timeout + __WFI(); // Enter sleep mode, waiting for interrupt + } + return -1; // Timeout } -int usb_hid_read_blocking(uint8_t iface_num, uint8_t *buf, uint32_t len, int timeout) { - const uint32_t start = HAL_GetTick(); - while (sectrue != usb_hid_can_read(iface_num)) { - if (timeout >= 0 && HAL_GetTick() - start >= timeout) { - return 0; // Timeout - } - __WFI(); // Enter sleep mode, waiting for interrupt +int usb_hid_read_blocking(uint8_t iface_num, uint8_t *buf, uint32_t len, + int timeout) { + const uint32_t start = HAL_GetTick(); + while (sectrue != usb_hid_can_read(iface_num)) { + if (timeout >= 0 && HAL_GetTick() - start >= timeout) { + return 0; // Timeout } - return usb_hid_read(iface_num, buf, len); + __WFI(); // Enter sleep mode, waiting for interrupt + } + return usb_hid_read(iface_num, buf, len); } -int usb_hid_write_blocking(uint8_t iface_num, const uint8_t *buf, uint32_t len, int timeout) { - const uint32_t start = HAL_GetTick(); - while (sectrue != usb_hid_can_write(iface_num)) { - if (timeout >= 0 && HAL_GetTick() - start >= timeout) { - return 0; // Timeout - } - __WFI(); // Enter sleep mode, waiting for interrupt +int usb_hid_write_blocking(uint8_t iface_num, const uint8_t *buf, uint32_t len, + int timeout) { + const uint32_t start = HAL_GetTick(); + while (sectrue != usb_hid_can_write(iface_num)) { + if (timeout >= 0 && HAL_GetTick() - start >= timeout) { + return 0; // Timeout } - return usb_hid_write(iface_num, buf, len); + __WFI(); // Enter sleep mode, waiting for interrupt + } + return usb_hid_write(iface_num, buf, len); } -static void usb_hid_class_init(USBD_HandleTypeDef *dev, usb_hid_state_t *state, uint8_t cfg_idx) { - // Open endpoints - USBD_LL_OpenEP(dev, state->ep_in, USBD_EP_TYPE_INTR, state->max_packet_len); - USBD_LL_OpenEP(dev, state->ep_out, USBD_EP_TYPE_INTR, state->max_packet_len); - - // Reset the state - state->protocol = 0; - state->idle_rate = 0; - state->alt_setting = 0; - state->last_read_len = 0; - state->ep_in_is_idle = 1; - - // Prepare the OUT EP to receive next packet - USBD_LL_PrepareReceive(dev, state->ep_out, state->rx_buffer, state->max_packet_len); +static void usb_hid_class_init(USBD_HandleTypeDef *dev, usb_hid_state_t *state, + uint8_t cfg_idx) { + // Open endpoints + USBD_LL_OpenEP(dev, state->ep_in, USBD_EP_TYPE_INTR, state->max_packet_len); + USBD_LL_OpenEP(dev, state->ep_out, USBD_EP_TYPE_INTR, state->max_packet_len); + + // Reset the state + state->protocol = 0; + state->idle_rate = 0; + state->alt_setting = 0; + state->last_read_len = 0; + state->ep_in_is_idle = 1; + + // Prepare the OUT EP to receive next packet + USBD_LL_PrepareReceive(dev, state->ep_out, state->rx_buffer, + state->max_packet_len); } -static void usb_hid_class_deinit(USBD_HandleTypeDef *dev, usb_hid_state_t *state, uint8_t cfg_idx) { - // Flush endpoints - USBD_LL_FlushEP(dev, state->ep_in); - USBD_LL_FlushEP(dev, state->ep_out); - // Close endpoints - USBD_LL_CloseEP(dev, state->ep_in); - USBD_LL_CloseEP(dev, state->ep_out); +static void usb_hid_class_deinit(USBD_HandleTypeDef *dev, + usb_hid_state_t *state, uint8_t cfg_idx) { + // Flush endpoints + USBD_LL_FlushEP(dev, state->ep_in); + USBD_LL_FlushEP(dev, state->ep_out); + // Close endpoints + USBD_LL_CloseEP(dev, state->ep_in); + USBD_LL_CloseEP(dev, state->ep_out); } -static int usb_hid_class_setup(USBD_HandleTypeDef *dev, usb_hid_state_t *state, USBD_SetupReqTypedef *req) { - switch (req->bmRequest & USB_REQ_TYPE_MASK) { - - // Class request - case USB_REQ_TYPE_CLASS: - switch (req->bRequest) { - - case USB_HID_REQ_SET_PROTOCOL: - state->protocol = req->wValue; - USBD_CtlSendStatus(dev); - return USBD_OK; - - case USB_HID_REQ_GET_PROTOCOL: - USBD_CtlSendData(dev, &state->protocol, sizeof(state->protocol)); - return USBD_OK; - - case USB_HID_REQ_SET_IDLE: - state->idle_rate = req->wValue >> 8; - USBD_CtlSendStatus(dev); - return USBD_OK; - - case USB_HID_REQ_GET_IDLE: - USBD_CtlSendData(dev, &state->idle_rate, sizeof(state->idle_rate)); - return USBD_OK; - - default: - USBD_CtlError(dev, req); - return USBD_FAIL; - } - break; - - // Interface & Endpoint request - case USB_REQ_TYPE_STANDARD: - switch (req->bRequest) { - - case USB_REQ_SET_INTERFACE: - state->alt_setting = req->wValue; - USBD_CtlSendStatus(dev); - return USBD_OK; - - case USB_REQ_GET_INTERFACE: - USBD_CtlSendData(dev, &state->alt_setting, sizeof(state->alt_setting)); - return USBD_OK; - - case USB_REQ_GET_DESCRIPTOR: - switch (req->wValue >> 8) { - - case USB_DESC_TYPE_HID: - USBD_CtlSendData(dev, UNCONST(&state->desc_block->hid), MIN_8bits(req->wLength, sizeof(state->desc_block->hid))); - return USBD_OK; - - case USB_DESC_TYPE_REPORT: - USBD_CtlSendData(dev, UNCONST(state->report_desc), MIN_8bits(req->wLength, state->report_desc_len)); - return USBD_OK; - - default: - USBD_CtlError(dev, req); - return USBD_FAIL; - } - break; - - default: - USBD_CtlError(dev, req); - return USBD_FAIL; - } - break; - } - - return USBD_OK; +static int usb_hid_class_setup(USBD_HandleTypeDef *dev, usb_hid_state_t *state, + USBD_SetupReqTypedef *req) { + switch (req->bmRequest & USB_REQ_TYPE_MASK) { + // Class request + case USB_REQ_TYPE_CLASS: + switch (req->bRequest) { + case USB_HID_REQ_SET_PROTOCOL: + state->protocol = req->wValue; + USBD_CtlSendStatus(dev); + return USBD_OK; + + case USB_HID_REQ_GET_PROTOCOL: + USBD_CtlSendData(dev, &state->protocol, sizeof(state->protocol)); + return USBD_OK; + + case USB_HID_REQ_SET_IDLE: + state->idle_rate = req->wValue >> 8; + USBD_CtlSendStatus(dev); + return USBD_OK; + + case USB_HID_REQ_GET_IDLE: + USBD_CtlSendData(dev, &state->idle_rate, sizeof(state->idle_rate)); + return USBD_OK; + + default: + USBD_CtlError(dev, req); + return USBD_FAIL; + } + break; + + // Interface & Endpoint request + case USB_REQ_TYPE_STANDARD: + switch (req->bRequest) { + case USB_REQ_SET_INTERFACE: + state->alt_setting = req->wValue; + USBD_CtlSendStatus(dev); + return USBD_OK; + + case USB_REQ_GET_INTERFACE: + USBD_CtlSendData(dev, &state->alt_setting, + sizeof(state->alt_setting)); + return USBD_OK; + + case USB_REQ_GET_DESCRIPTOR: + switch (req->wValue >> 8) { + case USB_DESC_TYPE_HID: + USBD_CtlSendData( + dev, UNCONST(&state->desc_block->hid), + MIN_8bits(req->wLength, sizeof(state->desc_block->hid))); + return USBD_OK; + + case USB_DESC_TYPE_REPORT: + USBD_CtlSendData(dev, UNCONST(state->report_desc), + MIN_8bits(req->wLength, state->report_desc_len)); + return USBD_OK; + + default: + USBD_CtlError(dev, req); + return USBD_FAIL; + } + break; + + default: + USBD_CtlError(dev, req); + return USBD_FAIL; + } + break; + } + + return USBD_OK; } -static void usb_hid_class_data_in(USBD_HandleTypeDef *dev, usb_hid_state_t *state, uint8_t ep_num) { - if ((ep_num | USB_EP_DIR_IN) == state->ep_in) { - state->ep_in_is_idle = 1; - } +static void usb_hid_class_data_in(USBD_HandleTypeDef *dev, + usb_hid_state_t *state, uint8_t ep_num) { + if ((ep_num | USB_EP_DIR_IN) == state->ep_in) { + state->ep_in_is_idle = 1; + } } -static void usb_hid_class_data_out(USBD_HandleTypeDef *dev, usb_hid_state_t *state, uint8_t ep_num) { - if (ep_num == state->ep_out) { - state->last_read_len = USBD_LL_GetRxDataSize(dev, ep_num); +static void usb_hid_class_data_out(USBD_HandleTypeDef *dev, + usb_hid_state_t *state, uint8_t ep_num) { + if (ep_num == state->ep_out) { + state->last_read_len = USBD_LL_GetRxDataSize(dev, ep_num); - // Prepare the OUT EP to receive next packet - // User should provide state->rx_buffer that is big enough for state->max_packet_len bytes - USBD_LL_PrepareReceive(dev, ep_num, state->rx_buffer, state->max_packet_len); - - if (state->last_read_len > 0) { - // Block the OUT EP until we process received data - usb_ep_set_nak(dev, ep_num); - } + // Prepare the OUT EP to receive next packet + // User should provide state->rx_buffer that is big enough for + // state->max_packet_len bytes + USBD_LL_PrepareReceive(dev, ep_num, state->rx_buffer, + state->max_packet_len); + + if (state->last_read_len > 0) { + // Block the OUT EP until we process received data + usb_ep_set_nak(dev, ep_num); } + } } diff --git a/embed/trezorhal/usb_vcp-defs.h b/embed/trezorhal/usb_vcp-defs.h index a0c702b5c..a82ad33b9 100644 --- a/embed/trezorhal/usb_vcp-defs.h +++ b/embed/trezorhal/usb_vcp-defs.h @@ -20,119 +20,128 @@ #include typedef struct __attribute__((packed)) { - uint8_t bFunctionLength; - uint8_t bDescriptorType; - uint8_t bDescriptorSubtype; - uint16_t bcdCDC; + uint8_t bFunctionLength; + uint8_t bDescriptorType; + uint8_t bDescriptorSubtype; + uint16_t bcdCDC; } usb_vcp_header_descriptor_t; typedef struct __attribute__((packed)) { - uint8_t bFunctionLength; - uint8_t bDescriptorType; - uint8_t bDescriptorSubtype; - uint8_t bmCapabilities; - uint8_t bDataInterface; + uint8_t bFunctionLength; + uint8_t bDescriptorType; + uint8_t bDescriptorSubtype; + uint8_t bmCapabilities; + uint8_t bDataInterface; } usb_vcp_cm_descriptor_t; typedef struct __attribute__((packed)) { - uint8_t bFunctionLength; - uint8_t bDescriptorType; - uint8_t bDescriptorSubtype; - uint8_t bmCapabilities; + uint8_t bFunctionLength; + uint8_t bDescriptorType; + uint8_t bDescriptorSubtype; + uint8_t bmCapabilities; } usb_vcp_acm_descriptor_t; typedef struct __attribute__((packed)) { - uint8_t bFunctionLength; - uint8_t bDescriptorType; - uint8_t bDescriptorSubtype; - uint8_t bControlInterface; - uint8_t bSubordinateInterface0; + uint8_t bFunctionLength; + uint8_t bDescriptorType; + uint8_t bDescriptorSubtype; + uint8_t bControlInterface; + uint8_t bSubordinateInterface0; } usb_vcp_union_descriptor_t; typedef struct __attribute__((packed)) { - usb_interface_assoc_descriptor_t assoc; - usb_interface_descriptor_t iface_cdc; - usb_vcp_header_descriptor_t fheader; // Class-Specific Descriptor Header Format - usb_vcp_cm_descriptor_t fcm; // Call Management Functional Descriptor - usb_vcp_acm_descriptor_t facm; // Abstract Control Management Functional Descriptor - usb_vcp_union_descriptor_t funion; // Union Interface Functional Descriptor - usb_endpoint_descriptor_t ep_cmd; - usb_interface_descriptor_t iface_data; - usb_endpoint_descriptor_t ep_in; - usb_endpoint_descriptor_t ep_out; + usb_interface_assoc_descriptor_t assoc; + usb_interface_descriptor_t iface_cdc; + usb_vcp_header_descriptor_t + fheader; // Class-Specific Descriptor Header Format + usb_vcp_cm_descriptor_t fcm; // Call Management Functional Descriptor + usb_vcp_acm_descriptor_t + facm; // Abstract Control Management Functional Descriptor + usb_vcp_union_descriptor_t funion; // Union Interface Functional Descriptor + usb_endpoint_descriptor_t ep_cmd; + usb_interface_descriptor_t iface_data; + usb_endpoint_descriptor_t ep_in; + usb_endpoint_descriptor_t ep_out; } usb_vcp_descriptor_block_t; typedef struct __attribute__((packed)) { - uint32_t dwDTERate; - uint8_t bCharFormat; // usb_cdc_line_coding_bCharFormat_t - uint8_t bParityType; // usb_cdc_line_coding_bParityType_t - uint8_t bDataBits; + uint32_t dwDTERate; + uint8_t bCharFormat; // usb_cdc_line_coding_bCharFormat_t + uint8_t bParityType; // usb_cdc_line_coding_bParityType_t + uint8_t bDataBits; } usb_cdc_line_coding_t; typedef enum { - USB_CDC_1_STOP_BITS = 0, - USB_CDC_1_5_STOP_BITS = 1, - USB_CDC_2_STOP_BITS = 2, + USB_CDC_1_STOP_BITS = 0, + USB_CDC_1_5_STOP_BITS = 1, + USB_CDC_2_STOP_BITS = 2, } usb_cdc_line_coding_bCharFormat_t; typedef enum { - USB_CDC_NO_PARITY = 0, - USB_CDC_ODD_PARITY = 1, - USB_CDC_EVEN_PARITY = 2, - USB_CDC_MARK_PARITY = 3, - USB_CDC_SPACE_PARITY = 4, + USB_CDC_NO_PARITY = 0, + USB_CDC_ODD_PARITY = 1, + USB_CDC_EVEN_PARITY = 2, + USB_CDC_MARK_PARITY = 3, + USB_CDC_SPACE_PARITY = 4, } usb_cdc_line_coding_bParityType_t; /* usb_vcp_info_t contains all information for setting up a VCP interface. All * passed pointers need to live at least until the interface is disabled * (usb_stop is called). */ typedef struct { - uint8_t *tx_packet; // Buffer for one packet, with length of at least max_packet_len bytes - uint8_t *tx_buffer; // Buffer for IN EP ring buffer, with length of at least tx_buffer_len bytes - uint8_t *rx_packet; // Buffer for one packet, with length of at least max_packet_len bytes - uint8_t *rx_buffer; // Buffer for OUT EP ring buffer, with length of at least rx_buffer_len bytes - size_t tx_buffer_len; // Length of tx_buffer, needs to be a power of 2 - size_t rx_buffer_len; // Length of rx_buffer, needs to be a power of 2 - void (*rx_intr_fn)(void); // Callback called from usb_vcp_class_data_out IRQ handler if rx_intr_byte matches - uint8_t rx_intr_byte; // Value matched against every received byte - uint8_t iface_num; // Address of this VCP interface - uint8_t data_iface_num; // Address of data interface of the VCP interface association - uint8_t ep_cmd; // Address of IN CMD endpoint (with the highest bit set) - uint8_t ep_in; // Address of IN endpoint (with the highest bit set) - uint8_t ep_out; // Address of OUT endpoint - uint8_t polling_interval; // In units of 1ms - uint8_t max_packet_len; // Length of the biggest packet, and of tx_packet and rx_packet + uint8_t *tx_packet; // Buffer for one packet, with length of at least + // max_packet_len bytes + uint8_t *tx_buffer; // Buffer for IN EP ring buffer, with length of at least + // tx_buffer_len bytes + uint8_t *rx_packet; // Buffer for one packet, with length of at least + // max_packet_len bytes + uint8_t *rx_buffer; // Buffer for OUT EP ring buffer, with length of at least + // rx_buffer_len bytes + size_t tx_buffer_len; // Length of tx_buffer, needs to be a power of 2 + size_t rx_buffer_len; // Length of rx_buffer, needs to be a power of 2 + void (*rx_intr_fn)(void); // Callback called from usb_vcp_class_data_out IRQ + // handler if rx_intr_byte matches + uint8_t rx_intr_byte; // Value matched against every received byte + uint8_t iface_num; // Address of this VCP interface + uint8_t data_iface_num; // Address of data interface of the VCP interface + // association + uint8_t ep_cmd; // Address of IN CMD endpoint (with the highest bit set) + uint8_t ep_in; // Address of IN endpoint (with the highest bit set) + uint8_t ep_out; // Address of OUT endpoint + uint8_t polling_interval; // In units of 1ms + uint8_t max_packet_len; // Length of the biggest packet, and of tx_packet and + // rx_packet } usb_vcp_info_t; /* usb_rbuf_t is used internally for the RX/TX buffering. */ typedef struct { - size_t cap; - volatile size_t read; - volatile size_t write; - uint8_t *buf; + size_t cap; + volatile size_t read; + volatile size_t write; + uint8_t *buf; } usb_rbuf_t; // Maximal length of packets on IN CMD EP -#define USB_CDC_MAX_CMD_PACKET_LEN 0x08 +#define USB_CDC_MAX_CMD_PACKET_LEN 0x08 /* usb_vcp_state_t encapsulates all state used by enabled VCP interface. It * needs to be completely initialized in usb_vcp_add and reset in * usb_vcp_class_init. See usb_vcp_info_t for details of the configuration * fields. */ typedef struct { - const usb_vcp_descriptor_block_t *desc_block; - usb_rbuf_t rx_ring; - usb_rbuf_t tx_ring; - uint8_t *rx_packet; - uint8_t *tx_packet; - void (*rx_intr_fn)(void); - uint8_t rx_intr_byte; - uint8_t ep_cmd; - uint8_t ep_in; - uint8_t ep_out; - uint8_t max_packet_len; - uint8_t ep_in_is_idle; // Set to 1 after IN endpoint gets idle - uint8_t cmd_buffer[USB_CDC_MAX_CMD_PACKET_LEN]; + const usb_vcp_descriptor_block_t *desc_block; + usb_rbuf_t rx_ring; + usb_rbuf_t tx_ring; + uint8_t *rx_packet; + uint8_t *tx_packet; + void (*rx_intr_fn)(void); + uint8_t rx_intr_byte; + uint8_t ep_cmd; + uint8_t ep_in; + uint8_t ep_out; + uint8_t max_packet_len; + uint8_t ep_in_is_idle; // Set to 1 after IN endpoint gets idle + uint8_t cmd_buffer[USB_CDC_MAX_CMD_PACKET_LEN]; } usb_vcp_state_t; secbool __wur usb_vcp_add(const usb_vcp_info_t *vcp_info); @@ -141,5 +150,7 @@ secbool __wur usb_vcp_can_write(uint8_t iface_num); int __wur usb_vcp_read(uint8_t iface_num, uint8_t *buf, uint32_t len); int __wur usb_vcp_write(uint8_t iface_num, const uint8_t *buf, uint32_t len); -int __wur usb_vcp_read_blocking(uint8_t iface_num, uint8_t *buf, uint32_t len, int timeout); -int __wur usb_vcp_write_blocking(uint8_t iface_num, const uint8_t *buf, uint32_t len, int timeout); +int __wur usb_vcp_read_blocking(uint8_t iface_num, uint8_t *buf, uint32_t len, + int timeout); +int __wur usb_vcp_write_blocking(uint8_t iface_num, const uint8_t *buf, + uint32_t len, int timeout); diff --git a/embed/trezorhal/usb_vcp-impl.h b/embed/trezorhal/usb_vcp-impl.h index 9f8d81e2a..3a0852e3f 100644 --- a/embed/trezorhal/usb_vcp-impl.h +++ b/embed/trezorhal/usb_vcp-impl.h @@ -18,416 +18,429 @@ */ // Communications Device Class Code (bFunctionClass, bInterfaceClass) -#define USB_CLASS_CDC 0x02 +#define USB_CLASS_CDC 0x02 // Data Interface Class Code (bInterfaceClass) -#define USB_CLASS_DATA 0x0A +#define USB_CLASS_DATA 0x0A // Class Subclass Code (bFunctionSubClass, bInterfaceSubClass) -#define USB_CDC_SUBCLASS_ACM 0x02 +#define USB_CDC_SUBCLASS_ACM 0x02 -// Communications Interface Class Control Protocol Codes (bFunctionProtocol, bInterfaceProtocol) -#define USB_CDC_PROTOCOL_AT 0x01 +// Communications Interface Class Control Protocol Codes (bFunctionProtocol, +// bInterfaceProtocol) +#define USB_CDC_PROTOCOL_AT 0x01 // Descriptor Types (bDescriptorType) -#define USB_DESC_TYPE_ASSOCIATION 0x0B -#define USB_DESC_TYPE_CS_INTERACE 0x24 +#define USB_DESC_TYPE_ASSOCIATION 0x0B +#define USB_DESC_TYPE_CS_INTERACE 0x24 // Descriptor SubTypes (bDescriptorSubtype) -#define USB_DESC_TYPE_HEADER 0x00 -#define USB_DESC_TYPE_CM 0x01 -#define USB_DESC_TYPE_ACM 0x02 -#define USB_DESC_TYPE_UNION 0x06 +#define USB_DESC_TYPE_HEADER 0x00 +#define USB_DESC_TYPE_CM 0x01 +#define USB_DESC_TYPE_ACM 0x02 +#define USB_DESC_TYPE_UNION 0x06 // Data Phase Transfer Direction (bmRequest) -#define USB_REQ_DIR_MASK 0x80 -#define USB_REQ_DIR_H2D 0x00 -#define USB_REQ_DIR_D2H 0x80 +#define USB_REQ_DIR_MASK 0x80 +#define USB_REQ_DIR_H2D 0x00 +#define USB_REQ_DIR_D2H 0x80 // Class-Specific Request Codes for PSTN subclasses -#define USB_CDC_SET_LINE_CODING 0x20 -#define USB_CDC_GET_LINE_CODING 0x21 -#define USB_CDC_SET_CONTROL_LINE_STATE 0x22 +#define USB_CDC_SET_LINE_CODING 0x20 +#define USB_CDC_GET_LINE_CODING 0x21 +#define USB_CDC_SET_CONTROL_LINE_STATE 0x22 /* usb_vcp_add adds and configures new USB VCP interface according to * configuration options passed in `info`. */ secbool usb_vcp_add(const usb_vcp_info_t *info) { - - usb_iface_t *iface = usb_get_iface(info->iface_num); - - if (iface == NULL) { - return secfalse; // Invalid interface number - } - if (iface->type != USB_IFACE_TYPE_DISABLED) { - return secfalse; // Interface is already enabled - } - - usb_vcp_descriptor_block_t *d = usb_desc_alloc_iface(sizeof(usb_vcp_descriptor_block_t)); - - if (d == NULL) { - return secfalse; // Not enough space in the configuration descriptor - } - - if ((info->ep_cmd & USB_EP_DIR_MASK) != USB_EP_DIR_IN) { - return secfalse; // IN CMD EP is invalid - } - if ((info->ep_in & USB_EP_DIR_MASK) != USB_EP_DIR_IN) { - return secfalse; // IN EP is invalid - } - if ((info->ep_out & USB_EP_DIR_MASK) != USB_EP_DIR_OUT) { - return secfalse; // OUT EP is invalid - } - if ((info->rx_buffer_len == 0) || (info->rx_buffer_len & (info->rx_buffer_len - 1)) != 0) { - return secfalse; // Capacity needs to be a power of 2 - } - if ((info->tx_buffer_len == 0) || (info->tx_buffer_len & (info->tx_buffer_len - 1)) != 0) { - return secfalse; // Capacity needs to be a power of 2 - } - if (info->rx_buffer == NULL) { - return secfalse; - } - if (info->rx_packet == NULL) { - return secfalse; - } - if (info->tx_buffer == NULL) { - return secfalse; - } - if (info->tx_packet == NULL) { - return secfalse; - } - - // Interface association descriptor - d->assoc.bLength = sizeof(usb_interface_assoc_descriptor_t); - d->assoc.bDescriptorType = USB_DESC_TYPE_ASSOCIATION; - d->assoc.bFirstInterface = info->iface_num; - d->assoc.bInterfaceCount = 2; - d->assoc.bFunctionClass = USB_CLASS_CDC; - d->assoc.bFunctionSubClass = USB_CDC_SUBCLASS_ACM; - d->assoc.bFunctionProtocol = USB_CDC_PROTOCOL_AT; - d->assoc.iFunction = 0; - - // Interface descriptor - d->iface_cdc.bLength = sizeof(usb_interface_descriptor_t); - d->iface_cdc.bDescriptorType = USB_DESC_TYPE_INTERFACE; - d->iface_cdc.bInterfaceNumber = info->iface_num; - d->iface_cdc.bAlternateSetting = 0; - d->iface_cdc.bNumEndpoints = 1; - d->iface_cdc.bInterfaceClass = USB_CLASS_CDC; - d->iface_cdc.bInterfaceSubClass = USB_CDC_SUBCLASS_ACM; - d->iface_cdc.bInterfaceProtocol = USB_CDC_PROTOCOL_AT; - d->iface_cdc.iInterface = USBD_IDX_INTERFACE_STR; - - // Header Functional Descriptor - d->fheader.bFunctionLength = sizeof(usb_vcp_header_descriptor_t); - d->fheader.bDescriptorType = USB_DESC_TYPE_CS_INTERACE; - d->fheader.bDescriptorSubtype = USB_DESC_TYPE_HEADER; - d->fheader.bcdCDC = 0x1001; // USB Class Definitions for Communication Devices Specification release number. - - // Call Management Functional Descriptor - d->fcm.bFunctionLength = sizeof(usb_vcp_cm_descriptor_t); - d->fcm.bDescriptorType = USB_DESC_TYPE_CS_INTERACE; - d->fcm.bDescriptorSubtype = USB_DESC_TYPE_CM; - // Device sends/receives call management information only over the Communication Class interface. - // Device does not handle call management itself. - d->fcm.bmCapabilities = 0x00; - d->fcm.bDataInterface = info->data_iface_num; - - // ACM Functional Descriptor - d->facm.bFunctionLength = sizeof(usb_vcp_acm_descriptor_t); - d->facm.bDescriptorType = USB_DESC_TYPE_CS_INTERACE; - d->facm.bDescriptorSubtype = USB_DESC_TYPE_ACM; - // Device supports the request combination of Set_Line_Coding, Set_Control_Line_State, - // Get_Line_Coding, and the notification Serial_State. - d->facm.bmCapabilities = 0x02; - - // Union Functional Descriptor - d->funion.bFunctionLength = sizeof(usb_vcp_union_descriptor_t); - d->funion.bDescriptorType = USB_DESC_TYPE_CS_INTERACE; - d->funion.bDescriptorSubtype = USB_DESC_TYPE_UNION; - d->funion.bControlInterface = info->iface_num; - d->funion.bSubordinateInterface0 = info->data_iface_num; - - // IN CMD endpoint (control) - d->ep_cmd.bLength = sizeof(usb_endpoint_descriptor_t); - d->ep_cmd.bDescriptorType = USB_DESC_TYPE_ENDPOINT; - d->ep_cmd.bEndpointAddress = info->ep_cmd; - d->ep_cmd.bmAttributes = USBD_EP_TYPE_INTR; - d->ep_cmd.wMaxPacketSize = USB_CDC_MAX_CMD_PACKET_LEN; - d->ep_cmd.bInterval = info->polling_interval; - - // Interface descriptor - d->iface_data.bLength = sizeof(usb_interface_descriptor_t); - d->iface_data.bDescriptorType = USB_DESC_TYPE_INTERFACE; - d->iface_data.bInterfaceNumber = info->data_iface_num; - d->iface_data.bAlternateSetting = 0; - d->iface_data.bNumEndpoints = 2; - d->iface_data.bInterfaceClass = USB_CLASS_DATA; - d->iface_data.bInterfaceSubClass = 0; - d->iface_data.bInterfaceProtocol = 0; - d->iface_data.iInterface = USBD_IDX_INTERFACE_STR; - - // OUT endpoint (receiving) - d->ep_out.bLength = sizeof(usb_endpoint_descriptor_t); - d->ep_out.bDescriptorType = USB_DESC_TYPE_ENDPOINT; - d->ep_out.bEndpointAddress = info->ep_out; - d->ep_out.bmAttributes = USBD_EP_TYPE_BULK; - d->ep_out.wMaxPacketSize = info->max_packet_len; - d->ep_out.bInterval = 0; - - // IN endpoint (sending) - d->ep_in.bLength = sizeof(usb_endpoint_descriptor_t); - d->ep_in.bDescriptorType = USB_DESC_TYPE_ENDPOINT; - d->ep_in.bEndpointAddress = info->ep_in; - d->ep_in.bmAttributes = USBD_EP_TYPE_BULK; - d->ep_in.wMaxPacketSize = info->max_packet_len; - d->ep_in.bInterval = 0; - - // Config descriptor - usb_desc_add_iface(sizeof(usb_vcp_descriptor_block_t)); - usb_config_desc->bNumInterfaces++; // usb_vcp_descriptor_block_t contains 2 interfaces - - // Interface state - - iface->type = USB_IFACE_TYPE_VCP; - iface->vcp.desc_block = d; - - iface->vcp.rx_ring.buf = info->rx_buffer; - iface->vcp.rx_ring.cap = info->rx_buffer_len; - iface->vcp.rx_ring.read = 0; - iface->vcp.rx_ring.write = 0; - - iface->vcp.tx_ring.buf = info->tx_buffer; - iface->vcp.tx_ring.cap = info->tx_buffer_len; - iface->vcp.tx_ring.read = 0; - iface->vcp.tx_ring.write = 0; - - iface->vcp.rx_packet = info->rx_packet; - iface->vcp.tx_packet = info->tx_packet; - - iface->vcp.rx_intr_fn = info->rx_intr_fn; - iface->vcp.rx_intr_byte = info->rx_intr_byte; - - iface->vcp.ep_cmd = info->ep_cmd; - iface->vcp.ep_in = info->ep_in; - iface->vcp.ep_out = info->ep_out; - iface->vcp.max_packet_len = info->max_packet_len; - - iface->vcp.ep_in_is_idle = 1; - - return sectrue; + usb_iface_t *iface = usb_get_iface(info->iface_num); + + if (iface == NULL) { + return secfalse; // Invalid interface number + } + if (iface->type != USB_IFACE_TYPE_DISABLED) { + return secfalse; // Interface is already enabled + } + + usb_vcp_descriptor_block_t *d = + usb_desc_alloc_iface(sizeof(usb_vcp_descriptor_block_t)); + + if (d == NULL) { + return secfalse; // Not enough space in the configuration descriptor + } + + if ((info->ep_cmd & USB_EP_DIR_MASK) != USB_EP_DIR_IN) { + return secfalse; // IN CMD EP is invalid + } + if ((info->ep_in & USB_EP_DIR_MASK) != USB_EP_DIR_IN) { + return secfalse; // IN EP is invalid + } + if ((info->ep_out & USB_EP_DIR_MASK) != USB_EP_DIR_OUT) { + return secfalse; // OUT EP is invalid + } + if ((info->rx_buffer_len == 0) || + (info->rx_buffer_len & (info->rx_buffer_len - 1)) != 0) { + return secfalse; // Capacity needs to be a power of 2 + } + if ((info->tx_buffer_len == 0) || + (info->tx_buffer_len & (info->tx_buffer_len - 1)) != 0) { + return secfalse; // Capacity needs to be a power of 2 + } + if (info->rx_buffer == NULL) { + return secfalse; + } + if (info->rx_packet == NULL) { + return secfalse; + } + if (info->tx_buffer == NULL) { + return secfalse; + } + if (info->tx_packet == NULL) { + return secfalse; + } + + // Interface association descriptor + d->assoc.bLength = sizeof(usb_interface_assoc_descriptor_t); + d->assoc.bDescriptorType = USB_DESC_TYPE_ASSOCIATION; + d->assoc.bFirstInterface = info->iface_num; + d->assoc.bInterfaceCount = 2; + d->assoc.bFunctionClass = USB_CLASS_CDC; + d->assoc.bFunctionSubClass = USB_CDC_SUBCLASS_ACM; + d->assoc.bFunctionProtocol = USB_CDC_PROTOCOL_AT; + d->assoc.iFunction = 0; + + // Interface descriptor + d->iface_cdc.bLength = sizeof(usb_interface_descriptor_t); + d->iface_cdc.bDescriptorType = USB_DESC_TYPE_INTERFACE; + d->iface_cdc.bInterfaceNumber = info->iface_num; + d->iface_cdc.bAlternateSetting = 0; + d->iface_cdc.bNumEndpoints = 1; + d->iface_cdc.bInterfaceClass = USB_CLASS_CDC; + d->iface_cdc.bInterfaceSubClass = USB_CDC_SUBCLASS_ACM; + d->iface_cdc.bInterfaceProtocol = USB_CDC_PROTOCOL_AT; + d->iface_cdc.iInterface = USBD_IDX_INTERFACE_STR; + + // Header Functional Descriptor + d->fheader.bFunctionLength = sizeof(usb_vcp_header_descriptor_t); + d->fheader.bDescriptorType = USB_DESC_TYPE_CS_INTERACE; + d->fheader.bDescriptorSubtype = USB_DESC_TYPE_HEADER; + d->fheader.bcdCDC = 0x1001; // USB Class Definitions for Communication + // Devices Specification release number. + + // Call Management Functional Descriptor + d->fcm.bFunctionLength = sizeof(usb_vcp_cm_descriptor_t); + d->fcm.bDescriptorType = USB_DESC_TYPE_CS_INTERACE; + d->fcm.bDescriptorSubtype = USB_DESC_TYPE_CM; + // Device sends/receives call management information only over the + // Communication Class interface. Device does not handle call management + // itself. + d->fcm.bmCapabilities = 0x00; + d->fcm.bDataInterface = info->data_iface_num; + + // ACM Functional Descriptor + d->facm.bFunctionLength = sizeof(usb_vcp_acm_descriptor_t); + d->facm.bDescriptorType = USB_DESC_TYPE_CS_INTERACE; + d->facm.bDescriptorSubtype = USB_DESC_TYPE_ACM; + // Device supports the request combination of Set_Line_Coding, + // Set_Control_Line_State, Get_Line_Coding, and the notification Serial_State. + d->facm.bmCapabilities = 0x02; + + // Union Functional Descriptor + d->funion.bFunctionLength = sizeof(usb_vcp_union_descriptor_t); + d->funion.bDescriptorType = USB_DESC_TYPE_CS_INTERACE; + d->funion.bDescriptorSubtype = USB_DESC_TYPE_UNION; + d->funion.bControlInterface = info->iface_num; + d->funion.bSubordinateInterface0 = info->data_iface_num; + + // IN CMD endpoint (control) + d->ep_cmd.bLength = sizeof(usb_endpoint_descriptor_t); + d->ep_cmd.bDescriptorType = USB_DESC_TYPE_ENDPOINT; + d->ep_cmd.bEndpointAddress = info->ep_cmd; + d->ep_cmd.bmAttributes = USBD_EP_TYPE_INTR; + d->ep_cmd.wMaxPacketSize = USB_CDC_MAX_CMD_PACKET_LEN; + d->ep_cmd.bInterval = info->polling_interval; + + // Interface descriptor + d->iface_data.bLength = sizeof(usb_interface_descriptor_t); + d->iface_data.bDescriptorType = USB_DESC_TYPE_INTERFACE; + d->iface_data.bInterfaceNumber = info->data_iface_num; + d->iface_data.bAlternateSetting = 0; + d->iface_data.bNumEndpoints = 2; + d->iface_data.bInterfaceClass = USB_CLASS_DATA; + d->iface_data.bInterfaceSubClass = 0; + d->iface_data.bInterfaceProtocol = 0; + d->iface_data.iInterface = USBD_IDX_INTERFACE_STR; + + // OUT endpoint (receiving) + d->ep_out.bLength = sizeof(usb_endpoint_descriptor_t); + d->ep_out.bDescriptorType = USB_DESC_TYPE_ENDPOINT; + d->ep_out.bEndpointAddress = info->ep_out; + d->ep_out.bmAttributes = USBD_EP_TYPE_BULK; + d->ep_out.wMaxPacketSize = info->max_packet_len; + d->ep_out.bInterval = 0; + + // IN endpoint (sending) + d->ep_in.bLength = sizeof(usb_endpoint_descriptor_t); + d->ep_in.bDescriptorType = USB_DESC_TYPE_ENDPOINT; + d->ep_in.bEndpointAddress = info->ep_in; + d->ep_in.bmAttributes = USBD_EP_TYPE_BULK; + d->ep_in.wMaxPacketSize = info->max_packet_len; + d->ep_in.bInterval = 0; + + // Config descriptor + usb_desc_add_iface(sizeof(usb_vcp_descriptor_block_t)); + usb_config_desc + ->bNumInterfaces++; // usb_vcp_descriptor_block_t contains 2 interfaces + + // Interface state + + iface->type = USB_IFACE_TYPE_VCP; + iface->vcp.desc_block = d; + + iface->vcp.rx_ring.buf = info->rx_buffer; + iface->vcp.rx_ring.cap = info->rx_buffer_len; + iface->vcp.rx_ring.read = 0; + iface->vcp.rx_ring.write = 0; + + iface->vcp.tx_ring.buf = info->tx_buffer; + iface->vcp.tx_ring.cap = info->tx_buffer_len; + iface->vcp.tx_ring.read = 0; + iface->vcp.tx_ring.write = 0; + + iface->vcp.rx_packet = info->rx_packet; + iface->vcp.tx_packet = info->tx_packet; + + iface->vcp.rx_intr_fn = info->rx_intr_fn; + iface->vcp.rx_intr_byte = info->rx_intr_byte; + + iface->vcp.ep_cmd = info->ep_cmd; + iface->vcp.ep_in = info->ep_in; + iface->vcp.ep_out = info->ep_out; + iface->vcp.max_packet_len = info->max_packet_len; + + iface->vcp.ep_in_is_idle = 1; + + return sectrue; } -static inline size_t ring_length(usb_rbuf_t *b) { - return (b->write - b->read); -} +static inline size_t ring_length(usb_rbuf_t *b) { return (b->write - b->read); } -static inline int ring_empty(usb_rbuf_t *b) { - return ring_length(b) == 0; -} +static inline int ring_empty(usb_rbuf_t *b) { return ring_length(b) == 0; } -static inline int ring_full(usb_rbuf_t *b) { - return ring_length(b) == b->cap; -} +static inline int ring_full(usb_rbuf_t *b) { return ring_length(b) == b->cap; } secbool usb_vcp_can_read(uint8_t iface_num) { - usb_iface_t *iface = usb_get_iface(iface_num); - if (iface == NULL) { - return secfalse; // Invalid interface number - } - if (iface->type != USB_IFACE_TYPE_VCP) { - return secfalse; // Invalid interface type - } - if (ring_empty(&iface->vcp.rx_ring)) { - return secfalse; // Nothing in the rx buffer - } - return sectrue; + usb_iface_t *iface = usb_get_iface(iface_num); + if (iface == NULL) { + return secfalse; // Invalid interface number + } + if (iface->type != USB_IFACE_TYPE_VCP) { + return secfalse; // Invalid interface type + } + if (ring_empty(&iface->vcp.rx_ring)) { + return secfalse; // Nothing in the rx buffer + } + return sectrue; } secbool usb_vcp_can_write(uint8_t iface_num) { - usb_iface_t *iface = usb_get_iface(iface_num); - if (iface == NULL) { - return secfalse; // Invalid interface number - } - if (iface->type != USB_IFACE_TYPE_VCP) { - return secfalse; // Invalid interface type - } - if (ring_full(&iface->vcp.tx_ring)) { - return secfalse; // Tx ring buffer is full - } - return sectrue; + usb_iface_t *iface = usb_get_iface(iface_num); + if (iface == NULL) { + return secfalse; // Invalid interface number + } + if (iface->type != USB_IFACE_TYPE_VCP) { + return secfalse; // Invalid interface type + } + if (ring_full(&iface->vcp.tx_ring)) { + return secfalse; // Tx ring buffer is full + } + return sectrue; } int usb_vcp_read(uint8_t iface_num, uint8_t *buf, uint32_t len) { - usb_iface_t *iface = usb_get_iface(iface_num); - if (iface == NULL) { - return -1; // Invalid interface number - } - if (iface->type != USB_IFACE_TYPE_VCP) { - return -2; // Interface interface type - } - usb_vcp_state_t *state = &iface->vcp; - - // Read from the rx ring buffer - usb_rbuf_t *b = &state->rx_ring; - size_t mask = b->cap - 1; - size_t i; - for (i = 0; (i < len) && !ring_empty(b); i++) { - buf[i] = b->buf[b->read & mask]; - b->read++; - } - return i; + usb_iface_t *iface = usb_get_iface(iface_num); + if (iface == NULL) { + return -1; // Invalid interface number + } + if (iface->type != USB_IFACE_TYPE_VCP) { + return -2; // Interface interface type + } + usb_vcp_state_t *state = &iface->vcp; + + // Read from the rx ring buffer + usb_rbuf_t *b = &state->rx_ring; + size_t mask = b->cap - 1; + size_t i; + for (i = 0; (i < len) && !ring_empty(b); i++) { + buf[i] = b->buf[b->read & mask]; + b->read++; + } + return i; } int usb_vcp_write(uint8_t iface_num, const uint8_t *buf, uint32_t len) { - usb_iface_t *iface = usb_get_iface(iface_num); - if (iface == NULL) { - return -1; // Invalid interface number - } - if (iface->type != USB_IFACE_TYPE_VCP) { - return -2; // Interface interface type - } - usb_vcp_state_t *state = &iface->vcp; - - // Write into the tx ring buffer - usb_rbuf_t *b = &state->tx_ring; - size_t mask = b->cap - 1; - size_t i; - for (i = 0; (i < len) && !ring_full(b); i++) { - b->buf[b->write & mask] = buf[i]; - b->write++; - } - - return len; + usb_iface_t *iface = usb_get_iface(iface_num); + if (iface == NULL) { + return -1; // Invalid interface number + } + if (iface->type != USB_IFACE_TYPE_VCP) { + return -2; // Interface interface type + } + usb_vcp_state_t *state = &iface->vcp; + + // Write into the tx ring buffer + usb_rbuf_t *b = &state->tx_ring; + size_t mask = b->cap - 1; + size_t i; + for (i = 0; (i < len) && !ring_full(b); i++) { + b->buf[b->write & mask] = buf[i]; + b->write++; + } + + return len; } -int usb_vcp_read_blocking(uint8_t iface_num, uint8_t *buf, uint32_t len, int timeout) { - uint32_t start = HAL_GetTick(); - while (sectrue != usb_vcp_can_read(iface_num)) { - if (timeout >= 0 && HAL_GetTick() - start >= timeout) { - return 0; // Timeout - } - __WFI(); // Enter sleep mode, waiting for interrupt +int usb_vcp_read_blocking(uint8_t iface_num, uint8_t *buf, uint32_t len, + int timeout) { + uint32_t start = HAL_GetTick(); + while (sectrue != usb_vcp_can_read(iface_num)) { + if (timeout >= 0 && HAL_GetTick() - start >= timeout) { + return 0; // Timeout } - return usb_vcp_read(iface_num, buf, len); + __WFI(); // Enter sleep mode, waiting for interrupt + } + return usb_vcp_read(iface_num, buf, len); } -int usb_vcp_write_blocking(uint8_t iface_num, const uint8_t *buf, uint32_t len, int timeout) { - uint32_t start = HAL_GetTick(); - while (sectrue != usb_vcp_can_write(iface_num)) { - if (timeout >= 0 && HAL_GetTick() - start >= timeout) { - return 0; // Timeout - } - __WFI(); // Enter sleep mode, waiting for interrupt +int usb_vcp_write_blocking(uint8_t iface_num, const uint8_t *buf, uint32_t len, + int timeout) { + uint32_t start = HAL_GetTick(); + while (sectrue != usb_vcp_can_write(iface_num)) { + if (timeout >= 0 && HAL_GetTick() - start >= timeout) { + return 0; // Timeout } - return usb_vcp_write(iface_num, buf, len); + __WFI(); // Enter sleep mode, waiting for interrupt + } + return usb_vcp_write(iface_num, buf, len); } -static void usb_vcp_class_init(USBD_HandleTypeDef *dev, usb_vcp_state_t *state, uint8_t cfg_idx) { - // Open endpoints - USBD_LL_OpenEP(dev, state->ep_in, USBD_EP_TYPE_BULK, state->max_packet_len); - USBD_LL_OpenEP(dev, state->ep_out, USBD_EP_TYPE_BULK, state->max_packet_len); - USBD_LL_OpenEP(dev, state->ep_cmd, USBD_EP_TYPE_INTR, USB_CDC_MAX_CMD_PACKET_LEN); - - // Reset the state - state->rx_ring.read = 0; - state->rx_ring.write = 0; - state->tx_ring.read = 0; - state->tx_ring.write = 0; - state->ep_in_is_idle = 1; - - // Prepare the OUT EP to receive next packet - USBD_LL_PrepareReceive(dev, state->ep_out, state->rx_packet, state->max_packet_len); +static void usb_vcp_class_init(USBD_HandleTypeDef *dev, usb_vcp_state_t *state, + uint8_t cfg_idx) { + // Open endpoints + USBD_LL_OpenEP(dev, state->ep_in, USBD_EP_TYPE_BULK, state->max_packet_len); + USBD_LL_OpenEP(dev, state->ep_out, USBD_EP_TYPE_BULK, state->max_packet_len); + USBD_LL_OpenEP(dev, state->ep_cmd, USBD_EP_TYPE_INTR, + USB_CDC_MAX_CMD_PACKET_LEN); + + // Reset the state + state->rx_ring.read = 0; + state->rx_ring.write = 0; + state->tx_ring.read = 0; + state->tx_ring.write = 0; + state->ep_in_is_idle = 1; + + // Prepare the OUT EP to receive next packet + USBD_LL_PrepareReceive(dev, state->ep_out, state->rx_packet, + state->max_packet_len); } -static void usb_vcp_class_deinit(USBD_HandleTypeDef *dev, usb_vcp_state_t *state, uint8_t cfg_idx) { - // Flush endpoints - USBD_LL_FlushEP(dev, state->ep_in); - USBD_LL_FlushEP(dev, state->ep_out); - USBD_LL_FlushEP(dev, state->ep_cmd); - // Close endpoints - USBD_LL_CloseEP(dev, state->ep_in); - USBD_LL_CloseEP(dev, state->ep_out); - USBD_LL_CloseEP(dev, state->ep_cmd); +static void usb_vcp_class_deinit(USBD_HandleTypeDef *dev, + usb_vcp_state_t *state, uint8_t cfg_idx) { + // Flush endpoints + USBD_LL_FlushEP(dev, state->ep_in); + USBD_LL_FlushEP(dev, state->ep_out); + USBD_LL_FlushEP(dev, state->ep_cmd); + // Close endpoints + USBD_LL_CloseEP(dev, state->ep_in); + USBD_LL_CloseEP(dev, state->ep_out); + USBD_LL_CloseEP(dev, state->ep_cmd); } -static int usb_vcp_class_setup(USBD_HandleTypeDef *dev, usb_vcp_state_t *state, USBD_SetupReqTypedef *req) { - static const usb_cdc_line_coding_t line_coding = { - .dwDTERate = 115200, - .bCharFormat = USB_CDC_1_STOP_BITS, - .bParityType = USB_CDC_NO_PARITY, - .bDataBits = 8, - }; - - if ((req->bmRequest & USB_REQ_TYPE_MASK) != USB_REQ_TYPE_CLASS) { - return USBD_OK; - } - - if ((req->bmRequest & USB_REQ_DIR_MASK) == USB_REQ_DIR_D2H) { - if (req->bRequest == USB_CDC_GET_LINE_CODING) { - USBD_CtlSendData(dev, UNCONST(&line_coding), MIN_8bits(req->wLength, sizeof(line_coding))); - } else { - USBD_CtlSendData(dev, state->cmd_buffer, MIN_8bits(req->wLength, USB_CDC_MAX_CMD_PACKET_LEN)); - } - } else { // USB_REQ_DIR_H2D - if (req->wLength > 0) { - USBD_CtlPrepareRx(dev, state->cmd_buffer, MIN_8bits(req->wLength, USB_CDC_MAX_CMD_PACKET_LEN)); - } - } +static int usb_vcp_class_setup(USBD_HandleTypeDef *dev, usb_vcp_state_t *state, + USBD_SetupReqTypedef *req) { + static const usb_cdc_line_coding_t line_coding = { + .dwDTERate = 115200, + .bCharFormat = USB_CDC_1_STOP_BITS, + .bParityType = USB_CDC_NO_PARITY, + .bDataBits = 8, + }; + if ((req->bmRequest & USB_REQ_TYPE_MASK) != USB_REQ_TYPE_CLASS) { return USBD_OK; -} + } -static void usb_vcp_class_data_in(USBD_HandleTypeDef *dev, usb_vcp_state_t *state, uint8_t ep_num) { - if ((ep_num | USB_EP_DIR_IN) == state->ep_in) { - state->ep_in_is_idle = 1; + if ((req->bmRequest & USB_REQ_DIR_MASK) == USB_REQ_DIR_D2H) { + if (req->bRequest == USB_CDC_GET_LINE_CODING) { + USBD_CtlSendData(dev, UNCONST(&line_coding), + MIN_8bits(req->wLength, sizeof(line_coding))); + } else { + USBD_CtlSendData(dev, state->cmd_buffer, + MIN_8bits(req->wLength, USB_CDC_MAX_CMD_PACKET_LEN)); } -} + } else { // USB_REQ_DIR_H2D + if (req->wLength > 0) { + USBD_CtlPrepareRx(dev, state->cmd_buffer, + MIN_8bits(req->wLength, USB_CDC_MAX_CMD_PACKET_LEN)); + } + } -static void usb_vcp_class_data_out(USBD_HandleTypeDef *dev, usb_vcp_state_t *state, uint8_t ep_num) { - if (ep_num == state->ep_out) { - uint32_t len = USBD_LL_GetRxDataSize(dev, ep_num); - - // Write into the rx ring buffer - usb_rbuf_t *b = &state->rx_ring; - size_t mask = b->cap - 1; - size_t i; - for (i = 0; i < len; i++) { - if (state->rx_intr_fn != NULL) { - if (state->rx_packet[i] == state->rx_intr_byte) { - state->rx_intr_fn(); - } - } - if (!ring_full(b)) { - b->buf[b->write & mask] = state->rx_packet[i]; - b->write++; - } - } + return USBD_OK; +} - // Prepare the OUT EP to receive next packet - USBD_LL_PrepareReceive(dev, state->ep_out, state->rx_packet, state->max_packet_len); - } +static void usb_vcp_class_data_in(USBD_HandleTypeDef *dev, + usb_vcp_state_t *state, uint8_t ep_num) { + if ((ep_num | USB_EP_DIR_IN) == state->ep_in) { + state->ep_in_is_idle = 1; + } } -static void usb_vcp_class_sof(USBD_HandleTypeDef *dev, usb_vcp_state_t *state) { - if (!state->ep_in_is_idle) { - return; - } +static void usb_vcp_class_data_out(USBD_HandleTypeDef *dev, + usb_vcp_state_t *state, uint8_t ep_num) { + if (ep_num == state->ep_out) { + uint32_t len = USBD_LL_GetRxDataSize(dev, ep_num); - // Read from the tx ring buffer - usb_rbuf_t *b = &state->tx_ring; - uint8_t *buf = state->tx_packet; - // We avoid sending full packets as they stall the hosts pipeline, see: - // - size_t len = state->max_packet_len - 1; + // Write into the rx ring buffer + usb_rbuf_t *b = &state->rx_ring; size_t mask = b->cap - 1; size_t i; - for (i = 0; (i < len) && !ring_empty(b); i++) { - buf[i] = b->buf[b->read & mask]; - b->read++; + for (i = 0; i < len; i++) { + if (state->rx_intr_fn != NULL) { + if (state->rx_packet[i] == state->rx_intr_byte) { + state->rx_intr_fn(); + } + } + if (!ring_full(b)) { + b->buf[b->write & mask] = state->rx_packet[i]; + b->write++; + } } - if (i > 0) { - state->ep_in_is_idle = 0; - USBD_LL_Transmit(&usb_dev_handle, state->ep_in, buf, (uint16_t)i); - } + // Prepare the OUT EP to receive next packet + USBD_LL_PrepareReceive(dev, state->ep_out, state->rx_packet, + state->max_packet_len); + } +} + +static void usb_vcp_class_sof(USBD_HandleTypeDef *dev, usb_vcp_state_t *state) { + if (!state->ep_in_is_idle) { + return; + } + + // Read from the tx ring buffer + usb_rbuf_t *b = &state->tx_ring; + uint8_t *buf = state->tx_packet; + // We avoid sending full packets as they stall the hosts pipeline, see: + // + size_t len = state->max_packet_len - 1; + size_t mask = b->cap - 1; + size_t i; + for (i = 0; (i < len) && !ring_empty(b); i++) { + buf[i] = b->buf[b->read & mask]; + b->read++; + } + + if (i > 0) { + state->ep_in_is_idle = 0; + USBD_LL_Transmit(&usb_dev_handle, state->ep_in, buf, (uint16_t)i); + } } diff --git a/embed/trezorhal/usb_webusb-defs.h b/embed/trezorhal/usb_webusb-defs.h index bb6d65f95..2bca96354 100644 --- a/embed/trezorhal/usb_webusb-defs.h +++ b/embed/trezorhal/usb_webusb-defs.h @@ -17,43 +17,43 @@ * along with this program. If not, see . */ -#define USB_WEBUSB_VENDOR_CODE 0x01 // arbitrary -#define USB_WEBUSB_LANDING_PAGE 0x01 // arbitrary +#define USB_WEBUSB_VENDOR_CODE 0x01 // arbitrary +#define USB_WEBUSB_LANDING_PAGE 0x01 // arbitrary typedef struct __attribute__((packed)) { - usb_interface_descriptor_t iface; - usb_endpoint_descriptor_t ep_in; - usb_endpoint_descriptor_t ep_out; + usb_interface_descriptor_t iface; + usb_endpoint_descriptor_t ep_in; + usb_endpoint_descriptor_t ep_out; } usb_webusb_descriptor_block_t; -/* usb_webusb_info_t contains all information for setting up a WebUSB interface. All - * passed pointers need to live at least until the interface is disabled +/* usb_webusb_info_t contains all information for setting up a WebUSB interface. + * All passed pointers need to live at least until the interface is disabled * (usb_stop is called). */ typedef struct { - uint8_t *rx_buffer; // With length of max_packet_len bytes - uint8_t iface_num; // Address of this WebUSB interface - uint8_t ep_in; // Address of IN endpoint (with the highest bit set) - uint8_t ep_out; // Address of OUT endpoint - uint8_t subclass; // usb_iface_subclass_t - uint8_t protocol; // usb_iface_protocol_t - uint8_t polling_interval; // In units of 1ms - uint8_t max_packet_len; // Length of the biggest report and of rx_buffer + uint8_t *rx_buffer; // With length of max_packet_len bytes + uint8_t iface_num; // Address of this WebUSB interface + uint8_t ep_in; // Address of IN endpoint (with the highest bit set) + uint8_t ep_out; // Address of OUT endpoint + uint8_t subclass; // usb_iface_subclass_t + uint8_t protocol; // usb_iface_protocol_t + uint8_t polling_interval; // In units of 1ms + uint8_t max_packet_len; // Length of the biggest report and of rx_buffer } usb_webusb_info_t; -/* usb_webusb_state_t encapsulates all state used by enabled WebUSB interface. It - * needs to be completely initialized in usb_webusb_add and reset in - * usb_webusb_class_init. See usb_webusb_info_t for details of the configuration - * fields. */ +/* usb_webusb_state_t encapsulates all state used by enabled WebUSB interface. + * It needs to be completely initialized in usb_webusb_add and reset in + * usb_webusb_class_init. See usb_webusb_info_t for details of the + * configuration fields. */ typedef struct { - const usb_webusb_descriptor_block_t *desc_block; - uint8_t *rx_buffer; - uint8_t ep_in; - uint8_t ep_out; - uint8_t max_packet_len; + const usb_webusb_descriptor_block_t *desc_block; + uint8_t *rx_buffer; + uint8_t ep_in; + uint8_t ep_out; + uint8_t max_packet_len; - uint8_t alt_setting; // For SET_INTERFACE/GET_INTERFACE setup reqs - uint8_t last_read_len; // Length of data read into rx_buffer - uint8_t ep_in_is_idle; // Set to 1 after IN endpoint gets idle + uint8_t alt_setting; // For SET_INTERFACE/GET_INTERFACE setup reqs + uint8_t last_read_len; // Length of data read into rx_buffer + uint8_t ep_in_is_idle; // Set to 1 after IN endpoint gets idle } usb_webusb_state_t; secbool __wur usb_webusb_add(const usb_webusb_info_t *webusb_info); @@ -63,5 +63,7 @@ int __wur usb_webusb_read(uint8_t iface_num, uint8_t *buf, uint32_t len); int __wur usb_webusb_write(uint8_t iface_num, const uint8_t *buf, uint32_t len); int __wur usb_webusb_read_select(uint32_t timeout); -int __wur usb_webusb_read_blocking(uint8_t iface_num, uint8_t *buf, uint32_t len, int timeout); -int __wur usb_webusb_write_blocking(uint8_t iface_num, const uint8_t *buf, uint32_t len, int timeout); +int __wur usb_webusb_read_blocking(uint8_t iface_num, uint8_t *buf, + uint32_t len, int timeout); +int __wur usb_webusb_write_blocking(uint8_t iface_num, const uint8_t *buf, + uint32_t len, int timeout); diff --git a/embed/trezorhal/usb_webusb-impl.h b/embed/trezorhal/usb_webusb-impl.h index 08aabe629..946d3fb63 100644 --- a/embed/trezorhal/usb_webusb-impl.h +++ b/embed/trezorhal/usb_webusb-impl.h @@ -17,256 +17,268 @@ * along with this program. If not, see . */ -#define USB_CLASS_WEBUSB 0xFF +#define USB_CLASS_WEBUSB 0xFF /* usb_webusb_add adds and configures new USB WebUSB interface according to * configuration options passed in `info`. */ secbool usb_webusb_add(const usb_webusb_info_t *info) { - - usb_iface_t *iface = usb_get_iface(info->iface_num); - - if (iface == NULL) { - return secfalse; // Invalid interface number - } - if (iface->type != USB_IFACE_TYPE_DISABLED) { - return secfalse; // Interface is already enabled - } - - usb_webusb_descriptor_block_t *d = usb_desc_alloc_iface(sizeof(usb_webusb_descriptor_block_t)); - - if (d == NULL) { - return secfalse; // Not enough space in the configuration descriptor - } - - if ((info->ep_in & USB_EP_DIR_MASK) != USB_EP_DIR_IN) { - return secfalse; // IN EP is invalid - } - if ((info->ep_out & USB_EP_DIR_MASK) != USB_EP_DIR_OUT) { - return secfalse; // OUT EP is invalid - } - if (info->rx_buffer == NULL) { - return secfalse; - } - - // Interface descriptor - d->iface.bLength = sizeof(usb_interface_descriptor_t); - d->iface.bDescriptorType = USB_DESC_TYPE_INTERFACE; - d->iface.bInterfaceNumber = info->iface_num; - d->iface.bAlternateSetting = 0; - d->iface.bNumEndpoints = 2; - d->iface.bInterfaceClass = USB_CLASS_WEBUSB; - d->iface.bInterfaceSubClass = info->subclass; - d->iface.bInterfaceProtocol = info->protocol; - d->iface.iInterface = USBD_IDX_INTERFACE_STR; - - // IN endpoint (sending) - d->ep_in.bLength = sizeof(usb_endpoint_descriptor_t); - d->ep_in.bDescriptorType = USB_DESC_TYPE_ENDPOINT; - d->ep_in.bEndpointAddress = info->ep_in; - d->ep_in.bmAttributes = USBD_EP_TYPE_INTR; - d->ep_in.wMaxPacketSize = info->max_packet_len; - d->ep_in.bInterval = info->polling_interval; - - // OUT endpoint (receiving) - d->ep_out.bLength = sizeof(usb_endpoint_descriptor_t); - d->ep_out.bDescriptorType = USB_DESC_TYPE_ENDPOINT; - d->ep_out.bEndpointAddress = info->ep_out; - d->ep_out.bmAttributes = USBD_EP_TYPE_INTR; - d->ep_out.wMaxPacketSize = info->max_packet_len; - d->ep_out.bInterval = info->polling_interval; - - // Config descriptor - usb_desc_add_iface(sizeof(usb_webusb_descriptor_block_t)); - - // Interface state - iface->type = USB_IFACE_TYPE_WEBUSB; - iface->webusb.desc_block = d; - iface->webusb.rx_buffer = info->rx_buffer; - iface->webusb.ep_in = info->ep_in; - iface->webusb.ep_out = info->ep_out; - iface->webusb.max_packet_len = info->max_packet_len; - iface->webusb.alt_setting = 0; - iface->webusb.last_read_len = 0; - iface->webusb.ep_in_is_idle = 1; - - return sectrue; + usb_iface_t *iface = usb_get_iface(info->iface_num); + + if (iface == NULL) { + return secfalse; // Invalid interface number + } + if (iface->type != USB_IFACE_TYPE_DISABLED) { + return secfalse; // Interface is already enabled + } + + usb_webusb_descriptor_block_t *d = + usb_desc_alloc_iface(sizeof(usb_webusb_descriptor_block_t)); + + if (d == NULL) { + return secfalse; // Not enough space in the configuration descriptor + } + + if ((info->ep_in & USB_EP_DIR_MASK) != USB_EP_DIR_IN) { + return secfalse; // IN EP is invalid + } + if ((info->ep_out & USB_EP_DIR_MASK) != USB_EP_DIR_OUT) { + return secfalse; // OUT EP is invalid + } + if (info->rx_buffer == NULL) { + return secfalse; + } + + // Interface descriptor + d->iface.bLength = sizeof(usb_interface_descriptor_t); + d->iface.bDescriptorType = USB_DESC_TYPE_INTERFACE; + d->iface.bInterfaceNumber = info->iface_num; + d->iface.bAlternateSetting = 0; + d->iface.bNumEndpoints = 2; + d->iface.bInterfaceClass = USB_CLASS_WEBUSB; + d->iface.bInterfaceSubClass = info->subclass; + d->iface.bInterfaceProtocol = info->protocol; + d->iface.iInterface = USBD_IDX_INTERFACE_STR; + + // IN endpoint (sending) + d->ep_in.bLength = sizeof(usb_endpoint_descriptor_t); + d->ep_in.bDescriptorType = USB_DESC_TYPE_ENDPOINT; + d->ep_in.bEndpointAddress = info->ep_in; + d->ep_in.bmAttributes = USBD_EP_TYPE_INTR; + d->ep_in.wMaxPacketSize = info->max_packet_len; + d->ep_in.bInterval = info->polling_interval; + + // OUT endpoint (receiving) + d->ep_out.bLength = sizeof(usb_endpoint_descriptor_t); + d->ep_out.bDescriptorType = USB_DESC_TYPE_ENDPOINT; + d->ep_out.bEndpointAddress = info->ep_out; + d->ep_out.bmAttributes = USBD_EP_TYPE_INTR; + d->ep_out.wMaxPacketSize = info->max_packet_len; + d->ep_out.bInterval = info->polling_interval; + + // Config descriptor + usb_desc_add_iface(sizeof(usb_webusb_descriptor_block_t)); + + // Interface state + iface->type = USB_IFACE_TYPE_WEBUSB; + iface->webusb.desc_block = d; + iface->webusb.rx_buffer = info->rx_buffer; + iface->webusb.ep_in = info->ep_in; + iface->webusb.ep_out = info->ep_out; + iface->webusb.max_packet_len = info->max_packet_len; + iface->webusb.alt_setting = 0; + iface->webusb.last_read_len = 0; + iface->webusb.ep_in_is_idle = 1; + + return sectrue; } secbool usb_webusb_can_read(uint8_t iface_num) { - usb_iface_t *iface = usb_get_iface(iface_num); - if (iface == NULL) { - return secfalse; // Invalid interface number - } - if (iface->type != USB_IFACE_TYPE_WEBUSB) { - return secfalse; // Invalid interface type - } - if (iface->webusb.last_read_len == 0) { - return secfalse; // Nothing in the receiving buffer - } - if (usb_dev_handle.dev_state != USBD_STATE_CONFIGURED) { - return secfalse; // Device is not configured - } - return sectrue; + usb_iface_t *iface = usb_get_iface(iface_num); + if (iface == NULL) { + return secfalse; // Invalid interface number + } + if (iface->type != USB_IFACE_TYPE_WEBUSB) { + return secfalse; // Invalid interface type + } + if (iface->webusb.last_read_len == 0) { + return secfalse; // Nothing in the receiving buffer + } + if (usb_dev_handle.dev_state != USBD_STATE_CONFIGURED) { + return secfalse; // Device is not configured + } + return sectrue; } secbool usb_webusb_can_write(uint8_t iface_num) { - usb_iface_t *iface = usb_get_iface(iface_num); - if (iface == NULL) { - return secfalse; // Invalid interface number - } - if (iface->type != USB_IFACE_TYPE_WEBUSB) { - return secfalse; // Invalid interface type - } - if (iface->webusb.ep_in_is_idle == 0) { - return secfalse; // Last transmission is not over yet - } - if (usb_dev_handle.dev_state != USBD_STATE_CONFIGURED) { - return secfalse; // Device is not configured - } - return sectrue; + usb_iface_t *iface = usb_get_iface(iface_num); + if (iface == NULL) { + return secfalse; // Invalid interface number + } + if (iface->type != USB_IFACE_TYPE_WEBUSB) { + return secfalse; // Invalid interface type + } + if (iface->webusb.ep_in_is_idle == 0) { + return secfalse; // Last transmission is not over yet + } + if (usb_dev_handle.dev_state != USBD_STATE_CONFIGURED) { + return secfalse; // Device is not configured + } + return sectrue; } int usb_webusb_read(uint8_t iface_num, uint8_t *buf, uint32_t len) { - usb_iface_t *iface = usb_get_iface(iface_num); - if (iface == NULL) { - return -1; // Invalid interface number - } - if (iface->type != USB_IFACE_TYPE_WEBUSB) { - return -2; // Invalid interface type - } - usb_webusb_state_t *state = &iface->webusb; - - // Copy maximum possible amount of data and truncate the buffer length - if (len < state->last_read_len) { - return 0; // Not enough data in the read buffer - } - len = state->last_read_len; - state->last_read_len = 0; - memcpy(buf, state->rx_buffer, len); - - // Clear NAK to indicate we are ready to read more data - usb_ep_clear_nak(&usb_dev_handle, state->ep_out); - - return len; + usb_iface_t *iface = usb_get_iface(iface_num); + if (iface == NULL) { + return -1; // Invalid interface number + } + if (iface->type != USB_IFACE_TYPE_WEBUSB) { + return -2; // Invalid interface type + } + usb_webusb_state_t *state = &iface->webusb; + + // Copy maximum possible amount of data and truncate the buffer length + if (len < state->last_read_len) { + return 0; // Not enough data in the read buffer + } + len = state->last_read_len; + state->last_read_len = 0; + memcpy(buf, state->rx_buffer, len); + + // Clear NAK to indicate we are ready to read more data + usb_ep_clear_nak(&usb_dev_handle, state->ep_out); + + return len; } int usb_webusb_write(uint8_t iface_num, const uint8_t *buf, uint32_t len) { - usb_iface_t *iface = usb_get_iface(iface_num); - if (iface == NULL) { - return -1; // Invalid interface number - } - if (iface->type != USB_IFACE_TYPE_WEBUSB) { - return -2; // Invalid interface type - } - usb_webusb_state_t *state = &iface->webusb; - - state->ep_in_is_idle = 0; - USBD_LL_Transmit(&usb_dev_handle, state->ep_in, UNCONST(buf), (uint16_t)len); - - return len; + usb_iface_t *iface = usb_get_iface(iface_num); + if (iface == NULL) { + return -1; // Invalid interface number + } + if (iface->type != USB_IFACE_TYPE_WEBUSB) { + return -2; // Invalid interface type + } + usb_webusb_state_t *state = &iface->webusb; + + state->ep_in_is_idle = 0; + USBD_LL_Transmit(&usb_dev_handle, state->ep_in, UNCONST(buf), (uint16_t)len); + + return len; } int usb_webusb_read_select(uint32_t timeout) { - const uint32_t start = HAL_GetTick(); - for (;;) { - for (int i = 0; i < USBD_MAX_NUM_INTERFACES; i++) { - if (sectrue == usb_webusb_can_read(i)) { - return i; - } - } - if (HAL_GetTick() - start >= timeout) { - break; - } - __WFI(); // Enter sleep mode, waiting for interrupt + const uint32_t start = HAL_GetTick(); + for (;;) { + for (int i = 0; i < USBD_MAX_NUM_INTERFACES; i++) { + if (sectrue == usb_webusb_can_read(i)) { + return i; + } + } + if (HAL_GetTick() - start >= timeout) { + break; } - return -1; // Timeout + __WFI(); // Enter sleep mode, waiting for interrupt + } + return -1; // Timeout } -int usb_webusb_read_blocking(uint8_t iface_num, uint8_t *buf, uint32_t len, int timeout) { - const uint32_t start = HAL_GetTick(); - while (sectrue != usb_webusb_can_read(iface_num)) { - if (timeout >= 0 && HAL_GetTick() - start >= timeout) { - return 0; // Timeout - } - __WFI(); // Enter sleep mode, waiting for interrupt +int usb_webusb_read_blocking(uint8_t iface_num, uint8_t *buf, uint32_t len, + int timeout) { + const uint32_t start = HAL_GetTick(); + while (sectrue != usb_webusb_can_read(iface_num)) { + if (timeout >= 0 && HAL_GetTick() - start >= timeout) { + return 0; // Timeout } - return usb_webusb_read(iface_num, buf, len); + __WFI(); // Enter sleep mode, waiting for interrupt + } + return usb_webusb_read(iface_num, buf, len); } -int usb_webusb_write_blocking(uint8_t iface_num, const uint8_t *buf, uint32_t len, int timeout) { - const uint32_t start = HAL_GetTick(); - while (sectrue != usb_webusb_can_write(iface_num)) { - if (timeout >= 0 && HAL_GetTick() - start >= timeout) { - return 0; // Timeout - } - __WFI(); // Enter sleep mode, waiting for interrupt +int usb_webusb_write_blocking(uint8_t iface_num, const uint8_t *buf, + uint32_t len, int timeout) { + const uint32_t start = HAL_GetTick(); + while (sectrue != usb_webusb_can_write(iface_num)) { + if (timeout >= 0 && HAL_GetTick() - start >= timeout) { + return 0; // Timeout } - return usb_webusb_write(iface_num, buf, len); + __WFI(); // Enter sleep mode, waiting for interrupt + } + return usb_webusb_write(iface_num, buf, len); } -static void usb_webusb_class_init(USBD_HandleTypeDef *dev, usb_webusb_state_t *state, uint8_t cfg_idx) { - // Open endpoints - USBD_LL_OpenEP(dev, state->ep_in, USBD_EP_TYPE_INTR, state->max_packet_len); - USBD_LL_OpenEP(dev, state->ep_out, USBD_EP_TYPE_INTR, state->max_packet_len); +static void usb_webusb_class_init(USBD_HandleTypeDef *dev, + usb_webusb_state_t *state, uint8_t cfg_idx) { + // Open endpoints + USBD_LL_OpenEP(dev, state->ep_in, USBD_EP_TYPE_INTR, state->max_packet_len); + USBD_LL_OpenEP(dev, state->ep_out, USBD_EP_TYPE_INTR, state->max_packet_len); - // Reset the state - state->alt_setting = 0; - state->last_read_len = 0; - state->ep_in_is_idle = 1; + // Reset the state + state->alt_setting = 0; + state->last_read_len = 0; + state->ep_in_is_idle = 1; - // Prepare the OUT EP to receive next packet - USBD_LL_PrepareReceive(dev, state->ep_out, state->rx_buffer, state->max_packet_len); + // Prepare the OUT EP to receive next packet + USBD_LL_PrepareReceive(dev, state->ep_out, state->rx_buffer, + state->max_packet_len); } -static void usb_webusb_class_deinit(USBD_HandleTypeDef *dev, usb_webusb_state_t *state, uint8_t cfg_idx) { - // Flush endpoints - USBD_LL_FlushEP(dev, state->ep_in); - USBD_LL_FlushEP(dev, state->ep_out); - // Close endpoints - USBD_LL_CloseEP(dev, state->ep_in); - USBD_LL_CloseEP(dev, state->ep_out); +static void usb_webusb_class_deinit(USBD_HandleTypeDef *dev, + usb_webusb_state_t *state, + uint8_t cfg_idx) { + // Flush endpoints + USBD_LL_FlushEP(dev, state->ep_in); + USBD_LL_FlushEP(dev, state->ep_out); + // Close endpoints + USBD_LL_CloseEP(dev, state->ep_in); + USBD_LL_CloseEP(dev, state->ep_out); } -static int usb_webusb_class_setup(USBD_HandleTypeDef *dev, usb_webusb_state_t *state, USBD_SetupReqTypedef *req) { - - if ((req->bmRequest & USB_REQ_TYPE_MASK) != USB_REQ_TYPE_STANDARD) { - return USBD_OK; - } - - switch (req->bRequest) { - - case USB_REQ_SET_INTERFACE: - state->alt_setting = req->wValue; - USBD_CtlSendStatus(dev); - return USBD_OK; - - case USB_REQ_GET_INTERFACE: - USBD_CtlSendData(dev, &state->alt_setting, sizeof(state->alt_setting)); - return USBD_OK; - - default: - USBD_CtlError(dev, req); - return USBD_FAIL; - } +static int usb_webusb_class_setup(USBD_HandleTypeDef *dev, + usb_webusb_state_t *state, + USBD_SetupReqTypedef *req) { + if ((req->bmRequest & USB_REQ_TYPE_MASK) != USB_REQ_TYPE_STANDARD) { + return USBD_OK; + } + + switch (req->bRequest) { + case USB_REQ_SET_INTERFACE: + state->alt_setting = req->wValue; + USBD_CtlSendStatus(dev); + return USBD_OK; + + case USB_REQ_GET_INTERFACE: + USBD_CtlSendData(dev, &state->alt_setting, sizeof(state->alt_setting)); + return USBD_OK; + + default: + USBD_CtlError(dev, req); + return USBD_FAIL; + } } -static void usb_webusb_class_data_in(USBD_HandleTypeDef *dev, usb_webusb_state_t *state, uint8_t ep_num) { - if ((ep_num | USB_EP_DIR_IN) == state->ep_in) { - state->ep_in_is_idle = 1; - } +static void usb_webusb_class_data_in(USBD_HandleTypeDef *dev, + usb_webusb_state_t *state, + uint8_t ep_num) { + if ((ep_num | USB_EP_DIR_IN) == state->ep_in) { + state->ep_in_is_idle = 1; + } } -static void usb_webusb_class_data_out(USBD_HandleTypeDef *dev, usb_webusb_state_t *state, uint8_t ep_num) { - if (ep_num == state->ep_out) { - state->last_read_len = USBD_LL_GetRxDataSize(dev, ep_num); +static void usb_webusb_class_data_out(USBD_HandleTypeDef *dev, + usb_webusb_state_t *state, + uint8_t ep_num) { + if (ep_num == state->ep_out) { + state->last_read_len = USBD_LL_GetRxDataSize(dev, ep_num); - // Prepare the OUT EP to receive next packet - // User should provide state->rx_buffer that is big enough for state->max_packet_len bytes - USBD_LL_PrepareReceive(dev, ep_num, state->rx_buffer, state->max_packet_len); - - if (state->last_read_len > 0) { - // Block the OUT EP until we process received data - usb_ep_set_nak(dev, ep_num); - } + // Prepare the OUT EP to receive next packet + // User should provide state->rx_buffer that is big enough for + // state->max_packet_len bytes + USBD_LL_PrepareReceive(dev, ep_num, state->rx_buffer, + state->max_packet_len); + + if (state->last_read_len > 0) { + // Block the OUT EP until we process received data + usb_ep_set_nak(dev, ep_num); } + } } diff --git a/embed/trezorhal/usbd_conf.c b/embed/trezorhal/usbd_conf.c index ef25a58c8..26fdf00c3 100644 --- a/embed/trezorhal/usbd_conf.c +++ b/embed/trezorhal/usbd_conf.c @@ -1,3 +1,5 @@ +// clang-format off + /* * This file is part of the Micro Python project, http://micropython.org/ */ diff --git a/embed/trezorhal/usbd_conf.h b/embed/trezorhal/usbd_conf.h index cf00d92ba..6ff2c71c8 100644 --- a/embed/trezorhal/usbd_conf.h +++ b/embed/trezorhal/usbd_conf.h @@ -1,3 +1,5 @@ +// clang-format off + /* * This file is part of the Micro Python project, http://micropython.org/ */ diff --git a/embed/trezorhal/usbd_core.c b/embed/trezorhal/usbd_core.c index 2f62e4972..2663a6d88 100644 --- a/embed/trezorhal/usbd_core.c +++ b/embed/trezorhal/usbd_core.c @@ -1,3 +1,5 @@ +// clang-format off + /** ****************************************************************************** * @file usbd_core.c diff --git a/embed/trezorhal/usbd_core.h b/embed/trezorhal/usbd_core.h index fcfffa1e6..960d73b0d 100644 --- a/embed/trezorhal/usbd_core.h +++ b/embed/trezorhal/usbd_core.h @@ -1,3 +1,5 @@ +// clang-format off + /** ****************************************************************************** * @file usbd_core.h diff --git a/embed/trezorhal/usbd_ctlreq.c b/embed/trezorhal/usbd_ctlreq.c index fe6b60f01..5710b548d 100644 --- a/embed/trezorhal/usbd_ctlreq.c +++ b/embed/trezorhal/usbd_ctlreq.c @@ -1,3 +1,5 @@ +// clang-format off + /** ****************************************************************************** * @file usbd_req.c diff --git a/embed/trezorhal/usbd_ctlreq.h b/embed/trezorhal/usbd_ctlreq.h index 30597cffc..27e29356d 100644 --- a/embed/trezorhal/usbd_ctlreq.h +++ b/embed/trezorhal/usbd_ctlreq.h @@ -1,3 +1,5 @@ +// clang-format off + /** ****************************************************************************** * @file usbd_req.h diff --git a/embed/trezorhal/usbd_def.h b/embed/trezorhal/usbd_def.h index e3da6243d..6f20975a9 100644 --- a/embed/trezorhal/usbd_def.h +++ b/embed/trezorhal/usbd_def.h @@ -1,3 +1,5 @@ +// clang-format off + /** ****************************************************************************** * @file usbd_def.h diff --git a/embed/trezorhal/usbd_ioreq.c b/embed/trezorhal/usbd_ioreq.c index e1b9c75cb..ebbdd3b15 100644 --- a/embed/trezorhal/usbd_ioreq.c +++ b/embed/trezorhal/usbd_ioreq.c @@ -1,3 +1,5 @@ +// clang-format off + /** ****************************************************************************** * @file usbd_ioreq.c diff --git a/embed/trezorhal/usbd_ioreq.h b/embed/trezorhal/usbd_ioreq.h index bb5d85caf..78e6d2f17 100644 --- a/embed/trezorhal/usbd_ioreq.h +++ b/embed/trezorhal/usbd_ioreq.h @@ -1,3 +1,5 @@ +// clang-format off + /** ****************************************************************************** * @file usbd_ioreq.h diff --git a/embed/unix/common.c b/embed/unix/common.c index 73047d40e..00767b1b6 100644 --- a/embed/unix/common.c +++ b/embed/unix/common.c @@ -25,90 +25,88 @@ #include "display.h" #include "memzero.h" -void __shutdown(void) -{ - printf("SHUTDOWN\n"); - exit(3); +void __shutdown(void) { + printf("SHUTDOWN\n"); + exit(3); } #define COLOR_FATAL_ERROR RGB16(0x7F, 0x00, 0x00) -void __attribute__((noreturn)) __fatal_error(const char *expr, const char *msg, const char *file, int line, const char *func) -{ - display_orientation(0); - display_backlight(255); - display_print_color(COLOR_WHITE, COLOR_FATAL_ERROR); - display_printf("\nFATAL ERROR:\n"); - printf("\nFATAL ERROR:\n"); - if (expr) { - display_printf("expr: %s\n", expr); - printf("expr: %s\n", expr); - } - if (msg) { - display_printf("msg : %s\n", msg); - printf("msg : %s\n", msg); - } - if (file) { - display_printf("file: %s:%d\n", file, line); - printf("file: %s:%d\n", file, line); - } - if (func) { - display_printf("func: %s\n", func); - printf("func: %s\n", func); - } +void __attribute__((noreturn)) +__fatal_error(const char *expr, const char *msg, const char *file, int line, + const char *func) { + display_orientation(0); + display_backlight(255); + display_print_color(COLOR_WHITE, COLOR_FATAL_ERROR); + display_printf("\nFATAL ERROR:\n"); + printf("\nFATAL ERROR:\n"); + if (expr) { + display_printf("expr: %s\n", expr); + printf("expr: %s\n", expr); + } + if (msg) { + display_printf("msg : %s\n", msg); + printf("msg : %s\n", msg); + } + if (file) { + display_printf("file: %s:%d\n", file, line); + printf("file: %s:%d\n", file, line); + } + if (func) { + display_printf("func: %s\n", func); + printf("func: %s\n", func); + } #ifdef GITREV - display_printf("rev : %s\n", XSTR(GITREV)); - printf("rev : %s\n", XSTR(GITREV)); + display_printf("rev : %s\n", XSTR(GITREV)); + printf("rev : %s\n", XSTR(GITREV)); #endif - display_printf("\nPlease contact TREZOR support.\n"); - printf("\nPlease contact TREZOR support.\n"); - hal_delay(3000); - __shutdown(); - for (;;); + display_printf("\nPlease contact TREZOR support.\n"); + printf("\nPlease contact TREZOR support.\n"); + hal_delay(3000); + __shutdown(); + for (;;) + ; } -void __attribute__((noreturn)) error_shutdown(const char *line1, const char *line2, const char *line3, const char *line4) -{ - display_clear(); - display_bar(0, 0, DISPLAY_RESX, DISPLAY_RESY, COLOR_FATAL_ERROR); - int y = 32; - if (line1) { - display_text(8, y, line1, -1, FONT_NORMAL, COLOR_WHITE, COLOR_FATAL_ERROR); - printf("%s\n", line1); - y += 32; - } - if (line2) { - display_text(8, y, line2, -1, FONT_NORMAL, COLOR_WHITE, COLOR_FATAL_ERROR); - printf("%s\n", line2); - y += 32; - } - if (line3) { - display_text(8, y, line3, -1, FONT_NORMAL, COLOR_WHITE, COLOR_FATAL_ERROR); - printf("%s\n", line3); - y += 32; - } - if (line4) { - display_text(8, y, line4, -1, FONT_NORMAL, COLOR_WHITE, COLOR_FATAL_ERROR); - printf("%s\n", line4); - y += 32; - } +void __attribute__((noreturn)) +error_shutdown(const char *line1, const char *line2, const char *line3, + const char *line4) { + display_clear(); + display_bar(0, 0, DISPLAY_RESX, DISPLAY_RESY, COLOR_FATAL_ERROR); + int y = 32; + if (line1) { + display_text(8, y, line1, -1, FONT_NORMAL, COLOR_WHITE, COLOR_FATAL_ERROR); + printf("%s\n", line1); y += 32; - display_text(8, y, "Please unplug the device.", -1, FONT_NORMAL, COLOR_WHITE, COLOR_FATAL_ERROR); - printf("\nPlease unplug the device.\n"); - display_backlight(255); - hal_delay(5000); - __shutdown(); - for (;;); + } + if (line2) { + display_text(8, y, line2, -1, FONT_NORMAL, COLOR_WHITE, COLOR_FATAL_ERROR); + printf("%s\n", line2); + y += 32; + } + if (line3) { + display_text(8, y, line3, -1, FONT_NORMAL, COLOR_WHITE, COLOR_FATAL_ERROR); + printf("%s\n", line3); + y += 32; + } + if (line4) { + display_text(8, y, line4, -1, FONT_NORMAL, COLOR_WHITE, COLOR_FATAL_ERROR); + printf("%s\n", line4); + y += 32; + } + y += 32; + display_text(8, y, "Please unplug the device.", -1, FONT_NORMAL, COLOR_WHITE, + COLOR_FATAL_ERROR); + printf("\nPlease unplug the device.\n"); + display_backlight(255); + hal_delay(5000); + __shutdown(); + for (;;) + ; } -void hal_delay(uint32_t ms) -{ - usleep(1000 * ms); -} +void hal_delay(uint32_t ms) { usleep(1000 * ms); } uint8_t HW_ENTROPY_DATA[HW_ENTROPY_LEN]; -void collect_hw_entropy(void) -{ - memzero(HW_ENTROPY_DATA, HW_ENTROPY_LEN); -} +void collect_hw_entropy(void) { memzero(HW_ENTROPY_DATA, HW_ENTROPY_LEN); } diff --git a/embed/unix/common.h b/embed/unix/common.h index e0bc6dde8..4254940e2 100644 --- a/embed/unix/common.h +++ b/embed/unix/common.h @@ -27,16 +27,33 @@ #define STR(s) #s #ifndef MIN -#define MIN(a, b) ({ typeof(a) _a = (a); typeof(b) _b = (b); _a < _b ? _a : _b; }) +#define MIN(a, b) \ + ({ \ + typeof(a) _a = (a); \ + typeof(b) _b = (b); \ + _a < _b ? _a : _b; \ + }) #endif #ifndef MAX -#define MAX(a, b) ({ typeof(a) _a = (a); typeof(b) _b = (b); _a > _b ? _a : _b; }) +#define MAX(a, b) \ + ({ \ + typeof(a) _a = (a); \ + typeof(b) _b = (b); \ + _a > _b ? _a : _b; \ + }) #endif -void __attribute__((noreturn)) __fatal_error(const char *expr, const char *msg, const char *file, int line, const char *func); -void __attribute__((noreturn)) error_shutdown(const char *line1, const char *line2, const char *line3, const char *line4); +void __attribute__((noreturn)) +__fatal_error(const char *expr, const char *msg, const char *file, int line, + const char *func); +void __attribute__((noreturn)) +error_shutdown(const char *line1, const char *line2, const char *line3, + const char *line4); -#define ensure(expr, msg) (((expr) == sectrue) ? (void)0 : __fatal_error(#expr, msg, __FILE__, __LINE__, __func__)) +#define ensure(expr, msg) \ + (((expr) == sectrue) \ + ? (void)0 \ + : __fatal_error(#expr, msg, __FILE__, __LINE__, __func__)) void hal_delay(uint32_t ms); diff --git a/embed/unix/flash.c b/embed/unix/flash.c index 8e4febe6a..2e67b9597 100644 --- a/embed/unix/flash.c +++ b/embed/unix/flash.c @@ -17,12 +17,12 @@ * along with this program. If not, see . */ -#include -#include #include +#include #include #include #include +#include #include @@ -35,31 +35,31 @@ #endif static const uint32_t FLASH_SECTOR_TABLE[FLASH_SECTOR_COUNT + 1] = { - [ 0] = 0x08000000, // - 0x08003FFF | 16 KiB - [ 1] = 0x08004000, // - 0x08007FFF | 16 KiB - [ 2] = 0x08008000, // - 0x0800BFFF | 16 KiB - [ 3] = 0x0800C000, // - 0x0800FFFF | 16 KiB - [ 4] = 0x08010000, // - 0x0801FFFF | 64 KiB - [ 5] = 0x08020000, // - 0x0803FFFF | 128 KiB - [ 6] = 0x08040000, // - 0x0805FFFF | 128 KiB - [ 7] = 0x08060000, // - 0x0807FFFF | 128 KiB - [ 8] = 0x08080000, // - 0x0809FFFF | 128 KiB - [ 9] = 0x080A0000, // - 0x080BFFFF | 128 KiB - [10] = 0x080C0000, // - 0x080DFFFF | 128 KiB - [11] = 0x080E0000, // - 0x080FFFFF | 128 KiB - [12] = 0x08100000, // - 0x08103FFF | 16 KiB - [13] = 0x08104000, // - 0x08107FFF | 16 KiB - [14] = 0x08108000, // - 0x0810BFFF | 16 KiB - [15] = 0x0810C000, // - 0x0810FFFF | 16 KiB - [16] = 0x08110000, // - 0x0811FFFF | 64 KiB - [17] = 0x08120000, // - 0x0813FFFF | 128 KiB - [18] = 0x08140000, // - 0x0815FFFF | 128 KiB - [19] = 0x08160000, // - 0x0817FFFF | 128 KiB - [20] = 0x08180000, // - 0x0819FFFF | 128 KiB - [21] = 0x081A0000, // - 0x081BFFFF | 128 KiB - [22] = 0x081C0000, // - 0x081DFFFF | 128 KiB - [23] = 0x081E0000, // - 0x081FFFFF | 128 KiB - [24] = 0x08200000, // last element - not a valid sector + [0] = 0x08000000, // - 0x08003FFF | 16 KiB + [1] = 0x08004000, // - 0x08007FFF | 16 KiB + [2] = 0x08008000, // - 0x0800BFFF | 16 KiB + [3] = 0x0800C000, // - 0x0800FFFF | 16 KiB + [4] = 0x08010000, // - 0x0801FFFF | 64 KiB + [5] = 0x08020000, // - 0x0803FFFF | 128 KiB + [6] = 0x08040000, // - 0x0805FFFF | 128 KiB + [7] = 0x08060000, // - 0x0807FFFF | 128 KiB + [8] = 0x08080000, // - 0x0809FFFF | 128 KiB + [9] = 0x080A0000, // - 0x080BFFFF | 128 KiB + [10] = 0x080C0000, // - 0x080DFFFF | 128 KiB + [11] = 0x080E0000, // - 0x080FFFFF | 128 KiB + [12] = 0x08100000, // - 0x08103FFF | 16 KiB + [13] = 0x08104000, // - 0x08107FFF | 16 KiB + [14] = 0x08108000, // - 0x0810BFFF | 16 KiB + [15] = 0x0810C000, // - 0x0810FFFF | 16 KiB + [16] = 0x08110000, // - 0x0811FFFF | 64 KiB + [17] = 0x08120000, // - 0x0813FFFF | 128 KiB + [18] = 0x08140000, // - 0x0815FFFF | 128 KiB + [19] = 0x08160000, // - 0x0817FFFF | 128 KiB + [20] = 0x08180000, // - 0x0819FFFF | 128 KiB + [21] = 0x081A0000, // - 0x081BFFFF | 128 KiB + [22] = 0x081C0000, // - 0x081DFFFF | 128 KiB + [23] = 0x081E0000, // - 0x081FFFFF | 128 KiB + [24] = 0x08200000, // last element - not a valid sector }; const uint8_t FIRMWARE_SECTORS[FIRMWARE_SECTORS_COUNT] = { @@ -86,129 +86,116 @@ const uint8_t STORAGE_SECTORS[STORAGE_SECTORS_COUNT] = { static uint8_t *FLASH_BUFFER; static uint32_t FLASH_SIZE; -static void flash_exit(void) -{ - int r = munmap(FLASH_BUFFER, FLASH_SIZE); - ensure(sectrue * (r == 0), "munmap failed"); +static void flash_exit(void) { + int r = munmap(FLASH_BUFFER, FLASH_SIZE); + ensure(sectrue * (r == 0), "munmap failed"); } -void flash_init(void) -{ - FLASH_SIZE = FLASH_SECTOR_TABLE[FLASH_SECTOR_COUNT] - FLASH_SECTOR_TABLE[0]; - - // check whether the file exists and it has the correct size - struct stat sb; - int r = stat(FLASH_FILE, &sb); - - // (re)create if non existant or wrong size - if (r != 0 || sb.st_size != FLASH_SIZE) { - int fd = open(FLASH_FILE, O_RDWR | O_CREAT | O_TRUNC, (mode_t)0600); - ensure(sectrue * (fd >= 0), "open failed"); - for (int i = 0; i < FLASH_SIZE / 16; i++) { - ssize_t s = write(fd, "\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF", 16); - ensure(sectrue * (s >= 0), "write failed"); - } - r = close(fd); - ensure(sectrue * (r == 0), "close failed"); - } +void flash_init(void) { + FLASH_SIZE = FLASH_SECTOR_TABLE[FLASH_SECTOR_COUNT] - FLASH_SECTOR_TABLE[0]; + + // check whether the file exists and it has the correct size + struct stat sb; + int r = stat(FLASH_FILE, &sb); - // mmap file - int fd = open(FLASH_FILE, O_RDWR); + // (re)create if non existant or wrong size + if (r != 0 || sb.st_size != FLASH_SIZE) { + int fd = open(FLASH_FILE, O_RDWR | O_CREAT | O_TRUNC, (mode_t)0600); ensure(sectrue * (fd >= 0), "open failed"); + for (int i = 0; i < FLASH_SIZE / 16; i++) { + ssize_t s = write( + fd, + "\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF", + 16); + ensure(sectrue * (s >= 0), "write failed"); + } + r = close(fd); + ensure(sectrue * (r == 0), "close failed"); + } - void *map = mmap(0, FLASH_SIZE, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0); - ensure(sectrue * (map != MAP_FAILED), "mmap failed"); + // mmap file + int fd = open(FLASH_FILE, O_RDWR); + ensure(sectrue * (fd >= 0), "open failed"); - FLASH_BUFFER = (uint8_t *)map; + void *map = mmap(0, FLASH_SIZE, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0); + ensure(sectrue * (map != MAP_FAILED), "mmap failed"); - atexit(flash_exit); -} + FLASH_BUFFER = (uint8_t *)map; -secbool flash_unlock_write(void) -{ - return sectrue; + atexit(flash_exit); } -secbool flash_lock_write(void) -{ - return sectrue; -} +secbool flash_unlock_write(void) { return sectrue; } -const void *flash_get_address(uint8_t sector, uint32_t offset, uint32_t size) -{ - if (sector >= FLASH_SECTOR_COUNT) { - return NULL; - } - const uint32_t addr = FLASH_SECTOR_TABLE[sector] + offset; - const uint32_t next = FLASH_SECTOR_TABLE[sector + 1]; - if (addr + size > next) { - return NULL; - } - return FLASH_BUFFER + addr - FLASH_SECTOR_TABLE[0]; -} +secbool flash_lock_write(void) { return sectrue; } -secbool flash_erase_sectors(const uint8_t *sectors, int len, void (*progress)(int pos, int len)) -{ - if (progress) { - progress(0, len); - } - for (int i = 0; i < len; i++) { - const uint8_t sector = sectors[i]; - const uint32_t offset = FLASH_SECTOR_TABLE[sector] - FLASH_SECTOR_TABLE[0]; - const uint32_t size = FLASH_SECTOR_TABLE[sector + 1] - FLASH_SECTOR_TABLE[sector]; - memset(FLASH_BUFFER + offset, 0xFF, size); - if (progress) { - progress(i + 1, len); - } - } - return sectrue; +const void *flash_get_address(uint8_t sector, uint32_t offset, uint32_t size) { + if (sector >= FLASH_SECTOR_COUNT) { + return NULL; + } + const uint32_t addr = FLASH_SECTOR_TABLE[sector] + offset; + const uint32_t next = FLASH_SECTOR_TABLE[sector + 1]; + if (addr + size > next) { + return NULL; + } + return FLASH_BUFFER + addr - FLASH_SECTOR_TABLE[0]; } -secbool flash_write_byte(uint8_t sector, uint32_t offset, uint8_t data) -{ - uint8_t *flash = (uint8_t *)flash_get_address(sector, offset, 1); - if (!flash) { - return secfalse; - } - if ((flash[0] & data) != data) { - return secfalse; // we cannot change zeroes to ones - } - flash[0] = data; - return sectrue; -} - -secbool flash_write_word(uint8_t sector, uint32_t offset, uint32_t data) -{ - if (offset % sizeof(uint32_t)) { // we write only at 4-byte boundary - return secfalse; - } - uint32_t *flash = (uint32_t *)flash_get_address(sector, offset, sizeof(data)); - if (!flash) { - return secfalse; - } - if ((flash[0] & data) != data) { - return secfalse; // we cannot change zeroes to ones +secbool flash_erase_sectors(const uint8_t *sectors, int len, + void (*progress)(int pos, int len)) { + if (progress) { + progress(0, len); + } + for (int i = 0; i < len; i++) { + const uint8_t sector = sectors[i]; + const uint32_t offset = FLASH_SECTOR_TABLE[sector] - FLASH_SECTOR_TABLE[0]; + const uint32_t size = + FLASH_SECTOR_TABLE[sector + 1] - FLASH_SECTOR_TABLE[sector]; + memset(FLASH_BUFFER + offset, 0xFF, size); + if (progress) { + progress(i + 1, len); } - flash[0] = data; - return sectrue; + } + return sectrue; } -secbool flash_otp_read(uint8_t block, uint8_t offset, uint8_t *data, uint8_t datalen) -{ +secbool flash_write_byte(uint8_t sector, uint32_t offset, uint8_t data) { + uint8_t *flash = (uint8_t *)flash_get_address(sector, offset, 1); + if (!flash) { return secfalse; + } + if ((flash[0] & data) != data) { + return secfalse; // we cannot change zeroes to ones + } + flash[0] = data; + return sectrue; } -secbool flash_otp_write(uint8_t block, uint8_t offset, const uint8_t *data, uint8_t datalen) -{ +secbool flash_write_word(uint8_t sector, uint32_t offset, uint32_t data) { + if (offset % sizeof(uint32_t)) { // we write only at 4-byte boundary + return secfalse; + } + uint32_t *flash = (uint32_t *)flash_get_address(sector, offset, sizeof(data)); + if (!flash) { return secfalse; + } + if ((flash[0] & data) != data) { + return secfalse; // we cannot change zeroes to ones + } + flash[0] = data; + return sectrue; } -secbool flash_otp_lock(uint8_t block) -{ - return secfalse; +secbool flash_otp_read(uint8_t block, uint8_t offset, uint8_t *data, + uint8_t datalen) { + return secfalse; } -secbool flash_otp_is_locked(uint8_t block) -{ - return secfalse; +secbool flash_otp_write(uint8_t block, uint8_t offset, const uint8_t *data, + uint8_t datalen) { + return secfalse; } + +secbool flash_otp_lock(uint8_t block) { return secfalse; } + +secbool flash_otp_is_locked(uint8_t block) { return secfalse; } diff --git a/embed/unix/main.c b/embed/unix/main.c index aef92a8cc..c31c260ab 100644 --- a/embed/unix/main.c +++ b/embed/unix/main.c @@ -24,31 +24,31 @@ * THE SOFTWARE. */ -#include +#include +#include +#include +#include #include +#include #include -#include #include -#include -#include -#include +#include #include #include -#include -#include +#include -#include "py/compile.h" -#include "py/runtime.h" -#include "py/builtin.h" -#include "py/repl.h" -#include "py/gc.h" -#include "py/stackctrl.h" -#include "py/mphal.h" -#include "py/mpthread.h" #include "extmod/misc.h" #include "genhdr/mpversion.h" #include "input.h" #include "profile.h" +#include "py/builtin.h" +#include "py/compile.h" +#include "py/gc.h" +#include "py/mphal.h" +#include "py/mpthread.h" +#include "py/repl.h" +#include "py/runtime.h" +#include "py/stackctrl.h" #include "common.h" @@ -59,14 +59,14 @@ STATIC uint emit_opt = MP_EMIT_OPT_NONE; #if MICROPY_ENABLE_GC // Heap size of GC heap (if enabled) // Make it larger on a 64 bit machine, because pointers are larger. -long heap_size = 1024*1024 * (sizeof(mp_uint_t) / 4); +long heap_size = 1024 * 1024 * (sizeof(mp_uint_t) / 4); #endif STATIC void stderr_print_strn(void *env, const char *str, size_t len) { - (void)env; - ssize_t dummy = write(STDERR_FILENO, str, len); - mp_uos_dupterm_tx_strn(str, len); - (void)dummy; + (void)env; + ssize_t dummy = write(STDERR_FILENO, str, len); + mp_uos_dupterm_tx_strn(str, len); + (void)dummy; } const mp_print_t mp_stderr_print = {NULL, stderr_print_strn}; @@ -76,20 +76,21 @@ const mp_print_t mp_stderr_print = {NULL, stderr_print_strn}; // and lower 8 bits are SystemExit value. For all other exceptions, // return 1. STATIC int handle_uncaught_exception(mp_obj_base_t *exc) { - // check for SystemExit - if (mp_obj_is_subclass_fast(MP_OBJ_FROM_PTR(exc->type), MP_OBJ_FROM_PTR(&mp_type_SystemExit))) { - // None is an exit value of 0; an int is its value; anything else is 1 - mp_obj_t exit_val = mp_obj_exception_get_value(MP_OBJ_FROM_PTR(exc)); - mp_int_t val = 0; - if (exit_val != mp_const_none && !mp_obj_get_int_maybe(exit_val, &val)) { - val = 1; - } - return FORCED_EXIT | (val & 255); + // check for SystemExit + if (mp_obj_is_subclass_fast(MP_OBJ_FROM_PTR(exc->type), + MP_OBJ_FROM_PTR(&mp_type_SystemExit))) { + // None is an exit value of 0; an int is its value; anything else is 1 + mp_obj_t exit_val = mp_obj_exception_get_value(MP_OBJ_FROM_PTR(exc)); + mp_int_t val = 0; + if (exit_val != mp_const_none && !mp_obj_get_int_maybe(exit_val, &val)) { + val = 1; } + return FORCED_EXIT | (val & 255); + } - // Report all other exceptions - mp_obj_print_exception(&mp_stderr_print, MP_OBJ_FROM_PTR(exc)); - return 1; + // Report all other exceptions + mp_obj_print_exception(&mp_stderr_print, MP_OBJ_FROM_PTR(exc)); + return 1; } #define LEX_SRC_STR (1) @@ -100,302 +101,309 @@ STATIC int handle_uncaught_exception(mp_obj_base_t *exc) { // Returns standard error codes: 0 for success, 1 for all other errors, // except if FORCED_EXIT bit is set then script raised SystemExit and the // value of the exit is in the lower 8 bits of the return value -STATIC int execute_from_lexer(int source_kind, const void *source, mp_parse_input_kind_t input_kind, bool is_repl) { - mp_hal_set_interrupt_char(CHAR_CTRL_C); - - nlr_buf_t nlr; - if (nlr_push(&nlr) == 0) { - // create lexer based on source kind - mp_lexer_t *lex; - if (source_kind == LEX_SRC_STR) { - const char *line = source; - lex = mp_lexer_new_from_str_len(MP_QSTR__lt_stdin_gt_, line, strlen(line), false); - } else if (source_kind == LEX_SRC_VSTR) { - const vstr_t *vstr = source; - lex = mp_lexer_new_from_str_len(MP_QSTR__lt_stdin_gt_, vstr->buf, vstr->len, false); - } else if (source_kind == LEX_SRC_FILENAME) { - lex = mp_lexer_new_from_file((const char*)source); - } else { // LEX_SRC_STDIN - lex = mp_lexer_new_from_fd(MP_QSTR__lt_stdin_gt_, 0, false); - } +STATIC int execute_from_lexer(int source_kind, const void *source, + mp_parse_input_kind_t input_kind, bool is_repl) { + mp_hal_set_interrupt_char(CHAR_CTRL_C); + + nlr_buf_t nlr; + if (nlr_push(&nlr) == 0) { + // create lexer based on source kind + mp_lexer_t *lex; + if (source_kind == LEX_SRC_STR) { + const char *line = source; + lex = mp_lexer_new_from_str_len(MP_QSTR__lt_stdin_gt_, line, strlen(line), + false); + } else if (source_kind == LEX_SRC_VSTR) { + const vstr_t *vstr = source; + lex = mp_lexer_new_from_str_len(MP_QSTR__lt_stdin_gt_, vstr->buf, + vstr->len, false); + } else if (source_kind == LEX_SRC_FILENAME) { + lex = mp_lexer_new_from_file((const char *)source); + } else { // LEX_SRC_STDIN + lex = mp_lexer_new_from_fd(MP_QSTR__lt_stdin_gt_, 0, false); + } - qstr source_name = lex->source_name; + qstr source_name = lex->source_name; - #if MICROPY_PY___FILE__ - if (input_kind == MP_PARSE_FILE_INPUT) { - mp_store_global(MP_QSTR___file__, MP_OBJ_NEW_QSTR(source_name)); - } - #endif +#if MICROPY_PY___FILE__ + if (input_kind == MP_PARSE_FILE_INPUT) { + mp_store_global(MP_QSTR___file__, MP_OBJ_NEW_QSTR(source_name)); + } +#endif - mp_parse_tree_t parse_tree = mp_parse(lex, input_kind); + mp_parse_tree_t parse_tree = mp_parse(lex, input_kind); - #if defined(MICROPY_UNIX_COVERAGE) - // allow to print the parse tree in the coverage build - if (mp_verbose_flag >= 3) { - printf("----------------\n"); - mp_parse_node_print(parse_tree.root, 0); - printf("----------------\n"); - } - #endif - - mp_obj_t module_fun = mp_compile(&parse_tree, source_name, emit_opt, is_repl); - - if (!compile_only) { - // execute it - mp_call_function_0(module_fun); - // check for pending exception - if (MP_STATE_VM(mp_pending_exception) != MP_OBJ_NULL) { - mp_obj_t obj = MP_STATE_VM(mp_pending_exception); - MP_STATE_VM(mp_pending_exception) = MP_OBJ_NULL; - nlr_raise(obj); - } - } - - mp_hal_set_interrupt_char(-1); - nlr_pop(); - return 0; +#if defined(MICROPY_UNIX_COVERAGE) + // allow to print the parse tree in the coverage build + if (mp_verbose_flag >= 3) { + printf("----------------\n"); + mp_parse_node_print(parse_tree.root, 0); + printf("----------------\n"); + } +#endif - } else { - // uncaught exception - mp_hal_set_interrupt_char(-1); - return handle_uncaught_exception(nlr.ret_val); + mp_obj_t module_fun = + mp_compile(&parse_tree, source_name, emit_opt, is_repl); + + if (!compile_only) { + // execute it + mp_call_function_0(module_fun); + // check for pending exception + if (MP_STATE_VM(mp_pending_exception) != MP_OBJ_NULL) { + mp_obj_t obj = MP_STATE_VM(mp_pending_exception); + MP_STATE_VM(mp_pending_exception) = MP_OBJ_NULL; + nlr_raise(obj); + } } + + mp_hal_set_interrupt_char(-1); + nlr_pop(); + return 0; + + } else { + // uncaught exception + mp_hal_set_interrupt_char(-1); + return handle_uncaught_exception(nlr.ret_val); + } } #if MICROPY_USE_READLINE == 1 #include "lib/mp-readline/readline.h" #else STATIC char *strjoin(const char *s1, int sep_char, const char *s2) { - int l1 = strlen(s1); - int l2 = strlen(s2); - char *s = malloc(l1 + l2 + 2); - memcpy(s, s1, l1); - if (sep_char != 0) { - s[l1] = sep_char; - l1 += 1; - } - memcpy(s + l1, s2, l2); - s[l1 + l2] = 0; - return s; + int l1 = strlen(s1); + int l2 = strlen(s2); + char *s = malloc(l1 + l2 + 2); + memcpy(s, s1, l1); + if (sep_char != 0) { + s[l1] = sep_char; + l1 += 1; + } + memcpy(s + l1, s2, l2); + s[l1 + l2] = 0; + return s; } #endif STATIC int do_repl(void) { - mp_hal_stdout_tx_str("MicroPython " MICROPY_GIT_TAG " on " MICROPY_BUILD_DATE "; " - MICROPY_PY_SYS_PLATFORM " version\nUse Ctrl-D to exit, Ctrl-E for paste mode\n"); - - #if MICROPY_USE_READLINE == 1 - - // use MicroPython supplied readline + mp_hal_stdout_tx_str("MicroPython " MICROPY_GIT_TAG " on " MICROPY_BUILD_DATE + "; " MICROPY_PY_SYS_PLATFORM + " version\nUse Ctrl-D to exit, Ctrl-E for paste mode\n"); - vstr_t line; - vstr_init(&line, 16); - for (;;) { - mp_hal_stdio_mode_raw(); - - input_restart: - vstr_reset(&line); - int ret = readline(&line, ">>> "); - mp_parse_input_kind_t parse_input_kind = MP_PARSE_SINGLE_INPUT; +#if MICROPY_USE_READLINE == 1 + // use MicroPython supplied readline + + vstr_t line; + vstr_init(&line, 16); + for (;;) { + mp_hal_stdio_mode_raw(); + + input_restart: + vstr_reset(&line); + int ret = readline(&line, ">>> "); + mp_parse_input_kind_t parse_input_kind = MP_PARSE_SINGLE_INPUT; + + if (ret == CHAR_CTRL_C) { + // cancel input + mp_hal_stdout_tx_str("\r\n"); + goto input_restart; + } else if (ret == CHAR_CTRL_D) { + // EOF + printf("\n"); + mp_hal_stdio_mode_orig(); + vstr_clear(&line); + return 0; + } else if (ret == CHAR_CTRL_E) { + // paste mode + mp_hal_stdout_tx_str( + "\npaste mode; Ctrl-C to cancel, Ctrl-D to finish\n=== "); + vstr_reset(&line); + for (;;) { + char c = mp_hal_stdin_rx_chr(); + if (c == CHAR_CTRL_C) { + // cancel everything + mp_hal_stdout_tx_str("\n"); + goto input_restart; + } else if (c == CHAR_CTRL_D) { + // end of input + mp_hal_stdout_tx_str("\n"); + break; + } else { + // add char to buffer and echo + vstr_add_byte(&line, c); + if (c == '\r') { + mp_hal_stdout_tx_str("\n=== "); + } else { + mp_hal_stdout_tx_strn(&c, 1); + } + } + } + parse_input_kind = MP_PARSE_FILE_INPUT; + } else if (line.len == 0) { + if (ret != 0) { + printf("\n"); + } + goto input_restart; + } else { + // got a line with non-zero length, see if it needs continuing + while (mp_repl_continue_with_input(vstr_null_terminated_str(&line))) { + vstr_add_byte(&line, '\n'); + ret = readline(&line, "... "); if (ret == CHAR_CTRL_C) { - // cancel input - mp_hal_stdout_tx_str("\r\n"); - goto input_restart; + // cancel everything + printf("\n"); + goto input_restart; } else if (ret == CHAR_CTRL_D) { - // EOF - printf("\n"); - mp_hal_stdio_mode_orig(); - vstr_clear(&line); - return 0; - } else if (ret == CHAR_CTRL_E) { - // paste mode - mp_hal_stdout_tx_str("\npaste mode; Ctrl-C to cancel, Ctrl-D to finish\n=== "); - vstr_reset(&line); - for (;;) { - char c = mp_hal_stdin_rx_chr(); - if (c == CHAR_CTRL_C) { - // cancel everything - mp_hal_stdout_tx_str("\n"); - goto input_restart; - } else if (c == CHAR_CTRL_D) { - // end of input - mp_hal_stdout_tx_str("\n"); - break; - } else { - // add char to buffer and echo - vstr_add_byte(&line, c); - if (c == '\r') { - mp_hal_stdout_tx_str("\n=== "); - } else { - mp_hal_stdout_tx_strn(&c, 1); - } - } - } - parse_input_kind = MP_PARSE_FILE_INPUT; - } else if (line.len == 0) { - if (ret != 0) { - printf("\n"); - } - goto input_restart; - } else { - // got a line with non-zero length, see if it needs continuing - while (mp_repl_continue_with_input(vstr_null_terminated_str(&line))) { - vstr_add_byte(&line, '\n'); - ret = readline(&line, "... "); - if (ret == CHAR_CTRL_C) { - // cancel everything - printf("\n"); - goto input_restart; - } else if (ret == CHAR_CTRL_D) { - // stop entering compound statement - break; - } - } + // stop entering compound statement + break; } + } + } - mp_hal_stdio_mode_orig(); + mp_hal_stdio_mode_orig(); - ret = execute_from_lexer(LEX_SRC_VSTR, &line, parse_input_kind, true); - if (ret & FORCED_EXIT) { - return ret; - } + ret = execute_from_lexer(LEX_SRC_VSTR, &line, parse_input_kind, true); + if (ret & FORCED_EXIT) { + return ret; } + } - #else +#else - // use simple readline + // use simple readline - for (;;) { - char *line = prompt(">>> "); - if (line == NULL) { - // EOF - return 0; - } - while (mp_repl_continue_with_input(line)) { - char *line2 = prompt("... "); - if (line2 == NULL) { - break; - } - char *line3 = strjoin(line, '\n', line2); - free(line); - free(line2); - line = line3; - } + for (;;) { + char *line = prompt(">>> "); + if (line == NULL) { + // EOF + return 0; + } + while (mp_repl_continue_with_input(line)) { + char *line2 = prompt("... "); + if (line2 == NULL) { + break; + } + char *line3 = strjoin(line, '\n', line2); + free(line); + free(line2); + line = line3; + } - int ret = execute_from_lexer(LEX_SRC_STR, line, MP_PARSE_SINGLE_INPUT, true); - if (ret & FORCED_EXIT) { - return ret; - } - free(line); + int ret = + execute_from_lexer(LEX_SRC_STR, line, MP_PARSE_SINGLE_INPUT, true); + if (ret & FORCED_EXIT) { + return ret; } + free(line); + } - #endif +#endif } STATIC int do_file(const char *file) { - return execute_from_lexer(LEX_SRC_FILENAME, file, MP_PARSE_FILE_INPUT, false); + return execute_from_lexer(LEX_SRC_FILENAME, file, MP_PARSE_FILE_INPUT, false); } STATIC int do_str(const char *str) { - return execute_from_lexer(LEX_SRC_STR, str, MP_PARSE_FILE_INPUT, false); + return execute_from_lexer(LEX_SRC_STR, str, MP_PARSE_FILE_INPUT, false); } STATIC int usage(char **argv) { - printf( -"usage: %s [] [-X ] [-c ] []\n" -"Options:\n" -"-v : verbose (trace various operations); can be multiple\n" -"-O[N] : apply bytecode optimizations of level N\n" -"\n" -"Implementation specific options (-X):\n", argv[0] -); - int impl_opts_cnt = 0; - printf( -" compile-only -- parse and compile only\n" -" emit={bytecode,native,viper} -- set the default code emitter\n" -); - impl_opts_cnt++; + printf( + "usage: %s [] [-X ] [-c ] []\n" + "Options:\n" + "-v : verbose (trace various operations); can be multiple\n" + "-O[N] : apply bytecode optimizations of level N\n" + "\n" + "Implementation specific options (-X):\n", + argv[0]); + int impl_opts_cnt = 0; + printf( + " compile-only -- parse and compile only\n" + " emit={bytecode,native,viper} -- set the default code emitter\n"); + impl_opts_cnt++; #if MICROPY_ENABLE_GC - printf( -" heapsize=[w][K|M] -- set the heap size for the GC (default %ld)\n" -, heap_size); - impl_opts_cnt++; + printf( + " heapsize=[w][K|M] -- set the heap size for the GC (default %ld)\n", + heap_size); + impl_opts_cnt++; #endif - if (impl_opts_cnt == 0) { - printf(" (none)\n"); - } + if (impl_opts_cnt == 0) { + printf(" (none)\n"); + } - return 1; + return 1; } // Process options which set interpreter init options STATIC void pre_process_options(int argc, char **argv) { - for (int a = 1; a < argc; a++) { - if (argv[a][0] == '-') { - if (strcmp(argv[a], "-X") == 0) { - if (a + 1 >= argc) { - exit(usage(argv)); - } - if (0) { - } else if (strcmp(argv[a + 1], "compile-only") == 0) { - compile_only = true; - } else if (strcmp(argv[a + 1], "emit=bytecode") == 0) { - emit_opt = MP_EMIT_OPT_BYTECODE; - } else if (strcmp(argv[a + 1], "emit=native") == 0) { - emit_opt = MP_EMIT_OPT_NATIVE_PYTHON; - } else if (strcmp(argv[a + 1], "emit=viper") == 0) { - emit_opt = MP_EMIT_OPT_VIPER; + for (int a = 1; a < argc; a++) { + if (argv[a][0] == '-') { + if (strcmp(argv[a], "-X") == 0) { + if (a + 1 >= argc) { + exit(usage(argv)); + } + if (0) { + } else if (strcmp(argv[a + 1], "compile-only") == 0) { + compile_only = true; + } else if (strcmp(argv[a + 1], "emit=bytecode") == 0) { + emit_opt = MP_EMIT_OPT_BYTECODE; + } else if (strcmp(argv[a + 1], "emit=native") == 0) { + emit_opt = MP_EMIT_OPT_NATIVE_PYTHON; + } else if (strcmp(argv[a + 1], "emit=viper") == 0) { + emit_opt = MP_EMIT_OPT_VIPER; #if MICROPY_ENABLE_GC - } else if (strncmp(argv[a + 1], "heapsize=", sizeof("heapsize=") - 1) == 0) { - char *end; - heap_size = strtol(argv[a + 1] + sizeof("heapsize=") - 1, &end, 0); - // Don't bring unneeded libc dependencies like tolower() - // If there's 'w' immediately after number, adjust it for - // target word size. Note that it should be *before* size - // suffix like K or M, to avoid confusion with kilowords, - // etc. the size is still in bytes, just can be adjusted - // for word size (taking 32bit as baseline). - bool word_adjust = false; - if ((*end | 0x20) == 'w') { - word_adjust = true; - end++; - } - if ((*end | 0x20) == 'k') { - heap_size *= 1024; - } else if ((*end | 0x20) == 'm') { - heap_size *= 1024 * 1024; - } else { - // Compensate for ++ below - --end; - } - if (*++end != 0) { - goto invalid_arg; - } - if (word_adjust) { - heap_size = heap_size * BYTES_PER_WORD / 4; - } - // If requested size too small, we'll crash anyway - if (heap_size < 700) { - goto invalid_arg; - } + } else if (strncmp(argv[a + 1], "heapsize=", sizeof("heapsize=") - 1) == + 0) { + char *end; + heap_size = strtol(argv[a + 1] + sizeof("heapsize=") - 1, &end, 0); + // Don't bring unneeded libc dependencies like tolower() + // If there's 'w' immediately after number, adjust it for + // target word size. Note that it should be *before* size + // suffix like K or M, to avoid confusion with kilowords, + // etc. the size is still in bytes, just can be adjusted + // for word size (taking 32bit as baseline). + bool word_adjust = false; + if ((*end | 0x20) == 'w') { + word_adjust = true; + end++; + } + if ((*end | 0x20) == 'k') { + heap_size *= 1024; + } else if ((*end | 0x20) == 'm') { + heap_size *= 1024 * 1024; + } else { + // Compensate for ++ below + --end; + } + if (*++end != 0) { + goto invalid_arg; + } + if (word_adjust) { + heap_size = heap_size * BYTES_PER_WORD / 4; + } + // If requested size too small, we'll crash anyway + if (heap_size < 700) { + goto invalid_arg; + } #endif - } else { -invalid_arg: - printf("Invalid option\n"); - exit(usage(argv)); - } - a++; - } + } else { + invalid_arg: + printf("Invalid option\n"); + exit(usage(argv)); } + a++; + } } + } } STATIC void set_sys_argv(char *argv[], int argc, int start_arg) { - for (int i = start_arg; i < argc; i++) { - mp_obj_list_append(mp_sys_argv, MP_OBJ_NEW_QSTR(qstr_from_str(argv[i]))); - } + for (int i = start_arg; i < argc; i++) { + mp_obj_list_append(mp_sys_argv, MP_OBJ_NEW_QSTR(qstr_from_str(argv[i]))); + } } #ifdef _WIN32 @@ -407,261 +415,266 @@ STATIC void set_sys_argv(char *argv[], int argc, int start_arg) { MP_NOINLINE int main_(int argc, char **argv); int main(int argc, char **argv) { - - // Through TREZOR_PROFILE you can set the directory for trezor.flash file. - profile_init(); - - collect_hw_entropy(); - - #if MICROPY_PY_THREAD - mp_thread_init(); - #endif - // We should capture stack top ASAP after start, and it should be - // captured guaranteedly before any other stack variables are allocated. - // For this, actual main (renamed main_) should not be inlined into - // this function. main_() itself may have other functions inlined (with - // their own stack variables), that's why we need this main/main_ split. - mp_stack_ctrl_init(); - return main_(argc, argv); + // Through TREZOR_PROFILE you can set the directory for trezor.flash file. + profile_init(); + + collect_hw_entropy(); + +#if MICROPY_PY_THREAD + mp_thread_init(); +#endif + // We should capture stack top ASAP after start, and it should be + // captured guaranteedly before any other stack variables are allocated. + // For this, actual main (renamed main_) should not be inlined into + // this function. main_() itself may have other functions inlined (with + // their own stack variables), that's why we need this main/main_ split. + mp_stack_ctrl_init(); + return main_(argc, argv); } MP_NOINLINE int main_(int argc, char **argv) { - #ifdef SIGPIPE - // Do not raise SIGPIPE, instead return EPIPE. Otherwise, e.g. writing - // to peer-closed socket will lead to sudden termination of MicroPython - // process. SIGPIPE is particularly nasty, because unix shell doesn't - // print anything for it, so the above looks like completely sudden and - // silent termination for unknown reason. Ignoring SIGPIPE is also what - // CPython does. Note that this may lead to problems using MicroPython - // scripts as pipe filters, but again, that's what CPython does. So, - // scripts which want to follow unix shell pipe semantics (where SIGPIPE - // means "pipe was requested to terminate, it's not an error"), should - // catch EPIPE themselves. - signal(SIGPIPE, SIG_IGN); - #endif - - mp_stack_set_limit(60000 * (BYTES_PER_WORD / 4)); - - pre_process_options(argc, argv); +#ifdef SIGPIPE + // Do not raise SIGPIPE, instead return EPIPE. Otherwise, e.g. writing + // to peer-closed socket will lead to sudden termination of MicroPython + // process. SIGPIPE is particularly nasty, because unix shell doesn't + // print anything for it, so the above looks like completely sudden and + // silent termination for unknown reason. Ignoring SIGPIPE is also what + // CPython does. Note that this may lead to problems using MicroPython + // scripts as pipe filters, but again, that's what CPython does. So, + // scripts which want to follow unix shell pipe semantics (where SIGPIPE + // means "pipe was requested to terminate, it's not an error"), should + // catch EPIPE themselves. + signal(SIGPIPE, SIG_IGN); +#endif + + mp_stack_set_limit(60000 * (BYTES_PER_WORD / 4)); + + pre_process_options(argc, argv); #if MICROPY_ENABLE_GC - char *heap = malloc(heap_size); - gc_init(heap, heap + heap_size); + char *heap = malloc(heap_size); + gc_init(heap, heap + heap_size); #endif - mp_init(); + mp_init(); - char *home = getenv("HOME"); - char *path = getenv("MICROPYPATH"); - if (path == NULL) { - #ifdef MICROPY_PY_SYS_PATH_DEFAULT - path = MICROPY_PY_SYS_PATH_DEFAULT; - #else - path = "~/.micropython/lib:/usr/lib/micropython"; - #endif - } - size_t path_num = 1; // [0] is for current dir (or base dir of the script) - if (*path == ':') { - path_num++; - } - for (char *p = path; p != NULL; p = strchr(p, PATHLIST_SEP_CHAR)) { - path_num++; - if (p != NULL) { - p++; - } + char *home = getenv("HOME"); + char *path = getenv("MICROPYPATH"); + if (path == NULL) { +#ifdef MICROPY_PY_SYS_PATH_DEFAULT + path = MICROPY_PY_SYS_PATH_DEFAULT; +#else + path = "~/.micropython/lib:/usr/lib/micropython"; +#endif + } + size_t path_num = 1; // [0] is for current dir (or base dir of the script) + if (*path == ':') { + path_num++; + } + for (char *p = path; p != NULL; p = strchr(p, PATHLIST_SEP_CHAR)) { + path_num++; + if (p != NULL) { + p++; } - mp_obj_list_init(MP_OBJ_TO_PTR(mp_sys_path), path_num); - mp_obj_t *path_items; - mp_obj_list_get(mp_sys_path, &path_num, &path_items); - path_items[0] = MP_OBJ_NEW_QSTR(MP_QSTR_); - { + } + mp_obj_list_init(MP_OBJ_TO_PTR(mp_sys_path), path_num); + mp_obj_t *path_items; + mp_obj_list_get(mp_sys_path, &path_num, &path_items); + path_items[0] = MP_OBJ_NEW_QSTR(MP_QSTR_); + { char *p = path; for (mp_uint_t i = 1; i < path_num; i++) { - char *p1 = strchr(p, PATHLIST_SEP_CHAR); - if (p1 == NULL) { - p1 = p + strlen(p); - } - if (p[0] == '~' && p[1] == '/' && home != NULL) { - // Expand standalone ~ to $HOME - int home_l = strlen(home); - vstr_t vstr; - vstr_init(&vstr, home_l + (p1 - p - 1) + 1); - vstr_add_strn(&vstr, home, home_l); - vstr_add_strn(&vstr, p + 1, p1 - p - 1); - path_items[i] = mp_obj_new_str_from_vstr(&mp_type_str, &vstr); - } else { - path_items[i] = MP_OBJ_NEW_QSTR(qstr_from_strn(p, p1 - p)); - } - p = p1 + 1; - } + char *p1 = strchr(p, PATHLIST_SEP_CHAR); + if (p1 == NULL) { + p1 = p + strlen(p); + } + if (p[0] == '~' && p[1] == '/' && home != NULL) { + // Expand standalone ~ to $HOME + int home_l = strlen(home); + vstr_t vstr; + vstr_init(&vstr, home_l + (p1 - p - 1) + 1); + vstr_add_strn(&vstr, home, home_l); + vstr_add_strn(&vstr, p + 1, p1 - p - 1); + path_items[i] = mp_obj_new_str_from_vstr(&mp_type_str, &vstr); + } else { + path_items[i] = MP_OBJ_NEW_QSTR(qstr_from_strn(p, p1 - p)); + } + p = p1 + 1; } + } - mp_obj_list_init(MP_OBJ_TO_PTR(mp_sys_argv), 0); + mp_obj_list_init(MP_OBJ_TO_PTR(mp_sys_argv), 0); - #if defined(MICROPY_UNIX_COVERAGE) - { - MP_DECLARE_CONST_FUN_OBJ_0(extra_coverage_obj); - mp_store_global(QSTR_FROM_STR_STATIC("extra_coverage"), MP_OBJ_FROM_PTR(&extra_coverage_obj)); - } - #endif - - // Here is some example code to create a class and instance of that class. - // First is the Python, then the C code. - // - // class TestClass: - // pass - // test_obj = TestClass() - // test_obj.attr = 42 - // - // mp_obj_t test_class_type, test_class_instance; - // test_class_type = mp_obj_new_type(QSTR_FROM_STR_STATIC("TestClass"), mp_const_empty_tuple, mp_obj_new_dict(0)); - // mp_store_name(QSTR_FROM_STR_STATIC("test_obj"), test_class_instance = mp_call_function_0(test_class_type)); - // mp_store_attr(test_class_instance, QSTR_FROM_STR_STATIC("attr"), mp_obj_new_int(42)); - - /* - printf("bytes:\n"); - printf(" total %d\n", m_get_total_bytes_allocated()); - printf(" cur %d\n", m_get_current_bytes_allocated()); - printf(" peak %d\n", m_get_peak_bytes_allocated()); - */ - - const int NOTHING_EXECUTED = -2; - int ret = NOTHING_EXECUTED; - bool inspect = false; - for (int a = 1; a < argc; a++) { - if (argv[a][0] == '-') { - if (strcmp(argv[a], "-i") == 0) { - inspect = true; - } else if (strcmp(argv[a], "-c") == 0) { - if (a + 1 >= argc) { - return usage(argv); - } - ret = do_str(argv[a + 1]); - if (ret & FORCED_EXIT) { - break; - } - a += 1; - } else if (strcmp(argv[a], "-m") == 0) { - if (a + 1 >= argc) { - return usage(argv); - } - mp_obj_t import_args[4]; - import_args[0] = mp_obj_new_str(argv[a + 1], strlen(argv[a + 1])); - import_args[1] = import_args[2] = mp_const_none; - // Ask __import__ to handle imported module specially - set its __name__ - // to __main__, and also return this leaf module, not top-level package - // containing it. - import_args[3] = mp_const_false; - // TODO: https://docs.python.org/3/using/cmdline.html#cmdoption-m : - // "the first element of sys.argv will be the full path to - // the module file (while the module file is being located, - // the first element will be set to "-m")." - set_sys_argv(argv, argc, a + 1); - - mp_obj_t mod; - nlr_buf_t nlr; - bool subpkg_tried = false; - - reimport: - if (nlr_push(&nlr) == 0) { - mod = mp_builtin___import__(MP_ARRAY_SIZE(import_args), import_args); - nlr_pop(); - } else { - // uncaught exception - return handle_uncaught_exception(nlr.ret_val) & 0xff; - } - - if (mp_obj_is_package(mod) && !subpkg_tried) { - subpkg_tried = true; - vstr_t vstr; - int len = strlen(argv[a + 1]); - vstr_init(&vstr, len + sizeof(".__main__")); - vstr_add_strn(&vstr, argv[a + 1], len); - vstr_add_strn(&vstr, ".__main__", sizeof(".__main__") - 1); - import_args[0] = mp_obj_new_str_from_vstr(&mp_type_str, &vstr); - goto reimport; - } - - ret = 0; - break; - } else if (strcmp(argv[a], "-X") == 0) { - a += 1; - #if MICROPY_DEBUG_PRINTERS - } else if (strcmp(argv[a], "-v") == 0) { - mp_verbose_flag++; - #endif - } else if (strncmp(argv[a], "-O", 2) == 0) { - if (unichar_isdigit(argv[a][2])) { - MP_STATE_VM(mp_optimise_value) = argv[a][2] & 0xf; - } else { - MP_STATE_VM(mp_optimise_value) = 0; - for (char *p = argv[a] + 1; *p && *p == 'O'; p++, MP_STATE_VM(mp_optimise_value)++); - } - } else { - return usage(argv); - } +#if defined(MICROPY_UNIX_COVERAGE) + { + MP_DECLARE_CONST_FUN_OBJ_0(extra_coverage_obj); + mp_store_global(QSTR_FROM_STR_STATIC("extra_coverage"), + MP_OBJ_FROM_PTR(&extra_coverage_obj)); + } +#endif + + // Here is some example code to create a class and instance of that class. + // First is the Python, then the C code. + // + // class TestClass: + // pass + // test_obj = TestClass() + // test_obj.attr = 42 + // + // mp_obj_t test_class_type, test_class_instance; + // test_class_type = mp_obj_new_type(QSTR_FROM_STR_STATIC("TestClass"), + // mp_const_empty_tuple, mp_obj_new_dict(0)); + // mp_store_name(QSTR_FROM_STR_STATIC("test_obj"), test_class_instance = + // mp_call_function_0(test_class_type)); mp_store_attr(test_class_instance, + // QSTR_FROM_STR_STATIC("attr"), mp_obj_new_int(42)); + + /* + printf("bytes:\n"); + printf(" total %d\n", m_get_total_bytes_allocated()); + printf(" cur %d\n", m_get_current_bytes_allocated()); + printf(" peak %d\n", m_get_peak_bytes_allocated()); + */ + + const int NOTHING_EXECUTED = -2; + int ret = NOTHING_EXECUTED; + bool inspect = false; + for (int a = 1; a < argc; a++) { + if (argv[a][0] == '-') { + if (strcmp(argv[a], "-i") == 0) { + inspect = true; + } else if (strcmp(argv[a], "-c") == 0) { + if (a + 1 >= argc) { + return usage(argv); + } + ret = do_str(argv[a + 1]); + if (ret & FORCED_EXIT) { + break; + } + a += 1; + } else if (strcmp(argv[a], "-m") == 0) { + if (a + 1 >= argc) { + return usage(argv); + } + mp_obj_t import_args[4]; + import_args[0] = mp_obj_new_str(argv[a + 1], strlen(argv[a + 1])); + import_args[1] = import_args[2] = mp_const_none; + // Ask __import__ to handle imported module specially - set its __name__ + // to __main__, and also return this leaf module, not top-level package + // containing it. + import_args[3] = mp_const_false; + // TODO: https://docs.python.org/3/using/cmdline.html#cmdoption-m : + // "the first element of sys.argv will be the full path to + // the module file (while the module file is being located, + // the first element will be set to "-m")." + set_sys_argv(argv, argc, a + 1); + + mp_obj_t mod; + nlr_buf_t nlr; + bool subpkg_tried = false; + + reimport: + if (nlr_push(&nlr) == 0) { + mod = mp_builtin___import__(MP_ARRAY_SIZE(import_args), import_args); + nlr_pop(); } else { - char *pathbuf = malloc(PATH_MAX); - char *basedir = realpath(argv[a], pathbuf); - if (basedir == NULL) { - mp_printf(&mp_stderr_print, "%s: can't open file '%s': [Errno %d] %s\n", argv[0], argv[a], errno, strerror(errno)); - // CPython exits with 2 in such case - ret = 2; - break; - } - - // Set base dir of the script as first entry in sys.path - char *p = strrchr(basedir, '/'); - path_items[0] = MP_OBJ_NEW_QSTR(qstr_from_strn(basedir, p - basedir)); - free(pathbuf); - - set_sys_argv(argv, argc, a); - ret = do_file(argv[a]); - break; + // uncaught exception + return handle_uncaught_exception(nlr.ret_val) & 0xff; + } + + if (mp_obj_is_package(mod) && !subpkg_tried) { + subpkg_tried = true; + vstr_t vstr; + int len = strlen(argv[a + 1]); + vstr_init(&vstr, len + sizeof(".__main__")); + vstr_add_strn(&vstr, argv[a + 1], len); + vstr_add_strn(&vstr, ".__main__", sizeof(".__main__") - 1); + import_args[0] = mp_obj_new_str_from_vstr(&mp_type_str, &vstr); + goto reimport; } - } - if (ret == NOTHING_EXECUTED || inspect) { - if (isatty(0)) { - prompt_read_history(); - ret = do_repl(); - prompt_write_history(); + ret = 0; + break; + } else if (strcmp(argv[a], "-X") == 0) { + a += 1; +#if MICROPY_DEBUG_PRINTERS + } else if (strcmp(argv[a], "-v") == 0) { + mp_verbose_flag++; +#endif + } else if (strncmp(argv[a], "-O", 2) == 0) { + if (unichar_isdigit(argv[a][2])) { + MP_STATE_VM(mp_optimise_value) = argv[a][2] & 0xf; } else { - ret = execute_from_lexer(LEX_SRC_STDIN, NULL, MP_PARSE_FILE_INPUT, false); + MP_STATE_VM(mp_optimise_value) = 0; + for (char *p = argv[a] + 1; *p && *p == 'O'; + p++, MP_STATE_VM(mp_optimise_value)++) + ; } + } else { + return usage(argv); + } + } else { + char *pathbuf = malloc(PATH_MAX); + char *basedir = realpath(argv[a], pathbuf); + if (basedir == NULL) { + mp_printf(&mp_stderr_print, "%s: can't open file '%s': [Errno %d] %s\n", + argv[0], argv[a], errno, strerror(errno)); + // CPython exits with 2 in such case + ret = 2; + break; + } + + // Set base dir of the script as first entry in sys.path + char *p = strrchr(basedir, '/'); + path_items[0] = MP_OBJ_NEW_QSTR(qstr_from_strn(basedir, p - basedir)); + free(pathbuf); + + set_sys_argv(argv, argc, a); + ret = do_file(argv[a]); + break; } + } - #if MICROPY_PY_MICROPYTHON_MEM_INFO - if (mp_verbose_flag) { - mp_micropython_mem_info(0, NULL); + if (ret == NOTHING_EXECUTED || inspect) { + if (isatty(0)) { + prompt_read_history(); + ret = do_repl(); + prompt_write_history(); + } else { + ret = execute_from_lexer(LEX_SRC_STDIN, NULL, MP_PARSE_FILE_INPUT, false); } - #endif + } - mp_deinit(); +#if MICROPY_PY_MICROPYTHON_MEM_INFO + if (mp_verbose_flag) { + mp_micropython_mem_info(0, NULL); + } +#endif + + mp_deinit(); #if MICROPY_ENABLE_GC && !defined(NDEBUG) - // We don't really need to free memory since we are about to exit the - // process, but doing so helps to find memory leaks. - free(heap); + // We don't really need to free memory since we are about to exit the + // process, but doing so helps to find memory leaks. + free(heap); #endif - //printf("total bytes = %d\n", m_get_total_bytes_allocated()); - return ret & 0xff; + // printf("total bytes = %d\n", m_get_total_bytes_allocated()); + return ret & 0xff; } uint mp_import_stat(const char *path) { - struct stat st; - if (stat(path, &st) == 0) { - if (S_ISDIR(st.st_mode)) { - return MP_IMPORT_STAT_DIR; - } else if (S_ISREG(st.st_mode)) { - return MP_IMPORT_STAT_FILE; - } + struct stat st; + if (stat(path, &st) == 0) { + if (S_ISDIR(st.st_mode)) { + return MP_IMPORT_STAT_DIR; + } else if (S_ISREG(st.st_mode)) { + return MP_IMPORT_STAT_FILE; } - return MP_IMPORT_STAT_NO_EXIST; + } + return MP_IMPORT_STAT_NO_EXIST; } void nlr_jump_fail(void *val) { - printf("FATAL: uncaught NLR %p\n", val); - exit(1); + printf("FATAL: uncaught NLR %p\n", val); + exit(1); } diff --git a/embed/unix/mpconfigport.h b/embed/unix/mpconfigport.h index b83895fb3..bc6802b5b 100644 --- a/embed/unix/mpconfigport.h +++ b/embed/unix/mpconfigport.h @@ -26,53 +26,53 @@ // options to control how MicroPython is built -#define MICROPY_ALLOC_PATH_MAX (PATH_MAX) +#define MICROPY_ALLOC_PATH_MAX (PATH_MAX) #define MICROPY_PERSISTENT_CODE_LOAD (1) #if !defined(MICROPY_EMIT_X64) && defined(__x86_64__) - #define MICROPY_EMIT_X64 (0) +#define MICROPY_EMIT_X64 (0) #endif #if !defined(MICROPY_EMIT_X86) && defined(__i386__) - #define MICROPY_EMIT_X86 (0) +#define MICROPY_EMIT_X86 (0) #endif #if !defined(MICROPY_EMIT_THUMB) && defined(__thumb2__) - #define MICROPY_EMIT_THUMB (0) - #define MICROPY_MAKE_POINTER_CALLABLE(p) ((void*)((mp_uint_t)(p) | 1)) +#define MICROPY_EMIT_THUMB (0) +#define MICROPY_MAKE_POINTER_CALLABLE(p) ((void *)((mp_uint_t)(p) | 1)) #endif // Some compilers define __thumb2__ and __arm__ at the same time, let // autodetected thumb2 emitter have priority. #if !defined(MICROPY_EMIT_ARM) && defined(__arm__) && !defined(__thumb2__) - #define MICROPY_EMIT_ARM (0) +#define MICROPY_EMIT_ARM (0) #endif -#define MICROPY_COMP_MODULE_CONST (1) +#define MICROPY_COMP_MODULE_CONST (1) #define MICROPY_COMP_TRIPLE_TUPLE_ASSIGN (1) #define MICROPY_COMP_RETURN_IF_EXPR (1) -#define MICROPY_ENABLE_GC (1) -#define MICROPY_ENABLE_FINALISER (1) -#define MICROPY_STACK_CHECK (1) +#define MICROPY_ENABLE_GC (1) +#define MICROPY_ENABLE_FINALISER (1) +#define MICROPY_STACK_CHECK (1) #define MICROPY_MALLOC_USES_ALLOCATED_SIZE (1) -#define MICROPY_MEM_STATS (1) -#define MICROPY_DEBUG_PRINTERS (1) +#define MICROPY_MEM_STATS (1) +#define MICROPY_DEBUG_PRINTERS (1) // Printing debug to stderr may give tests which // check stdout a chance to pass, etc. -#define MICROPY_DEBUG_PRINTER_DEST mp_stderr_print -#define MICROPY_READER_POSIX (1) +#define MICROPY_DEBUG_PRINTER_DEST mp_stderr_print +#define MICROPY_READER_POSIX (1) #define MICROPY_USE_READLINE_HISTORY (1) -#define MICROPY_HELPER_REPL (1) -#define MICROPY_REPL_EMACS_KEYS (1) -#define MICROPY_REPL_AUTO_INDENT (1) -#define MICROPY_HELPER_LEXER_UNIX (1) -#define MICROPY_ENABLE_SOURCE_LINE (1) -#define MICROPY_FLOAT_IMPL (MICROPY_FLOAT_IMPL_DOUBLE) -#define MICROPY_LONGINT_IMPL (MICROPY_LONGINT_IMPL_MPZ) -#define MICROPY_STREAMS_NON_BLOCK (1) -#define MICROPY_STREAMS_POSIX_API (1) -#define MICROPY_OPT_COMPUTED_GOTO (1) +#define MICROPY_HELPER_REPL (1) +#define MICROPY_REPL_EMACS_KEYS (1) +#define MICROPY_REPL_AUTO_INDENT (1) +#define MICROPY_HELPER_LEXER_UNIX (1) +#define MICROPY_ENABLE_SOURCE_LINE (1) +#define MICROPY_FLOAT_IMPL (MICROPY_FLOAT_IMPL_DOUBLE) +#define MICROPY_LONGINT_IMPL (MICROPY_LONGINT_IMPL_MPZ) +#define MICROPY_STREAMS_NON_BLOCK (1) +#define MICROPY_STREAMS_POSIX_API (1) +#define MICROPY_OPT_COMPUTED_GOTO (1) #ifndef MICROPY_OPT_CACHE_MAP_LOOKUP_IN_BYTECODE #define MICROPY_OPT_CACHE_MAP_LOOKUP_IN_BYTECODE (1) #endif #define MICROPY_CAN_OVERRIDE_BUILTINS (0) -#define MICROPY_PY_FUNCTION_ATTRS (1) -#define MICROPY_PY_DESCRIPTORS (1) +#define MICROPY_PY_FUNCTION_ATTRS (1) +#define MICROPY_PY_DESCRIPTORS (1) #define MICROPY_PY_BUILTINS_STR_UNICODE (1) #define MICROPY_PY_BUILTINS_STR_CENTER (1) #define MICROPY_PY_BUILTINS_STR_PARTITION (0) @@ -81,82 +81,82 @@ #define MICROPY_PY_BUILTINS_FROZENSET (0) #define MICROPY_PY_BUILTINS_COMPILE (1) #define MICROPY_PY_BUILTINS_NOTIMPLEMENTED (1) -#define MICROPY_PY_BUILTINS_INPUT (1) -#define MICROPY_PY_BUILTINS_POW3 (1) +#define MICROPY_PY_BUILTINS_INPUT (1) +#define MICROPY_PY_BUILTINS_POW3 (1) #define MICROPY_PY_MICROPYTHON_MEM_INFO (1) #define MICROPY_PY_ALL_SPECIAL_METHODS (0) #define MICROPY_PY_REVERSE_SPECIAL_METHODS (0) #define MICROPY_PY_ARRAY_SLICE_ASSIGN (1) #define MICROPY_PY_BUILTINS_SLICE_ATTRS (1) -#define MICROPY_PY_SYS_EXIT (1) +#define MICROPY_PY_SYS_EXIT (1) #if defined(__APPLE__) && defined(__MACH__) - #define MICROPY_PY_SYS_PLATFORM "darwin" +#define MICROPY_PY_SYS_PLATFORM "darwin" #else - #define MICROPY_PY_SYS_PLATFORM "linux" +#define MICROPY_PY_SYS_PLATFORM "linux" #endif -#define MICROPY_PY_SYS_MAXSIZE (0) -#define MICROPY_PY_SYS_STDFILES (0) -#define MICROPY_PY_SYS_EXC_INFO (1) -#define MICROPY_PY_COLLECTIONS (0) +#define MICROPY_PY_SYS_MAXSIZE (0) +#define MICROPY_PY_SYS_STDFILES (0) +#define MICROPY_PY_SYS_EXC_INFO (1) +#define MICROPY_PY_COLLECTIONS (0) #define MICROPY_PY_COLLECTIONS_ORDEREDDICT (0) #ifndef MICROPY_PY_MATH_SPECIAL_FUNCTIONS #define MICROPY_PY_MATH_SPECIAL_FUNCTIONS (0) #endif -#define MICROPY_PY_CMATH (0) -#define MICROPY_PY_IO (0) -#define MICROPY_PY_IO_FILEIO (0) +#define MICROPY_PY_CMATH (0) +#define MICROPY_PY_IO (0) +#define MICROPY_PY_IO_FILEIO (0) #define MICROPY_PY_IO_RESOURCE_STREAM (0) #define MICROPY_PY_GC_COLLECT_RETVAL (1) -#define MICROPY_MODULE_FROZEN_STR (0) +#define MICROPY_MODULE_FROZEN_STR (0) -#define MICROPY_STACKLESS (0) -#define MICROPY_STACKLESS_STRICT (0) +#define MICROPY_STACKLESS (0) +#define MICROPY_STACKLESS_STRICT (0) -#define MICROPY_PY_OS_STATVFS (0) -#define MICROPY_PY_UTIME (1) -#define MICROPY_PY_UTIME_MP_HAL (1) -#define MICROPY_PY_UERRNO (0) -#define MICROPY_PY_UCTYPES (1) -#define MICROPY_PY_UZLIB (0) -#define MICROPY_PY_UJSON (0) -#define MICROPY_PY_URE (0) -#define MICROPY_PY_UHEAPQ (0) -#define MICROPY_PY_UTIMEQ (1) -#define MICROPY_PY_UHASHLIB (0) +#define MICROPY_PY_OS_STATVFS (0) +#define MICROPY_PY_UTIME (1) +#define MICROPY_PY_UTIME_MP_HAL (1) +#define MICROPY_PY_UERRNO (0) +#define MICROPY_PY_UCTYPES (1) +#define MICROPY_PY_UZLIB (0) +#define MICROPY_PY_UJSON (0) +#define MICROPY_PY_URE (0) +#define MICROPY_PY_UHEAPQ (0) +#define MICROPY_PY_UTIMEQ (1) +#define MICROPY_PY_UHASHLIB (0) #if MICROPY_PY_USSL && MICROPY_SSL_AXTLS -#define MICROPY_PY_UHASHLIB_SHA1 (0) +#define MICROPY_PY_UHASHLIB_SHA1 (0) #endif -#define MICROPY_PY_UBINASCII (1) -#define MICROPY_PY_UBINASCII_CRC32 (0) -#define MICROPY_PY_URANDOM (0) +#define MICROPY_PY_UBINASCII (1) +#define MICROPY_PY_UBINASCII_CRC32 (0) +#define MICROPY_PY_URANDOM (0) #ifndef MICROPY_PY_USELECT_POSIX -#define MICROPY_PY_USELECT_POSIX (0) +#define MICROPY_PY_USELECT_POSIX (0) #endif -#define MICROPY_PY_WEBSOCKET (0) -#define MICROPY_PY_MACHINE (0) -#define MICROPY_PY_MACHINE_PULSE (0) -#define MICROPY_MACHINE_MEM_GET_READ_ADDR mod_machine_mem_get_addr -#define MICROPY_MACHINE_MEM_GET_WRITE_ADDR mod_machine_mem_get_addr +#define MICROPY_PY_WEBSOCKET (0) +#define MICROPY_PY_MACHINE (0) +#define MICROPY_PY_MACHINE_PULSE (0) +#define MICROPY_MACHINE_MEM_GET_READ_ADDR mod_machine_mem_get_addr +#define MICROPY_MACHINE_MEM_GET_WRITE_ADDR mod_machine_mem_get_addr -#define MICROPY_PY_TREZORCONFIG (1) -#define MICROPY_PY_TREZORCRYPTO (1) -#define MICROPY_PY_TREZORIO (1) -#define MICROPY_PY_TREZORMSG (1) -#define MICROPY_PY_TREZORUI (1) -#define MICROPY_PY_TREZORUTILS (1) +#define MICROPY_PY_TREZORCONFIG (1) +#define MICROPY_PY_TREZORCRYPTO (1) +#define MICROPY_PY_TREZORIO (1) +#define MICROPY_PY_TREZORMSG (1) +#define MICROPY_PY_TREZORUI (1) +#define MICROPY_PY_TREZORUTILS (1) -#define MICROPY_FATFS_ENABLE_LFN (1) -#define MICROPY_FATFS_RPATH (2) -#define MICROPY_FATFS_MAX_SS (4096) -#define MICROPY_FATFS_LFN_CODE_PAGE (437) /* 1=SFN/ANSI 437=LFN/U.S.(OEM) */ -#define MICROPY_VFS (0) -#define MICROPY_VFS_FAT (0) +#define MICROPY_FATFS_ENABLE_LFN (1) +#define MICROPY_FATFS_RPATH (2) +#define MICROPY_FATFS_MAX_SS (4096) +#define MICROPY_FATFS_LFN_CODE_PAGE (437) /* 1=SFN/ANSI 437=LFN/U.S.(OEM) */ +#define MICROPY_VFS (0) +#define MICROPY_VFS_FAT (0) // Define to MICROPY_ERROR_REPORTING_DETAILED to get function, etc. // names in exception messages (may require more RAM). -#define MICROPY_ERROR_REPORTING (MICROPY_ERROR_REPORTING_DETAILED) -#define MICROPY_WARNINGS (1) -#define MICROPY_ERROR_PRINTER (&mp_stderr_print) +#define MICROPY_ERROR_REPORTING (MICROPY_ERROR_REPORTING_DETAILED) +#define MICROPY_WARNINGS (1) +#define MICROPY_ERROR_PRINTER (&mp_stderr_print) #define MICROPY_PY_STR_BYTES_CMP_WARN (1) extern const struct _mp_print_t mp_stderr_print; @@ -164,17 +164,17 @@ extern const struct _mp_print_t mp_stderr_print; // Define to 1 to use undertested inefficient GC helper implementation // (if more efficient arch-specific one is not available). #ifndef MICROPY_GCREGS_SETJMP - #ifdef __mips__ - #define MICROPY_GCREGS_SETJMP (1) - #else - #define MICROPY_GCREGS_SETJMP (0) - #endif +#ifdef __mips__ +#define MICROPY_GCREGS_SETJMP (1) +#else +#define MICROPY_GCREGS_SETJMP (0) +#endif #endif -#define MICROPY_ENABLE_EMERGENCY_EXCEPTION_BUF (1) -#define MICROPY_EMERGENCY_EXCEPTION_BUF_SIZE (256) -#define MICROPY_KBD_EXCEPTION (1) -#define MICROPY_ASYNC_KBD_INTR (1) +#define MICROPY_ENABLE_EMERGENCY_EXCEPTION_BUF (1) +#define MICROPY_EMERGENCY_EXCEPTION_BUF_SIZE (256) +#define MICROPY_KBD_EXCEPTION (1) +#define MICROPY_ASYNC_KBD_INTR (1) // extern const struct _mp_obj_module_t mp_module_machine; // extern const struct _mp_obj_module_t mp_module_os; @@ -193,82 +193,94 @@ extern const struct _mp_obj_module_t mp_module_trezorui; extern const struct _mp_obj_module_t mp_module_trezorutils; #if MICROPY_PY_UOS_VFS -#define MICROPY_PY_UOS_VFS_DEF { MP_ROM_QSTR(MP_QSTR_uos_vfs), MP_ROM_PTR(&mp_module_uos_vfs) }, +#define MICROPY_PY_UOS_VFS_DEF \ + {MP_ROM_QSTR(MP_QSTR_uos_vfs), MP_ROM_PTR(&mp_module_uos_vfs)}, #else #define MICROPY_PY_UOS_VFS_DEF #endif #if MICROPY_PY_FFI -#define MICROPY_PY_FFI_DEF { MP_ROM_QSTR(MP_QSTR_ffi), MP_ROM_PTR(&mp_module_ffi) }, +#define MICROPY_PY_FFI_DEF \ + {MP_ROM_QSTR(MP_QSTR_ffi), MP_ROM_PTR(&mp_module_ffi)}, #else #define MICROPY_PY_FFI_DEF #endif #if MICROPY_PY_JNI -#define MICROPY_PY_JNI_DEF { MP_ROM_QSTR(MP_QSTR_jni), MP_ROM_PTR(&mp_module_jni) }, +#define MICROPY_PY_JNI_DEF \ + {MP_ROM_QSTR(MP_QSTR_jni), MP_ROM_PTR(&mp_module_jni)}, #else #define MICROPY_PY_JNI_DEF #endif #if MICROPY_PY_UTIME -#define MICROPY_PY_UTIME_DEF { MP_ROM_QSTR(MP_QSTR_utime), MP_ROM_PTR(&mp_module_time) }, +#define MICROPY_PY_UTIME_DEF \ + {MP_ROM_QSTR(MP_QSTR_utime), MP_ROM_PTR(&mp_module_time)}, #else #define MICROPY_PY_UTIME_DEF #endif #if MICROPY_PY_TERMIOS -#define MICROPY_PY_TERMIOS_DEF { MP_ROM_QSTR(MP_QSTR_termios), MP_ROM_PTR(&mp_module_termios) }, +#define MICROPY_PY_TERMIOS_DEF \ + {MP_ROM_QSTR(MP_QSTR_termios), MP_ROM_PTR(&mp_module_termios)}, #else #define MICROPY_PY_TERMIOS_DEF #endif #if MICROPY_PY_SOCKET -#define MICROPY_PY_SOCKET_DEF { MP_ROM_QSTR(MP_QSTR_usocket), MP_ROM_PTR(&mp_module_socket) }, +#define MICROPY_PY_SOCKET_DEF \ + {MP_ROM_QSTR(MP_QSTR_usocket), MP_ROM_PTR(&mp_module_socket)}, #else #define MICROPY_PY_SOCKET_DEF #endif #if MICROPY_PY_USELECT_POSIX -#define MICROPY_PY_USELECT_DEF { MP_ROM_QSTR(MP_QSTR_uselect), MP_ROM_PTR(&mp_module_uselect) }, +#define MICROPY_PY_USELECT_DEF \ + {MP_ROM_QSTR(MP_QSTR_uselect), MP_ROM_PTR(&mp_module_uselect)}, #else #define MICROPY_PY_USELECT_DEF #endif #if MICROPY_PY_TREZORCONFIG -#define MICROPY_PY_TREZORCONFIG_DEF { MP_ROM_QSTR(MP_QSTR_trezorconfig), MP_ROM_PTR(&mp_module_trezorconfig) }, +#define MICROPY_PY_TREZORCONFIG_DEF \ + {MP_ROM_QSTR(MP_QSTR_trezorconfig), MP_ROM_PTR(&mp_module_trezorconfig)}, #else #define MICROPY_PY_TREZORCONFIG_DEF #endif #if MICROPY_PY_TREZORCRYPTO -#define MICROPY_PY_TREZORCRYPTO_DEF { MP_ROM_QSTR(MP_QSTR_trezorcrypto), MP_ROM_PTR(&mp_module_trezorcrypto) }, +#define MICROPY_PY_TREZORCRYPTO_DEF \ + {MP_ROM_QSTR(MP_QSTR_trezorcrypto), MP_ROM_PTR(&mp_module_trezorcrypto)}, #else #define MICROPY_PY_TREZORCRYPTO_DEF #endif #if MICROPY_PY_TREZORIO -#define MICROPY_PY_TREZORIO_DEF { MP_ROM_QSTR(MP_QSTR_trezorio), MP_ROM_PTR(&mp_module_trezorio) }, +#define MICROPY_PY_TREZORIO_DEF \ + {MP_ROM_QSTR(MP_QSTR_trezorio), MP_ROM_PTR(&mp_module_trezorio)}, #else #define MICROPY_PY_TREZORIO_DEF #endif #if MICROPY_PY_TREZORUI -#define MICROPY_PY_TREZORUI_DEF { MP_ROM_QSTR(MP_QSTR_trezorui), MP_ROM_PTR(&mp_module_trezorui) }, +#define MICROPY_PY_TREZORUI_DEF \ + {MP_ROM_QSTR(MP_QSTR_trezorui), MP_ROM_PTR(&mp_module_trezorui)}, #else #define MICROPY_PY_TREZORUI_DEF #endif #if MICROPY_PY_TREZORUTILS -#define MICROPY_PY_TREZORUTILS_DEF { MP_ROM_QSTR(MP_QSTR_trezorutils), MP_ROM_PTR(&mp_module_trezorutils) }, +#define MICROPY_PY_TREZORUTILS_DEF \ + {MP_ROM_QSTR(MP_QSTR_trezorutils), MP_ROM_PTR(&mp_module_trezorutils)}, #else #define MICROPY_PY_TREZORUTILS_DEF #endif -#define MICROPY_PORT_BUILTIN_MODULES \ - MICROPY_PY_FFI_DEF \ - MICROPY_PY_JNI_DEF \ - MICROPY_PY_UTIME_DEF \ - MICROPY_PY_SOCKET_DEF \ - /* { MP_ROM_QSTR(MP_QSTR_umachine), MP_ROM_PTR(&mp_module_machine) }, */ \ - /* { MP_ROM_QSTR(MP_QSTR_uos), MP_ROM_PTR(&mp_module_os) }, */ \ - MICROPY_PY_UOS_VFS_DEF \ - MICROPY_PY_USELECT_DEF \ - MICROPY_PY_TERMIOS_DEF \ - MICROPY_PY_TREZORCONFIG_DEF \ - MICROPY_PY_TREZORCRYPTO_DEF \ - MICROPY_PY_TREZORIO_DEF \ - MICROPY_PY_TREZORUI_DEF \ - MICROPY_PY_TREZORUTILS_DEF \ +#define MICROPY_PORT_BUILTIN_MODULES \ + MICROPY_PY_FFI_DEF \ + MICROPY_PY_JNI_DEF \ + MICROPY_PY_UTIME_DEF \ + MICROPY_PY_SOCKET_DEF \ + /* { MP_ROM_QSTR(MP_QSTR_umachine), MP_ROM_PTR(&mp_module_machine) }, */ \ + /* { MP_ROM_QSTR(MP_QSTR_uos), MP_ROM_PTR(&mp_module_os) }, */ \ + MICROPY_PY_UOS_VFS_DEF \ + MICROPY_PY_USELECT_DEF \ + MICROPY_PY_TERMIOS_DEF \ + MICROPY_PY_TREZORCONFIG_DEF \ + MICROPY_PY_TREZORCRYPTO_DEF \ + MICROPY_PY_TREZORIO_DEF \ + MICROPY_PY_TREZORUI_DEF \ + MICROPY_PY_TREZORUTILS_DEF // type definitions for the specific machine @@ -278,17 +290,17 @@ extern const struct _mp_obj_module_t mp_module_trezorutils; // assume that if we already defined the obj repr then we also defined types #ifndef MICROPY_OBJ_REPR #ifdef __LP64__ -typedef long mp_int_t; // must be pointer size -typedef unsigned long mp_uint_t; // must be pointer size +typedef long mp_int_t; // must be pointer size +typedef unsigned long mp_uint_t; // must be pointer size #else // These are definitions for machines where sizeof(int) == sizeof(void*), // regardless of actual size. -typedef int mp_int_t; // must be pointer size -typedef unsigned int mp_uint_t; // must be pointer size +typedef int mp_int_t; // must be pointer size +typedef unsigned int mp_uint_t; // must be pointer size #endif #endif -#define MICROPY_EVENT_POLL_HOOK mp_hal_delay_ms(1); +#define MICROPY_EVENT_POLL_HOOK mp_hal_delay_ms(1); // Cannot include , as it may lead to symbol name clashes #if _FILE_OFFSET_BITS == 64 && !defined(__LP64__) @@ -297,26 +309,31 @@ typedef long long mp_off_t; typedef long mp_off_t; #endif -void mp_unix_alloc_exec(size_t min_size, void** ptr, size_t *size); +void mp_unix_alloc_exec(size_t min_size, void **ptr, size_t *size); void mp_unix_free_exec(void *ptr, size_t size); void mp_unix_mark_exec(void); -#define MP_PLAT_ALLOC_EXEC(min_size, ptr, size) mp_unix_alloc_exec(min_size, ptr, size) +#define MP_PLAT_ALLOC_EXEC(min_size, ptr, size) \ + mp_unix_alloc_exec(min_size, ptr, size) #define MP_PLAT_FREE_EXEC(ptr, size) mp_unix_free_exec(ptr, size) #ifndef MICROPY_FORCE_PLAT_ALLOC_EXEC -// Use MP_PLAT_ALLOC_EXEC for any executable memory allocation, including for FFI -// (overriding libffi own implementation) +// Use MP_PLAT_ALLOC_EXEC for any executable memory allocation, including for +// FFI (overriding libffi own implementation) #define MICROPY_FORCE_PLAT_ALLOC_EXEC (1) #endif #if MICROPY_PY_OS_DUPTERM #define MP_PLAT_PRINT_STRN(str, len) mp_hal_stdout_tx_strn_cooked(str, len) #else -#define MP_PLAT_PRINT_STRN(str, len) do { ssize_t ret = write(1, str, len); (void)ret; } while (0) +#define MP_PLAT_PRINT_STRN(str, len) \ + do { \ + ssize_t ret = write(1, str, len); \ + (void)ret; \ + } while (0) #endif #ifdef __linux__ // Can access physical memory using /dev/mem -#define MICROPY_PLAT_DEV_MEM (1) +#define MICROPY_PLAT_DEV_MEM (1) #endif // Assume that select() call, interrupted with a signal, and erroring @@ -337,8 +354,8 @@ void mp_unix_mark_exec(void); #define MP_STATE_PORT MP_STATE_VM #define MICROPY_PORT_ROOT_POINTERS \ - const char *readline_hist[50]; \ - void *mmap_region_head; \ + const char *readline_hist[50]; \ + void *mmap_region_head; // We need to provide a declaration/definition of alloca() // unless support for it is disabled. diff --git a/embed/unix/profile.c b/embed/unix/profile.c index ca47ed492..443deae35 100644 --- a/embed/unix/profile.c +++ b/embed/unix/profile.c @@ -18,111 +18,112 @@ */ #define _GNU_SOURCE +#include #include #include #include -#include #include -#include +#include #include -#include "profile.h" #include "common.h" +#include "profile.h" static int mkpath(const char *path, mode_t mode) { - if (!path) { - errno = EINVAL; - return 1; - } - - struct stat sb; - if (!stat(strdup(path), &sb)) { - return 0; - } - - // dirname has multiple incompatible implementations. - // Some modify input argument some share output buffer. - char *pathdup = strdup(path); - char *subpath = strdup(dirname(pathdup)); - mkpath(subpath, mode); - free(pathdup); - free(subpath); - return mkdir(path, mode); + if (!path) { + errno = EINVAL; + return 1; + } + + struct stat sb; + if (!stat(strdup(path), &sb)) { + return 0; + } + + // dirname has multiple incompatible implementations. + // Some modify input argument some share output buffer. + char *pathdup = strdup(path); + char *subpath = strdup(dirname(pathdup)); + mkpath(subpath, mode); + free(pathdup); + free(subpath); + return mkdir(path, mode); } void profile_init(void) { - const char *dir = profile_dir(); - if (mkpath(dir, 0755)) { - perror(dir); - printf("!!! Unable to initialize profile directory `%s`. Quitting\n", dir); - exit(1); - } - printf("Profile directory: %s\n", dir); + const char *dir = profile_dir(); + if (mkpath(dir, 0755)) { + perror(dir); + printf("!!! Unable to initialize profile directory `%s`. Quitting\n", dir); + exit(1); + } + printf("Profile directory: %s\n", dir); } const char *profile_dir(void) { - static const char *_profile_dir; - - if (_profile_dir) { - return _profile_dir; - } + static const char *_profile_dir; - char *trezor_profile = getenv("TREZOR_PROFILE"); - if (!trezor_profile || strlen(trezor_profile) < 1) { - trezor_profile = PROFILE_DEFAULT; - } + if (_profile_dir) { + return _profile_dir; + } - char *path; - if (trezor_profile[0] == '/') { + char *trezor_profile = getenv("TREZOR_PROFILE"); + if (!trezor_profile || strlen(trezor_profile) < 1) { + trezor_profile = PROFILE_DEFAULT; + } + + char *path; + if (trezor_profile[0] == '/') { // TREZOR_PROFILE is a full path to profile directory - path = strdup(trezor_profile); - } else { + path = strdup(trezor_profile); + } else { // TREZOR_PROFILE is just a profile name and will be put in ~/.trezoremu/ - int print_length = asprintf(&path, "%s/" PROFILE_HOMEDOT "/%s", getenv("HOME"), trezor_profile); - if (print_length == -1) { - path = NULL; - } + int print_length = asprintf(&path, "%s/" PROFILE_HOMEDOT "/%s", + getenv("HOME"), trezor_profile); + if (print_length == -1) { + path = NULL; } + } - if (!path) { // last resort fallback - path = PROFILE_DEFAULT; - } + if (!path) { // last resort fallback + path = PROFILE_DEFAULT; + } - _profile_dir = path; + _profile_dir = path; - return _profile_dir; + return _profile_dir; } const char *profile_flash_path(void) { - static char *_flash_path; - if (_flash_path) { - return _flash_path; - } + static char *_flash_path; + if (_flash_path) { + return _flash_path; + } - if (asprintf(&_flash_path, "%s/trezor.flash", profile_dir()) < 0) { - _flash_path = NULL; - } + if (asprintf(&_flash_path, "%s/trezor.flash", profile_dir()) < 0) { + _flash_path = NULL; + } - if (!_flash_path) { // last resort fallback - _flash_path = PROFILE_DEFAULT "/trezor.flash"; - } + if (!_flash_path) { // last resort fallback + _flash_path = PROFILE_DEFAULT "/trezor.flash"; + } - return _flash_path; + return _flash_path; } const char *profile_sdcard_path(void) { - static char *_sdcard_path; - if (_sdcard_path) { - return _sdcard_path; - } + static char *_sdcard_path; + if (_sdcard_path) { + return _sdcard_path; + } - if (asprintf(&_sdcard_path, "%s/trezor.sdcard", profile_dir()) < 0) { - _sdcard_path = NULL; - } + if (asprintf(&_sdcard_path, "%s/trezor.sdcard", profile_dir()) < 0) { + _sdcard_path = NULL; + } - if (!_sdcard_path) { // last resort fallback - _sdcard_path = PROFILE_DEFAULT "/trezor.sdcard"; - } + if (!_sdcard_path) { // last resort fallback + _sdcard_path = PROFILE_DEFAULT "/trezor.sdcard"; + } - return _sdcard_path; + return _sdcard_path; } diff --git a/embed/unix/profile.h b/embed/unix/profile.h index 097cb807d..0a15c4023 100644 --- a/embed/unix/profile.h +++ b/embed/unix/profile.h @@ -38,4 +38,4 @@ const char *profile_dir(void); const char *profile_flash_path(void); const char *profile_sdcard_path(void); -#endif // __TREZOR_PROFILE_H__ +#endif // __TREZOR_PROFILE_H__ diff --git a/embed/unix/rng.c b/embed/unix/rng.c index 62dc8d72b..2630450b4 100644 --- a/embed/unix/rng.c +++ b/embed/unix/rng.c @@ -23,14 +23,14 @@ #include "common.h" #include "rng.h" -uint32_t rng_get(void) -{ - static FILE *frand = NULL; - if (!frand) { - frand = fopen("/dev/urandom", "r"); - } - ensure(sectrue * (frand != NULL), "fopen failed"); - uint32_t r; - ensure(sectrue * (sizeof(r) == fread(&r, 1, sizeof(r), frand)), "fread failed"); - return r; +uint32_t rng_get(void) { + static FILE *frand = NULL; + if (!frand) { + frand = fopen("/dev/urandom", "r"); + } + ensure(sectrue * (frand != NULL), "fopen failed"); + uint32_t r; + ensure(sectrue * (sizeof(r) == fread(&r, 1, sizeof(r), frand)), + "fread failed"); + return r; } diff --git a/embed/unix/sbu.c b/embed/unix/sbu.c index 1c9530a40..8f4ca046f 100644 --- a/embed/unix/sbu.c +++ b/embed/unix/sbu.c @@ -19,10 +19,6 @@ #include "sbu.h" -void sbu_init(void) -{ -} +void sbu_init(void) {} -void sbu_set(secbool sbu1, secbool sbu2) -{ -} +void sbu_set(secbool sbu1, secbool sbu2) {} diff --git a/embed/unix/sdcard.c b/embed/unix/sdcard.c index 4b34b5ffa..ba1063f74 100644 --- a/embed/unix/sdcard.c +++ b/embed/unix/sdcard.c @@ -17,17 +17,17 @@ * along with this program. If not, see . */ -#include -#include -#include #include +#include +#include #include #include #include +#include #include "common.h" -#include "sdcard.h" #include "profile.h" +#include "sdcard.h" #ifndef SDCARD_FILE #define SDCARD_FILE profile_sdcard_path() @@ -38,74 +38,76 @@ static uint8_t *sdcard_buffer; static secbool sdcard_powered; -static void sdcard_exit(void) -{ - int r = munmap(sdcard_buffer, SDCARD_SIZE); - ensure(sectrue * (r == 0), "munmap failed"); +static void sdcard_exit(void) { + int r = munmap(sdcard_buffer, SDCARD_SIZE); + ensure(sectrue * (r == 0), "munmap failed"); } void sdcard_init(void) { - int r; - - // check whether the file exists and it has the correct size - struct stat sb; - r = stat(SDCARD_FILE, &sb); - - // (re)create if non existant or wrong size - if (r != 0 || sb.st_size != SDCARD_SIZE) { - int fd = open(SDCARD_FILE, O_RDWR | O_CREAT | O_TRUNC, (mode_t)0600); - ensure(sectrue * (fd >= 0), "open failed"); - for (int i = 0; i < SDCARD_SIZE / 16; i++) { - ssize_t s = write(fd, "\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF", 16); - ensure(sectrue * (s >= 0), "write failed"); - } - r = close(fd); - ensure(sectrue * (r == 0), "close failed"); - } + int r; + + // check whether the file exists and it has the correct size + struct stat sb; + r = stat(SDCARD_FILE, &sb); - // mmap file - int fd = open(SDCARD_FILE, O_RDWR); + // (re)create if non existant or wrong size + if (r != 0 || sb.st_size != SDCARD_SIZE) { + int fd = open(SDCARD_FILE, O_RDWR | O_CREAT | O_TRUNC, (mode_t)0600); ensure(sectrue * (fd >= 0), "open failed"); + for (int i = 0; i < SDCARD_SIZE / 16; i++) { + ssize_t s = write( + fd, + "\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF", + 16); + ensure(sectrue * (s >= 0), "write failed"); + } + r = close(fd); + ensure(sectrue * (r == 0), "close failed"); + } - void *map = mmap(0, SDCARD_SIZE, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0); - ensure(sectrue * (map != MAP_FAILED), "mmap failed"); + // mmap file + int fd = open(SDCARD_FILE, O_RDWR); + ensure(sectrue * (fd >= 0), "open failed"); - sdcard_buffer = (uint8_t *)map; + void *map = mmap(0, SDCARD_SIZE, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0); + ensure(sectrue * (map != MAP_FAILED), "mmap failed"); - sdcard_powered = secfalse; + sdcard_buffer = (uint8_t *)map; - atexit(sdcard_exit); -} + sdcard_powered = secfalse; -secbool sdcard_is_present(void) { - return sectrue; + atexit(sdcard_exit); } +secbool sdcard_is_present(void) { return sectrue; } + secbool sdcard_power_on(void) { - sdcard_powered = sectrue; - return sectrue; + sdcard_powered = sectrue; + return sectrue; } -void sdcard_power_off(void) { - sdcard_powered = secfalse; -} +void sdcard_power_off(void) { sdcard_powered = secfalse; } uint64_t sdcard_get_capacity_in_bytes(void) { - return sdcard_powered == sectrue ? SDCARD_SIZE : 0; + return sdcard_powered == sectrue ? SDCARD_SIZE : 0; } -secbool sdcard_read_blocks(uint32_t *dest, uint32_t block_num, uint32_t num_blocks) { - if (sectrue != sdcard_powered) { - return secfalse; - } - memcpy(dest, sdcard_buffer + block_num * SDCARD_BLOCK_SIZE, num_blocks * SDCARD_BLOCK_SIZE); - return sectrue; +secbool sdcard_read_blocks(uint32_t *dest, uint32_t block_num, + uint32_t num_blocks) { + if (sectrue != sdcard_powered) { + return secfalse; + } + memcpy(dest, sdcard_buffer + block_num * SDCARD_BLOCK_SIZE, + num_blocks * SDCARD_BLOCK_SIZE); + return sectrue; } -secbool sdcard_write_blocks(const uint32_t *src, uint32_t block_num, uint32_t num_blocks) { - if (sectrue != sdcard_powered) { - return secfalse; - } - memcpy(sdcard_buffer + block_num * SDCARD_BLOCK_SIZE, src, num_blocks * SDCARD_BLOCK_SIZE); - return sectrue; +secbool sdcard_write_blocks(const uint32_t *src, uint32_t block_num, + uint32_t num_blocks) { + if (sectrue != sdcard_powered) { + return secfalse; + } + memcpy(sdcard_buffer + block_num * SDCARD_BLOCK_SIZE, src, + num_blocks * SDCARD_BLOCK_SIZE); + return sectrue; } diff --git a/embed/unix/touch.c b/embed/unix/touch.c index c66663f55..d16d1153d 100644 --- a/embed/unix/touch.c +++ b/embed/unix/touch.c @@ -30,81 +30,89 @@ extern int sdl_touch_offset_x, sdl_touch_offset_y; extern void __shutdown(void); extern void display_save(const char *prefix); -uint32_t touch_read(void) -{ +uint32_t touch_read(void) { #ifndef TREZOR_EMULATOR_NOUI - SDL_Event event; - SDL_PumpEvents(); - if (SDL_PollEvent(&event) > 0) { - switch (event.type) { + SDL_Event event; + SDL_PumpEvents(); + if (SDL_PollEvent(&event) > 0) { + switch (event.type) { #if TREZOR_MODEL == T - case SDL_MOUSEBUTTONDOWN: - case SDL_MOUSEMOTION: - case SDL_MOUSEBUTTONUP: { - const int x = event.button.x - sdl_touch_offset_x; - const int y = event.button.y - sdl_touch_offset_y; - if (x < 0 || y < 0 || x >= sdl_display_res_x || y >= sdl_display_res_y) { - if (event.motion.state) { - const int clamp_x = (x < 0) ? 0 : ((x >= sdl_display_res_x) ? sdl_display_res_x - 1 : x); - const int clamp_y = (y < 0) ? 0 : ((y >= sdl_display_res_y) ? sdl_display_res_y - 1 : y); - return TOUCH_END | touch_pack_xy(clamp_x, clamp_y); - } else { - break; - } - } - switch (event.type) { - case SDL_MOUSEBUTTONDOWN: - return TOUCH_START | touch_pack_xy(x, y); - case SDL_MOUSEMOTION: - // remove other SDL_MOUSEMOTION events from queue - SDL_FlushEvent(SDL_MOUSEMOTION); - if (event.motion.state) { - return TOUCH_MOVE | touch_pack_xy(x, y); - } - break; - case SDL_MOUSEBUTTONUP: - return TOUCH_END | touch_pack_xy(x, y); - } - break; + case SDL_MOUSEBUTTONDOWN: + case SDL_MOUSEMOTION: + case SDL_MOUSEBUTTONUP: { + const int x = event.button.x - sdl_touch_offset_x; + const int y = event.button.y - sdl_touch_offset_y; + if (x < 0 || y < 0 || x >= sdl_display_res_x || + y >= sdl_display_res_y) { + if (event.motion.state) { + const int clamp_x = + (x < 0) + ? 0 + : ((x >= sdl_display_res_x) ? sdl_display_res_x - 1 : x); + const int clamp_y = + (y < 0) + ? 0 + : ((y >= sdl_display_res_y) ? sdl_display_res_y - 1 : y); + return TOUCH_END | touch_pack_xy(clamp_x, clamp_y); + } else { + break; + } + } + switch (event.type) { + case SDL_MOUSEBUTTONDOWN: + return TOUCH_START | touch_pack_xy(x, y); + case SDL_MOUSEMOTION: + // remove other SDL_MOUSEMOTION events from queue + SDL_FlushEvent(SDL_MOUSEMOTION); + if (event.motion.state) { + return TOUCH_MOVE | touch_pack_xy(x, y); } + break; + case SDL_MOUSEBUTTONUP: + return TOUCH_END | touch_pack_xy(x, y); + } + break; + } #endif #if TREZOR_MODEL == 1 - case SDL_KEYDOWN: - if (event.key.repeat) { - break; - } - switch (event.key.keysym.sym) { - case SDLK_LEFT: - return TOUCH_START | touch_pack_xy(0, sdl_display_res_y - 1); - case SDLK_RIGHT: - return TOUCH_START | touch_pack_xy(sdl_display_res_x - 1, sdl_display_res_y - 1); - } - break; + case SDL_KEYDOWN: + if (event.key.repeat) { + break; + } + switch (event.key.keysym.sym) { + case SDLK_LEFT: + return TOUCH_START | touch_pack_xy(0, sdl_display_res_y - 1); + case SDLK_RIGHT: + return TOUCH_START | + touch_pack_xy(sdl_display_res_x - 1, sdl_display_res_y - 1); + } + break; #endif - case SDL_KEYUP: - if (event.key.repeat) { - break; - } - switch (event.key.keysym.sym) { - case SDLK_ESCAPE: - __shutdown(); - break; - case SDLK_p: - display_save("emu"); - break; + case SDL_KEYUP: + if (event.key.repeat) { + break; + } + switch (event.key.keysym.sym) { + case SDLK_ESCAPE: + __shutdown(); + break; + case SDLK_p: + display_save("emu"); + break; #if TREZOR_MODEL == 1 - case SDLK_LEFT: - return TOUCH_END | touch_pack_xy(0, sdl_display_res_y - 1); - case SDLK_RIGHT: - return TOUCH_END | touch_pack_xy(sdl_display_res_x - 1, sdl_display_res_y - 1); + case SDLK_LEFT: + return TOUCH_END | touch_pack_xy(0, sdl_display_res_y - 1); + case SDLK_RIGHT: + return TOUCH_END | + touch_pack_xy(sdl_display_res_x - 1, sdl_display_res_y - 1); #endif - } - break; - case SDL_QUIT: - __shutdown(); - break; } + break; + case SDL_QUIT: + __shutdown(); + break; } + } #endif - return 0; + return 0; } diff --git a/embed/unix/usb.c b/embed/unix/usb.c index 3a430379a..c470532b7 100644 --- a/embed/unix/usb.c +++ b/embed/unix/usb.c @@ -18,201 +18,223 @@ */ #include -#include -#include -#include #include +#include #include #include +#include +#include -#include "usb.h" #include "touch.h" +#include "usb.h" #include "memzero.h" -void __attribute__((noreturn)) __fatal_error(const char *expr, const char *msg, const char *file, int line, const char *func); +void __attribute__((noreturn)) +__fatal_error(const char *expr, const char *msg, const char *file, int line, + const char *func); -#define ensure(expr, msg) (((expr) == sectrue) ? (void)0 : __fatal_error(#expr, msg, __FILE__, __LINE__, __func__)) +#define ensure(expr, msg) \ + (((expr) == sectrue) \ + ? (void)0 \ + : __fatal_error(#expr, msg, __FILE__, __LINE__, __func__)) // emulator opens UDP server on TREZOR_UDP_PORT port // and emulates HID/WebUSB interface TREZOR_UDP_IFACE // gracefully ignores all other USB interfaces -#define USBD_MAX_NUM_INTERFACES 8 -#define TREZOR_UDP_PORT 21324 +#define USBD_MAX_NUM_INTERFACES 8 +#define TREZOR_UDP_PORT 21324 static struct { - usb_iface_type_t type; - int sock; - struct sockaddr_in si_me, si_other; - socklen_t slen; + usb_iface_type_t type; + int sock; + struct sockaddr_in si_me, si_other; + socklen_t slen; } usb_ifaces[USBD_MAX_NUM_INTERFACES]; void usb_init(const usb_dev_info_t *dev_info) { - (void)dev_info; - for (int i = 0; i < USBD_MAX_NUM_INTERFACES; i++) { - usb_ifaces[i].type = USB_IFACE_TYPE_DISABLED; - usb_ifaces[i].sock = -1; - memzero(&usb_ifaces[i].si_me, sizeof(struct sockaddr_in)); - memzero(&usb_ifaces[i].si_other, sizeof(struct sockaddr_in)); - usb_ifaces[i].slen = 0; - } + (void)dev_info; + for (int i = 0; i < USBD_MAX_NUM_INTERFACES; i++) { + usb_ifaces[i].type = USB_IFACE_TYPE_DISABLED; + usb_ifaces[i].sock = -1; + memzero(&usb_ifaces[i].si_me, sizeof(struct sockaddr_in)); + memzero(&usb_ifaces[i].si_other, sizeof(struct sockaddr_in)); + usb_ifaces[i].slen = 0; + } } -void usb_deinit(void) { -} +void usb_deinit(void) {} void usb_start(void) { - const char *ip = getenv("TREZOR_UDP_IP"); - const char *port = getenv("TREZOR_UDP_PORT"); - - // iterate interfaces - for (int i = 0; i < USBD_MAX_NUM_INTERFACES; i++) { - // skip if not HID or WebUSB interface - if (usb_ifaces[i].type != USB_IFACE_TYPE_HID && usb_ifaces[i].type != USB_IFACE_TYPE_WEBUSB) { - continue; - } - - usb_ifaces[i].sock = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP); - ensure(sectrue * (usb_ifaces[i].sock >= 0), NULL); - - fcntl(usb_ifaces[i].sock, F_SETFL, O_NONBLOCK); - - usb_ifaces[i].si_me.sin_family = AF_INET; - if (ip) { - usb_ifaces[i].si_me.sin_addr.s_addr = inet_addr(ip); - } else { - usb_ifaces[i].si_me.sin_addr.s_addr = htonl(INADDR_LOOPBACK); - } - if (port) { - usb_ifaces[i].si_me.sin_port = htons(atoi(port) + i); - } else { - usb_ifaces[i].si_me.sin_port = htons(TREZOR_UDP_PORT + i); - } - - ensure(sectrue * (0 == bind(usb_ifaces[i].sock, (struct sockaddr*)&usb_ifaces[i].si_me, sizeof(struct sockaddr_in))), NULL); + const char *ip = getenv("TREZOR_UDP_IP"); + const char *port = getenv("TREZOR_UDP_PORT"); + + // iterate interfaces + for (int i = 0; i < USBD_MAX_NUM_INTERFACES; i++) { + // skip if not HID or WebUSB interface + if (usb_ifaces[i].type != USB_IFACE_TYPE_HID && + usb_ifaces[i].type != USB_IFACE_TYPE_WEBUSB) { + continue; } -} -void usb_stop(void) { + usb_ifaces[i].sock = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP); + ensure(sectrue * (usb_ifaces[i].sock >= 0), NULL); + + fcntl(usb_ifaces[i].sock, F_SETFL, O_NONBLOCK); + + usb_ifaces[i].si_me.sin_family = AF_INET; + if (ip) { + usb_ifaces[i].si_me.sin_addr.s_addr = inet_addr(ip); + } else { + usb_ifaces[i].si_me.sin_addr.s_addr = htonl(INADDR_LOOPBACK); + } + if (port) { + usb_ifaces[i].si_me.sin_port = htons(atoi(port) + i); + } else { + usb_ifaces[i].si_me.sin_port = htons(TREZOR_UDP_PORT + i); + } + + ensure(sectrue * (0 == bind(usb_ifaces[i].sock, + (struct sockaddr *)&usb_ifaces[i].si_me, + sizeof(struct sockaddr_in))), + NULL); + } } +void usb_stop(void) {} + secbool usb_hid_add(const usb_hid_info_t *info) { - if (info->iface_num < USBD_MAX_NUM_INTERFACES && usb_ifaces[info->iface_num].type == USB_IFACE_TYPE_DISABLED) { - usb_ifaces[info->iface_num].type = USB_IFACE_TYPE_HID; - } - return sectrue; + if (info->iface_num < USBD_MAX_NUM_INTERFACES && + usb_ifaces[info->iface_num].type == USB_IFACE_TYPE_DISABLED) { + usb_ifaces[info->iface_num].type = USB_IFACE_TYPE_HID; + } + return sectrue; } secbool usb_webusb_add(const usb_webusb_info_t *info) { - if (info->iface_num < USBD_MAX_NUM_INTERFACES && usb_ifaces[info->iface_num].type == USB_IFACE_TYPE_DISABLED) { - usb_ifaces[info->iface_num].type = USB_IFACE_TYPE_WEBUSB; - } - return sectrue; + if (info->iface_num < USBD_MAX_NUM_INTERFACES && + usb_ifaces[info->iface_num].type == USB_IFACE_TYPE_DISABLED) { + usb_ifaces[info->iface_num].type = USB_IFACE_TYPE_WEBUSB; + } + return sectrue; } secbool usb_vcp_add(const usb_vcp_info_t *info) { - if (info->iface_num < USBD_MAX_NUM_INTERFACES && usb_ifaces[info->iface_num].type == USB_IFACE_TYPE_DISABLED) { - usb_ifaces[info->iface_num].type = USB_IFACE_TYPE_VCP; - } - return sectrue; + if (info->iface_num < USBD_MAX_NUM_INTERFACES && + usb_ifaces[info->iface_num].type == USB_IFACE_TYPE_DISABLED) { + usb_ifaces[info->iface_num].type = USB_IFACE_TYPE_VCP; + } + return sectrue; } static secbool usb_emulated_poll(uint8_t iface_num, short dir) { - struct pollfd fds[] = { - { usb_ifaces[iface_num].sock, dir, 0 }, - }; - int r = poll(fds, 1, 0); - return sectrue * (r > 0); + struct pollfd fds[] = { + {usb_ifaces[iface_num].sock, dir, 0}, + }; + int r = poll(fds, 1, 0); + return sectrue * (r > 0); } static int usb_emulated_read(uint8_t iface_num, uint8_t *buf, uint32_t len) { - struct sockaddr_in si; - socklen_t sl = sizeof(si); - ssize_t r = recvfrom(usb_ifaces[iface_num].sock, buf, len, MSG_DONTWAIT, (struct sockaddr *)&si, &sl); - if (r < 0) { - return r; - } - usb_ifaces[iface_num].si_other = si; - usb_ifaces[iface_num].slen = sl; - static const char *ping_req = "PINGPING"; - static const char *ping_resp = "PONGPONG"; - if (r == strlen(ping_req) && 0 == memcmp(ping_req, buf, strlen(ping_req))) { - if (usb_ifaces[iface_num].slen > 0) { - sendto(usb_ifaces[iface_num].sock, ping_resp, strlen(ping_resp), MSG_DONTWAIT, (const struct sockaddr *)&usb_ifaces[iface_num].si_other, usb_ifaces[iface_num].slen); - } - return 0; - } + struct sockaddr_in si; + socklen_t sl = sizeof(si); + ssize_t r = recvfrom(usb_ifaces[iface_num].sock, buf, len, MSG_DONTWAIT, + (struct sockaddr *)&si, &sl); + if (r < 0) { return r; -} - -static int usb_emulated_write(uint8_t iface_num, const uint8_t *buf, uint32_t len) -{ - ssize_t r = len; + } + usb_ifaces[iface_num].si_other = si; + usb_ifaces[iface_num].slen = sl; + static const char *ping_req = "PINGPING"; + static const char *ping_resp = "PONGPONG"; + if (r == strlen(ping_req) && 0 == memcmp(ping_req, buf, strlen(ping_req))) { if (usb_ifaces[iface_num].slen > 0) { - r = sendto(usb_ifaces[iface_num].sock, buf, len, MSG_DONTWAIT, (const struct sockaddr *)&usb_ifaces[iface_num].si_other, usb_ifaces[iface_num].slen); + sendto(usb_ifaces[iface_num].sock, ping_resp, strlen(ping_resp), + MSG_DONTWAIT, + (const struct sockaddr *)&usb_ifaces[iface_num].si_other, + usb_ifaces[iface_num].slen); } - return r; + return 0; + } + return r; +} + +static int usb_emulated_write(uint8_t iface_num, const uint8_t *buf, + uint32_t len) { + ssize_t r = len; + if (usb_ifaces[iface_num].slen > 0) { + r = sendto(usb_ifaces[iface_num].sock, buf, len, MSG_DONTWAIT, + (const struct sockaddr *)&usb_ifaces[iface_num].si_other, + usb_ifaces[iface_num].slen); + } + return r; } secbool usb_hid_can_read(uint8_t iface_num) { - if (iface_num >= USBD_MAX_NUM_INTERFACES || usb_ifaces[iface_num].type != USB_IFACE_TYPE_HID) { - return secfalse; - } - return usb_emulated_poll(iface_num, POLLIN); + if (iface_num >= USBD_MAX_NUM_INTERFACES || + usb_ifaces[iface_num].type != USB_IFACE_TYPE_HID) { + return secfalse; + } + return usb_emulated_poll(iface_num, POLLIN); } secbool usb_webusb_can_read(uint8_t iface_num) { - if (iface_num >= USBD_MAX_NUM_INTERFACES || usb_ifaces[iface_num].type != USB_IFACE_TYPE_WEBUSB) { - return secfalse; - } - return usb_emulated_poll(iface_num, POLLIN); + if (iface_num >= USBD_MAX_NUM_INTERFACES || + usb_ifaces[iface_num].type != USB_IFACE_TYPE_WEBUSB) { + return secfalse; + } + return usb_emulated_poll(iface_num, POLLIN); } secbool usb_hid_can_write(uint8_t iface_num) { - if (iface_num >= USBD_MAX_NUM_INTERFACES || usb_ifaces[iface_num].type != USB_IFACE_TYPE_HID) { - return secfalse; - } - return usb_emulated_poll(iface_num, POLLOUT); + if (iface_num >= USBD_MAX_NUM_INTERFACES || + usb_ifaces[iface_num].type != USB_IFACE_TYPE_HID) { + return secfalse; + } + return usb_emulated_poll(iface_num, POLLOUT); } secbool usb_webusb_can_write(uint8_t iface_num) { - if (iface_num >= USBD_MAX_NUM_INTERFACES || usb_ifaces[iface_num].type != USB_IFACE_TYPE_WEBUSB) { - return secfalse; - } - return usb_emulated_poll(iface_num, POLLOUT); + if (iface_num >= USBD_MAX_NUM_INTERFACES || + usb_ifaces[iface_num].type != USB_IFACE_TYPE_WEBUSB) { + return secfalse; + } + return usb_emulated_poll(iface_num, POLLOUT); } int usb_hid_read(uint8_t iface_num, uint8_t *buf, uint32_t len) { - if (iface_num >= USBD_MAX_NUM_INTERFACES || usb_ifaces[iface_num].type != USB_IFACE_TYPE_HID) { - return 0; - } - return usb_emulated_read(iface_num, buf, len); + if (iface_num >= USBD_MAX_NUM_INTERFACES || + usb_ifaces[iface_num].type != USB_IFACE_TYPE_HID) { + return 0; + } + return usb_emulated_read(iface_num, buf, len); } int usb_webusb_read(uint8_t iface_num, uint8_t *buf, uint32_t len) { - if (iface_num >= USBD_MAX_NUM_INTERFACES || usb_ifaces[iface_num].type != USB_IFACE_TYPE_WEBUSB) { - return 0; - } - return usb_emulated_read(iface_num, buf, len); + if (iface_num >= USBD_MAX_NUM_INTERFACES || + usb_ifaces[iface_num].type != USB_IFACE_TYPE_WEBUSB) { + return 0; + } + return usb_emulated_read(iface_num, buf, len); } int usb_hid_write(uint8_t iface_num, const uint8_t *buf, uint32_t len) { - if (iface_num >= USBD_MAX_NUM_INTERFACES || usb_ifaces[iface_num].type != USB_IFACE_TYPE_HID) { - return 0; - } - return usb_emulated_write(iface_num, buf, len); + if (iface_num >= USBD_MAX_NUM_INTERFACES || + usb_ifaces[iface_num].type != USB_IFACE_TYPE_HID) { + return 0; + } + return usb_emulated_write(iface_num, buf, len); } int usb_webusb_write(uint8_t iface_num, const uint8_t *buf, uint32_t len) { - if (iface_num >= USBD_MAX_NUM_INTERFACES || usb_ifaces[iface_num].type != USB_IFACE_TYPE_WEBUSB) { - return 0; - } - return usb_emulated_write(iface_num, buf, len); + if (iface_num >= USBD_MAX_NUM_INTERFACES || + usb_ifaces[iface_num].type != USB_IFACE_TYPE_WEBUSB) { + return 0; + } + return usb_emulated_write(iface_num, buf, len); } -void pendsv_kbd_intr(void) { -} +void pendsv_kbd_intr(void) {} -void mp_hal_set_vcp_iface(int iface_num) { -} +void mp_hal_set_vcp_iface(int iface_num) {} diff --git a/shell.nix b/shell.nix index fc41147d3..1588cc3ca 100644 --- a/shell.nix +++ b/shell.nix @@ -5,5 +5,5 @@ let in stdenv.mkDerivation { name = "trezor-core-dev"; - buildInputs = [ myPython protobuf scons gnumake gcc gcc-arm-embedded pkgconfig SDL2 SDL2_image autoflake ]; + buildInputs = [ myPython protobuf scons gnumake gcc gcc-arm-embedded pkgconfig SDL2 SDL2_image autoflake clang-tools ]; }