1
0
mirror of https://github.com/trezor/trezor-firmware.git synced 2025-07-06 14:52:33 +00:00

format: start using clang-format with style=Google

This commit is contained in:
Pavol Rusnak 2019-03-29 16:26:02 +01:00
parent e53826e951
commit 0b7dbc12cb
No known key found for this signature in database
GPG Key ID: 91F3B339B9A02A3D
126 changed files with 11745 additions and 10141 deletions

View File

@ -1,3 +1,2 @@
--- ---
BasedOnStyle: Google BasedOnStyle: Google
IndentWidth: 4

View File

@ -86,10 +86,11 @@ style: ## apply code style on application sources and tests
black $(shell find src -name *.py ! -path 'src/trezor/messages/*') black $(shell find src -name *.py ! -path 'src/trezor/messages/*')
cstyle_check: ## run code style check on low-level C code 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 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: ## code generation:

View File

@ -21,8 +21,8 @@
#include "common.h" #include "common.h"
#include "display.h" #include "display.h"
#include "image.h"
#include "flash.h" #include "flash.h"
#include "image.h"
#include "rng.h" #include "rng.h"
#include "sdcard.h" #include "sdcard.h"
@ -45,8 +45,7 @@ static const uint8_t * const BOARDLOADER_KEYS[] = {
#endif #endif
}; };
static uint32_t check_sdcard(void) static uint32_t check_sdcard(void) {
{
if (sectrue != sdcard_power_on()) { if (sectrue != sdcard_power_on()) {
return 0; return 0;
} }
@ -61,25 +60,27 @@ static uint32_t check_sdcard(void)
memzero(buf, sizeof(buf)); memzero(buf, sizeof(buf));
const secbool read_status = sdcard_read_blocks(buf, 0, IMAGE_HEADER_SIZE / SDCARD_BLOCK_SIZE); const secbool read_status =
sdcard_read_blocks(buf, 0, IMAGE_HEADER_SIZE / SDCARD_BLOCK_SIZE);
sdcard_power_off(); sdcard_power_off();
image_header hdr; image_header hdr;
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))) { 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; return hdr.codelen;
} else { } else {
return 0; return 0;
} }
} }
static void progress_callback(int pos, int len) { static void progress_callback(int pos, int len) { display_printf("."); }
display_printf(".");
}
static secbool copy_sdcard(void) static secbool copy_sdcard(void) {
{
display_backlight(255); display_backlight(255);
display_printf("TREZOR Boardloader\n"); display_printf("TREZOR Boardloader\n");
@ -127,7 +128,8 @@ static secbool copy_sdcard(void)
22, 22,
FLASH_SECTOR_FIRMWARE_EXTRA_END, FLASH_SECTOR_FIRMWARE_EXTRA_END,
}; };
if (sectrue != flash_erase_sectors(sectors, sizeof(sectors), progress_callback)) { if (sectrue !=
flash_erase_sectors(sectors, sizeof(sectors), progress_callback)) {
display_printf(" failed\n"); display_printf(" failed\n");
return secfalse; return secfalse;
} }
@ -144,7 +146,10 @@ static secbool copy_sdcard(void)
for (int i = 0; i < (IMAGE_HEADER_SIZE + codelen) / SDCARD_BLOCK_SIZE; i++) { for (int i = 0; i < (IMAGE_HEADER_SIZE + codelen) / SDCARD_BLOCK_SIZE; i++) {
ensure(sdcard_read_blocks(buf, i, 1), NULL); ensure(sdcard_read_blocks(buf, i, 1), NULL);
for (int j = 0; j < SDCARD_BLOCK_SIZE / sizeof(uint32_t); j++) { 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); ensure(flash_write_word(FLASH_SECTOR_BOOTLOADER,
i * SDCARD_BLOCK_SIZE + j * sizeof(uint32_t),
buf[j]),
NULL);
} }
} }
@ -157,8 +162,7 @@ static secbool copy_sdcard(void)
return sectrue; return sectrue;
} }
int main(void) int main(void) {
{
if (sectrue != reset_flags_check()) { if (sectrue != reset_flags_check()) {
return 1; return 1;
} }
@ -169,7 +173,8 @@ int main(void)
if (sectrue != flash_configure_option_bytes()) { if (sectrue != flash_configure_option_bytes()) {
// display is not initialized so don't call ensure // display is not initialized so don't call ensure
secbool r = flash_erase_sectors(STORAGE_SECTORS, STORAGE_SECTORS_COUNT, NULL); secbool r =
flash_erase_sectors(STORAGE_SECTORS, STORAGE_SECTORS_COUNT, NULL);
(void)r; (void)r;
return 2; return 2;
} }
@ -185,15 +190,16 @@ int main(void)
image_header hdr; image_header hdr;
ensure( ensure(load_image_header((const uint8_t *)BOOTLOADER_START,
load_image_header((const uint8_t *)BOOTLOADER_START, BOOTLOADER_IMAGE_MAGIC, BOOTLOADER_IMAGE_MAXSIZE, BOARDLOADER_KEY_M, BOARDLOADER_KEY_N, BOARDLOADER_KEYS, &hdr), BOOTLOADER_IMAGE_MAGIC, BOOTLOADER_IMAGE_MAXSIZE,
BOARDLOADER_KEY_M, BOARDLOADER_KEY_N,
BOARDLOADER_KEYS, &hdr),
"invalid bootloader header"); "invalid bootloader header");
const uint8_t sectors[] = { const uint8_t sectors[] = {
FLASH_SECTOR_BOOTLOADER, FLASH_SECTOR_BOOTLOADER,
}; };
ensure( ensure(check_image_contents(&hdr, IMAGE_HEADER_SIZE, sectors, 1),
check_image_contents(&hdr, IMAGE_HEADER_SIZE, sectors, 1),
"invalid bootloader hash"); "invalid bootloader hash");
jump_to(BOOTLOADER_START + IMAGE_HEADER_SIZE); jump_to(BOOTLOADER_START + IMAGE_HEADER_SIZE);

View File

@ -28,9 +28,9 @@
#include "icon_cancel.h" #include "icon_cancel.h"
#include "icon_confirm.h" #include "icon_confirm.h"
#include "icon_info.h"
#include "icon_done.h" #include "icon_done.h"
#include "icon_fail.h" #include "icon_fail.h"
#include "icon_info.h"
#include "icon_install.h" #include "icon_install.h"
#include "icon_wipe.h" #include "icon_wipe.h"
@ -47,21 +47,21 @@
// common shared functions // common shared functions
static void ui_confirm_cancel_buttons(void) static void ui_confirm_cancel_buttons(void) {
{
display_bar_radius(9, 184, 108, 50, COLOR_BL_FAIL, COLOR_WHITE, 4); 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_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_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); 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 const char *format_ver(const char *format, uint32_t version) {
{
static char ver_str[64]; static char ver_str[64];
mini_snprintf(ver_str, sizeof(ver_str), format, mini_snprintf(ver_str, sizeof(ver_str), format, (int)(version & 0xFF),
(int)(version & 0xFF), (int)((version >> 8) & 0xFF), (int)((version >> 16) & 0xFF)
(int)((version >> 8) & 0xFF),
(int)((version >> 16) & 0xFF)
// ignore build field (int)((version >> 24) & 0xFF) // ignore build field (int)((version >> 24) & 0xFF)
); );
return ver_str; return ver_str;
@ -71,8 +71,8 @@ static const char *format_ver(const char *format, uint32_t version)
static uint16_t boot_background; static uint16_t boot_background;
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) {
const int show_string = ((vhdr->vtrust & VTRUST_STRING) == 0); const int show_string = ((vhdr->vtrust & VTRUST_STRING) == 0);
if ((vhdr->vtrust & VTRUST_RED) == 0) { if ((vhdr->vtrust & VTRUST_RED) == 0) {
boot_background = COLOR_BL_FAIL; boot_background = COLOR_BL_FAIL;
@ -90,176 +90,209 @@ void ui_screen_boot(const vendor_header * const vhdr, const image_header * const
// check whether vendor image is 120x120 // check whether vendor image is 120x120
if (memcmp(vimg, "TOIf\x78\x00\x78\x00", 4) == 0) { if (memcmp(vimg, "TOIf\x78\x00\x78\x00", 4) == 0) {
uint32_t datalen = *(uint32_t *)(vimg + 8); uint32_t datalen = *(uint32_t *)(vimg + 8);
display_image((DISPLAY_RESX - 120) / 2, image_top, 120, 120, vimg + 12, datalen); display_image((DISPLAY_RESX - 120) / 2, image_top, 120, 120, vimg + 12,
datalen);
} }
if (show_string) { if (show_string) {
display_text_center(DISPLAY_RESX / 2, DISPLAY_RESY - 5 - 50, vhdr->vstr, vhdr->vstr_len, FONT_NORMAL, COLOR_WHITE, boot_background); 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); 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); 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) void ui_screen_boot_wait(int wait_seconds) {
{
char wait_str[16]; char wait_str[16];
mini_snprintf(wait_str, sizeof(wait_str), "starting in %d s", wait_seconds); 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_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); display_text_center(DISPLAY_RESX / 2, DISPLAY_RESY - 5, wait_str, -1,
FONT_NORMAL, COLOR_WHITE, boot_background);
} }
void ui_screen_boot_click(void) { void ui_screen_boot_click(void) {
display_bar(0, DISPLAY_RESY - 5 - 20, DISPLAY_RESX, 5 + 20, 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); display_text_center(DISPLAY_RESX / 2, DISPLAY_RESY - 5,
"click to continue ...", -1, FONT_NORMAL, COLOR_WHITE,
boot_background);
} }
// welcome UI // welcome UI
void ui_screen_first(void) void ui_screen_first(void) {
{ display_icon(0, 0, 240, 240, toi_icon_logo + 12, sizeof(toi_icon_logo) - 12,
display_icon(0, 0, 240, 240, toi_icon_logo + 12, sizeof(toi_icon_logo) - 12, COLOR_BLACK, COLOR_WHITE); COLOR_BLACK, COLOR_WHITE);
} }
void ui_screen_second(void) void ui_screen_second(void) {
{
display_bar(0, 0, DISPLAY_RESX, DISPLAY_RESY, COLOR_WHITE); 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); 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) void ui_screen_third(void) {
{
display_bar(0, 0, DISPLAY_RESX, DISPLAY_RESY, COLOR_WHITE); 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_icon((DISPLAY_RESX - 180) / 2, (DISPLAY_RESY - 30) / 2 - 5, 180, 30,
display_text_center(120, 220, "Go to trezor.io/start", -1, FONT_NORMAL, COLOR_BLACK, COLOR_WHITE); 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 // info UI
void ui_screen_info(secbool buttons, const vendor_header * const vhdr, const image_header * const hdr) 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); display_bar(0, 0, DISPLAY_RESX, DISPLAY_RESY, COLOR_WHITE);
const char *ver_str = format_ver("Bootloader %d.%d.%d", VERSION_UINT32); 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_text(16, 32, ver_str, -1, FONT_NORMAL, COLOR_BLACK, COLOR_WHITE);
display_bar(16, 44, DISPLAY_RESX - 14 * 2, 1, COLOR_BLACK); 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); display_icon(16, 54, 32, 32, toi_icon_info + 12, sizeof(toi_icon_info) - 12,
COLOR_BL_GRAY, COLOR_WHITE);
if (vhdr && hdr) { if (vhdr && hdr) {
ver_str = format_ver("Firmware %d.%d.%d", (hdr->version)); 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, 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, 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); display_text(55, 120, vhdr->vstr, vhdr->vstr_len, FONT_NORMAL,
COLOR_BL_GRAY, COLOR_WHITE);
} else { } else {
display_text(55, 70, "No Firmware", -1, FONT_NORMAL, COLOR_BL_GRAY, COLOR_WHITE); display_text(55, 70, "No Firmware", -1, FONT_NORMAL, COLOR_BL_GRAY,
COLOR_WHITE);
} }
if (sectrue == buttons) { if (sectrue == buttons) {
display_text_center(120, 170, "Connect to host?", -1, FONT_NORMAL, COLOR_BLACK, COLOR_WHITE); display_text_center(120, 170, "Connect to host?", -1, FONT_NORMAL,
COLOR_BLACK, COLOR_WHITE);
ui_confirm_cancel_buttons(); ui_confirm_cancel_buttons();
} else { } else {
display_text_center(120, 220, "Go to trezor.io/start", -1, FONT_NORMAL, COLOR_BLACK, COLOR_WHITE); 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) void ui_screen_info_fingerprint(const image_header *const hdr) {
{
display_bar(0, 0, DISPLAY_RESX, DISPLAY_RESY, COLOR_WHITE); display_bar(0, 0, DISPLAY_RESX, DISPLAY_RESY, COLOR_WHITE);
display_text(16, 32, "Firmware fingerprint", -1, FONT_NORMAL, COLOR_BLACK, 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); display_bar(16, 44, DISPLAY_RESX - 14 * 2, 1, COLOR_BLACK);
static const char *hexdigits = "0123456789abcdef"; static const char *hexdigits = "0123456789abcdef";
char fingerprint_str[64]; char fingerprint_str[64];
for (int i = 0; i < 32; i++) { for (int i = 0; i < 32; i++) {
fingerprint_str[i * 2 ] = hexdigits[(hdr->fingerprint[i] >> 4) & 0xF]; fingerprint_str[i * 2] = hexdigits[(hdr->fingerprint[i] >> 4) & 0xF];
fingerprint_str[i * 2 + 1] = hexdigits[hdr->fingerprint[i] & 0xF]; fingerprint_str[i * 2 + 1] = hexdigits[hdr->fingerprint[i] & 0xF];
} }
for (int i = 0; i < 4; i++) { 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_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_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); 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 // install UI
void ui_screen_install_confirm_upgrade(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) {
display_bar(0, 0, DISPLAY_RESX, DISPLAY_RESY, COLOR_WHITE); display_bar(0, 0, DISPLAY_RESX, DISPLAY_RESY, COLOR_WHITE);
display_text(16, 32, "Firmware update", -1, FONT_NORMAL, COLOR_BLACK, 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_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_icon(16, 54, 32, 32, toi_icon_info + 12, sizeof(toi_icon_info) - 12,
display_text(55, 70, "Update firmware by", -1, FONT_NORMAL, COLOR_BLACK, COLOR_WHITE); COLOR_BLACK, COLOR_WHITE);
display_text(55, 95, vhdr->vstr, vhdr->vstr_len, FONT_NORMAL, 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); 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); display_text(55, 120, ver_str, -1, FONT_NORMAL, COLOR_BLACK, COLOR_WHITE);
ui_confirm_cancel_buttons(); ui_confirm_cancel_buttons();
} }
void ui_screen_install_confirm_newvendor(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) {
display_bar(0, 0, DISPLAY_RESX, DISPLAY_RESY, COLOR_WHITE); display_bar(0, 0, DISPLAY_RESX, DISPLAY_RESY, COLOR_WHITE);
display_text(16, 32, "Vendor change", -1, FONT_NORMAL, COLOR_BLACK, 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_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_icon(16, 54, 32, 32, toi_icon_info + 12, sizeof(toi_icon_info) - 12,
display_text(55, 70, "Install firmware by", -1, FONT_NORMAL, COLOR_BLACK, COLOR_WHITE); COLOR_BLACK, COLOR_WHITE);
display_text(55, 95, vhdr->vstr, vhdr->vstr_len, FONT_NORMAL, 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); 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(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); display_text_center(120, 170, "Seed will be erased!", -1, FONT_NORMAL,
COLOR_BL_FAIL, COLOR_WHITE);
ui_confirm_cancel_buttons(); ui_confirm_cancel_buttons();
} }
void ui_screen_install(void) void ui_screen_install(void) {
{
display_bar(0, 0, DISPLAY_RESX, DISPLAY_RESY, COLOR_WHITE); 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_loader(0, -20, COLOR_BL_PROCESS, COLOR_WHITE, toi_icon_install,
display_text_center(DISPLAY_RESX / 2, DISPLAY_RESY - 24, "Installing firmware", -1, FONT_NORMAL, COLOR_BLACK, COLOR_WHITE); 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) void ui_screen_install_progress_erase(int pos, int len) {
{ display_loader(250 * pos / len, -20, COLOR_BL_PROCESS, COLOR_WHITE,
display_loader(250 * pos / len, -20, COLOR_BL_PROCESS, COLOR_WHITE, toi_icon_install, sizeof(toi_icon_install), COLOR_BLACK); toi_icon_install, sizeof(toi_icon_install), COLOR_BLACK);
} }
void ui_screen_install_progress_upload(int pos) void ui_screen_install_progress_upload(int pos) {
{ display_loader(pos, -20, COLOR_BL_PROCESS, COLOR_WHITE, toi_icon_install,
display_loader(pos, -20, COLOR_BL_PROCESS, COLOR_WHITE, toi_icon_install, sizeof(toi_icon_install), COLOR_BLACK); sizeof(toi_icon_install), COLOR_BLACK);
} }
// wipe UI // wipe UI
void ui_screen_wipe_confirm(void) void ui_screen_wipe_confirm(void) {
{
display_bar(0, 0, DISPLAY_RESX, DISPLAY_RESY, COLOR_WHITE); display_bar(0, 0, DISPLAY_RESX, DISPLAY_RESY, COLOR_WHITE);
display_text(16, 32, "Wipe device", -1, FONT_NORMAL, COLOR_BLACK, 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_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_icon(16, 54, 32, 32, toi_icon_info + 12, sizeof(toi_icon_info) - 12,
display_text(55, 70, "Do you want to", -1, FONT_NORMAL, COLOR_BLACK, COLOR_WHITE); COLOR_BLACK, COLOR_WHITE);
display_text(55, 95, "wipe the device?", -1, FONT_NORMAL, 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); display_text_center(120, 170, "Seed will be erased!", -1, FONT_NORMAL,
COLOR_BL_FAIL, COLOR_WHITE);
ui_confirm_cancel_buttons(); ui_confirm_cancel_buttons();
} }
void ui_screen_wipe(void) void ui_screen_wipe(void) {
{
display_bar(0, 0, DISPLAY_RESX, DISPLAY_RESY, COLOR_WHITE); 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_loader(0, -20, COLOR_BL_PROCESS, COLOR_WHITE, toi_icon_wipe,
display_text_center(DISPLAY_RESX / 2, DISPLAY_RESY - 24, "Wiping device", -1, FONT_NORMAL, COLOR_BLACK, COLOR_WHITE); 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) void ui_screen_wipe_progress(int pos, int len) {
{ display_loader(1000 * pos / len, -20, COLOR_BL_PROCESS, COLOR_WHITE,
display_loader(1000 * pos / len, -20, COLOR_BL_PROCESS, COLOR_WHITE, toi_icon_wipe, sizeof(toi_icon_wipe), COLOR_BLACK); toi_icon_wipe, sizeof(toi_icon_wipe), COLOR_BLACK);
} }
// done UI // done UI
void ui_screen_done(int restart_seconds, secbool full_redraw) void ui_screen_done(int restart_seconds, secbool full_redraw) {
{
const char *str; const char *str;
char count_str[24]; char count_str[24];
if (restart_seconds >= 1) { if (restart_seconds >= 1) {
mini_snprintf(count_str, sizeof(count_str), "Done! Restarting in %d s", restart_seconds); mini_snprintf(count_str, sizeof(count_str), "Done! Restarting in %d s",
restart_seconds);
str = count_str; str = count_str;
} else { } else {
str = "Done! Unplug the device."; str = "Done! Unplug the device.";
@ -267,55 +300,58 @@ void ui_screen_done(int restart_seconds, secbool full_redraw)
if (sectrue == full_redraw) { if (sectrue == full_redraw) {
display_bar(0, 0, DISPLAY_RESX, DISPLAY_RESY, COLOR_WHITE); 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); display_loader(1000, -20, COLOR_BL_DONE, COLOR_WHITE, toi_icon_done,
sizeof(toi_icon_done), COLOR_BLACK);
if (secfalse == full_redraw) { if (secfalse == full_redraw) {
display_bar(0, DISPLAY_RESY - 24 - 18, 240, 23, COLOR_WHITE); 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); display_text_center(DISPLAY_RESX / 2, DISPLAY_RESY - 24, str, -1, FONT_NORMAL,
COLOR_BLACK, COLOR_WHITE);
} }
// error UI // error UI
void ui_screen_fail(void) void ui_screen_fail(void) {
{
display_bar(0, 0, DISPLAY_RESX, DISPLAY_RESY, COLOR_WHITE); 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_loader(1000, -20, COLOR_BL_FAIL, COLOR_WHITE, toi_icon_fail,
display_text_center(DISPLAY_RESX / 2, DISPLAY_RESY - 24, "Failed! Please, reconnect.", -1, FONT_NORMAL, COLOR_BLACK, COLOR_WHITE); 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 // general functions
void ui_fadein(void) void ui_fadein(void) { display_fade(0, BACKLIGHT_NORMAL, 1000); }
{
display_fade(0, BACKLIGHT_NORMAL, 1000);
}
void ui_fadeout(void) void ui_fadeout(void) {
{
display_fade(BACKLIGHT_NORMAL, 0, 500); display_fade(BACKLIGHT_NORMAL, 0, 500);
display_clear(); display_clear();
} }
int ui_user_input(int zones) int ui_user_input(int zones) {
{
for (;;) { for (;;) {
uint32_t evt = touch_click(); uint32_t evt = touch_click();
uint16_t x = touch_unpack_x(evt); uint16_t x = touch_unpack_x(evt);
uint16_t y = touch_unpack_y(evt); uint16_t y = touch_unpack_y(evt);
// clicked on Cancel button // clicked on Cancel button
if ((zones & INPUT_CANCEL) && x >= 9 && x < 9 + 108 && y > 184 && y < 184 + 50) { if ((zones & INPUT_CANCEL) && x >= 9 && x < 9 + 108 && y > 184 &&
y < 184 + 50) {
return INPUT_CANCEL; return INPUT_CANCEL;
} }
// clicked on Confirm button // clicked on Confirm button
if ((zones & INPUT_CONFIRM) && x >= 123 && x < 123 + 108 && y > 184 && y < 184 + 50) { if ((zones & INPUT_CONFIRM) && x >= 123 && x < 123 + 108 && y > 184 &&
y < 184 + 50) {
return INPUT_CONFIRM; return INPUT_CONFIRM;
} }
// clicked on Long Confirm button // clicked on Long Confirm button
if ((zones & INPUT_LONG_CONFIRM) && x >= 9 && x < 9 + 222 && y > 184 && y < 184 + 50) { if ((zones & INPUT_LONG_CONFIRM) && x >= 9 && x < 9 + 222 && y > 184 &&
y < 184 + 50) {
return INPUT_LONG_CONFIRM; return INPUT_LONG_CONFIRM;
} }
// clicked on Info icon // clicked on Info icon
if ((zones & INPUT_INFO) && x >= 16 && x < 16 + 32 && y > 54 && y < 54 + 32) { if ((zones & INPUT_INFO) && x >= 16 && x < 16 + 32 && y > 54 &&
y < 54 + 32) {
return INPUT_INFO; return INPUT_INFO;
} }
} }

View File

@ -20,10 +20,11 @@
#ifndef __BOOTUI_H__ #ifndef __BOOTUI_H__
#define __BOOTUI_H__ #define __BOOTUI_H__
#include "secbool.h"
#include "image.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_wait(int wait_seconds);
void ui_screen_boot_click(void); void ui_screen_boot_click(void);
@ -31,11 +32,14 @@ void ui_screen_first(void);
void ui_screen_second(void); void ui_screen_second(void);
void ui_screen_third(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(secbool buttons, const vendor_header* const vhdr,
void ui_screen_info_fingerprint(const image_header * const hdr); 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_upgrade(const vendor_header* const vhdr,
void ui_screen_install_confirm_newvendor(const vendor_header * const vhdr, const image_header * const hdr); 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(void);
void ui_screen_install_progress_erase(int pos, int len); void ui_screen_install_progress_erase(int pos, int len);
void ui_screen_install_progress_upload(int pos); void ui_screen_install_progress_upload(int pos);

View File

@ -21,11 +21,11 @@
#include <sys/types.h> #include <sys/types.h>
#include "common.h" #include "common.h"
#include "mpu.h"
#include "image.h"
#include "flash.h"
#include "display.h" #include "display.h"
#include "flash.h"
#include "image.h"
#include "mini_printf.h" #include "mini_printf.h"
#include "mpu.h"
#include "rng.h" #include "rng.h"
#include "secbool.h" #include "secbool.h"
#include "touch.h" #include "touch.h"
@ -51,7 +51,6 @@ static const uint8_t * const BOOTLOADER_KEYS[] = {
#define USB_IFACE_NUM 0 #define USB_IFACE_NUM 0
static void usb_init_all(void) { static void usb_init_all(void) {
static const usb_dev_info_t dev_info = { static const usb_dev_info_t dev_info = {
.device_class = 0x00, .device_class = 0x00,
.device_subclass = 0x00, .device_subclass = 0x00,
@ -87,14 +86,15 @@ static void usb_init_all(void) {
usb_start(); usb_start();
} }
static secbool bootloader_usb_loop(const vendor_header * const vhdr, const image_header * const hdr) static secbool bootloader_usb_loop(const vendor_header *const vhdr,
{ const image_header *const hdr) {
usb_init_all(); usb_init_all();
uint8_t buf[USB_PACKET_SIZE]; uint8_t buf[USB_PACKET_SIZE];
for (;;) { for (;;) {
int r = usb_webusb_read_blocking(USB_IFACE_NUM, buf, USB_PACKET_SIZE, USB_TIMEOUT); int r = usb_webusb_read_blocking(USB_IFACE_NUM, buf, USB_PACKET_SIZE,
USB_TIMEOUT);
if (r != USB_PACKET_SIZE) { if (r != USB_PACKET_SIZE) {
continue; continue;
} }
@ -155,8 +155,7 @@ static secbool bootloader_usb_loop(const vendor_header * const vhdr, const image
usb_stop(); usb_stop();
usb_deinit(); usb_deinit();
return secfalse; // shutdown return secfalse; // shutdown
} else } else if (r == 0) { // last chunk received
if (r == 0) { // last chunk received
ui_screen_install_progress_upload(1000); ui_screen_install_progress_upload(1000);
ui_fadeout(); ui_fadeout();
ui_screen_done(4, sectrue); ui_screen_done(4, sectrue);
@ -183,15 +182,22 @@ static secbool bootloader_usb_loop(const vendor_header * const vhdr, const image
} }
} }
secbool load_vendor_header_keys(const uint8_t * const data, vendor_header * const 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); 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) { static secbool check_vendor_keys_lock(const vendor_header *const vhdr) {
uint8_t lock[FLASH_OTP_BLOCK_SIZE]; uint8_t lock[FLASH_OTP_BLOCK_SIZE];
ensure(flash_otp_read(FLASH_OTP_BLOCK_VENDOR_KEYS_LOCK, 0, lock, FLASH_OTP_BLOCK_SIZE), NULL); ensure(flash_otp_read(FLASH_OTP_BLOCK_VENDOR_KEYS_LOCK, 0, lock,
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)) { 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; return sectrue;
} }
uint8_t hash[32]; uint8_t hash[32];
@ -203,8 +209,7 @@ static secbool check_vendor_keys_lock(const vendor_header * const vhdr) {
#if PRODUCTION #if PRODUCTION
static void check_bootloader_version(void) static void check_bootloader_version(void) {
{
uint8_t bits[FLASH_OTP_BLOCK_SIZE]; uint8_t bits[FLASH_OTP_BLOCK_SIZE];
for (int i = 0; i < FLASH_OTP_BLOCK_SIZE * 8; i++) { for (int i = 0; i < FLASH_OTP_BLOCK_SIZE * 8; i++) {
if (i < VERSION_MONOTONIC) { if (i < VERSION_MONOTONIC) {
@ -213,18 +218,22 @@ static void check_bootloader_version(void)
bits[i / 8] |= (1 << (7 - (i % 8))); bits[i / 8] |= (1 << (7 - (i % 8)));
} }
} }
ensure(flash_otp_write(FLASH_OTP_BLOCK_BOOTLOADER_VERSION, 0, bits, FLASH_OTP_BLOCK_SIZE), NULL); ensure(flash_otp_write(FLASH_OTP_BLOCK_BOOTLOADER_VERSION, 0, bits,
FLASH_OTP_BLOCK_SIZE),
NULL);
uint8_t bits2[FLASH_OTP_BLOCK_SIZE]; uint8_t bits2[FLASH_OTP_BLOCK_SIZE];
ensure(flash_otp_read(FLASH_OTP_BLOCK_BOOTLOADER_VERSION, 0, bits2, FLASH_OTP_BLOCK_SIZE), NULL); 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(sectrue * (0 == memcmp(bits, bits2, FLASH_OTP_BLOCK_SIZE)),
"Bootloader downgraded");
} }
#endif #endif
int main(void) int main(void) {
{
touch_init(); touch_init();
touch_power_on(); touch_power_on();
@ -254,15 +263,20 @@ main_start:
// detect whether the devices contains a valid firmware // detect whether the devices contains a valid firmware
firmware_present = load_vendor_header_keys((const uint8_t *)FIRMWARE_START, &vhdr); firmware_present =
load_vendor_header_keys((const uint8_t *)FIRMWARE_START, &vhdr);
if (sectrue == firmware_present) { if (sectrue == firmware_present) {
firmware_present = check_vendor_keys_lock(&vhdr); firmware_present = check_vendor_keys_lock(&vhdr);
} }
if (sectrue == firmware_present) { 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); 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) { if (sectrue == firmware_present) {
firmware_present = check_image_contents(&hdr, IMAGE_HEADER_SIZE + vhdr.hdrlen, FIRMWARE_SECTORS, FIRMWARE_SECTORS_COUNT); 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 ... // start the bootloader if no or broken firmware found ...
@ -286,7 +300,8 @@ main_start:
ui_fadein(); ui_fadein();
// erase storage // erase storage
ensure(flash_erase_sectors(STORAGE_SECTORS, STORAGE_SECTORS_COUNT, NULL), NULL); ensure(flash_erase_sectors(STORAGE_SECTORS, STORAGE_SECTORS_COUNT, NULL),
NULL);
// and start the usb loop // and start the usb loop
if (bootloader_usb_loop(NULL, NULL) != sectrue) { if (bootloader_usb_loop(NULL, NULL) != sectrue) {
@ -323,7 +338,8 @@ main_start:
// show fingerprint // show fingerprint
ui_screen_info_fingerprint(&hdr); ui_screen_info_fingerprint(&hdr);
ui_fadein(); ui_fadein();
while (INPUT_LONG_CONFIRM != ui_user_input(INPUT_LONG_CONFIRM)) { } while (INPUT_LONG_CONFIRM != ui_user_input(INPUT_LONG_CONFIRM)) {
}
ui_fadeout(); ui_fadeout();
ui_screen_info(sectrue, &vhdr, &hdr); ui_screen_info(sectrue, &vhdr, &hdr);
ui_fadein(); ui_fadein();
@ -336,26 +352,23 @@ main_start:
} }
} }
ensure( ensure(load_vendor_header_keys((const uint8_t *)FIRMWARE_START, &vhdr),
load_vendor_header_keys((const uint8_t *)FIRMWARE_START, &vhdr),
"invalid vendor header"); "invalid vendor header");
ensure( ensure(check_vendor_keys_lock(&vhdr), "unauthorized vendor keys");
check_vendor_keys_lock(&vhdr),
"unauthorized vendor keys");
ensure( ensure(load_image_header((const uint8_t *)(FIRMWARE_START + vhdr.hdrlen),
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), FIRMWARE_IMAGE_MAGIC, FIRMWARE_IMAGE_MAXSIZE,
vhdr.vsig_m, vhdr.vsig_n, vhdr.vpub, &hdr),
"invalid firmware header"); "invalid firmware header");
ensure( ensure(check_image_contents(&hdr, IMAGE_HEADER_SIZE + vhdr.hdrlen,
check_image_contents(&hdr, IMAGE_HEADER_SIZE + vhdr.hdrlen, FIRMWARE_SECTORS, FIRMWARE_SECTORS_COUNT), FIRMWARE_SECTORS, FIRMWARE_SECTORS_COUNT),
"invalid firmware hash"); "invalid firmware hash");
// if all VTRUST flags are unset = ultimate trust => skip the procedure // if all VTRUST flags are unset = ultimate trust => skip the procedure
if ((vhdr.vtrust & VTRUST_ALL) != VTRUST_ALL) { if ((vhdr.vtrust & VTRUST_ALL) != VTRUST_ALL) {
// ui_fadeout(); // no fadeout - we start from black screen // ui_fadeout(); // no fadeout - we start from black screen
ui_screen_boot(&vhdr, &hdr); ui_screen_boot(&vhdr, &hdr);
ui_fadein(); ui_fadein();

View File

@ -39,8 +39,8 @@
#define MSG_HEADER1_LEN 9 #define MSG_HEADER1_LEN 9
#define MSG_HEADER2_LEN 1 #define MSG_HEADER2_LEN 1
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) {
if (buf[0] != '?' || buf[1] != '#' || buf[2] != '#') { if (buf[0] != '?' || buf[1] != '#' || buf[2] != '#') {
return secfalse; return secfalse;
} }
@ -57,8 +57,8 @@ typedef struct {
} usb_write_state; } usb_write_state;
/* we don't use secbool/sectrue/secfalse here as it is a nanopb api */ /* 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) 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); usb_write_state *state = (usb_write_state *)(stream->state);
size_t written = 0; size_t written = 0;
@ -75,10 +75,12 @@ static bool _usb_write(pb_ostream_t *stream, const pb_byte_t *buf, size_t count)
return true; return true;
} else { } else {
// append data that fits // append data that fits
memcpy(state->buf + state->packet_pos, buf + written, USB_PACKET_SIZE - state->packet_pos); memcpy(state->buf + state->packet_pos, buf + written,
USB_PACKET_SIZE - state->packet_pos);
written += USB_PACKET_SIZE - state->packet_pos; written += USB_PACKET_SIZE - state->packet_pos;
// send packet // send packet
int r = usb_webusb_write_blocking(state->iface_num, state->buf, USB_PACKET_SIZE, USB_TIMEOUT); int r = usb_webusb_write_blocking(state->iface_num, state->buf,
USB_PACKET_SIZE, USB_TIMEOUT);
ensure(sectrue * (r == USB_PACKET_SIZE), NULL); ensure(sectrue * (r == USB_PACKET_SIZE), NULL);
// prepare new packet // prepare new packet
state->packet_index++; state->packet_index++;
@ -91,23 +93,23 @@ static bool _usb_write(pb_ostream_t *stream, const pb_byte_t *buf, size_t count)
return true; return true;
} }
static void _usb_write_flush(usb_write_state *state) static void _usb_write_flush(usb_write_state *state) {
{
// if packet is not filled up completely // if packet is not filled up completely
if (state->packet_pos < USB_PACKET_SIZE) { if (state->packet_pos < USB_PACKET_SIZE) {
// pad it with zeroes // pad it with zeroes
memzero(state->buf + state->packet_pos, USB_PACKET_SIZE - state->packet_pos); memzero(state->buf + state->packet_pos,
USB_PACKET_SIZE - state->packet_pos);
} }
// send packet // send packet
int r = usb_webusb_write_blocking(state->iface_num, state->buf, USB_PACKET_SIZE, USB_TIMEOUT); int r = usb_webusb_write_blocking(state->iface_num, state->buf,
USB_PACKET_SIZE, USB_TIMEOUT);
ensure(sectrue * (r == USB_PACKET_SIZE), NULL); 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) 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 // determine message size by serializing it into a dummy stream
pb_ostream_t sizestream = { pb_ostream_t sizestream = {.callback = NULL,
.callback = NULL,
.state = NULL, .state = NULL,
.max_size = SIZE_MAX, .max_size = SIZE_MAX,
.bytes_written = 0, .bytes_written = 0,
@ -121,20 +123,25 @@ static secbool _send_msg(uint8_t iface_num, uint16_t msg_id, const pb_field_t fi
.iface_num = iface_num, .iface_num = iface_num,
.packet_index = 0, .packet_index = 0,
.packet_pos = MSG_HEADER1_LEN, .packet_pos = MSG_HEADER1_LEN,
.buf = { .buf =
'?', '#', '#', {
(msg_id >> 8) & 0xFF, msg_id & 0xFF, '?',
(msg_size >> 24) & 0xFF, (msg_size >> 16) & 0xFF, (msg_size >> 8) & 0xFF, msg_size & 0xFF, '#',
'#',
(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 = { pb_ostream_t stream = {.callback = &_usb_write,
.callback = &_usb_write,
.state = &state, .state = &state,
.max_size = SIZE_MAX, .max_size = SIZE_MAX,
.bytes_written = 0, .bytes_written = 0,
.errmsg = NULL .errmsg = NULL};
};
if (false == pb_encode(&stream, fields, msg)) { if (false == pb_encode(&stream, fields, msg)) {
return secfalse; return secfalse;
@ -146,11 +153,33 @@ static secbool _send_msg(uint8_t iface_num, uint16_t msg_id, const pb_field_t fi
} }
#define MSG_SEND_INIT(TYPE) TYPE msg_send = TYPE##_init_default #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_VALUE(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)); } msg_send.has_##FIELD = true; \
#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)); } msg_send.FIELD = VALUE; \
#define MSG_SEND(TYPE) _send_msg(iface_num, MessageType_MessageType_##TYPE, TYPE##_fields, &msg_send) }
#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 { typedef struct {
uint8_t iface_num; uint8_t iface_num;
@ -160,8 +189,7 @@ typedef struct {
} usb_read_state; } usb_read_state;
/* we don't use secbool/sectrue/secfalse here as it is a nanopb api */ /* 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) static bool _usb_read(pb_istream_t *stream, uint8_t *buf, size_t count) {
{
usb_read_state *state = (usb_read_state *)(stream->state); usb_read_state *state = (usb_read_state *)(stream->state);
size_t read = 0; size_t read = 0;
@ -178,10 +206,12 @@ static bool _usb_read(pb_istream_t *stream, uint8_t *buf, size_t count)
return true; return true;
} else { } else {
// append data that fits // append data that fits
memcpy(buf + read, state->buf + state->packet_pos, USB_PACKET_SIZE - state->packet_pos); memcpy(buf + read, state->buf + state->packet_pos,
USB_PACKET_SIZE - state->packet_pos);
read += USB_PACKET_SIZE - state->packet_pos; read += USB_PACKET_SIZE - state->packet_pos;
// read next packet // read next packet
int r = usb_webusb_read_blocking(state->iface_num, state->buf, USB_PACKET_SIZE, USB_TIMEOUT); int r = usb_webusb_read_blocking(state->iface_num, state->buf,
USB_PACKET_SIZE, USB_TIMEOUT);
ensure(sectrue * (r == USB_PACKET_SIZE), NULL); ensure(sectrue * (r == USB_PACKET_SIZE), NULL);
// prepare next packet // prepare next packet
state->packet_index++; state->packet_index++;
@ -192,26 +222,19 @@ static bool _usb_read(pb_istream_t *stream, uint8_t *buf, size_t count)
return true; return true;
} }
static void _usb_read_flush(usb_read_state *state) static void _usb_read_flush(usb_read_state *state) { (void)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) 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 = { usb_read_state state = {.iface_num = iface_num,
.iface_num = iface_num,
.packet_index = 0, .packet_index = 0,
.packet_pos = MSG_HEADER1_LEN, .packet_pos = MSG_HEADER1_LEN,
.buf = buf .buf = buf};
};
pb_istream_t stream = { pb_istream_t stream = {.callback = &_usb_read,
.callback = &_usb_read,
.state = &state, .state = &state,
.bytes_left = msg_size, .bytes_left = msg_size,
.errmsg = NULL .errmsg = NULL};
};
if (false == pb_decode_noinit(&stream, fields, msg)) { if (false == pb_decode_noinit(&stream, fields, msg)) {
return secfalse; return secfalse;
@ -223,19 +246,21 @@ static secbool _recv_msg(uint8_t iface_num, uint32_t msg_size, uint8_t *buf, con
} }
#define MSG_RECV_INIT(TYPE) TYPE msg_recv = TYPE##_init_default #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_CALLBACK(FIELD, CALLBACK) \
#define MSG_RECV(TYPE) _recv_msg(iface_num, msg_size, buf, TYPE##_fields, &msg_recv) { 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) void send_user_abort(uint8_t iface_num, const char *msg) {
{
MSG_SEND_INIT(Failure); MSG_SEND_INIT(Failure);
MSG_SEND_ASSIGN_VALUE(code, FailureType_Failure_ActionCancelled); MSG_SEND_ASSIGN_VALUE(code, FailureType_Failure_ActionCancelled);
MSG_SEND_ASSIGN_STRING(message, msg); MSG_SEND_ASSIGN_STRING(message, msg);
MSG_SEND(Failure); MSG_SEND(Failure);
} }
static void send_msg_features(uint8_t iface_num, const vendor_header * const vhdr, const image_header * const hdr) 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_INIT(Features);
MSG_SEND_ASSIGN_STRING(vendor, "trezor.io"); MSG_SEND_ASSIGN_STRING(vendor, "trezor.io");
MSG_SEND_ASSIGN_VALUE(major_version, VERSION_MAJOR); MSG_SEND_ASSIGN_VALUE(major_version, VERSION_MAJOR);
@ -258,22 +283,23 @@ static void send_msg_features(uint8_t iface_num, const vendor_header * const vhd
MSG_SEND(Features); 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) 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_INIT(Initialize);
MSG_RECV(Initialize); MSG_RECV(Initialize);
send_msg_features(iface_num, vhdr, hdr); 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) 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_INIT(GetFeatures);
MSG_RECV(GetFeatures); MSG_RECV(GetFeatures);
send_msg_features(iface_num, vhdr, hdr); send_msg_features(iface_num, vhdr, hdr);
} }
void process_msg_Ping(uint8_t iface_num, uint32_t msg_size, uint8_t *buf) void process_msg_Ping(uint8_t iface_num, uint32_t msg_size, uint8_t *buf) {
{
MSG_RECV_INIT(Ping); MSG_RECV_INIT(Ping);
MSG_RECV(Ping); MSG_RECV(Ping);
@ -284,8 +310,8 @@ void process_msg_Ping(uint8_t iface_num, uint32_t msg_size, uint8_t *buf)
static uint32_t firmware_remaining, firmware_block, chunk_requested; static uint32_t firmware_remaining, firmware_block, chunk_requested;
void process_msg_FirmwareErase(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) {
firmware_remaining = 0; firmware_remaining = 0;
firmware_block = 0; firmware_block = 0;
chunk_requested = 0; chunk_requested = 0;
@ -294,9 +320,13 @@ void process_msg_FirmwareErase(uint8_t iface_num, uint32_t msg_size, uint8_t *bu
MSG_RECV(FirmwareErase); MSG_RECV(FirmwareErase);
firmware_remaining = msg_recv.has_length ? msg_recv.length : 0; 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))) { if ((firmware_remaining > 0) &&
((firmware_remaining % sizeof(uint32_t)) == 0) &&
(firmware_remaining <= (FIRMWARE_SECTORS_COUNT * IMAGE_CHUNK_SIZE))) {
// request new firmware // request new firmware
chunk_requested = (firmware_remaining > IMAGE_CHUNK_SIZE) ? IMAGE_CHUNK_SIZE : firmware_remaining; chunk_requested = (firmware_remaining > IMAGE_CHUNK_SIZE)
? IMAGE_CHUNK_SIZE
: firmware_remaining;
MSG_SEND_INIT(FirmwareRequest); MSG_SEND_INIT(FirmwareRequest);
MSG_SEND_ASSIGN_VALUE(offset, 0); MSG_SEND_ASSIGN_VALUE(offset, 0);
MSG_SEND_ASSIGN_VALUE(length, chunk_requested); MSG_SEND_ASSIGN_VALUE(length, chunk_requested);
@ -312,11 +342,11 @@ void process_msg_FirmwareErase(uint8_t iface_num, uint32_t msg_size, uint8_t *bu
static uint32_t chunk_size = 0; static uint32_t chunk_size = 0;
// SRAM is unused, so we can use it for chunk buffer // 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 */ /* 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 #define BUFSIZE 32768
if (stream->bytes_left > IMAGE_CHUNK_SIZE) { if (stream->bytes_left > IMAGE_CHUNK_SIZE) {
@ -333,10 +363,14 @@ static bool _read_payload(pb_istream_t *stream, const pb_field_t *field, void **
while (stream->bytes_left) { while (stream->bytes_left) {
// update loader but skip first block // update loader but skip first block
if (firmware_block > 0) { 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)); ui_screen_install_progress_upload(
250 + 750 * (firmware_block * IMAGE_CHUNK_SIZE + chunk_written) /
(firmware_block * IMAGE_CHUNK_SIZE + firmware_remaining));
} }
// read data // read data
if (!pb_read(stream, (pb_byte_t *)(chunk_buffer + chunk_written), (stream->bytes_left > BUFSIZE) ? BUFSIZE : stream->bytes_left)) { if (!pb_read(
stream, (pb_byte_t *)(chunk_buffer + chunk_written),
(stream->bytes_left > BUFSIZE) ? BUFSIZE : stream->bytes_left)) {
chunk_size = 0; chunk_size = 0;
return false; return false;
} }
@ -346,10 +380,10 @@ static bool _read_payload(pb_istream_t *stream, const pb_field_t *field, void **
return true; return true;
} }
secbool load_vendor_header_keys(const uint8_t * const data, vendor_header * const vhdr); secbool load_vendor_header_keys(const uint8_t *const data,
vendor_header *const vhdr);
static int version_compare(uint32_t vera, uint32_t verb) static int version_compare(uint32_t vera, uint32_t verb) {
{
int a, b; int a, b;
a = vera & 0xFF; a = vera & 0xFF;
b = verb & 0xFF; b = verb & 0xFF;
@ -365,15 +399,23 @@ static int version_compare(uint32_t vera, uint32_t verb)
return a - b; 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) 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_new = secfalse;
*is_upgrade = secfalse; *is_upgrade = secfalse;
if (sectrue != load_vendor_header_keys((const uint8_t *)FIRMWARE_START, current_vhdr)) { if (sectrue !=
load_vendor_header_keys((const uint8_t *)FIRMWARE_START, current_vhdr)) {
*is_new = sectrue; *is_new = sectrue;
return; 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)) { 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; *is_new = sectrue;
return; return;
} }
@ -391,8 +433,8 @@ static void detect_installation(vendor_header *current_vhdr, image_header *curre
static int firmware_upload_chunk_retry = FIRMWARE_UPLOAD_CHUNK_RETRY_COUNT; 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) int process_msg_FirmwareUpload(uint8_t iface_num, uint32_t msg_size,
{ uint8_t *buf) {
MSG_RECV_INIT(FirmwareUpload); MSG_RECV_INIT(FirmwareUpload);
MSG_RECV_CALLBACK(payload, _read_payload); MSG_RECV_CALLBACK(payload, _read_payload);
secbool r = MSG_RECV(FirmwareUpload); secbool r = MSG_RECV(FirmwareUpload);
@ -417,7 +459,10 @@ int process_msg_FirmwareUpload(uint8_t iface_num, uint32_t msg_size, uint8_t *bu
MSG_SEND(Failure); MSG_SEND(Failure);
return -2; 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)) { 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_INIT(Failure);
MSG_SEND_ASSIGN_VALUE(code, FailureType_Failure_ProcessError); MSG_SEND_ASSIGN_VALUE(code, FailureType_Failure_ProcessError);
MSG_SEND_ASSIGN_STRING(message, "Invalid firmware header"); MSG_SEND_ASSIGN_STRING(message, "Invalid firmware header");
@ -428,14 +473,14 @@ int process_msg_FirmwareUpload(uint8_t iface_num, uint32_t msg_size, uint8_t *bu
vendor_header current_vhdr; vendor_header current_vhdr;
image_header current_hdr; image_header current_hdr;
secbool is_new = secfalse, is_upgrade = secfalse; secbool is_new = secfalse, is_upgrade = secfalse;
detect_installation(&current_vhdr, &current_hdr, &vhdr, &hdr, &is_new, &is_upgrade); detect_installation(&current_vhdr, &current_hdr, &vhdr, &hdr, &is_new,
&is_upgrade);
int response = INPUT_CANCEL; int response = INPUT_CANCEL;
if (sectrue == is_new) { if (sectrue == is_new) {
// new installation - auto confirm // new installation - auto confirm
response = INPUT_CONFIRM; response = INPUT_CONFIRM;
} else } else if (sectrue == is_upgrade) {
if (sectrue == is_upgrade) {
// firmware upgrade // firmware upgrade
ui_fadeout(); ui_fadeout();
ui_screen_install_confirm_upgrade(&vhdr, &hdr); ui_screen_install_confirm_upgrade(&vhdr, &hdr);
@ -463,9 +508,12 @@ int process_msg_FirmwareUpload(uint8_t iface_num, uint32_t msg_size, uint8_t *bu
// if firmware is not upgrade, erase storage // if firmware is not upgrade, erase storage
if (sectrue != is_upgrade) { if (sectrue != is_upgrade) {
ensure(flash_erase_sectors(STORAGE_SECTORS, STORAGE_SECTORS_COUNT, NULL), NULL); 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); ensure(flash_erase_sectors(FIRMWARE_SECTORS, FIRMWARE_SECTORS_COUNT,
ui_screen_install_progress_erase),
NULL);
firstskip = IMAGE_HEADER_SIZE + vhdr.hdrlen; firstskip = IMAGE_HEADER_SIZE + vhdr.hdrlen;
} }
@ -479,8 +527,9 @@ int process_msg_FirmwareUpload(uint8_t iface_num, uint32_t msg_size, uint8_t *bu
return -5; return -5;
} }
if (sectrue != check_single_hash(hdr.hashes + firmware_block * 32, chunk_buffer + firstskip, chunk_size - firstskip)) { if (sectrue != check_single_hash(hdr.hashes + firmware_block * 32,
chunk_buffer + firstskip,
chunk_size - firstskip)) {
if (firmware_upload_chunk_retry > 0) { if (firmware_upload_chunk_retry > 0) {
--firmware_upload_chunk_retry; --firmware_upload_chunk_retry;
MSG_SEND_INIT(FirmwareRequest); MSG_SEND_INIT(FirmwareRequest);
@ -499,9 +548,11 @@ int process_msg_FirmwareUpload(uint8_t iface_num, uint32_t msg_size, uint8_t *bu
ensure(flash_unlock_write(), NULL); ensure(flash_unlock_write(), NULL);
const uint32_t * const src = (const uint32_t * const)chunk_buffer; const uint32_t *const src = (const uint32_t *const)chunk_buffer;
for (int i = 0; i < chunk_size / sizeof(uint32_t); i++) { 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_write_word(FIRMWARE_SECTORS[firmware_block],
i * sizeof(uint32_t), src[i]),
NULL);
} }
ensure(flash_lock_write(), NULL); ensure(flash_lock_write(), NULL);
@ -511,7 +562,9 @@ int process_msg_FirmwareUpload(uint8_t iface_num, uint32_t msg_size, uint8_t *bu
firmware_upload_chunk_retry = FIRMWARE_UPLOAD_CHUNK_RETRY_COUNT; firmware_upload_chunk_retry = FIRMWARE_UPLOAD_CHUNK_RETRY_COUNT;
if (firmware_remaining > 0) { if (firmware_remaining > 0) {
chunk_requested = (firmware_remaining > IMAGE_CHUNK_SIZE) ? IMAGE_CHUNK_SIZE : firmware_remaining; chunk_requested = (firmware_remaining > IMAGE_CHUNK_SIZE)
? IMAGE_CHUNK_SIZE
: firmware_remaining;
MSG_SEND_INIT(FirmwareRequest); MSG_SEND_INIT(FirmwareRequest);
MSG_SEND_ASSIGN_VALUE(offset, firmware_block * IMAGE_CHUNK_SIZE); MSG_SEND_ASSIGN_VALUE(offset, firmware_block * IMAGE_CHUNK_SIZE);
MSG_SEND_ASSIGN_VALUE(length, chunk_requested); MSG_SEND_ASSIGN_VALUE(length, chunk_requested);
@ -523,8 +576,7 @@ int process_msg_FirmwareUpload(uint8_t iface_num, uint32_t msg_size, uint8_t *bu
return (int)firmware_remaining; return (int)firmware_remaining;
} }
int process_msg_WipeDevice(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) {
{
static const uint8_t sectors[] = { static const uint8_t sectors[] = {
FLASH_SECTOR_STORAGE_1, FLASH_SECTOR_STORAGE_1,
FLASH_SECTOR_STORAGE_2, FLASH_SECTOR_STORAGE_2,
@ -547,7 +599,8 @@ int process_msg_WipeDevice(uint8_t iface_num, uint32_t msg_size, uint8_t *buf)
22, 22,
FLASH_SECTOR_FIRMWARE_EXTRA_END, FLASH_SECTOR_FIRMWARE_EXTRA_END,
}; };
if (sectrue != flash_erase_sectors(sectors, sizeof(sectors), ui_screen_wipe_progress)) { if (sectrue !=
flash_erase_sectors(sectors, sizeof(sectors), ui_screen_wipe_progress)) {
MSG_SEND_INIT(Failure); MSG_SEND_INIT(Failure);
MSG_SEND_ASSIGN_VALUE(code, FailureType_Failure_ProcessError); MSG_SEND_ASSIGN_VALUE(code, FailureType_Failure_ProcessError);
MSG_SEND_ASSIGN_STRING(message, "Could not erase flash"); MSG_SEND_ASSIGN_STRING(message, "Could not erase flash");
@ -560,18 +613,21 @@ 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) void process_msg_unknown(uint8_t iface_num, uint32_t msg_size, uint8_t *buf) {
{
// consume remaining message // consume remaining message
int remaining_chunks = 0; int remaining_chunks = 0;
if (msg_size > (USB_PACKET_SIZE - MSG_HEADER1_LEN)) { 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) // calculate how many blocks need to be read to drain the message (rounded
remaining_chunks = (msg_size - (USB_PACKET_SIZE - MSG_HEADER1_LEN) + ((USB_PACKET_SIZE - MSG_HEADER2_LEN) - 1)) / (USB_PACKET_SIZE - MSG_HEADER2_LEN); // 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++) { for (int i = 0; i < remaining_chunks; i++) {
int r = usb_webusb_read_blocking(iface_num, buf, USB_PACKET_SIZE, USB_TIMEOUT); int r =
usb_webusb_read_blocking(iface_num, buf, USB_PACKET_SIZE, USB_TIMEOUT);
ensure(sectrue * (r == USB_PACKET_SIZE), NULL); ensure(sectrue * (r == USB_PACKET_SIZE), NULL);
} }

View File

@ -29,15 +29,22 @@
#define FIRMWARE_UPLOAD_CHUNK_RETRY_COUNT 2 #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 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_Initialize(uint8_t iface_num, uint32_t msg_size, uint8_t *buf,
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); 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_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); void process_msg_FirmwareErase(uint8_t iface_num, uint32_t msg_size,
int process_msg_FirmwareUpload(uint8_t iface_num, uint32_t msg_size, uint8_t *buf); 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); 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); void process_msg_unknown(uint8_t iface_num, uint32_t msg_size, uint8_t *buf);

View File

@ -2,7 +2,9 @@
#define VERSION_MINOR 0 #define VERSION_MINOR 0
#define VERSION_PATCH 3 #define VERSION_PATCH 3
#define VERSION_BUILD 0 #define VERSION_BUILD 0
#define VERSION_UINT32 (VERSION_MAJOR | (VERSION_MINOR << 8) | (VERSION_PATCH << 16) | (VERSION_BUILD << 24)) #define VERSION_UINT32 \
(VERSION_MAJOR | (VERSION_MINOR << 8) | (VERSION_PATCH << 16) | \
(VERSION_BUILD << 24))
#define FIX_VERSION_MAJOR 2 #define FIX_VERSION_MAJOR 2
#define FIX_VERSION_MINOR 0 #define FIX_VERSION_MINOR 0

View File

@ -19,21 +19,22 @@
#include <string.h> #include <string.h>
#include "py/runtime.h"
#include "py/mphal.h" #include "py/mphal.h"
#include "py/objstr.h" #include "py/objstr.h"
#include "py/runtime.h"
#if MICROPY_PY_TREZORCONFIG #if MICROPY_PY_TREZORCONFIG
#include "embed/extmod/trezorobj.h" #include "embed/extmod/trezorobj.h"
#include "storage.h"
#include "common.h" #include "common.h"
#include "memzero.h" #include "memzero.h"
#include "storage.h"
STATIC mp_obj_t ui_wait_callback = mp_const_none; 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) { STATIC secbool wrapped_ui_wait_callback(uint32_t wait, uint32_t progress,
const char *message) {
if (mp_obj_is_callable(ui_wait_callback)) { if (mp_obj_is_callable(ui_wait_callback)) {
mp_obj_t args[3]; mp_obj_t args[3];
args[0] = mp_obj_new_int(wait); args[0] = mp_obj_new_int(wait);
@ -61,7 +62,8 @@ STATIC mp_obj_t mod_trezorconfig_init(size_t n_args, const mp_obj_t *args) {
memzero(HW_ENTROPY_DATA, sizeof(HW_ENTROPY_DATA)); memzero(HW_ENTROPY_DATA, sizeof(HW_ENTROPY_DATA));
return mp_const_none; 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: /// def check_pin(pin: int) -> bool:
/// ''' /// '''
@ -74,7 +76,8 @@ STATIC mp_obj_t mod_trezorconfig_check_pin(mp_obj_t pin) {
} }
return mp_const_true; 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: /// def unlock(pin: int) -> bool:
/// ''' /// '''
@ -88,7 +91,8 @@ STATIC mp_obj_t mod_trezorconfig_unlock(mp_obj_t pin) {
} }
return mp_const_true; 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: /// def lock() -> None:
/// ''' /// '''
@ -98,7 +102,8 @@ STATIC mp_obj_t mod_trezorconfig_lock(void) {
storage_lock(); storage_lock();
return mp_const_none; 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: /// def has_pin() -> bool:
/// ''' /// '''
@ -110,7 +115,8 @@ STATIC mp_obj_t mod_trezorconfig_has_pin(void) {
} }
return mp_const_true; 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: /// def get_pin_rem() -> int:
/// ''' /// '''
@ -119,7 +125,8 @@ STATIC MP_DEFINE_CONST_FUN_OBJ_0(mod_trezorconfig_has_pin_obj, mod_trezorconfig_
STATIC mp_obj_t mod_trezorconfig_get_pin_rem(void) { 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: /// def change_pin(pin: int, newpin: int) -> bool:
/// ''' /// '''
@ -133,12 +140,14 @@ STATIC mp_obj_t mod_trezorconfig_change_pin(mp_obj_t pin, mp_obj_t newpin) {
} }
return mp_const_true; 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: /// 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). /// 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) { 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 app = trezor_obj_get_uint8(args[0]) & 0x3F;
@ -162,7 +171,8 @@ STATIC mp_obj_t mod_trezorconfig_get(size_t n_args, const mp_obj_t *args) {
} }
return mp_obj_new_str_from_vstr(&mp_type_bytes, &vstr); 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: /// def set(app: int, key: int, value: bytes, public: bool=False) -> None:
/// ''' /// '''
@ -182,7 +192,8 @@ STATIC mp_obj_t mod_trezorconfig_set(size_t n_args, const mp_obj_t *args) {
} }
return mp_const_none; 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: /// def delete(app: int, key: int, public: bool=False) -> bool:
/// ''' /// '''
@ -200,13 +211,16 @@ STATIC mp_obj_t mod_trezorconfig_delete(size_t n_args, const mp_obj_t *args) {
} }
return mp_const_true; 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. /// 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) { 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 app = trezor_obj_get_uint8(args[0]) & 0x3F;
uint8_t key = trezor_obj_get_uint8(args[1]); uint8_t key = trezor_obj_get_uint8(args[1]);
if (n_args > 3 && args[3] == mp_const_true) { if (n_args > 3 && args[3] == mp_const_true) {
@ -227,13 +241,16 @@ STATIC mp_obj_t mod_trezorconfig_set_counter(size_t n_args, const mp_obj_t *args
} }
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: /// 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) { 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 app = trezor_obj_get_uint8(args[0]) & 0x3F;
uint8_t key = trezor_obj_get_uint8(args[1]); uint8_t key = trezor_obj_get_uint8(args[1]);
if (n_args > 2 && args[2] == mp_const_true) { if (n_args > 2 && args[2] == mp_const_true) {
@ -248,7 +265,8 @@ STATIC mp_obj_t mod_trezorconfig_next_counter(size_t n_args, const mp_obj_t *arg
} }
return mp_obj_new_int_from_uint(count); 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: /// def wipe() -> None:
/// ''' /// '''
@ -258,29 +276,36 @@ STATIC mp_obj_t mod_trezorconfig_wipe(void) {
storage_wipe(); storage_wipe();
return mp_const_none; 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[] = { 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___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_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_check_pin),
{ MP_ROM_QSTR(MP_QSTR_unlock), MP_ROM_PTR(&mod_trezorconfig_unlock_obj) }, MP_ROM_PTR(&mod_trezorconfig_check_pin_obj)},
{ MP_ROM_QSTR(MP_QSTR_lock), MP_ROM_PTR(&mod_trezorconfig_lock_obj) }, {MP_ROM_QSTR(MP_QSTR_unlock), MP_ROM_PTR(&mod_trezorconfig_unlock_obj)},
{ MP_ROM_QSTR(MP_QSTR_has_pin), MP_ROM_PTR(&mod_trezorconfig_has_pin_obj) }, {MP_ROM_QSTR(MP_QSTR_lock), MP_ROM_PTR(&mod_trezorconfig_lock_obj)},
{ MP_ROM_QSTR(MP_QSTR_get_pin_rem), MP_ROM_PTR(&mod_trezorconfig_get_pin_rem_obj) }, {MP_ROM_QSTR(MP_QSTR_has_pin), MP_ROM_PTR(&mod_trezorconfig_has_pin_obj)},
{ MP_ROM_QSTR(MP_QSTR_change_pin), MP_ROM_PTR(&mod_trezorconfig_change_pin_obj) }, {MP_ROM_QSTR(MP_QSTR_get_pin_rem),
{ MP_ROM_QSTR(MP_QSTR_get), MP_ROM_PTR(&mod_trezorconfig_get_obj) }, MP_ROM_PTR(&mod_trezorconfig_get_pin_rem_obj)},
{ MP_ROM_QSTR(MP_QSTR_set), MP_ROM_PTR(&mod_trezorconfig_set_obj) }, {MP_ROM_QSTR(MP_QSTR_change_pin),
{ MP_ROM_QSTR(MP_QSTR_delete), MP_ROM_PTR(&mod_trezorconfig_delete_obj) }, MP_ROM_PTR(&mod_trezorconfig_change_pin_obj)},
{ MP_ROM_QSTR(MP_QSTR_set_counter), MP_ROM_PTR(&mod_trezorconfig_set_counter_obj) }, {MP_ROM_QSTR(MP_QSTR_get), MP_ROM_PTR(&mod_trezorconfig_get_obj)},
{ MP_ROM_QSTR(MP_QSTR_next_counter), MP_ROM_PTR(&mod_trezorconfig_next_counter_obj) }, {MP_ROM_QSTR(MP_QSTR_set), MP_ROM_PTR(&mod_trezorconfig_set_obj)},
{ MP_ROM_QSTR(MP_QSTR_wipe), MP_ROM_PTR(&mod_trezorconfig_wipe_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 = { const mp_obj_module_t mp_module_trezorconfig = {
.base = { &mp_type_module }, .base = {&mp_type_module},
.globals = (mp_obj_dict_t*)&mp_module_trezorconfig_globals, .globals = (mp_obj_dict_t *)&mp_module_trezorconfig_globals,
}; };
#endif // MICROPY_PY_TREZORCONFIG #endif // MICROPY_PY_TREZORCONFIG

View File

@ -27,13 +27,15 @@
#if TREZOR_MODEL == T #if TREZOR_MODEL == T
#define NORCOW_SECTOR_SIZE (64*1024) #define NORCOW_SECTOR_SIZE (64 * 1024)
#define NORCOW_SECTORS {FLASH_SECTOR_STORAGE_1, FLASH_SECTOR_STORAGE_2} #define NORCOW_SECTORS \
{ FLASH_SECTOR_STORAGE_1, FLASH_SECTOR_STORAGE_2 }
#elif TREZOR_MODEL == 1 #elif TREZOR_MODEL == 1
#define NORCOW_SECTOR_SIZE (16*1024) #define NORCOW_SECTOR_SIZE (16 * 1024)
#define NORCOW_SECTORS {2, 3} #define NORCOW_SECTORS \
{ 2, 3 }
#else #else

View File

@ -58,15 +58,12 @@
#include "crc.h" #include "crc.h"
static const uint32_t crc32tab[16] = { static const uint32_t crc32tab[16] = {
0x00000000, 0x1db71064, 0x3b6e20c8, 0x26d930ac, 0x76dc4190, 0x00000000, 0x1db71064, 0x3b6e20c8, 0x26d930ac, 0x76dc4190, 0x6b6b51f4,
0x6b6b51f4, 0x4db26158, 0x5005713c, 0xedb88320, 0xf00f9344, 0x4db26158, 0x5005713c, 0xedb88320, 0xf00f9344, 0xd6d6a3e8, 0xcb61b38c,
0xd6d6a3e8, 0xcb61b38c, 0x9b64c2b0, 0x86d3d2d4, 0xa00ae278, 0x9b64c2b0, 0x86d3d2d4, 0xa00ae278, 0xbdbdf21c};
0xbdbdf21c
};
/* crc is previous value for incremental computation, 0xffffffff initially */ /* crc is previous value for incremental computation, 0xffffffff initially */
uint32_t checksum_crc32(const uint8_t *data, uint32_t length, uint32_t crc) uint32_t checksum_crc32(const uint8_t *data, uint32_t length, uint32_t crc) {
{
for (uint32_t i = 0; i < length; ++i) { for (uint32_t i = 0; i < length; ++i) {
crc ^= data[i]; crc ^= data[i];
crc = crc32tab[crc & 0x0f] ^ (crc >> 4); crc = crc32tab[crc & 0x0f] ^ (crc >> 4);
@ -74,5 +71,5 @@ uint32_t checksum_crc32(const uint8_t *data, uint32_t length, uint32_t crc)
} }
// return value suitable for passing in next time, for final value invert it // return value suitable for passing in next time, for final value invert it
return crc/* ^ 0xffffffff*/; return crc /* ^ 0xffffffff*/;
} }

View File

@ -48,7 +48,9 @@ typedef struct _mp_obj_AES_t {
/// ''' /// '''
/// Initialize AES context. /// 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) { 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_arg_check_num(n_args, n_kw, 2, 3, false);
mp_obj_AES_t *o = m_new_obj(mp_obj_AES_t); mp_obj_AES_t *o = m_new_obj(mp_obj_AES_t);
o->base.type = type; o->base.type = type;
@ -59,13 +61,15 @@ STATIC mp_obj_t mod_trezorcrypto_AES_make_new(const mp_obj_type_t *type, size_t
mp_buffer_info_t key; mp_buffer_info_t key;
mp_get_buffer_raise(args[1], &key, MP_BUFFER_READ); mp_get_buffer_raise(args[1], &key, MP_BUFFER_READ);
if (key.len != 16 && key.len != 24 && key.len != 32) { 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)"); mp_raise_ValueError(
"Invalid length of key (has to be 128, 192 or 256 bits)");
} }
if (n_args > 2) { if (n_args > 2) {
mp_buffer_info_t iv; mp_buffer_info_t iv;
mp_get_buffer_raise(args[2], &iv, MP_BUFFER_READ); mp_get_buffer_raise(args[2], &iv, MP_BUFFER_READ);
if (iv.len != AES_BLOCK_SIZE) { if (iv.len != AES_BLOCK_SIZE) {
mp_raise_ValueError("Invalid length of initialization vector (has to be 128 bits)"); mp_raise_ValueError(
"Invalid length of initialization vector (has to be 128 bits)");
} }
memcpy(o->iv, iv.buf, AES_BLOCK_SIZE); memcpy(o->iv, iv.buf, AES_BLOCK_SIZE);
} else { } else {
@ -103,9 +107,11 @@ static mp_obj_t aes_update(mp_obj_t self, mp_obj_t data, bool encrypt) {
mp_raise_ValueError("Invalid data length"); mp_raise_ValueError("Invalid data length");
} }
if (encrypt) { if (encrypt) {
aes_ecb_encrypt(buf.buf, (uint8_t *)vstr.buf, buf.len, &(o->encrypt_ctx)); aes_ecb_encrypt(buf.buf, (uint8_t *)vstr.buf, buf.len,
&(o->encrypt_ctx));
} else { } else {
aes_ecb_decrypt(buf.buf, (uint8_t *)vstr.buf, buf.len, &(o->decrypt_ctx)); aes_ecb_decrypt(buf.buf, (uint8_t *)vstr.buf, buf.len,
&(o->decrypt_ctx));
} }
break; break;
case CBC: case CBC:
@ -113,23 +119,29 @@ static mp_obj_t aes_update(mp_obj_t self, mp_obj_t data, bool encrypt) {
mp_raise_ValueError("Invalid data length"); mp_raise_ValueError("Invalid data length");
} }
if (encrypt) { if (encrypt) {
aes_cbc_encrypt(buf.buf, (uint8_t *)vstr.buf, buf.len, o->iv, &(o->encrypt_ctx)); aes_cbc_encrypt(buf.buf, (uint8_t *)vstr.buf, buf.len, o->iv,
&(o->encrypt_ctx));
} else { } else {
aes_cbc_decrypt(buf.buf, (uint8_t *)vstr.buf, buf.len, o->iv, &(o->decrypt_ctx)); aes_cbc_decrypt(buf.buf, (uint8_t *)vstr.buf, buf.len, o->iv,
&(o->decrypt_ctx));
} }
break; break;
case CFB: case CFB:
if (encrypt) { if (encrypt) {
aes_cfb_encrypt(buf.buf, (uint8_t *)vstr.buf, buf.len, o->iv, &(o->encrypt_ctx)); aes_cfb_encrypt(buf.buf, (uint8_t *)vstr.buf, buf.len, o->iv,
&(o->encrypt_ctx));
} else { } else {
aes_cfb_decrypt(buf.buf, (uint8_t *)vstr.buf, buf.len, o->iv, &(o->encrypt_ctx)); // decrypt uses encrypt_ctx aes_cfb_decrypt(buf.buf, (uint8_t *)vstr.buf, buf.len, o->iv,
&(o->encrypt_ctx)); // decrypt uses encrypt_ctx
} }
break; break;
case OFB: // (encrypt == decrypt) case OFB: // (encrypt == decrypt)
aes_ofb_crypt(buf.buf, (uint8_t *)vstr.buf, buf.len, o->iv, &(o->encrypt_ctx)); aes_ofb_crypt(buf.buf, (uint8_t *)vstr.buf, buf.len, o->iv,
&(o->encrypt_ctx));
break; break;
case CTR: // (encrypt == decrypt) case CTR: // (encrypt == decrypt)
aes_ctr_crypt(buf.buf, (uint8_t *)vstr.buf, buf.len, o->iv, aes_ctr_cbuf_inc, &(o->encrypt_ctx)); aes_ctr_crypt(buf.buf, (uint8_t *)vstr.buf, buf.len, o->iv,
aes_ctr_cbuf_inc, &(o->encrypt_ctx));
break; break;
} }
return mp_obj_new_str_from_vstr(&mp_type_bytes, &vstr); return mp_obj_new_str_from_vstr(&mp_type_bytes, &vstr);
@ -142,7 +154,8 @@ static mp_obj_t aes_update(mp_obj_t self, mp_obj_t data, bool encrypt) {
STATIC mp_obj_t mod_trezorcrypto_AES_encrypt(mp_obj_t self, mp_obj_t data) { 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: /// def decrypt(self, data: bytes) -> bytes:
/// ''' /// '''
@ -151,7 +164,8 @@ STATIC MP_DEFINE_CONST_FUN_OBJ_2(mod_trezorcrypto_AES_encrypt_obj, mod_trezorcry
STATIC mp_obj_t mod_trezorcrypto_AES_decrypt(mp_obj_t self, mp_obj_t data) { 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) { STATIC mp_obj_t mod_trezorcrypto_AES___del__(mp_obj_t self) {
mp_obj_AES_t *o = MP_OBJ_TO_PTR(self); mp_obj_AES_t *o = MP_OBJ_TO_PTR(self);
@ -160,23 +174,28 @@ STATIC mp_obj_t mod_trezorcrypto_AES___del__(mp_obj_t self) {
memzero(o->iv, AES_BLOCK_SIZE); memzero(o->iv, AES_BLOCK_SIZE);
return mp_const_none; 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[] = { 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_encrypt),
{ MP_ROM_QSTR(MP_QSTR_decrypt), MP_ROM_PTR(&mod_trezorcrypto_AES_decrypt_obj) }, MP_ROM_PTR(&mod_trezorcrypto_AES_encrypt_obj)},
{ MP_ROM_QSTR(MP_QSTR___del__), MP_ROM_PTR(&mod_trezorcrypto_AES___del___obj) }, {MP_ROM_QSTR(MP_QSTR_decrypt),
{ MP_ROM_QSTR(MP_QSTR_ECB), MP_OBJ_NEW_SMALL_INT(ECB) }, MP_ROM_PTR(&mod_trezorcrypto_AES_decrypt_obj)},
{ MP_ROM_QSTR(MP_QSTR_CBC), MP_OBJ_NEW_SMALL_INT(CBC) }, {MP_ROM_QSTR(MP_QSTR___del__),
{ MP_ROM_QSTR(MP_QSTR_CFB), MP_OBJ_NEW_SMALL_INT(CFB) }, MP_ROM_PTR(&mod_trezorcrypto_AES___del___obj)},
{ MP_ROM_QSTR(MP_QSTR_OFB), MP_OBJ_NEW_SMALL_INT(OFB) }, {MP_ROM_QSTR(MP_QSTR_ECB), MP_OBJ_NEW_SMALL_INT(ECB)},
{ MP_ROM_QSTR(MP_QSTR_CTR), MP_OBJ_NEW_SMALL_INT(CTR) }, {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 = { STATIC const mp_obj_type_t mod_trezorcrypto_AES_type = {
{ &mp_type_type }, {&mp_type_type},
.name = MP_QSTR_AES, .name = MP_QSTR_AES,
.make_new = mod_trezorcrypto_AES_make_new, .make_new = mod_trezorcrypto_AES_make_new,
.locals_dict = (void*)&mod_trezorcrypto_AES_locals_dict, .locals_dict = (void *)&mod_trezorcrypto_AES_locals_dict,
}; };

View File

@ -54,19 +54,35 @@ STATIC const mp_obj_type_t mod_trezorcrypto_HDNode_type;
/// curve_name: str = None) -> None: /// 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 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[] = { 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_depth,
{ MP_QSTR_fingerprint, MP_ARG_REQUIRED | MP_ARG_KW_ONLY | MP_ARG_OBJ, {.u_obj = mp_const_none} }, MP_ARG_REQUIRED | MP_ARG_KW_ONLY | MP_ARG_OBJ,
{ MP_QSTR_child_num, MP_ARG_REQUIRED | MP_ARG_KW_ONLY | MP_ARG_OBJ, {.u_obj = mp_const_none} }, {.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_fingerprint,
{ MP_QSTR_private_key, MP_ARG_KW_ONLY | MP_ARG_OBJ, {.u_obj = mp_const_empty_bytes} }, MP_ARG_REQUIRED | MP_ARG_KW_ONLY | MP_ARG_OBJ,
{ MP_QSTR_public_key, MP_ARG_KW_ONLY | MP_ARG_OBJ, {.u_obj = mp_const_empty_bytes} }, {.u_obj = mp_const_none}},
{ MP_QSTR_curve_name, MP_ARG_KW_ONLY | MP_ARG_OBJ, {.u_obj = mp_const_empty_bytes} }, {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_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_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 chain_code;
mp_buffer_info_t private_key; mp_buffer_info_t private_key;
@ -132,7 +148,8 @@ STATIC mp_obj_t mod_trezorcrypto_HDNode_make_new(const mp_obj_type_t *type, size
/// ''' /// '''
/// Derive a BIP0032 child node in place. /// Derive a BIP0032 child node in place.
/// ''' /// '''
STATIC mp_obj_t mod_trezorcrypto_HDNode_derive(size_t n_args, const mp_obj_t *args) { 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]); mp_obj_HDNode_t *o = MP_OBJ_TO_PTR(args[0]);
uint32_t i = trezor_obj_get_uint(args[1]); uint32_t i = trezor_obj_get_uint(args[1]);
uint32_t fp = hdnode_fingerprint(&o->hdnode); uint32_t fp = hdnode_fingerprint(&o->hdnode);
@ -142,7 +159,12 @@ STATIC mp_obj_t mod_trezorcrypto_HDNode_derive(size_t n_args, const mp_obj_t *ar
if (public) { if (public) {
res = hdnode_public_ckd(&o->hdnode, i); res = hdnode_public_ckd(&o->hdnode, i);
} else { } 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)) { 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)); memzero(&o->hdnode, sizeof(o->hdnode));
mp_raise_ValueError("Failed to derive, private key not set"); mp_raise_ValueError("Failed to derive, private key not set");
} }
@ -156,20 +178,27 @@ STATIC mp_obj_t mod_trezorcrypto_HDNode_derive(size_t n_args, const mp_obj_t *ar
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: /// def derive_cardano(self, index: int) -> None:
/// ''' /// '''
/// Derive a BIP0032 child node in place using Cardano algorithm. /// 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) { 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); mp_obj_HDNode_t *o = MP_OBJ_TO_PTR(self);
uint32_t i = mp_obj_get_int_truncated(index); uint32_t i = mp_obj_get_int_truncated(index);
uint32_t fp = hdnode_fingerprint(&o->hdnode); uint32_t fp = hdnode_fingerprint(&o->hdnode);
int res; int res;
// same as in derive // 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)) { 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)); memzero(&o->hdnode, sizeof(o->hdnode));
mp_raise_ValueError("Failed to derive, private key not set"); mp_raise_ValueError("Failed to derive, private key not set");
} }
@ -183,13 +212,16 @@ STATIC mp_obj_t mod_trezorcrypto_HDNode_derive_cardano(mp_obj_t self, mp_obj_t i
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: /// def derive_path(self, path: List[int]) -> None:
/// ''' /// '''
/// Go through a list of indexes and iteratively derive a child node in place. /// 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) { 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); mp_obj_HDNode_t *o = MP_OBJ_TO_PTR(self);
// get path objects and length // get path objects and length
@ -216,43 +248,52 @@ STATIC mp_obj_t mod_trezorcrypto_HDNode_derive_path(mp_obj_t self, mp_obj_t 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_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) { 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); mp_obj_HDNode_t *o = MP_OBJ_TO_PTR(self);
char xpub[XPUB_MAXLEN] = {0}; char xpub[XPUB_MAXLEN] = {0};
int written; int written;
if (use_public) { if (use_public) {
hdnode_fill_public_key(&o->hdnode); hdnode_fill_public_key(&o->hdnode);
written = hdnode_serialize_public(&o->hdnode, o->fingerprint, version, xpub, XPUB_MAXLEN); written = hdnode_serialize_public(&o->hdnode, o->fingerprint, version, xpub,
XPUB_MAXLEN);
} else { } else {
written = hdnode_serialize_private(&o->hdnode, o->fingerprint, version, xpub, XPUB_MAXLEN); written = hdnode_serialize_private(&o->hdnode, o->fingerprint, version,
xpub, XPUB_MAXLEN);
} }
if (written <= 0) { if (written <= 0) {
mp_raise_ValueError("Failed to serialize"); 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 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: /// def serialize_public(self, version: int) -> str:
/// ''' /// '''
/// Serialize the public info from HD node to base58 string. /// 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) { 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); uint32_t ver = trezor_obj_get_uint(version);
return serialize_public_private(self, true, ver); 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: /// def serialize_private(self, version: int) -> str:
/// ''' /// '''
/// Serialize the private info HD node to base58 string. /// 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) { 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); uint32_t ver = trezor_obj_get_uint(version);
return serialize_public_private(self, false, ver); 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: /// def clone(self) -> HDNode:
/// ''' /// '''
@ -266,7 +307,8 @@ STATIC mp_obj_t mod_trezorcrypto_HDNode_clone(mp_obj_t self) {
copy->fingerprint = o->fingerprint; copy->fingerprint = o->fingerprint;
return MP_OBJ_FROM_PTR(copy); 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: /// def depth(self) -> int:
/// ''' /// '''
@ -276,7 +318,8 @@ STATIC mp_obj_t mod_trezorcrypto_HDNode_depth(mp_obj_t self) {
mp_obj_HDNode_t *o = MP_OBJ_TO_PTR(self); mp_obj_HDNode_t *o = MP_OBJ_TO_PTR(self);
return mp_obj_new_int_from_uint(o->hdnode.depth); 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: /// def fingerprint(self) -> int:
/// ''' /// '''
@ -286,7 +329,8 @@ STATIC mp_obj_t mod_trezorcrypto_HDNode_fingerprint(mp_obj_t self) {
mp_obj_HDNode_t *o = MP_OBJ_TO_PTR(self); mp_obj_HDNode_t *o = MP_OBJ_TO_PTR(self);
return mp_obj_new_int_from_uint(o->fingerprint); 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: /// def child_num(self) -> int:
/// ''' /// '''
@ -296,7 +340,8 @@ STATIC mp_obj_t mod_trezorcrypto_HDNode_child_num(mp_obj_t self) {
mp_obj_HDNode_t *o = MP_OBJ_TO_PTR(self); mp_obj_HDNode_t *o = MP_OBJ_TO_PTR(self);
return mp_obj_new_int_from_uint(o->hdnode.child_num); 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: /// def chain_code(self) -> bytes:
/// ''' /// '''
@ -306,7 +351,8 @@ STATIC mp_obj_t mod_trezorcrypto_HDNode_chain_code(mp_obj_t self) {
mp_obj_HDNode_t *o = MP_OBJ_TO_PTR(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)); 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: /// def private_key(self) -> bytes:
/// ''' /// '''
@ -316,7 +362,8 @@ STATIC mp_obj_t mod_trezorcrypto_HDNode_private_key(mp_obj_t self) {
mp_obj_HDNode_t *o = MP_OBJ_TO_PTR(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)); 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: /// def private_key_ext(self) -> bytes:
/// ''' /// '''
@ -324,9 +371,11 @@ STATIC MP_DEFINE_CONST_FUN_OBJ_1(mod_trezorcrypto_HDNode_private_key_obj, mod_tr
/// ''' /// '''
STATIC mp_obj_t mod_trezorcrypto_HDNode_private_key_ext(mp_obj_t self) { STATIC mp_obj_t mod_trezorcrypto_HDNode_private_key_ext(mp_obj_t self) {
mp_obj_HDNode_t *o = MP_OBJ_TO_PTR(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)); 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: /// def public_key(self) -> bytes:
/// ''' /// '''
@ -337,28 +386,33 @@ STATIC mp_obj_t mod_trezorcrypto_HDNode_public_key(mp_obj_t self) {
hdnode_fill_public_key(&o->hdnode); hdnode_fill_public_key(&o->hdnode);
return mp_obj_new_bytes(o->hdnode.public_key, sizeof(o->hdnode.public_key)); 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: /// def address(self, version: int) -> str:
/// ''' /// '''
/// Compute a base58-encoded address string from the HD node. /// 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) { 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); 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}; char address[ADDRESS_MAXLEN] = {0};
hdnode_get_address(&o->hdnode, v, address, ADDRESS_MAXLEN); hdnode_get_address(&o->hdnode, v, address, ADDRESS_MAXLEN);
return mp_obj_new_str_copy(&mp_type_str, (const uint8_t *)address, strlen(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_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: /// def nem_address(self, network: int) -> str:
/// ''' /// '''
/// Compute a NEM address string from the HD node. /// 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) { 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); 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);
@ -367,15 +421,19 @@ STATIC mp_obj_t mod_trezorcrypto_HDNode_nem_address(mp_obj_t self, mp_obj_t netw
if (!hdnode_get_nem_address(&o->hdnode, n, address)) { if (!hdnode_get_nem_address(&o->hdnode, n, address)) {
mp_raise_ValueError("Failed to compute a NEM 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)); 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 /// 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) { 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_obj_HDNode_t *o = MP_OBJ_TO_PTR(args[0]);
mp_buffer_info_t transfer_pk; mp_buffer_info_t transfer_pk;
@ -402,12 +460,16 @@ STATIC mp_obj_t mod_trezorcrypto_HDNode_nem_encrypt(size_t n_args, const mp_obj_
vstr_t vstr; vstr_t vstr;
vstr_init_len(&vstr, NEM_ENCRYPTED_SIZE(payload.len)); 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)) { 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"); mp_raise_ValueError("HDNode nem encrypt failed");
} }
return mp_obj_new_str_from_vstr(&mp_type_bytes, &vstr); 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: /// def ethereum_pubkeyhash(self) -> bytes:
/// ''' /// '''
@ -420,7 +482,9 @@ STATIC mp_obj_t mod_trezorcrypto_HDNode_ethereum_pubkeyhash(mp_obj_t self) {
hdnode_get_ethereum_pubkeyhash(&o->hdnode, pkh); hdnode_get_ethereum_pubkeyhash(&o->hdnode, pkh);
return mp_obj_new_bytes(pkh, sizeof(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) { STATIC mp_obj_t mod_trezorcrypto_HDNode___del__(mp_obj_t self) {
mp_obj_HDNode_t *o = MP_OBJ_TO_PTR(self); mp_obj_HDNode_t *o = MP_OBJ_TO_PTR(self);
@ -428,43 +492,66 @@ STATIC mp_obj_t mod_trezorcrypto_HDNode___del__(mp_obj_t self) {
memzero(&o->hdnode, sizeof(o->hdnode)); memzero(&o->hdnode, sizeof(o->hdnode));
return mp_const_none; 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[] = { 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___del__),
{ MP_ROM_QSTR(MP_QSTR_derive), MP_ROM_PTR(&mod_trezorcrypto_HDNode_derive_obj) }, MP_ROM_PTR(&mod_trezorcrypto_HDNode___del___obj)},
{ MP_ROM_QSTR(MP_QSTR_derive_cardano), MP_ROM_PTR(&mod_trezorcrypto_HDNode_derive_cardano_obj) }, {MP_ROM_QSTR(MP_QSTR_derive),
{ MP_ROM_QSTR(MP_QSTR_derive_path), MP_ROM_PTR(&mod_trezorcrypto_HDNode_derive_path_obj) }, MP_ROM_PTR(&mod_trezorcrypto_HDNode_derive_obj)},
{ MP_ROM_QSTR(MP_QSTR_serialize_private), MP_ROM_PTR(&mod_trezorcrypto_HDNode_serialize_private_obj) }, {MP_ROM_QSTR(MP_QSTR_derive_cardano),
{ MP_ROM_QSTR(MP_QSTR_serialize_public), MP_ROM_PTR(&mod_trezorcrypto_HDNode_serialize_public_obj) }, 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_clone),
{ MP_ROM_QSTR(MP_QSTR_depth), MP_ROM_PTR(&mod_trezorcrypto_HDNode_depth_obj) }, MP_ROM_PTR(&mod_trezorcrypto_HDNode_clone_obj)},
{ MP_ROM_QSTR(MP_QSTR_fingerprint), MP_ROM_PTR(&mod_trezorcrypto_HDNode_fingerprint_obj) }, {MP_ROM_QSTR(MP_QSTR_depth),
{ MP_ROM_QSTR(MP_QSTR_child_num), MP_ROM_PTR(&mod_trezorcrypto_HDNode_child_num_obj) }, MP_ROM_PTR(&mod_trezorcrypto_HDNode_depth_obj)},
{ MP_ROM_QSTR(MP_QSTR_chain_code), MP_ROM_PTR(&mod_trezorcrypto_HDNode_chain_code_obj) }, {MP_ROM_QSTR(MP_QSTR_fingerprint),
{ MP_ROM_QSTR(MP_QSTR_private_key), MP_ROM_PTR(&mod_trezorcrypto_HDNode_private_key_obj) }, MP_ROM_PTR(&mod_trezorcrypto_HDNode_fingerprint_obj)},
{ MP_ROM_QSTR(MP_QSTR_private_key_ext), MP_ROM_PTR(&mod_trezorcrypto_HDNode_private_key_ext_obj) }, {MP_ROM_QSTR(MP_QSTR_child_num),
{ MP_ROM_QSTR(MP_QSTR_public_key), MP_ROM_PTR(&mod_trezorcrypto_HDNode_public_key_obj) }, MP_ROM_PTR(&mod_trezorcrypto_HDNode_child_num_obj)},
{ MP_ROM_QSTR(MP_QSTR_address), MP_ROM_PTR(&mod_trezorcrypto_HDNode_address_obj) }, {MP_ROM_QSTR(MP_QSTR_chain_code),
{ MP_ROM_QSTR(MP_QSTR_nem_address), MP_ROM_PTR(&mod_trezorcrypto_HDNode_nem_address_obj) }, MP_ROM_PTR(&mod_trezorcrypto_HDNode_chain_code_obj)},
{ MP_ROM_QSTR(MP_QSTR_nem_encrypt), MP_ROM_PTR(&mod_trezorcrypto_HDNode_nem_encrypt_obj) }, {MP_ROM_QSTR(MP_QSTR_private_key),
{ MP_ROM_QSTR(MP_QSTR_ethereum_pubkeyhash), MP_ROM_PTR(&mod_trezorcrypto_HDNode_ethereum_pubkeyhash_obj) }, 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 = { STATIC const mp_obj_type_t mod_trezorcrypto_HDNode_type = {
{ &mp_type_type }, {&mp_type_type},
.name = MP_QSTR_HDNode, .name = MP_QSTR_HDNode,
.make_new = mod_trezorcrypto_HDNode_make_new, .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. /// 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) { 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_buffer_info_t valueb;
mp_get_buffer_raise(value, &valueb, MP_BUFFER_READ); mp_get_buffer_raise(value, &valueb, MP_BUFFER_READ);
if (valueb.len == 0) { if (valueb.len == 0) {
@ -474,7 +561,8 @@ STATIC mp_obj_t mod_trezorcrypto_bip32_deserialize(mp_obj_t value, mp_obj_t vers
uint32_t vpriv = trezor_obj_get_uint(version_private); uint32_t vpriv = trezor_obj_get_uint(version_private);
HDNode hdnode; HDNode hdnode;
uint32_t fingerprint; uint32_t fingerprint;
if (hdnode_deserialize(valueb.buf, vpub, vpriv, SECP256K1_NAME, &hdnode, &fingerprint) < 0) { if (hdnode_deserialize(valueb.buf, vpub, vpriv, SECP256K1_NAME, &hdnode,
&fingerprint) < 0) {
mp_raise_ValueError("Failed to deserialize"); mp_raise_ValueError("Failed to deserialize");
} }
@ -484,13 +572,15 @@ STATIC mp_obj_t mod_trezorcrypto_bip32_deserialize(mp_obj_t value, mp_obj_t vers
o->fingerprint = fingerprint; o->fingerprint = fingerprint;
return MP_OBJ_FROM_PTR(o); 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: /// def from_seed(seed: bytes, curve_name: str) -> HDNode:
/// ''' /// '''
/// Construct a BIP0032 HD node from a BIP0039 seed value. /// 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) { STATIC mp_obj_t mod_trezorcrypto_bip32_from_seed(mp_obj_t seed,
mp_obj_t curve_name) {
mp_buffer_info_t seedb; mp_buffer_info_t seedb;
mp_get_buffer_raise(seed, &seedb, MP_BUFFER_READ); mp_get_buffer_raise(seed, &seedb, MP_BUFFER_READ);
if (seedb.len == 0) { if (seedb.len == 0) {
@ -511,13 +601,15 @@ STATIC mp_obj_t mod_trezorcrypto_bip32_from_seed(mp_obj_t seed, mp_obj_t curve_n
o->fingerprint = 0; o->fingerprint = 0;
return MP_OBJ_FROM_PTR(o); 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: /// def from_mnemonic_cardano(mnemonic: str, passphrase: str) -> bytes:
/// ''' /// '''
/// Convert mnemonic to hdnode /// Convert mnemonic to hdnode
/// ''' /// '''
STATIC mp_obj_t mod_trezorcrypto_bip32_from_mnemonic_cardano(mp_obj_t mnemonic, mp_obj_t passphrase) { 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_buffer_info_t mnemo, phrase;
mp_get_buffer_raise(mnemonic, &mnemo, MP_BUFFER_READ); mp_get_buffer_raise(mnemonic, &mnemo, MP_BUFFER_READ);
mp_get_buffer_raise(passphrase, &phrase, MP_BUFFER_READ); mp_get_buffer_raise(passphrase, &phrase, MP_BUFFER_READ);
@ -532,12 +624,14 @@ STATIC mp_obj_t mod_trezorcrypto_bip32_from_mnemonic_cardano(mp_obj_t mnemonic,
mp_raise_ValueError("Invalid mnemonic"); mp_raise_ValueError("Invalid mnemonic");
} }
const int res = hdnode_from_seed_cardano((const uint8_t *)ppassphrase, phrase.len, entropy, entropy_len / 8, &hdnode); const int res =
hdnode_from_seed_cardano((const uint8_t *)ppassphrase, phrase.len,
entropy, entropy_len / 8, &hdnode);
if (!res) { if (!res) {
mp_raise_ValueError("Secret key generation from mnemonic is looping forever"); mp_raise_ValueError(
} else "Secret key generation from mnemonic is looping forever");
if (res == -1) { } else if (res == -1) {
mp_raise_ValueError("Invalid mnemonic"); mp_raise_ValueError("Invalid mnemonic");
} }
@ -548,18 +642,24 @@ STATIC mp_obj_t mod_trezorcrypto_bip32_from_mnemonic_cardano(mp_obj_t mnemonic,
return MP_OBJ_FROM_PTR(o); 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[] = { 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___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_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_deserialize),
{ MP_ROM_QSTR(MP_QSTR_from_seed), MP_ROM_PTR(&mod_trezorcrypto_bip32_from_seed_obj) }, MP_ROM_PTR(&mod_trezorcrypto_bip32_deserialize_obj)},
{ MP_ROM_QSTR(MP_QSTR_from_mnemonic_cardano), MP_ROM_PTR(&mod_trezorcrypto_bip32_from_mnemonic_cardano_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 = { STATIC const mp_obj_module_t mod_trezorcrypto_bip32_module = {
.base = { &mp_type_module }, .base = {&mp_type_module},
.globals = (mp_obj_dict_t*)&mod_trezorcrypto_bip32_globals, .globals = (mp_obj_dict_t *)&mod_trezorcrypto_bip32_globals,
}; };

View File

@ -17,8 +17,8 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>. * along with this program. If not, see <http://www.gnu.org/licenses/>.
*/ */
#include "py/runtime.h"
#include "py/objstr.h" #include "py/objstr.h"
#include "py/runtime.h"
#include "bip39.h" #include "bip39.h"
@ -28,29 +28,29 @@
/// ''' /// '''
/// Return the first word from the wordlist starting with prefix. /// Return the first word from the wordlist starting with prefix.
/// ''' /// '''
STATIC mp_obj_t mod_trezorcrypto_bip39_find_word(mp_obj_t prefix) STATIC mp_obj_t mod_trezorcrypto_bip39_find_word(mp_obj_t prefix) {
{
mp_buffer_info_t pfx; mp_buffer_info_t pfx;
mp_get_buffer_raise(prefix, &pfx, MP_BUFFER_READ); mp_get_buffer_raise(prefix, &pfx, MP_BUFFER_READ);
if (pfx.len == 0) { if (pfx.len == 0) {
return mp_const_none; return mp_const_none;
} }
for (const char * const *w = mnemonic_wordlist(); *w != 0; w++) { for (const char *const *w = mnemonic_wordlist(); *w != 0; w++) {
if (strncmp(*w, pfx.buf, pfx.len) == 0) { if (strncmp(*w, pfx.buf, pfx.len) == 0) {
return mp_obj_new_str(*w, strlen(*w)); return mp_obj_new_str(*w, strlen(*w));
} }
} }
return mp_const_none; 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: /// def complete_word(prefix: str) -> int:
/// ''' /// '''
/// Return possible 1-letter suffixes for given word prefix. /// 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) STATIC mp_obj_t mod_trezorcrypto_bip39_complete_word(mp_obj_t prefix) {
{
mp_buffer_info_t pfx; mp_buffer_info_t pfx;
mp_get_buffer_raise(prefix, &pfx, MP_BUFFER_READ); mp_get_buffer_raise(prefix, &pfx, MP_BUFFER_READ);
if (pfx.len == 0) { if (pfx.len == 0) {
@ -69,7 +69,8 @@ STATIC mp_obj_t mod_trezorcrypto_bip39_complete_word(mp_obj_t prefix)
} }
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: /// def generate(strength: int) -> str:
/// ''' /// '''
@ -78,14 +79,18 @@ STATIC MP_DEFINE_CONST_FUN_OBJ_1(mod_trezorcrypto_bip39_complete_word_obj, mod_t
STATIC mp_obj_t mod_trezorcrypto_bip39_generate(mp_obj_t strength) { STATIC mp_obj_t mod_trezorcrypto_bip39_generate(mp_obj_t strength) {
int bits = mp_obj_get_int(strength); int bits = mp_obj_get_int(strength);
if (bits % 32 || bits < 128 || bits > 256) { if (bits % 32 || bits < 128 || bits > 256) {
mp_raise_ValueError("Invalid bit strength (only 128, 160, 192, 224 and 256 values are allowed)"); mp_raise_ValueError(
"Invalid bit strength (only 128, 160, 192, 224 and 256 values are "
"allowed)");
} }
const char *mnemo = mnemonic_generate(bits); const char *mnemo = mnemonic_generate(bits);
mp_obj_t res = mp_obj_new_str_copy(&mp_type_str, (const uint8_t *)mnemo, strlen(mnemo)); mp_obj_t res =
mp_obj_new_str_copy(&mp_type_str, (const uint8_t *)mnemo, strlen(mnemo));
mnemonic_clear(); mnemonic_clear();
return res; 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: /// def from_data(data: bytes) -> str:
/// ''' /// '''
@ -95,14 +100,17 @@ STATIC mp_obj_t mod_trezorcrypto_bip39_from_data(mp_obj_t data) {
mp_buffer_info_t bin; mp_buffer_info_t bin;
mp_get_buffer_raise(data, &bin, MP_BUFFER_READ); mp_get_buffer_raise(data, &bin, MP_BUFFER_READ);
if (bin.len % 4 || bin.len < 16 || bin.len > 32) { 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)"); 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); 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)); mp_obj_t res =
mp_obj_new_str_copy(&mp_type_str, (const uint8_t *)mnemo, strlen(mnemo));
mnemonic_clear(); mnemonic_clear();
return res; 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: /// def check(mnemonic: str) -> bool:
/// ''' /// '''
@ -111,23 +119,28 @@ STATIC MP_DEFINE_CONST_FUN_OBJ_1(mod_trezorcrypto_bip39_from_data_obj, mod_trezo
STATIC mp_obj_t mod_trezorcrypto_bip39_check(mp_obj_t mnemonic) { STATIC mp_obj_t mod_trezorcrypto_bip39_check(mp_obj_t mnemonic) {
mp_buffer_info_t text; mp_buffer_info_t text;
mp_get_buffer_raise(mnemonic, &text, MP_BUFFER_READ); mp_get_buffer_raise(mnemonic, &text, MP_BUFFER_READ);
return (text.len > 0 && mnemonic_check(text.buf)) ? mp_const_true : mp_const_false; 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 mp_obj_t ui_wait_callback = mp_const_none;
STATIC void wrapped_ui_wait_callback(uint32_t current, uint32_t total) { STATIC void wrapped_ui_wait_callback(uint32_t current, uint32_t total) {
if (mp_obj_is_callable(ui_wait_callback)) { 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)); 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. /// Generate seed from mnemonic and passphrase.
/// ''' /// '''
STATIC mp_obj_t mod_trezorcrypto_bip39_seed(size_t n_args, const mp_obj_t *args) { 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 mnemo;
mp_buffer_info_t phrase; mp_buffer_info_t phrase;
mp_get_buffer_raise(args[0], &mnemo, MP_BUFFER_READ); mp_get_buffer_raise(args[0], &mnemo, MP_BUFFER_READ);
@ -146,20 +159,26 @@ STATIC mp_obj_t mod_trezorcrypto_bip39_seed(size_t n_args, const mp_obj_t *args)
} }
return mp_obj_new_bytes(seed, sizeof(seed)); 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[] = { 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___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_find_word),
{ MP_ROM_QSTR(MP_QSTR_complete_word), MP_ROM_PTR(&mod_trezorcrypto_bip39_complete_word_obj) }, MP_ROM_PTR(&mod_trezorcrypto_bip39_find_word_obj)},
{ MP_ROM_QSTR(MP_QSTR_generate), MP_ROM_PTR(&mod_trezorcrypto_bip39_generate_obj) }, {MP_ROM_QSTR(MP_QSTR_complete_word),
{ MP_ROM_QSTR(MP_QSTR_from_data), MP_ROM_PTR(&mod_trezorcrypto_bip39_from_data_obj) }, MP_ROM_PTR(&mod_trezorcrypto_bip39_complete_word_obj)},
{ MP_ROM_QSTR(MP_QSTR_check), MP_ROM_PTR(&mod_trezorcrypto_bip39_check_obj) }, {MP_ROM_QSTR(MP_QSTR_generate),
{ MP_ROM_QSTR(MP_QSTR_seed), MP_ROM_PTR(&mod_trezorcrypto_bip39_seed_obj) }, 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 = { STATIC const mp_obj_module_t mod_trezorcrypto_bip39_module = {
.base = { &mp_type_module }, .base = {&mp_type_module},
.globals = (mp_obj_dict_t*)&mod_trezorcrypto_bip39_globals, .globals = (mp_obj_dict_t *)&mod_trezorcrypto_bip39_globals,
}; };

View File

@ -39,7 +39,9 @@ STATIC mp_obj_t mod_trezorcrypto_Blake256_update(mp_obj_t self, mp_obj_t data);
/// ''' /// '''
/// Creates a hash context object. /// 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) { 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_arg_check_num(n_args, n_kw, 0, 1, false);
mp_obj_Blake256_t *o = m_new_obj(mp_obj_Blake256_t); mp_obj_Blake256_t *o = m_new_obj(mp_obj_Blake256_t);
o->base.type = type; o->base.type = type;
@ -64,7 +66,8 @@ STATIC mp_obj_t mod_trezorcrypto_Blake256_update(mp_obj_t self, mp_obj_t data) {
} }
return mp_const_none; 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: /// def digest(self) -> bytes:
/// ''' /// '''
@ -79,27 +82,35 @@ STATIC mp_obj_t mod_trezorcrypto_Blake256_digest(mp_obj_t self) {
memzero(&ctx, sizeof(BLAKE256_CTX)); memzero(&ctx, sizeof(BLAKE256_CTX));
return mp_obj_new_bytes(hash, sizeof(hash)); 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) { STATIC mp_obj_t mod_trezorcrypto_Blake256___del__(mp_obj_t self) {
mp_obj_Blake256_t *o = MP_OBJ_TO_PTR(self); mp_obj_Blake256_t *o = MP_OBJ_TO_PTR(self);
memzero(&(o->ctx), sizeof(BLAKE256_CTX)); memzero(&(o->ctx), sizeof(BLAKE256_CTX));
return mp_const_none; 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[] = { 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_update),
{ MP_ROM_QSTR(MP_QSTR_digest), MP_ROM_PTR(&mod_trezorcrypto_Blake256_digest_obj) }, MP_ROM_PTR(&mod_trezorcrypto_Blake256_update_obj)},
{ MP_ROM_QSTR(MP_QSTR___del__), MP_ROM_PTR(&mod_trezorcrypto_Blake256___del___obj) }, {MP_ROM_QSTR(MP_QSTR_digest),
{ MP_ROM_QSTR(MP_QSTR_block_size), MP_OBJ_NEW_SMALL_INT(BLAKE256_BLOCK_LENGTH) }, MP_ROM_PTR(&mod_trezorcrypto_Blake256_digest_obj)},
{ MP_ROM_QSTR(MP_QSTR_digest_size), MP_OBJ_NEW_SMALL_INT(BLAKE256_DIGEST_LENGTH) }, {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 = { STATIC const mp_obj_type_t mod_trezorcrypto_Blake256_type = {
{ &mp_type_type }, {&mp_type_type},
.name = MP_QSTR_Blake256, .name = MP_QSTR_Blake256,
.make_new = mod_trezorcrypto_Blake256_make_new, .make_new = mod_trezorcrypto_Blake256_make_new,
.locals_dict = (void*)&mod_trezorcrypto_Blake256_locals_dict, .locals_dict = (void *)&mod_trezorcrypto_Blake256_locals_dict,
}; };

View File

@ -37,31 +37,45 @@ typedef struct _mp_obj_Blake2b_t {
STATIC mp_obj_t mod_trezorcrypto_Blake2b_update(mp_obj_t self, mp_obj_t data); 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. /// 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 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[] = { STATIC const mp_arg_t allowed_args[] = {
{ MP_QSTR_data, MP_ARG_OBJ, {.u_obj = mp_const_empty_bytes} }, {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_outlen,
{ MP_QSTR_key, MP_ARG_KW_ONLY | MP_ARG_OBJ, {.u_obj = mp_const_empty_bytes} }, MP_ARG_KW_ONLY | MP_ARG_INT,
{ MP_QSTR_personal, MP_ARG_KW_ONLY | MP_ARG_OBJ, {.u_obj = mp_const_empty_bytes} }, {.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_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_arg_parse_all_kw_array(n_args, n_kw, args, MP_ARRAY_SIZE(allowed_args),
allowed_args, vals);
size_t data_len; size_t data_len;
const uint8_t *data = (const uint8_t *)mp_obj_str_get_data(vals[0].u_obj, &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; const mp_int_t outlen = vals[1].u_int;
size_t key_len; size_t key_len;
const uint8_t *key = (const uint8_t *)mp_obj_str_get_data(vals[2].u_obj, &key_len); const uint8_t *key =
(const uint8_t *)mp_obj_str_get_data(vals[2].u_obj, &key_len);
size_t personal_len; size_t personal_len;
const uint8_t *personal = (const uint8_t *)mp_obj_str_get_data(vals[3].u_obj, &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) { if (key_len > 0 && personal_len > 0) {
mp_raise_ValueError("Invalid Blake2b parameters: cannot use key and personal at the same time"); 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); mp_obj_Blake2b_t *o = m_new_obj(mp_obj_Blake2b_t);
@ -101,7 +115,8 @@ STATIC mp_obj_t mod_trezorcrypto_Blake2b_update(mp_obj_t self, mp_obj_t data) {
} }
return mp_const_none; 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: /// def digest(self) -> bytes:
/// ''' /// '''
@ -116,27 +131,35 @@ STATIC mp_obj_t mod_trezorcrypto_Blake2b_digest(mp_obj_t self) {
memzero(&ctx, sizeof(BLAKE2B_CTX)); memzero(&ctx, sizeof(BLAKE2B_CTX));
return mp_obj_new_bytes(out, o->ctx.outlen); 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) { STATIC mp_obj_t mod_trezorcrypto_Blake2b___del__(mp_obj_t self) {
mp_obj_Blake2b_t *o = MP_OBJ_TO_PTR(self); mp_obj_Blake2b_t *o = MP_OBJ_TO_PTR(self);
memzero(&(o->ctx), sizeof(BLAKE2B_CTX)); memzero(&(o->ctx), sizeof(BLAKE2B_CTX));
return mp_const_none; 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[] = { 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_update),
{ MP_ROM_QSTR(MP_QSTR_digest), MP_ROM_PTR(&mod_trezorcrypto_Blake2b_digest_obj) }, MP_ROM_PTR(&mod_trezorcrypto_Blake2b_update_obj)},
{ MP_ROM_QSTR(MP_QSTR___del__), MP_ROM_PTR(&mod_trezorcrypto_Blake2b___del___obj) }, {MP_ROM_QSTR(MP_QSTR_digest),
{ MP_ROM_QSTR(MP_QSTR_block_size), MP_OBJ_NEW_SMALL_INT(BLAKE2B_BLOCK_LENGTH) }, MP_ROM_PTR(&mod_trezorcrypto_Blake2b_digest_obj)},
{ MP_ROM_QSTR(MP_QSTR_digest_size), MP_OBJ_NEW_SMALL_INT(BLAKE2B_DIGEST_LENGTH) }, {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 = { STATIC const mp_obj_type_t mod_trezorcrypto_Blake2b_type = {
{ &mp_type_type }, {&mp_type_type},
.name = MP_QSTR_Blake2b, .name = MP_QSTR_Blake2b,
.make_new = mod_trezorcrypto_Blake2b_make_new, .make_new = mod_trezorcrypto_Blake2b_make_new,
.locals_dict = (void*)&mod_trezorcrypto_Blake2b_locals_dict, .locals_dict = (void *)&mod_trezorcrypto_Blake2b_locals_dict,
}; };

View File

@ -37,31 +37,45 @@ typedef struct _mp_obj_Blake2s_t {
STATIC mp_obj_t mod_trezorcrypto_Blake2s_update(mp_obj_t self, mp_obj_t data); 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. /// 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 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[] = { STATIC const mp_arg_t allowed_args[] = {
{ MP_QSTR_data, MP_ARG_OBJ, {.u_obj = mp_const_empty_bytes} }, {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_outlen,
{ MP_QSTR_key, MP_ARG_KW_ONLY | MP_ARG_OBJ, {.u_obj = mp_const_empty_bytes} }, MP_ARG_KW_ONLY | MP_ARG_INT,
{ MP_QSTR_personal, MP_ARG_KW_ONLY | MP_ARG_OBJ, {.u_obj = mp_const_empty_bytes} }, {.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_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_arg_parse_all_kw_array(n_args, n_kw, args, MP_ARRAY_SIZE(allowed_args),
allowed_args, vals);
size_t data_len; size_t data_len;
const uint8_t *data = (const uint8_t *)mp_obj_str_get_data(vals[0].u_obj, &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; const mp_int_t outlen = vals[1].u_int;
size_t key_len; size_t key_len;
const uint8_t *key = (const uint8_t *)mp_obj_str_get_data(vals[2].u_obj, &key_len); const uint8_t *key =
(const uint8_t *)mp_obj_str_get_data(vals[2].u_obj, &key_len);
size_t personal_len; size_t personal_len;
const uint8_t *personal = (const uint8_t *)mp_obj_str_get_data(vals[3].u_obj, &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) { if (key_len > 0 && personal_len > 0) {
mp_raise_ValueError("Invalid Blake2s parameters: cannot use key and personal at the same time"); 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); mp_obj_Blake2s_t *o = m_new_obj(mp_obj_Blake2s_t);
@ -101,7 +115,8 @@ STATIC mp_obj_t mod_trezorcrypto_Blake2s_update(mp_obj_t self, mp_obj_t data) {
} }
return mp_const_none; 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: /// def digest(self) -> bytes:
/// ''' /// '''
@ -116,27 +131,35 @@ STATIC mp_obj_t mod_trezorcrypto_Blake2s_digest(mp_obj_t self) {
memzero(&ctx, sizeof(BLAKE2S_CTX)); memzero(&ctx, sizeof(BLAKE2S_CTX));
return mp_obj_new_bytes(out, o->ctx.outlen); 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) { STATIC mp_obj_t mod_trezorcrypto_Blake2s___del__(mp_obj_t self) {
mp_obj_Blake2s_t *o = MP_OBJ_TO_PTR(self); mp_obj_Blake2s_t *o = MP_OBJ_TO_PTR(self);
memzero(&(o->ctx), sizeof(BLAKE2S_CTX)); memzero(&(o->ctx), sizeof(BLAKE2S_CTX));
return mp_const_none; 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[] = { 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_update),
{ MP_ROM_QSTR(MP_QSTR_digest), MP_ROM_PTR(&mod_trezorcrypto_Blake2s_digest_obj) }, MP_ROM_PTR(&mod_trezorcrypto_Blake2s_update_obj)},
{ MP_ROM_QSTR(MP_QSTR___del__), MP_ROM_PTR(&mod_trezorcrypto_Blake2s___del___obj) }, {MP_ROM_QSTR(MP_QSTR_digest),
{ MP_ROM_QSTR(MP_QSTR_block_size), MP_OBJ_NEW_SMALL_INT(BLAKE2S_BLOCK_LENGTH) }, MP_ROM_PTR(&mod_trezorcrypto_Blake2s_digest_obj)},
{ MP_ROM_QSTR(MP_QSTR_digest_size), MP_OBJ_NEW_SMALL_INT(BLAKE2S_DIGEST_LENGTH) }, {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 = { STATIC const mp_obj_type_t mod_trezorcrypto_Blake2s_type = {
{ &mp_type_type }, {&mp_type_type},
.name = MP_QSTR_Blake2s, .name = MP_QSTR_Blake2s,
.make_new = mod_trezorcrypto_Blake2s_make_new, .make_new = mod_trezorcrypto_Blake2s_make_new,
.locals_dict = (void*)&mod_trezorcrypto_Blake2s_locals_dict, .locals_dict = (void *)&mod_trezorcrypto_Blake2s_locals_dict,
}; };

View File

@ -39,7 +39,9 @@ typedef struct _mp_obj_ChaCha20Poly1305_t {
/// Initialize the ChaCha20 + Poly1305 context for encryption or decryption /// Initialize the ChaCha20 + Poly1305 context for encryption or decryption
/// using a 32 byte key and 12 byte nonce as in the RFC 7539 style. /// 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) { 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_arg_check_num(n_args, n_kw, 2, 2, false);
mp_obj_ChaCha20Poly1305_t *o = m_new_obj(mp_obj_ChaCha20Poly1305_t); mp_obj_ChaCha20Poly1305_t *o = m_new_obj(mp_obj_ChaCha20Poly1305_t);
o->base.type = type; o->base.type = type;
@ -60,9 +62,11 @@ STATIC mp_obj_t mod_trezorcrypto_ChaCha20Poly1305_make_new(const mp_obj_type_t *
/// def encrypt(self, data: bytes) -> bytes: /// 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) { 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_obj_ChaCha20Poly1305_t *o = MP_OBJ_TO_PTR(self);
mp_buffer_info_t in; mp_buffer_info_t in;
mp_get_buffer_raise(data, &in, MP_BUFFER_READ); mp_get_buffer_raise(data, &in, MP_BUFFER_READ);
@ -72,13 +76,16 @@ STATIC mp_obj_t mod_trezorcrypto_ChaCha20Poly1305_encrypt(mp_obj_t self, mp_obj_
o->plen += in.len; o->plen += in.len;
return mp_obj_new_str_from_vstr(&mp_type_bytes, &vstr); 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: /// 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) { 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_obj_ChaCha20Poly1305_t *o = MP_OBJ_TO_PTR(self);
mp_buffer_info_t in; mp_buffer_info_t in;
mp_get_buffer_raise(data, &in, MP_BUFFER_READ); mp_get_buffer_raise(data, &in, MP_BUFFER_READ);
@ -88,7 +95,8 @@ STATIC mp_obj_t mod_trezorcrypto_ChaCha20Poly1305_decrypt(mp_obj_t self, mp_obj_
o->plen += in.len; o->plen += in.len;
return mp_obj_new_str_from_vstr(&mp_type_bytes, &vstr); 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: /// def auth(self, data: bytes) -> None:
/// ''' /// '''
@ -96,7 +104,8 @@ 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 /// style with 16 byte padding. This must only be called once and prior
/// to encryption or decryption. /// to encryption or decryption.
/// ''' /// '''
STATIC mp_obj_t mod_trezorcrypto_ChaCha20Poly1305_auth(mp_obj_t self, mp_obj_t data) { 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_obj_ChaCha20Poly1305_t *o = MP_OBJ_TO_PTR(self);
mp_buffer_info_t in; mp_buffer_info_t in;
mp_get_buffer_raise(data, &in, MP_BUFFER_READ); mp_get_buffer_raise(data, &in, MP_BUFFER_READ);
@ -104,7 +113,8 @@ STATIC mp_obj_t mod_trezorcrypto_ChaCha20Poly1305_auth(mp_obj_t self, mp_obj_t d
o->alen += in.len; o->alen += in.len;
return mp_const_none; 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: /// def finish(self) -> bytes:
/// ''' /// '''
@ -116,7 +126,8 @@ STATIC mp_obj_t mod_trezorcrypto_ChaCha20Poly1305_finish(mp_obj_t self) {
rfc7539_finish(&(o->ctx), o->alen, o->plen, out); rfc7539_finish(&(o->ctx), o->alen, o->plen, out);
return mp_obj_new_bytes(out, sizeof(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) { STATIC mp_obj_t mod_trezorcrypto_ChaCha20Poly1305___del__(mp_obj_t self) {
mp_obj_ChaCha20Poly1305_t *o = MP_OBJ_TO_PTR(self); mp_obj_ChaCha20Poly1305_t *o = MP_OBJ_TO_PTR(self);
@ -125,20 +136,29 @@ STATIC mp_obj_t mod_trezorcrypto_ChaCha20Poly1305___del__(mp_obj_t self) {
o->plen = 0; o->plen = 0;
return mp_const_none; 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[] = { STATIC const mp_rom_map_elem_t
{ MP_ROM_QSTR(MP_QSTR_encrypt), MP_ROM_PTR(&mod_trezorcrypto_ChaCha20Poly1305_encrypt_obj) }, mod_trezorcrypto_ChaCha20Poly1305_locals_dict_table[] = {
{ MP_ROM_QSTR(MP_QSTR_decrypt), MP_ROM_PTR(&mod_trezorcrypto_ChaCha20Poly1305_decrypt_obj) }, {MP_ROM_QSTR(MP_QSTR_encrypt),
{ MP_ROM_QSTR(MP_QSTR_auth), MP_ROM_PTR(&mod_trezorcrypto_ChaCha20Poly1305_auth_obj) }, MP_ROM_PTR(&mod_trezorcrypto_ChaCha20Poly1305_encrypt_obj)},
{ MP_ROM_QSTR(MP_QSTR_finish), MP_ROM_PTR(&mod_trezorcrypto_ChaCha20Poly1305_finish_obj) }, {MP_ROM_QSTR(MP_QSTR_decrypt),
{ MP_ROM_QSTR(MP_QSTR___del__), MP_ROM_PTR(&mod_trezorcrypto_ChaCha20Poly1305___del___obj) }, 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 = { STATIC const mp_obj_type_t mod_trezorcrypto_ChaCha20Poly1305_type = {
{ &mp_type_type }, {&mp_type_type},
.name = MP_QSTR_ChaCha20Poly1305, .name = MP_QSTR_ChaCha20Poly1305,
.make_new = mod_trezorcrypto_ChaCha20Poly1305_make_new, .make_new = mod_trezorcrypto_ChaCha20Poly1305_make_new,
.locals_dict = (void*)&mod_trezorcrypto_ChaCha20Poly1305_locals_dict, .locals_dict = (void *)&mod_trezorcrypto_ChaCha20Poly1305_locals_dict,
}; };

View File

@ -30,15 +30,17 @@ mp_obj_t mod_trezorcrypto_crc_crc32(size_t n_args, const mp_obj_t *args) {
crc = checksum_crc32(bufinfo.buf, bufinfo.len, crc ^ 0xffffffff); crc = checksum_crc32(bufinfo.buf, bufinfo.len, crc ^ 0xffffffff);
return mp_obj_new_int_from_uint(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[] = { 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___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_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 = { STATIC const mp_obj_module_t mod_trezorcrypto_crc_module = {
.base = { &mp_type_module }, .base = {&mp_type_module},
.globals = (mp_obj_dict_t*)&mod_trezorcrypto_crc_globals, .globals = (mp_obj_dict_t *)&mod_trezorcrypto_crc_globals,
}; };

View File

@ -38,7 +38,9 @@ STATIC mp_obj_t mod_trezorcrypto_curve25519_generate_secret() {
out[31] |= 64; out[31] |= 64;
return mp_obj_new_bytes(out, sizeof(out)); 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: /// def publickey(secret_key: bytes) -> bytes:
/// ''' /// '''
@ -54,14 +56,16 @@ STATIC mp_obj_t mod_trezorcrypto_curve25519_publickey(mp_obj_t secret_key) {
curve25519_scalarmult_basepoint(out, (const uint8_t *)sk.buf); curve25519_scalarmult_basepoint(out, (const uint8_t *)sk.buf);
return mp_obj_new_bytes(out, sizeof(out)); 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: /// def multiply(secret_key: bytes, public_key: bytes) -> bytes:
/// ''' /// '''
/// Multiplies point defined by public_key with scalar defined by secret_key. /// Multiplies point defined by public_key with scalar defined by
/// Useful for ECDH. /// secret_key. Useful for ECDH.
/// ''' /// '''
STATIC mp_obj_t mod_trezorcrypto_curve25519_multiply(mp_obj_t secret_key, mp_obj_t public_key) { 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_buffer_info_t sk, pk;
mp_get_buffer_raise(secret_key, &sk, MP_BUFFER_READ); mp_get_buffer_raise(secret_key, &sk, MP_BUFFER_READ);
mp_get_buffer_raise(public_key, &pk, MP_BUFFER_READ); mp_get_buffer_raise(public_key, &pk, MP_BUFFER_READ);
@ -75,17 +79,22 @@ STATIC mp_obj_t mod_trezorcrypto_curve25519_multiply(mp_obj_t secret_key, mp_obj
curve25519_scalarmult(out, (const uint8_t *)sk.buf, (const uint8_t *)pk.buf); curve25519_scalarmult(out, (const uint8_t *)sk.buf, (const uint8_t *)pk.buf);
return mp_obj_new_bytes(out, sizeof(out)); 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[] = { 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___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_generate_secret),
{ MP_ROM_QSTR(MP_QSTR_publickey), MP_ROM_PTR(&mod_trezorcrypto_curve25519_publickey_obj) }, MP_ROM_PTR(&mod_trezorcrypto_curve25519_generate_secret_obj)},
{ MP_ROM_QSTR(MP_QSTR_multiply), MP_ROM_PTR(&mod_trezorcrypto_curve25519_multiply_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 = { STATIC const mp_obj_module_t mod_trezorcrypto_curve25519_module = {
.base = { &mp_type_module }, .base = {&mp_type_module},
.globals = (mp_obj_dict_t*)&mod_trezorcrypto_curve25519_globals, .globals = (mp_obj_dict_t *)&mod_trezorcrypto_curve25519_globals,
}; };

View File

@ -19,8 +19,8 @@
#include "py/objstr.h" #include "py/objstr.h"
#include "ed25519-donna/ed25519.h"
#include "ed25519-donna/ed25519-keccak.h" #include "ed25519-donna/ed25519-keccak.h"
#include "ed25519-donna/ed25519.h"
#include "rand.h" #include "rand.h"
@ -39,7 +39,8 @@ STATIC mp_obj_t mod_trezorcrypto_ed25519_generate_secret() {
out[31] |= 64; out[31] |= 64;
return mp_obj_new_bytes(out, sizeof(out)); 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: /// def publickey(secret_key: bytes) -> bytes:
/// ''' /// '''
@ -52,16 +53,19 @@ STATIC mp_obj_t mod_trezorcrypto_ed25519_publickey(mp_obj_t secret_key) {
mp_raise_ValueError("Invalid length of secret key"); mp_raise_ValueError("Invalid length of secret key");
} }
uint8_t out[32]; uint8_t out[32];
ed25519_publickey(*(const ed25519_secret_key *)sk.buf, *(ed25519_public_key *)out); ed25519_publickey(*(const ed25519_secret_key *)sk.buf,
*(ed25519_public_key *)out);
return mp_obj_new_bytes(out, sizeof(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: /// def sign(secret_key: bytes, message: bytes, hasher: str='') -> bytes:
/// ''' /// '''
/// Uses secret key to produce the signature of message. /// 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) { STATIC mp_obj_t mod_trezorcrypto_ed25519_sign(size_t n_args,
const mp_obj_t *args) {
mp_buffer_info_t sk, msg; mp_buffer_info_t sk, msg;
mp_get_buffer_raise(args[0], &sk, MP_BUFFER_READ); 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[1], &msg, MP_BUFFER_READ);
@ -80,24 +84,30 @@ STATIC mp_obj_t mod_trezorcrypto_ed25519_sign(size_t n_args, const mp_obj_t *arg
// if hash_func == 'keccak': // if hash_func == 'keccak':
if (memcmp(hash_func.buf, "keccak", sizeof("keccak")) == 0) { if (memcmp(hash_func.buf, "keccak", sizeof("keccak")) == 0) {
ed25519_publickey_keccak(*(const ed25519_secret_key *)sk.buf, pk); 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); ed25519_sign_keccak(msg.buf, msg.len, *(const ed25519_secret_key *)sk.buf,
pk, *(ed25519_signature *)out);
} else { } else {
mp_raise_ValueError("Unknown hash function"); mp_raise_ValueError("Unknown hash function");
} }
} else { } else {
ed25519_publickey(*(const ed25519_secret_key *)sk.buf, pk); 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); 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. /// 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) { 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_buffer_info_t sk, skext, msg;
mp_get_buffer_raise(secret_key, &sk, MP_BUFFER_READ); mp_get_buffer_raise(secret_key, &sk, MP_BUFFER_READ);
mp_get_buffer_raise(secret_extension, &skext, MP_BUFFER_READ); mp_get_buffer_raise(secret_extension, &skext, MP_BUFFER_READ);
@ -113,19 +123,25 @@ STATIC mp_obj_t mod_trezorcrypto_ed25519_sign_ext(mp_obj_t secret_key, mp_obj_t
} }
ed25519_public_key pk; ed25519_public_key pk;
ed25519_publickey_ext(*(const ed25519_secret_key *)sk.buf, *(const ed25519_secret_key *)skext.buf, pk); ed25519_publickey_ext(*(const ed25519_secret_key *)sk.buf,
*(const ed25519_secret_key *)skext.buf, pk);
uint8_t out[64]; 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); 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)); 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: /// def verify(public_key: bytes, signature: bytes, message: bytes) -> bool:
/// ''' /// '''
/// Uses public key to verify the signature of the message. /// Uses public key to verify the signature of the message.
/// Returns True on success. /// 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) { 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_buffer_info_t pk, sig, msg;
mp_get_buffer_raise(public_key, &pk, MP_BUFFER_READ); mp_get_buffer_raise(public_key, &pk, MP_BUFFER_READ);
mp_get_buffer_raise(signature, &sig, MP_BUFFER_READ); mp_get_buffer_raise(signature, &sig, MP_BUFFER_READ);
@ -139,15 +155,21 @@ STATIC mp_obj_t mod_trezorcrypto_ed25519_verify(mp_obj_t public_key, mp_obj_t si
if (msg.len == 0) { if (msg.len == 0) {
mp_raise_ValueError("Empty data to verify"); 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; 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: /// def cosi_combine_publickeys(public_keys: List[bytes]) -> bytes:
/// ''' /// '''
/// Combines a list of public keys used in COSI cosigning scheme. /// 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) { STATIC mp_obj_t
mod_trezorcrypto_ed25519_cosi_combine_publickeys(mp_obj_t public_keys) {
size_t pklen; size_t pklen;
mp_obj_t *pkitems; mp_obj_t *pkitems;
mp_obj_get_array(public_keys, &pklen, &pkitems); mp_obj_get_array(public_keys, &pklen, &pkitems);
@ -164,18 +186,22 @@ STATIC mp_obj_t mod_trezorcrypto_ed25519_cosi_combine_publickeys(mp_obj_t public
memcpy(pks[i], buf.buf, buf.len); memcpy(pks[i], buf.buf, buf.len);
} }
uint8_t out[32]; uint8_t out[32];
if (0 != ed25519_cosi_combine_publickeys(*(ed25519_public_key *)out, pks, pklen)) { if (0 !=
ed25519_cosi_combine_publickeys(*(ed25519_public_key *)out, pks, pklen)) {
mp_raise_ValueError("Error combining public keys"); mp_raise_ValueError("Error combining public keys");
} }
return mp_obj_new_bytes(out, sizeof(out)); 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: /// def cosi_combine_signatures(R: bytes, signatures: List[bytes]) -> bytes:
/// ''' /// '''
/// Combines a list of signatures used in COSI cosigning scheme. /// 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) { STATIC mp_obj_t mod_trezorcrypto_ed25519_cosi_combine_signatures(
mp_obj_t R, mp_obj_t signatures) {
mp_buffer_info_t sigR; mp_buffer_info_t sigR;
mp_get_buffer_raise(R, &sigR, MP_BUFFER_READ); mp_get_buffer_raise(R, &sigR, MP_BUFFER_READ);
if (sigR.len != 32) { if (sigR.len != 32) {
@ -197,16 +223,22 @@ STATIC mp_obj_t mod_trezorcrypto_ed25519_cosi_combine_signatures(mp_obj_t R, mp_
memcpy(sigs[i], buf.buf, buf.len); memcpy(sigs[i], buf.buf, buf.len);
} }
uint8_t out[64]; uint8_t out[64];
ed25519_cosi_combine_signatures(*(ed25519_signature *)out, *(const ed25519_public_key *)sigR.buf, sigs, siglen); ed25519_cosi_combine_signatures(*(ed25519_signature *)out,
*(const ed25519_public_key *)sigR.buf, sigs,
siglen);
return mp_obj_new_bytes(out, sizeof(out)); 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. /// 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) { 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_buffer_info_t sk, msg, nonce, sigR, pk;
mp_get_buffer_raise(args[0], &sk, MP_BUFFER_READ); 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[1], &msg, MP_BUFFER_READ);
@ -226,25 +258,39 @@ STATIC mp_obj_t mod_trezorcrypto_ed25519_cosi_sign(size_t n_args, const mp_obj_t
mp_raise_ValueError("Invalid length of aggregated public key"); mp_raise_ValueError("Invalid length of aggregated public key");
} }
uint8_t out[32]; 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); 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)); 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[] = { 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___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_generate_secret),
{ MP_ROM_QSTR(MP_QSTR_publickey), MP_ROM_PTR(&mod_trezorcrypto_ed25519_publickey_obj) }, MP_ROM_PTR(&mod_trezorcrypto_ed25519_generate_secret_obj)},
{ MP_ROM_QSTR(MP_QSTR_sign), MP_ROM_PTR(&mod_trezorcrypto_ed25519_sign_obj) }, {MP_ROM_QSTR(MP_QSTR_publickey),
{ MP_ROM_QSTR(MP_QSTR_sign_ext), MP_ROM_PTR(&mod_trezorcrypto_ed25519_sign_ext_obj) }, MP_ROM_PTR(&mod_trezorcrypto_ed25519_publickey_obj)},
{ MP_ROM_QSTR(MP_QSTR_verify), MP_ROM_PTR(&mod_trezorcrypto_ed25519_verify_obj) }, {MP_ROM_QSTR(MP_QSTR_sign), MP_ROM_PTR(&mod_trezorcrypto_ed25519_sign_obj)},
{ MP_ROM_QSTR(MP_QSTR_cosi_combine_publickeys), MP_ROM_PTR(&mod_trezorcrypto_ed25519_cosi_combine_publickeys_obj) }, {MP_ROM_QSTR(MP_QSTR_sign_ext),
{ MP_ROM_QSTR(MP_QSTR_cosi_combine_signatures), MP_ROM_PTR(&mod_trezorcrypto_ed25519_cosi_combine_signatures_obj) }, MP_ROM_PTR(&mod_trezorcrypto_ed25519_sign_ext_obj)},
{ MP_ROM_QSTR(MP_QSTR_cosi_sign), MP_ROM_PTR(&mod_trezorcrypto_ed25519_cosi_sign_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 = { STATIC const mp_obj_module_t mod_trezorcrypto_ed25519_module = {
.base = { &mp_type_module }, .base = {&mp_type_module},
.globals = (mp_obj_dict_t*)&mod_trezorcrypto_ed25519_globals, .globals = (mp_obj_dict_t *)&mod_trezorcrypto_ed25519_globals,
}; };

View File

@ -36,13 +36,16 @@ typedef struct _mp_obj_Groestl512_t {
GROESTL512_CTX ctx; GROESTL512_CTX ctx;
} mp_obj_Groestl512_t; } 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: /// def __init__(self, data: bytes = None) -> None:
/// ''' /// '''
/// Creates a hash context object. /// 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) { 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_arg_check_num(n_args, n_kw, 0, 1, false);
mp_obj_Groestl512_t *o = m_new_obj(mp_obj_Groestl512_t); mp_obj_Groestl512_t *o = m_new_obj(mp_obj_Groestl512_t);
o->base.type = type; o->base.type = type;
@ -57,7 +60,8 @@ STATIC mp_obj_t mod_trezorcrypto_Groestl512_make_new(const mp_obj_type_t *type,
/// ''' /// '''
/// Update the hash context with hashed data. /// Update the hash context with hashed data.
/// ''' /// '''
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) {
mp_obj_Groestl512_t *o = MP_OBJ_TO_PTR(self); mp_obj_Groestl512_t *o = MP_OBJ_TO_PTR(self);
mp_buffer_info_t msg; mp_buffer_info_t msg;
mp_get_buffer_raise(data, &msg, MP_BUFFER_READ); mp_get_buffer_raise(data, &msg, MP_BUFFER_READ);
@ -66,7 +70,8 @@ STATIC mp_obj_t mod_trezorcrypto_Groestl512_update(mp_obj_t self, mp_obj_t data)
} }
return mp_const_none; 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: /// def digest(self) -> bytes:
/// ''' /// '''
@ -81,27 +86,36 @@ STATIC mp_obj_t mod_trezorcrypto_Groestl512_digest(mp_obj_t self) {
memzero(&ctx, sizeof(GROESTL512_CTX)); memzero(&ctx, sizeof(GROESTL512_CTX));
return mp_obj_new_bytes(out, sizeof(out)); 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) { STATIC mp_obj_t mod_trezorcrypto_Groestl512___del__(mp_obj_t self) {
mp_obj_Groestl512_t *o = MP_OBJ_TO_PTR(self); mp_obj_Groestl512_t *o = MP_OBJ_TO_PTR(self);
memzero(&(o->ctx), sizeof(GROESTL512_CTX)); memzero(&(o->ctx), sizeof(GROESTL512_CTX));
return mp_const_none; 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[] = { STATIC const mp_rom_map_elem_t
{ MP_ROM_QSTR(MP_QSTR_update), MP_ROM_PTR(&mod_trezorcrypto_Groestl512_update_obj) }, mod_trezorcrypto_Groestl512_locals_dict_table[] = {
{ MP_ROM_QSTR(MP_QSTR_digest), MP_ROM_PTR(&mod_trezorcrypto_Groestl512_digest_obj) }, {MP_ROM_QSTR(MP_QSTR_update),
{ MP_ROM_QSTR(MP_QSTR___del__), MP_ROM_PTR(&mod_trezorcrypto_Groestl512___del___obj) }, MP_ROM_PTR(&mod_trezorcrypto_Groestl512_update_obj)},
{ MP_ROM_QSTR(MP_QSTR_block_size), MP_OBJ_NEW_SMALL_INT(GROESTL512_BLOCK_LENGTH) }, {MP_ROM_QSTR(MP_QSTR_digest),
{ MP_ROM_QSTR(MP_QSTR_digest_size), MP_OBJ_NEW_SMALL_INT(GROESTL512_DIGEST_LENGTH) }, 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 = { STATIC const mp_obj_type_t mod_trezorcrypto_Groestl512_type = {
{ &mp_type_type }, {&mp_type_type},
.name = MP_QSTR_Groestl512, .name = MP_QSTR_Groestl512,
.make_new = mod_trezorcrypto_Groestl512_make_new, .make_new = mod_trezorcrypto_Groestl512_make_new,
.locals_dict = (void*)&mod_trezorcrypto_Groestl512_locals_dict, .locals_dict = (void *)&mod_trezorcrypto_Groestl512_locals_dict,
}; };

File diff suppressed because it is too large Load Diff

View File

@ -29,21 +29,23 @@
/// ''' /// '''
/// Validate a NEM address /// 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_buffer_info_t addr;
mp_get_buffer_raise(address, &addr, MP_BUFFER_READ); mp_get_buffer_raise(address, &addr, MP_BUFFER_READ);
uint32_t n = trezor_obj_get_uint(network); uint32_t n = trezor_obj_get_uint(network);
return mp_obj_new_bool(nem_validate_address(addr.buf, n)); 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: /// def compute_address(public_key: bytes, network: int) -> str:
/// ''' /// '''
/// Compute a NEM address from a public key /// 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) { STATIC mp_obj_t mod_trezorcrypto_nem_compute_address(mp_obj_t public_key,
mp_obj_t network) {
mp_buffer_info_t p; mp_buffer_info_t p;
mp_get_buffer_raise(public_key, &p, MP_BUFFER_READ); mp_get_buffer_raise(public_key, &p, MP_BUFFER_READ);
@ -51,21 +53,27 @@ STATIC mp_obj_t mod_trezorcrypto_nem_compute_address(mp_obj_t public_key, mp_obj
char address[NEM_ADDRESS_SIZE + 1]; // + 1 for the 0 byte char address[NEM_ADDRESS_SIZE + 1]; // + 1 for the 0 byte
if (!nem_get_address(p.buf, n, address)) { if (!nem_get_address(p.buf, n, address)) {
mp_raise_ValueError("Failed to compute a NEM address from provided public key"); 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)); 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 // objects definition
STATIC const mp_rom_map_elem_t mod_trezorcrypto_nem_globals_table[] = { 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_validate_address),
{ MP_ROM_QSTR(MP_QSTR_compute_address), MP_ROM_PTR(&mod_trezorcrypto_nem_compute_address_obj) }, 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 // module definition
STATIC const mp_obj_module_t mod_trezorcrypto_nem_module = { STATIC const mp_obj_module_t mod_trezorcrypto_nem_module = {
.base = { &mp_type_module }, .base = {&mp_type_module},
.globals = (mp_obj_dict_t*)&mod_trezorcrypto_nem_globals, .globals = (mp_obj_dict_t *)&mod_trezorcrypto_nem_globals,
}; };

View File

@ -33,19 +33,33 @@ STATIC mp_obj_t mod_trezorcrypto_nist256p1_generate_secret() {
for (;;) { for (;;) {
random_buffer(out, 32); random_buffer(out, 32);
// check whether secret > 0 && secret < curve_order // 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 ==
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; 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; break;
} }
return mp_obj_new_bytes(out, sizeof(out)); 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: /// def publickey(secret_key: bytes, compressed: bool = True) -> bytes:
/// ''' /// '''
/// Computes public key from secret key. /// Computes public key from secret key.
/// ''' /// '''
STATIC mp_obj_t mod_trezorcrypto_nist256p1_publickey(size_t n_args, const mp_obj_t *args) { STATIC mp_obj_t mod_trezorcrypto_nist256p1_publickey(size_t n_args,
const mp_obj_t *args) {
mp_buffer_info_t sk; mp_buffer_info_t sk;
mp_get_buffer_raise(args[0], &sk, MP_BUFFER_READ); mp_get_buffer_raise(args[0], &sk, MP_BUFFER_READ);
if (sk.len != 32) { if (sk.len != 32) {
@ -62,13 +76,17 @@ STATIC mp_obj_t mod_trezorcrypto_nist256p1_publickey(size_t n_args, const mp_obj
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_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. /// 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) { STATIC mp_obj_t mod_trezorcrypto_nist256p1_sign(size_t n_args,
const mp_obj_t *args) {
mp_buffer_info_t sk, dig; mp_buffer_info_t sk, dig;
mp_get_buffer_raise(args[0], &sk, MP_BUFFER_READ); mp_get_buffer_raise(args[0], &sk, MP_BUFFER_READ);
mp_get_buffer_raise(args[1], &dig, MP_BUFFER_READ); mp_get_buffer_raise(args[1], &dig, MP_BUFFER_READ);
@ -80,20 +98,25 @@ STATIC mp_obj_t mod_trezorcrypto_nist256p1_sign(size_t n_args, const mp_obj_t *a
mp_raise_ValueError("Invalid length of digest"); mp_raise_ValueError("Invalid length of digest");
} }
uint8_t out[65], pby; 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)) { 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"); mp_raise_ValueError("Signing failed");
} }
out[0] = 27 + pby + compressed * 4; out[0] = 27 + pby + compressed * 4;
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_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: /// def verify(public_key: bytes, signature: bytes, digest: bytes) -> bool:
/// ''' /// '''
/// Uses public key to verify the signature of the digest. /// Uses public key to verify the signature of the digest.
/// Returns True on success. /// 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) { 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_buffer_info_t pk, sig, dig;
mp_get_buffer_raise(public_key, &pk, MP_BUFFER_READ); mp_get_buffer_raise(public_key, &pk, MP_BUFFER_READ);
mp_get_buffer_raise(signature, &sig, MP_BUFFER_READ); mp_get_buffer_raise(signature, &sig, MP_BUFFER_READ);
@ -108,16 +131,21 @@ STATIC mp_obj_t mod_trezorcrypto_nist256p1_verify(mp_obj_t public_key, mp_obj_t
if (dig.len != 32) { if (dig.len != 32) {
mp_raise_ValueError("Invalid length of digest"); 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)); 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: /// def verify_recover(signature: bytes, digest: bytes) -> bytes:
/// ''' /// '''
/// Uses signature of the digest to verify the digest and recover the public key. /// Uses signature of the digest to verify the digest and recover the public
/// Returns public key on success, None on failure. /// 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) { STATIC mp_obj_t mod_trezorcrypto_nist256p1_verify_recover(mp_obj_t signature,
mp_obj_t digest) {
mp_buffer_info_t sig, dig; mp_buffer_info_t sig, dig;
mp_get_buffer_raise(signature, &sig, MP_BUFFER_READ); mp_get_buffer_raise(signature, &sig, MP_BUFFER_READ);
mp_get_buffer_raise(digest, &dig, MP_BUFFER_READ); mp_get_buffer_raise(digest, &dig, MP_BUFFER_READ);
@ -134,7 +162,9 @@ STATIC mp_obj_t mod_trezorcrypto_nist256p1_verify_recover(mp_obj_t signature, mp
bool compressed = (recid >= 4); bool compressed = (recid >= 4);
recid &= 3; recid &= 3;
uint8_t out[65]; 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 (0 == ecdsa_recover_pub_from_sig(&nist256p1, out,
(const uint8_t *)sig.buf + 1,
(const uint8_t *)dig.buf, recid)) {
if (compressed) { if (compressed) {
out[0] = 0x02 | (out[64] & 1); out[0] = 0x02 | (out[64] & 1);
return mp_obj_new_bytes(out, 33); return mp_obj_new_bytes(out, 33);
@ -144,14 +174,16 @@ STATIC mp_obj_t mod_trezorcrypto_nist256p1_verify_recover(mp_obj_t signature, mp
return mp_const_none; 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: /// def multiply(secret_key: bytes, public_key: bytes) -> bytes:
/// ''' /// '''
/// Multiplies point defined by public_key with scalar defined by secret_key. /// Multiplies point defined by public_key with scalar defined by
/// Useful for ECDH. /// secret_key. Useful for ECDH.
/// ''' /// '''
STATIC mp_obj_t mod_trezorcrypto_nist256p1_multiply(mp_obj_t secret_key, mp_obj_t public_key) { 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_buffer_info_t sk, pk;
mp_get_buffer_raise(secret_key, &sk, MP_BUFFER_READ); mp_get_buffer_raise(secret_key, &sk, MP_BUFFER_READ);
mp_get_buffer_raise(public_key, &pk, MP_BUFFER_READ); mp_get_buffer_raise(public_key, &pk, MP_BUFFER_READ);
@ -162,25 +194,34 @@ STATIC mp_obj_t mod_trezorcrypto_nist256p1_multiply(mp_obj_t secret_key, mp_obj_
mp_raise_ValueError("Invalid length of public key"); mp_raise_ValueError("Invalid length of public key");
} }
uint8_t out[65]; uint8_t out[65];
if (0 != ecdh_multiply(&nist256p1, (const uint8_t *)sk.buf, (const uint8_t *)pk.buf, out)) { if (0 != ecdh_multiply(&nist256p1, (const uint8_t *)sk.buf,
(const uint8_t *)pk.buf, out)) {
mp_raise_ValueError("Multiply failed"); mp_raise_ValueError("Multiply failed");
} }
return mp_obj_new_bytes(out, sizeof(out)); 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[] = { 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___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_generate_secret),
{ MP_ROM_QSTR(MP_QSTR_publickey), MP_ROM_PTR(&mod_trezorcrypto_nist256p1_publickey_obj) }, MP_ROM_PTR(&mod_trezorcrypto_nist256p1_generate_secret_obj)},
{ MP_ROM_QSTR(MP_QSTR_sign), MP_ROM_PTR(&mod_trezorcrypto_nist256p1_sign_obj) }, {MP_ROM_QSTR(MP_QSTR_publickey),
{ MP_ROM_QSTR(MP_QSTR_verify), MP_ROM_PTR(&mod_trezorcrypto_nist256p1_verify_obj) }, MP_ROM_PTR(&mod_trezorcrypto_nist256p1_publickey_obj)},
{ MP_ROM_QSTR(MP_QSTR_verify_recover), MP_ROM_PTR(&mod_trezorcrypto_nist256p1_verify_recover_obj) }, {MP_ROM_QSTR(MP_QSTR_sign),
{ MP_ROM_QSTR(MP_QSTR_multiply), MP_ROM_PTR(&mod_trezorcrypto_nist256p1_multiply_obj) }, 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 = { STATIC const mp_obj_module_t mod_trezorcrypto_nist256p1_module = {
.base = { &mp_type_module }, .base = {&mp_type_module},
.globals = (mp_obj_dict_t*)&mod_trezorcrypto_nist256p1_globals, .globals = (mp_obj_dict_t *)&mod_trezorcrypto_nist256p1_globals,
}; };

View File

@ -19,8 +19,8 @@
#include "py/objstr.h" #include "py/objstr.h"
#include "pbkdf2.h"
#include "memzero.h" #include "memzero.h"
#include "pbkdf2.h"
#define PRF_HMAC_SHA256 256 #define PRF_HMAC_SHA256 256
#define PRF_HMAC_SHA512 512 #define PRF_HMAC_SHA512 512
@ -42,11 +42,14 @@ typedef struct _mp_obj_Pbkdf2_t {
STATIC mp_obj_t mod_trezorcrypto_Pbkdf2_update(mp_obj_t self, mp_obj_t data); 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. /// 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) { 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_arg_check_num(n_args, n_kw, 3, 4, false);
mp_obj_Pbkdf2_t *o = m_new_obj(mp_obj_Pbkdf2_t); mp_obj_Pbkdf2_t *o = m_new_obj(mp_obj_Pbkdf2_t);
o->base.type = type; o->base.type = type;
@ -70,10 +73,11 @@ STATIC mp_obj_t mod_trezorcrypto_Pbkdf2_make_new(const mp_obj_type_t *type, size
o->prf = trezor_obj_get_uint(args[0]); o->prf = trezor_obj_get_uint(args[0]);
if (o->prf == PRF_HMAC_SHA256) { if (o->prf == PRF_HMAC_SHA256) {
pbkdf2_hmac_sha256_Init(&(o->ctx256), password.buf, password.len, salt.buf, salt.len, blocknr); pbkdf2_hmac_sha256_Init(&(o->ctx256), password.buf, password.len, salt.buf,
} else salt.len, blocknr);
if (o->prf == PRF_HMAC_SHA512) { } else if (o->prf == PRF_HMAC_SHA512) {
pbkdf2_hmac_sha512_Init(&(o->ctx512), password.buf, password.len, salt.buf, salt.len, blocknr); pbkdf2_hmac_sha512_Init(&(o->ctx512), password.buf, password.len, salt.buf,
salt.len, blocknr);
} else { } else {
mp_raise_ValueError("Invalid PRF"); mp_raise_ValueError("Invalid PRF");
} }
@ -88,7 +92,8 @@ STATIC mp_obj_t mod_trezorcrypto_Pbkdf2_make_new(const mp_obj_type_t *type, size
/// ''' /// '''
/// Update a PBKDF2 context. /// Update a PBKDF2 context.
/// ''' /// '''
STATIC mp_obj_t mod_trezorcrypto_Pbkdf2_update(mp_obj_t self, mp_obj_t iterations) { 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); mp_obj_Pbkdf2_t *o = MP_OBJ_TO_PTR(self);
uint32_t iter = trezor_obj_get_uint(iterations); uint32_t iter = trezor_obj_get_uint(iterations);
if (o->prf == PRF_HMAC_SHA256) { if (o->prf == PRF_HMAC_SHA256) {
@ -99,7 +104,8 @@ STATIC mp_obj_t mod_trezorcrypto_Pbkdf2_update(mp_obj_t self, mp_obj_t iteration
} }
return mp_const_none; 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: /// def key(self) -> bytes:
/// ''' /// '''
@ -125,7 +131,8 @@ STATIC mp_obj_t mod_trezorcrypto_Pbkdf2_key(mp_obj_t self) {
} }
return mp_const_none; 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) { STATIC mp_obj_t mod_trezorcrypto_Pbkdf2___del__(mp_obj_t self) {
mp_obj_Pbkdf2_t *o = MP_OBJ_TO_PTR(self); mp_obj_Pbkdf2_t *o = MP_OBJ_TO_PTR(self);
@ -133,20 +140,24 @@ STATIC mp_obj_t mod_trezorcrypto_Pbkdf2___del__(mp_obj_t self) {
memzero(&(o->ctx512), sizeof(PBKDF2_HMAC_SHA512_CTX)); memzero(&(o->ctx512), sizeof(PBKDF2_HMAC_SHA512_CTX));
return mp_const_none; 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[] = { 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_update),
{ MP_ROM_QSTR(MP_QSTR_key), MP_ROM_PTR(&mod_trezorcrypto_Pbkdf2_key_obj) }, MP_ROM_PTR(&mod_trezorcrypto_Pbkdf2_update_obj)},
{ MP_ROM_QSTR(MP_QSTR___del__), MP_ROM_PTR(&mod_trezorcrypto_Pbkdf2___del___obj) }, {MP_ROM_QSTR(MP_QSTR_key), MP_ROM_PTR(&mod_trezorcrypto_Pbkdf2_key_obj)},
{ MP_ROM_QSTR(MP_QSTR_HMAC_SHA256), MP_OBJ_NEW_SMALL_INT(PRF_HMAC_SHA256) }, {MP_ROM_QSTR(MP_QSTR___del__),
{ MP_ROM_QSTR(MP_QSTR_HMAC_SHA512), MP_OBJ_NEW_SMALL_INT(PRF_HMAC_SHA512) }, 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 = { STATIC const mp_obj_type_t mod_trezorcrypto_Pbkdf2_type = {
{ &mp_type_type }, {&mp_type_type},
.name = MP_QSTR_Pbkdf2, .name = MP_QSTR_Pbkdf2,
.make_new = mod_trezorcrypto_Pbkdf2_make_new, .make_new = mod_trezorcrypto_Pbkdf2_make_new,
.locals_dict = (void*)&mod_trezorcrypto_Pbkdf2_locals_dict, .locals_dict = (void *)&mod_trezorcrypto_Pbkdf2_locals_dict,
}; };

View File

@ -36,7 +36,8 @@ STATIC mp_obj_t mod_trezorcrypto_random_uniform(mp_obj_t n) {
} }
return mp_obj_new_int_from_uint(random_uniform(nn)); 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: /// def bytes(len: int) -> bytes:
/// ''' /// '''
@ -52,7 +53,8 @@ STATIC mp_obj_t mod_trezorcrypto_random_bytes(mp_obj_t len) {
random_buffer((uint8_t *)vstr.buf, l); random_buffer((uint8_t *)vstr.buf, l);
return mp_obj_new_str_from_vstr(&mp_type_bytes, &vstr); 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: /// def shuffle(data: list) -> None:
/// ''' /// '''
@ -78,17 +80,22 @@ STATIC mp_obj_t mod_trezorcrypto_random_shuffle(mp_obj_t data) {
} }
return mp_const_none; 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[] = { 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___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_uniform),
{ MP_ROM_QSTR(MP_QSTR_bytes), MP_ROM_PTR(&mod_trezorcrypto_random_bytes_obj) }, MP_ROM_PTR(&mod_trezorcrypto_random_uniform_obj)},
{ MP_ROM_QSTR(MP_QSTR_shuffle), MP_ROM_PTR(&mod_trezorcrypto_random_shuffle_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 = { STATIC const mp_obj_module_t mod_trezorcrypto_random_module = {
.base = { &mp_type_module }, .base = {&mp_type_module},
.globals = (mp_obj_dict_t*)&mod_trezorcrypto_random_globals, .globals = (mp_obj_dict_t *)&mod_trezorcrypto_random_globals,
}; };

View File

@ -36,7 +36,9 @@ typedef struct _mp_obj_Rfc6979_t {
/// ''' /// '''
/// Initialize RFC6979 context from secret key and a hash. /// 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) { 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_arg_check_num(n_args, n_kw, 2, 2, false);
mp_obj_Rfc6979_t *o = m_new_obj(mp_obj_Rfc6979_t); mp_obj_Rfc6979_t *o = m_new_obj(mp_obj_Rfc6979_t);
o->base.type = type; o->base.type = type;
@ -63,16 +65,18 @@ STATIC mp_obj_t mod_trezorcrypto_Rfc6979_next(mp_obj_t self) {
generate_rfc6979(out, &(o->rng)); generate_rfc6979(out, &(o->rng));
return mp_obj_new_bytes(out, sizeof(out)); 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[] = { 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 = { STATIC const mp_obj_type_t mod_trezorcrypto_Rfc6979_type = {
{ &mp_type_type }, {&mp_type_type},
.name = MP_QSTR_Rfc6979, .name = MP_QSTR_Rfc6979,
.make_new = mod_trezorcrypto_Rfc6979_make_new, .make_new = mod_trezorcrypto_Rfc6979_make_new,
.locals_dict = (void*)&mod_trezorcrypto_Rfc6979_locals_dict, .locals_dict = (void *)&mod_trezorcrypto_Rfc6979_locals_dict,
}; };

View File

@ -19,8 +19,8 @@
#include "py/objstr.h" #include "py/objstr.h"
#include "ripemd160.h"
#include "memzero.h" #include "memzero.h"
#include "ripemd160.h"
/// package: trezorcrypto.__init__ /// package: trezorcrypto.__init__
@ -39,7 +39,9 @@ STATIC mp_obj_t mod_trezorcrypto_Ripemd160_update(mp_obj_t self, mp_obj_t data);
/// ''' /// '''
/// Creates a hash context object. /// 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) { 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_arg_check_num(n_args, n_kw, 0, 1, false);
mp_obj_Ripemd160_t *o = m_new_obj(mp_obj_Ripemd160_t); mp_obj_Ripemd160_t *o = m_new_obj(mp_obj_Ripemd160_t);
o->base.type = type; o->base.type = type;
@ -55,7 +57,8 @@ STATIC mp_obj_t mod_trezorcrypto_Ripemd160_make_new(const mp_obj_type_t *type, s
/// ''' /// '''
/// Update the hash context with hashed data. /// Update the hash context with hashed data.
/// ''' /// '''
STATIC mp_obj_t mod_trezorcrypto_Ripemd160_update(mp_obj_t self, mp_obj_t 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_obj_Ripemd160_t *o = MP_OBJ_TO_PTR(self);
mp_buffer_info_t msg; mp_buffer_info_t msg;
mp_get_buffer_raise(data, &msg, MP_BUFFER_READ); mp_get_buffer_raise(data, &msg, MP_BUFFER_READ);
@ -64,7 +67,8 @@ STATIC mp_obj_t mod_trezorcrypto_Ripemd160_update(mp_obj_t self, mp_obj_t data)
} }
return mp_const_none; 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: /// def digest(self) -> bytes:
/// ''' /// '''
@ -79,27 +83,36 @@ STATIC mp_obj_t mod_trezorcrypto_Ripemd160_digest(mp_obj_t self) {
memzero(&ctx, sizeof(RIPEMD160_CTX)); memzero(&ctx, sizeof(RIPEMD160_CTX));
return mp_obj_new_bytes(out, sizeof(out)); 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) { STATIC mp_obj_t mod_trezorcrypto_Ripemd160___del__(mp_obj_t self) {
mp_obj_Ripemd160_t *o = MP_OBJ_TO_PTR(self); mp_obj_Ripemd160_t *o = MP_OBJ_TO_PTR(self);
memzero(&(o->ctx), sizeof(RIPEMD160_CTX)); memzero(&(o->ctx), sizeof(RIPEMD160_CTX));
return mp_const_none; 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[] = { STATIC const mp_rom_map_elem_t
{ MP_ROM_QSTR(MP_QSTR_update), MP_ROM_PTR(&mod_trezorcrypto_Ripemd160_update_obj) }, mod_trezorcrypto_Ripemd160_locals_dict_table[] = {
{ MP_ROM_QSTR(MP_QSTR_digest), MP_ROM_PTR(&mod_trezorcrypto_Ripemd160_digest_obj) }, {MP_ROM_QSTR(MP_QSTR_update),
{ MP_ROM_QSTR(MP_QSTR___del__), MP_ROM_PTR(&mod_trezorcrypto_Ripemd160___del___obj) }, MP_ROM_PTR(&mod_trezorcrypto_Ripemd160_update_obj)},
{ MP_ROM_QSTR(MP_QSTR_block_size), MP_OBJ_NEW_SMALL_INT(RIPEMD160_BLOCK_LENGTH) }, {MP_ROM_QSTR(MP_QSTR_digest),
{ MP_ROM_QSTR(MP_QSTR_digest_size), MP_OBJ_NEW_SMALL_INT(RIPEMD160_DIGEST_LENGTH) }, 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 = { STATIC const mp_obj_type_t mod_trezorcrypto_Ripemd160_type = {
{ &mp_type_type }, {&mp_type_type},
.name = MP_QSTR_Ripemd160, .name = MP_QSTR_Ripemd160,
.make_new = mod_trezorcrypto_Ripemd160_make_new, .make_new = mod_trezorcrypto_Ripemd160_make_new,
.locals_dict = (void*)&mod_trezorcrypto_Ripemd160_locals_dict, .locals_dict = (void *)&mod_trezorcrypto_Ripemd160_locals_dict,
}; };

View File

@ -33,19 +33,33 @@ STATIC mp_obj_t mod_trezorcrypto_secp256k1_generate_secret() {
for (;;) { for (;;) {
random_buffer(out, 32); random_buffer(out, 32);
// check whether secret > 0 && secret < curve_order // 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 ==
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; 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; break;
} }
return mp_obj_new_bytes(out, sizeof(out)); 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: /// def publickey(secret_key: bytes, compressed: bool = True) -> bytes:
/// ''' /// '''
/// Computes public key from secret key. /// Computes public key from secret key.
/// ''' /// '''
STATIC mp_obj_t mod_trezorcrypto_secp256k1_publickey(size_t n_args, const mp_obj_t *args) { STATIC mp_obj_t mod_trezorcrypto_secp256k1_publickey(size_t n_args,
const mp_obj_t *args) {
mp_buffer_info_t sk; mp_buffer_info_t sk;
mp_get_buffer_raise(args[0], &sk, MP_BUFFER_READ); mp_get_buffer_raise(args[0], &sk, MP_BUFFER_READ);
if (sk.len != 32) { if (sk.len != 32) {
@ -62,10 +76,11 @@ STATIC mp_obj_t mod_trezorcrypto_secp256k1_publickey(size_t n_args, const mp_obj
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_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]) static int ethereum_is_canonical(uint8_t v, uint8_t signature[64]) {
{
(void)signature; (void)signature;
return (v & 2) == 0; return (v & 2) == 0;
} }
@ -74,11 +89,13 @@ 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. /// 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) { STATIC mp_obj_t mod_trezorcrypto_secp256k1_sign(size_t n_args,
const mp_obj_t *args) {
mp_buffer_info_t sk, dig; mp_buffer_info_t sk, dig;
mp_get_buffer_raise(args[0], &sk, MP_BUFFER_READ); mp_get_buffer_raise(args[0], &sk, MP_BUFFER_READ);
mp_get_buffer_raise(args[1], &dig, MP_BUFFER_READ); mp_get_buffer_raise(args[1], &dig, MP_BUFFER_READ);
@ -97,20 +114,26 @@ STATIC mp_obj_t mod_trezorcrypto_secp256k1_sign(size_t n_args, const mp_obj_t *a
mp_raise_ValueError("Invalid length of digest"); mp_raise_ValueError("Invalid length of digest");
} }
uint8_t out[65], pby; 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)) { 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"); mp_raise_ValueError("Signing failed");
} }
out[0] = 27 + pby + compressed * 4; out[0] = 27 + pby + compressed * 4;
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_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: /// def verify(public_key: bytes, signature: bytes, digest: bytes) -> bool:
/// ''' /// '''
/// Uses public key to verify the signature of the digest. /// Uses public key to verify the signature of the digest.
/// Returns True on success. /// 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) { 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_buffer_info_t pk, sig, dig;
mp_get_buffer_raise(public_key, &pk, MP_BUFFER_READ); mp_get_buffer_raise(public_key, &pk, MP_BUFFER_READ);
mp_get_buffer_raise(signature, &sig, MP_BUFFER_READ); mp_get_buffer_raise(signature, &sig, MP_BUFFER_READ);
@ -125,16 +148,21 @@ STATIC mp_obj_t mod_trezorcrypto_secp256k1_verify(mp_obj_t public_key, mp_obj_t
if (dig.len != 32) { if (dig.len != 32) {
mp_raise_ValueError("Invalid length of digest"); 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)); 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: /// def verify_recover(signature: bytes, digest: bytes) -> bytes:
/// ''' /// '''
/// Uses signature of the digest to verify the digest and recover the public key. /// Uses signature of the digest to verify the digest and recover the public
/// Returns public key on success, None on failure. /// 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) { STATIC mp_obj_t mod_trezorcrypto_secp256k1_verify_recover(mp_obj_t signature,
mp_obj_t digest) {
mp_buffer_info_t sig, dig; mp_buffer_info_t sig, dig;
mp_get_buffer_raise(signature, &sig, MP_BUFFER_READ); mp_get_buffer_raise(signature, &sig, MP_BUFFER_READ);
mp_get_buffer_raise(digest, &dig, MP_BUFFER_READ); mp_get_buffer_raise(digest, &dig, MP_BUFFER_READ);
@ -151,7 +179,9 @@ STATIC mp_obj_t mod_trezorcrypto_secp256k1_verify_recover(mp_obj_t signature, mp
bool compressed = (recid >= 4); bool compressed = (recid >= 4);
recid &= 3; recid &= 3;
uint8_t out[65]; 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 (0 == ecdsa_recover_pub_from_sig(&secp256k1, out,
(const uint8_t *)sig.buf + 1,
(const uint8_t *)dig.buf, recid)) {
if (compressed) { if (compressed) {
out[0] = 0x02 | (out[64] & 1); out[0] = 0x02 | (out[64] & 1);
return mp_obj_new_bytes(out, 33); return mp_obj_new_bytes(out, 33);
@ -161,14 +191,16 @@ STATIC mp_obj_t mod_trezorcrypto_secp256k1_verify_recover(mp_obj_t signature, mp
return mp_const_none; 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: /// def multiply(secret_key: bytes, public_key: bytes) -> bytes:
/// ''' /// '''
/// Multiplies point defined by public_key with scalar defined by secret_key. /// Multiplies point defined by public_key with scalar defined by
/// Useful for ECDH. /// secret_key. Useful for ECDH.
/// ''' /// '''
STATIC mp_obj_t mod_trezorcrypto_secp256k1_multiply(mp_obj_t secret_key, mp_obj_t public_key) { 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_buffer_info_t sk, pk;
mp_get_buffer_raise(secret_key, &sk, MP_BUFFER_READ); mp_get_buffer_raise(secret_key, &sk, MP_BUFFER_READ);
mp_get_buffer_raise(public_key, &pk, MP_BUFFER_READ); mp_get_buffer_raise(public_key, &pk, MP_BUFFER_READ);
@ -179,26 +211,36 @@ STATIC mp_obj_t mod_trezorcrypto_secp256k1_multiply(mp_obj_t secret_key, mp_obj_
mp_raise_ValueError("Invalid length of public key"); mp_raise_ValueError("Invalid length of public key");
} }
uint8_t out[65]; uint8_t out[65];
if (0 != ecdh_multiply(&secp256k1, (const uint8_t *)sk.buf, (const uint8_t *)pk.buf, out)) { if (0 != ecdh_multiply(&secp256k1, (const uint8_t *)sk.buf,
(const uint8_t *)pk.buf, out)) {
mp_raise_ValueError("Multiply failed"); mp_raise_ValueError("Multiply failed");
} }
return mp_obj_new_bytes(out, sizeof(out)); 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[] = { 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___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_generate_secret),
{ MP_ROM_QSTR(MP_QSTR_publickey), MP_ROM_PTR(&mod_trezorcrypto_secp256k1_publickey_obj) }, MP_ROM_PTR(&mod_trezorcrypto_secp256k1_generate_secret_obj)},
{ MP_ROM_QSTR(MP_QSTR_sign), MP_ROM_PTR(&mod_trezorcrypto_secp256k1_sign_obj) }, {MP_ROM_QSTR(MP_QSTR_publickey),
{ MP_ROM_QSTR(MP_QSTR_verify), MP_ROM_PTR(&mod_trezorcrypto_secp256k1_verify_obj) }, MP_ROM_PTR(&mod_trezorcrypto_secp256k1_publickey_obj)},
{ MP_ROM_QSTR(MP_QSTR_verify_recover), MP_ROM_PTR(&mod_trezorcrypto_secp256k1_verify_recover_obj) }, {MP_ROM_QSTR(MP_QSTR_sign),
{ MP_ROM_QSTR(MP_QSTR_multiply), MP_ROM_PTR(&mod_trezorcrypto_secp256k1_multiply_obj) }, MP_ROM_PTR(&mod_trezorcrypto_secp256k1_sign_obj)},
{ MP_ROM_QSTR(MP_QSTR_CANONICAL_SIG_ETHEREUM), MP_OBJ_NEW_SMALL_INT(CANONICAL_SIG_ETHEREUM) }, {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 = { STATIC const mp_obj_module_t mod_trezorcrypto_secp256k1_module = {
.base = { &mp_type_module }, .base = {&mp_type_module},
.globals = (mp_obj_dict_t*)&mod_trezorcrypto_secp256k1_globals, .globals = (mp_obj_dict_t *)&mod_trezorcrypto_secp256k1_globals,
}; };

View File

@ -19,8 +19,8 @@
#include "py/objstr.h" #include "py/objstr.h"
#include "sha2.h"
#include "memzero.h" #include "memzero.h"
#include "sha2.h"
/// package: trezorcrypto.__init__ /// package: trezorcrypto.__init__
@ -39,7 +39,9 @@ STATIC mp_obj_t mod_trezorcrypto_Sha1_update(mp_obj_t self, mp_obj_t data);
/// ''' /// '''
/// Creates a hash context object. /// 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) { 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_arg_check_num(n_args, n_kw, 0, 1, false);
mp_obj_Sha1_t *o = m_new_obj(mp_obj_Sha1_t); mp_obj_Sha1_t *o = m_new_obj(mp_obj_Sha1_t);
o->base.type = type; o->base.type = type;
@ -64,7 +66,8 @@ STATIC mp_obj_t mod_trezorcrypto_Sha1_update(mp_obj_t self, mp_obj_t data) {
} }
return mp_const_none; 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: /// def digest(self) -> bytes:
/// ''' /// '''
@ -79,27 +82,34 @@ STATIC mp_obj_t mod_trezorcrypto_Sha1_digest(mp_obj_t self) {
memzero(&ctx, sizeof(SHA1_CTX)); memzero(&ctx, sizeof(SHA1_CTX));
return mp_obj_new_bytes(out, sizeof(out)); 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) { STATIC mp_obj_t mod_trezorcrypto_Sha1___del__(mp_obj_t self) {
mp_obj_Sha1_t *o = MP_OBJ_TO_PTR(self); mp_obj_Sha1_t *o = MP_OBJ_TO_PTR(self);
memzero(&(o->ctx), sizeof(SHA1_CTX)); memzero(&(o->ctx), sizeof(SHA1_CTX));
return mp_const_none; 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[] = { 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_update),
{ MP_ROM_QSTR(MP_QSTR_digest), MP_ROM_PTR(&mod_trezorcrypto_Sha1_digest_obj) }, MP_ROM_PTR(&mod_trezorcrypto_Sha1_update_obj)},
{ MP_ROM_QSTR(MP_QSTR___del__), MP_ROM_PTR(&mod_trezorcrypto_Sha1___del___obj) }, {MP_ROM_QSTR(MP_QSTR_digest),
{ MP_ROM_QSTR(MP_QSTR_block_size), MP_OBJ_NEW_SMALL_INT(SHA1_BLOCK_LENGTH) }, MP_ROM_PTR(&mod_trezorcrypto_Sha1_digest_obj)},
{ MP_ROM_QSTR(MP_QSTR_digest_size), MP_OBJ_NEW_SMALL_INT(SHA1_DIGEST_LENGTH) }, {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 = { STATIC const mp_obj_type_t mod_trezorcrypto_Sha1_type = {
{ &mp_type_type }, {&mp_type_type},
.name = MP_QSTR_Sha1, .name = MP_QSTR_Sha1,
.make_new = mod_trezorcrypto_Sha1_make_new, .make_new = mod_trezorcrypto_Sha1_make_new,
.locals_dict = (void*)&mod_trezorcrypto_Sha1_locals_dict, .locals_dict = (void *)&mod_trezorcrypto_Sha1_locals_dict,
}; };

View File

@ -19,8 +19,8 @@
#include "py/objstr.h" #include "py/objstr.h"
#include "sha2.h"
#include "memzero.h" #include "memzero.h"
#include "sha2.h"
/// package: trezorcrypto.__init__ /// package: trezorcrypto.__init__
@ -39,7 +39,9 @@ STATIC mp_obj_t mod_trezorcrypto_Sha256_update(mp_obj_t self, mp_obj_t data);
/// ''' /// '''
/// Creates a hash context object. /// 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) { 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_arg_check_num(n_args, n_kw, 0, 1, false);
mp_obj_Sha256_t *o = m_new_obj(mp_obj_Sha256_t); mp_obj_Sha256_t *o = m_new_obj(mp_obj_Sha256_t);
o->base.type = type; o->base.type = type;
@ -64,7 +66,8 @@ STATIC mp_obj_t mod_trezorcrypto_Sha256_update(mp_obj_t self, mp_obj_t data) {
} }
return mp_const_none; 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: /// def digest(self) -> bytes:
/// ''' /// '''
@ -79,27 +82,35 @@ STATIC mp_obj_t mod_trezorcrypto_Sha256_digest(mp_obj_t self) {
memzero(&ctx, sizeof(SHA256_CTX)); memzero(&ctx, sizeof(SHA256_CTX));
return mp_obj_new_bytes(out, sizeof(out)); 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) { STATIC mp_obj_t mod_trezorcrypto_Sha256___del__(mp_obj_t self) {
mp_obj_Sha256_t *o = MP_OBJ_TO_PTR(self); mp_obj_Sha256_t *o = MP_OBJ_TO_PTR(self);
memzero(&(o->ctx), sizeof(SHA256_CTX)); memzero(&(o->ctx), sizeof(SHA256_CTX));
return mp_const_none; 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[] = { 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_update),
{ MP_ROM_QSTR(MP_QSTR_digest), MP_ROM_PTR(&mod_trezorcrypto_Sha256_digest_obj) }, MP_ROM_PTR(&mod_trezorcrypto_Sha256_update_obj)},
{ MP_ROM_QSTR(MP_QSTR___del__), MP_ROM_PTR(&mod_trezorcrypto_Sha256___del___obj) }, {MP_ROM_QSTR(MP_QSTR_digest),
{ MP_ROM_QSTR(MP_QSTR_block_size), MP_OBJ_NEW_SMALL_INT(SHA256_BLOCK_LENGTH) }, MP_ROM_PTR(&mod_trezorcrypto_Sha256_digest_obj)},
{ MP_ROM_QSTR(MP_QSTR_digest_size), MP_OBJ_NEW_SMALL_INT(SHA256_DIGEST_LENGTH) }, {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 = { STATIC const mp_obj_type_t mod_trezorcrypto_Sha256_type = {
{ &mp_type_type }, {&mp_type_type},
.name = MP_QSTR_Sha256, .name = MP_QSTR_Sha256,
.make_new = mod_trezorcrypto_Sha256_make_new, .make_new = mod_trezorcrypto_Sha256_make_new,
.locals_dict = (void*)&mod_trezorcrypto_Sha256_locals_dict, .locals_dict = (void *)&mod_trezorcrypto_Sha256_locals_dict,
}; };

View File

@ -19,8 +19,8 @@
#include "py/objstr.h" #include "py/objstr.h"
#include "sha3.h"
#include "memzero.h" #include "memzero.h"
#include "sha3.h"
/// package: trezorcrypto.__init__ /// package: trezorcrypto.__init__
@ -40,7 +40,9 @@ STATIC mp_obj_t mod_trezorcrypto_Sha3_256_update(mp_obj_t self, mp_obj_t data);
/// ''' /// '''
/// Creates a hash context object. /// 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) { 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_arg_check_num(n_args, n_kw, 0, 1, true);
mp_obj_Sha3_256_t *o = m_new_obj(mp_obj_Sha3_256_t); mp_obj_Sha3_256_t *o = m_new_obj(mp_obj_Sha3_256_t);
o->base.type = type; o->base.type = type;
@ -48,16 +50,17 @@ STATIC mp_obj_t mod_trezorcrypto_Sha3_256_make_new(const mp_obj_type_t *type, si
sha3_256_Init(&(o->ctx)); sha3_256_Init(&(o->ctx));
STATIC const mp_arg_t allowed_args[] = { STATIC const mp_arg_t allowed_args[] = {
{ MP_QSTR_data, MP_ARG_OBJ, {.u_obj = mp_const_none} }, {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_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_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_arg_parse_all_kw_array(n_args, n_kw, args, MP_ARRAY_SIZE(allowed_args),
if (vals[1].u_obj != MP_OBJ_NULL){ allowed_args, vals);
if (vals[1].u_obj != MP_OBJ_NULL) {
o->keccak = mp_obj_is_true(vals[1].u_obj); o->keccak = mp_obj_is_true(vals[1].u_obj);
} }
if (vals[0].u_obj != mp_const_none){ if (vals[0].u_obj != mp_const_none) {
mod_trezorcrypto_Sha3_256_update(MP_OBJ_FROM_PTR(o), vals[0].u_obj); mod_trezorcrypto_Sha3_256_update(MP_OBJ_FROM_PTR(o), vals[0].u_obj);
} }
return MP_OBJ_FROM_PTR(o); return MP_OBJ_FROM_PTR(o);
@ -76,7 +79,8 @@ STATIC mp_obj_t mod_trezorcrypto_Sha3_256_update(mp_obj_t self, mp_obj_t data) {
} }
return mp_const_none; 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: /// def digest(self) -> bytes:
/// ''' /// '''
@ -95,14 +99,15 @@ STATIC mp_obj_t mod_trezorcrypto_Sha3_256_digest(mp_obj_t self) {
memzero(&ctx, sizeof(SHA3_CTX)); memzero(&ctx, sizeof(SHA3_CTX));
return mp_obj_new_bytes(out, sizeof(out)); 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: /// def copy(self) -> sha3:
/// ''' /// '''
/// Returns the copy of the digest object with the current state /// 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) { 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 *o = MP_OBJ_TO_PTR(args[0]);
mp_obj_Sha3_256_t *out = m_new_obj(mp_obj_Sha3_256_t); mp_obj_Sha3_256_t *out = m_new_obj(mp_obj_Sha3_256_t);
out->base.type = o->base.type; out->base.type = o->base.type;
@ -110,28 +115,38 @@ STATIC mp_obj_t mod_trezorcrypto_Sha3_256_copy(size_t n_args, const mp_obj_t *ar
memcpy(&(out->ctx), &(o->ctx), sizeof(SHA3_CTX)); memcpy(&(out->ctx), &(o->ctx), sizeof(SHA3_CTX));
return MP_OBJ_FROM_PTR(out); 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) { STATIC mp_obj_t mod_trezorcrypto_Sha3_256___del__(mp_obj_t self) {
mp_obj_Sha3_256_t *o = MP_OBJ_TO_PTR(self); mp_obj_Sha3_256_t *o = MP_OBJ_TO_PTR(self);
memzero(&(o->ctx), sizeof(SHA3_CTX)); memzero(&(o->ctx), sizeof(SHA3_CTX));
return mp_const_none; 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[] = { 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_update),
{ MP_ROM_QSTR(MP_QSTR_digest), MP_ROM_PTR(&mod_trezorcrypto_Sha3_256_digest_obj) }, MP_ROM_PTR(&mod_trezorcrypto_Sha3_256_update_obj)},
{ MP_ROM_QSTR(MP_QSTR_copy), MP_ROM_PTR(&mod_trezorcrypto_Sha3_256_copy_obj) }, {MP_ROM_QSTR(MP_QSTR_digest),
{ MP_ROM_QSTR(MP_QSTR___del__), MP_ROM_PTR(&mod_trezorcrypto_Sha3_256___del___obj) }, MP_ROM_PTR(&mod_trezorcrypto_Sha3_256_digest_obj)},
{ MP_ROM_QSTR(MP_QSTR_block_size), MP_OBJ_NEW_SMALL_INT(SHA3_256_BLOCK_LENGTH) }, {MP_ROM_QSTR(MP_QSTR_copy),
{ MP_ROM_QSTR(MP_QSTR_digest_size), MP_OBJ_NEW_SMALL_INT(SHA3_256_DIGEST_LENGTH) }, 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 = { STATIC const mp_obj_type_t mod_trezorcrypto_Sha3_256_type = {
{ &mp_type_type }, {&mp_type_type},
.name = MP_QSTR_Sha3_256, .name = MP_QSTR_Sha3_256,
.make_new = mod_trezorcrypto_Sha3_256_make_new, .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,
}; };

View File

@ -19,8 +19,8 @@
#include "py/objstr.h" #include "py/objstr.h"
#include "sha3.h"
#include "memzero.h" #include "memzero.h"
#include "sha3.h"
/// package: trezorcrypto.__init__ /// package: trezorcrypto.__init__
@ -40,7 +40,9 @@ STATIC mp_obj_t mod_trezorcrypto_Sha3_512_update(mp_obj_t self, mp_obj_t data);
/// ''' /// '''
/// Creates a hash context object. /// 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) { 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_arg_check_num(n_args, n_kw, 0, 1, true);
mp_obj_Sha3_512_t *o = m_new_obj(mp_obj_Sha3_512_t); mp_obj_Sha3_512_t *o = m_new_obj(mp_obj_Sha3_512_t);
o->base.type = type; o->base.type = type;
@ -48,16 +50,17 @@ STATIC mp_obj_t mod_trezorcrypto_Sha3_512_make_new(const mp_obj_type_t *type, si
sha3_512_Init(&(o->ctx)); sha3_512_Init(&(o->ctx));
STATIC const mp_arg_t allowed_args[] = { STATIC const mp_arg_t allowed_args[] = {
{ MP_QSTR_data, MP_ARG_OBJ, {.u_obj = mp_const_none} }, {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_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_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_arg_parse_all_kw_array(n_args, n_kw, args, MP_ARRAY_SIZE(allowed_args),
if (vals[1].u_obj != MP_OBJ_NULL){ allowed_args, vals);
if (vals[1].u_obj != MP_OBJ_NULL) {
o->keccak = mp_obj_is_true(vals[1].u_obj); o->keccak = mp_obj_is_true(vals[1].u_obj);
} }
if (vals[0].u_obj != mp_const_none){ if (vals[0].u_obj != mp_const_none) {
mod_trezorcrypto_Sha3_512_update(MP_OBJ_FROM_PTR(o), vals[0].u_obj); mod_trezorcrypto_Sha3_512_update(MP_OBJ_FROM_PTR(o), vals[0].u_obj);
} }
return MP_OBJ_FROM_PTR(o); return MP_OBJ_FROM_PTR(o);
@ -76,7 +79,8 @@ STATIC mp_obj_t mod_trezorcrypto_Sha3_512_update(mp_obj_t self, mp_obj_t data) {
} }
return mp_const_none; 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: /// def digest(self) -> bytes:
/// ''' /// '''
@ -95,14 +99,15 @@ STATIC mp_obj_t mod_trezorcrypto_Sha3_512_digest(mp_obj_t self) {
memzero(&ctx, sizeof(SHA3_CTX)); memzero(&ctx, sizeof(SHA3_CTX));
return mp_obj_new_bytes(out, sizeof(out)); 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: /// def copy(self) -> sha3:
/// ''' /// '''
/// Returns the copy of the digest object with the current state /// 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) { 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 *o = MP_OBJ_TO_PTR(args[0]);
mp_obj_Sha3_512_t *out = m_new_obj(mp_obj_Sha3_512_t); mp_obj_Sha3_512_t *out = m_new_obj(mp_obj_Sha3_512_t);
out->base.type = o->base.type; out->base.type = o->base.type;
@ -110,28 +115,38 @@ STATIC mp_obj_t mod_trezorcrypto_Sha3_512_copy(size_t n_args, const mp_obj_t *ar
memcpy(&(out->ctx), &(o->ctx), sizeof(SHA3_CTX)); memcpy(&(out->ctx), &(o->ctx), sizeof(SHA3_CTX));
return MP_OBJ_FROM_PTR(out); 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) { STATIC mp_obj_t mod_trezorcrypto_Sha3_512___del__(mp_obj_t self) {
mp_obj_Sha3_512_t *o = MP_OBJ_TO_PTR(self); mp_obj_Sha3_512_t *o = MP_OBJ_TO_PTR(self);
memzero(&(o->ctx), sizeof(SHA3_CTX)); memzero(&(o->ctx), sizeof(SHA3_CTX));
return mp_const_none; 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[] = { 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_update),
{ MP_ROM_QSTR(MP_QSTR_digest), MP_ROM_PTR(&mod_trezorcrypto_Sha3_512_digest_obj) }, MP_ROM_PTR(&mod_trezorcrypto_Sha3_512_update_obj)},
{ MP_ROM_QSTR(MP_QSTR_copy), MP_ROM_PTR(&mod_trezorcrypto_Sha3_512_copy_obj) }, {MP_ROM_QSTR(MP_QSTR_digest),
{ MP_ROM_QSTR(MP_QSTR___del__), MP_ROM_PTR(&mod_trezorcrypto_Sha3_512___del___obj) }, MP_ROM_PTR(&mod_trezorcrypto_Sha3_512_digest_obj)},
{ MP_ROM_QSTR(MP_QSTR_block_size), MP_OBJ_NEW_SMALL_INT(SHA3_512_BLOCK_LENGTH) }, {MP_ROM_QSTR(MP_QSTR_copy),
{ MP_ROM_QSTR(MP_QSTR_digest_size), MP_OBJ_NEW_SMALL_INT(SHA3_512_DIGEST_LENGTH) }, 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 = { STATIC const mp_obj_type_t mod_trezorcrypto_Sha3_512_type = {
{ &mp_type_type }, {&mp_type_type},
.name = MP_QSTR_Sha3_512, .name = MP_QSTR_Sha3_512,
.make_new = mod_trezorcrypto_Sha3_512_make_new, .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,
}; };

View File

@ -19,8 +19,8 @@
#include "py/objstr.h" #include "py/objstr.h"
#include "sha2.h"
#include "memzero.h" #include "memzero.h"
#include "sha2.h"
/// package: trezorcrypto.__init__ /// package: trezorcrypto.__init__
@ -39,7 +39,9 @@ STATIC mp_obj_t mod_trezorcrypto_Sha512_update(mp_obj_t self, mp_obj_t data);
/// ''' /// '''
/// Creates a hash context object. /// 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) { 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_arg_check_num(n_args, n_kw, 0, 1, false);
mp_obj_Sha512_t *o = m_new_obj(mp_obj_Sha512_t); mp_obj_Sha512_t *o = m_new_obj(mp_obj_Sha512_t);
o->base.type = type; o->base.type = type;
@ -63,7 +65,8 @@ STATIC mp_obj_t mod_trezorcrypto_Sha512_update(mp_obj_t self, mp_obj_t data) {
} }
return mp_const_none; 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: /// def digest(self) -> bytes:
/// ''' /// '''
@ -78,27 +81,35 @@ STATIC mp_obj_t mod_trezorcrypto_Sha512_digest(mp_obj_t self) {
memzero(&ctx, sizeof(SHA512_CTX)); memzero(&ctx, sizeof(SHA512_CTX));
return mp_obj_new_bytes(out, sizeof(out)); 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) { STATIC mp_obj_t mod_trezorcrypto_Sha512___del__(mp_obj_t self) {
mp_obj_Sha512_t *o = MP_OBJ_TO_PTR(self); mp_obj_Sha512_t *o = MP_OBJ_TO_PTR(self);
memzero(&(o->ctx), sizeof(SHA512_CTX)); memzero(&(o->ctx), sizeof(SHA512_CTX));
return mp_const_none; 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[] = { 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_update),
{ MP_ROM_QSTR(MP_QSTR_digest), MP_ROM_PTR(&mod_trezorcrypto_Sha512_digest_obj) }, MP_ROM_PTR(&mod_trezorcrypto_Sha512_update_obj)},
{ MP_ROM_QSTR(MP_QSTR___del__), MP_ROM_PTR(&mod_trezorcrypto_Sha512___del___obj) }, {MP_ROM_QSTR(MP_QSTR_digest),
{ MP_ROM_QSTR(MP_QSTR_block_size), MP_OBJ_NEW_SMALL_INT(SHA512_BLOCK_LENGTH) }, MP_ROM_PTR(&mod_trezorcrypto_Sha512_digest_obj)},
{ MP_ROM_QSTR(MP_QSTR_digest_size), MP_OBJ_NEW_SMALL_INT(SHA512_DIGEST_LENGTH) }, {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 = { STATIC const mp_obj_type_t mod_trezorcrypto_Sha512_type = {
{ &mp_type_type }, {&mp_type_type},
.name = MP_QSTR_Sha512, .name = MP_QSTR_Sha512,
.make_new = mod_trezorcrypto_Sha512_make_new, .make_new = mod_trezorcrypto_Sha512_make_new,
.locals_dict = (void*)&mod_trezorcrypto_Sha512_locals_dict, .locals_dict = (void *)&mod_trezorcrypto_Sha512_locals_dict,
}; };

View File

@ -17,9 +17,9 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>. * along with this program. If not, see <http://www.gnu.org/licenses/>.
*/ */
#include <stdint.h>
#include <stdio.h> #include <stdio.h>
#include <string.h> #include <string.h>
#include <stdint.h>
#include "py/runtime.h" #include "py/runtime.h"
@ -35,9 +35,10 @@
#include "modtrezorcrypto-crc.h" #include "modtrezorcrypto-crc.h"
#include "modtrezorcrypto-curve25519.h" #include "modtrezorcrypto-curve25519.h"
#include "modtrezorcrypto-ed25519.h" #include "modtrezorcrypto-ed25519.h"
#include "modtrezorcrypto-nist256p1.h"
#include "modtrezorcrypto-groestl.h" #include "modtrezorcrypto-groestl.h"
#include "modtrezorcrypto-monero.h"
#include "modtrezorcrypto-nem.h" #include "modtrezorcrypto-nem.h"
#include "modtrezorcrypto-nist256p1.h"
#include "modtrezorcrypto-pbkdf2.h" #include "modtrezorcrypto-pbkdf2.h"
#include "modtrezorcrypto-random.h" #include "modtrezorcrypto-random.h"
#include "modtrezorcrypto-rfc6979.h" #include "modtrezorcrypto-rfc6979.h"
@ -45,42 +46,52 @@
#include "modtrezorcrypto-secp256k1.h" #include "modtrezorcrypto-secp256k1.h"
#include "modtrezorcrypto-sha1.h" #include "modtrezorcrypto-sha1.h"
#include "modtrezorcrypto-sha256.h" #include "modtrezorcrypto-sha256.h"
#include "modtrezorcrypto-sha512.h"
#include "modtrezorcrypto-sha3-256.h" #include "modtrezorcrypto-sha3-256.h"
#include "modtrezorcrypto-sha3-512.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[] = { 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___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_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_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_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_blake256),
{ MP_ROM_QSTR(MP_QSTR_blake2b), MP_ROM_PTR(&mod_trezorcrypto_Blake2b_type) }, MP_ROM_PTR(&mod_trezorcrypto_Blake256_type)},
{ MP_ROM_QSTR(MP_QSTR_blake2s), MP_ROM_PTR(&mod_trezorcrypto_Blake2s_type) }, {MP_ROM_QSTR(MP_QSTR_blake2b), MP_ROM_PTR(&mod_trezorcrypto_Blake2b_type)},
{ MP_ROM_QSTR(MP_QSTR_chacha20poly1305), MP_ROM_PTR(&mod_trezorcrypto_ChaCha20Poly1305_type) }, {MP_ROM_QSTR(MP_QSTR_blake2s), MP_ROM_PTR(&mod_trezorcrypto_Blake2s_type)},
{ MP_ROM_QSTR(MP_QSTR_crc), MP_ROM_PTR(&mod_trezorcrypto_crc_module) }, {MP_ROM_QSTR(MP_QSTR_chacha20poly1305),
{ MP_ROM_QSTR(MP_QSTR_curve25519), MP_ROM_PTR(&mod_trezorcrypto_curve25519_module) }, MP_ROM_PTR(&mod_trezorcrypto_ChaCha20Poly1305_type)},
{ MP_ROM_QSTR(MP_QSTR_ed25519), MP_ROM_PTR(&mod_trezorcrypto_ed25519_module) }, {MP_ROM_QSTR(MP_QSTR_crc), MP_ROM_PTR(&mod_trezorcrypto_crc_module)},
{ MP_ROM_QSTR(MP_QSTR_monero), MP_ROM_PTR(&mod_trezorcrypto_monero_module) }, {MP_ROM_QSTR(MP_QSTR_curve25519),
{ MP_ROM_QSTR(MP_QSTR_nist256p1), MP_ROM_PTR(&mod_trezorcrypto_nist256p1_module) }, MP_ROM_PTR(&mod_trezorcrypto_curve25519_module)},
{ MP_ROM_QSTR(MP_QSTR_groestl512), MP_ROM_PTR(&mod_trezorcrypto_Groestl512_type) }, {MP_ROM_QSTR(MP_QSTR_ed25519),
{ MP_ROM_QSTR(MP_QSTR_nem), MP_ROM_PTR(&mod_trezorcrypto_nem_module) }, MP_ROM_PTR(&mod_trezorcrypto_ed25519_module)},
{ MP_ROM_QSTR(MP_QSTR_pbkdf2), MP_ROM_PTR(&mod_trezorcrypto_Pbkdf2_type) }, {MP_ROM_QSTR(MP_QSTR_monero), MP_ROM_PTR(&mod_trezorcrypto_monero_module)},
{ MP_ROM_QSTR(MP_QSTR_random), MP_ROM_PTR(&mod_trezorcrypto_random_module) }, {MP_ROM_QSTR(MP_QSTR_nist256p1),
{ MP_ROM_QSTR(MP_QSTR_rfc6979), MP_ROM_PTR(&mod_trezorcrypto_Rfc6979_type) }, MP_ROM_PTR(&mod_trezorcrypto_nist256p1_module)},
{ MP_ROM_QSTR(MP_QSTR_ripemd160), MP_ROM_PTR(&mod_trezorcrypto_Ripemd160_type) }, {MP_ROM_QSTR(MP_QSTR_groestl512),
{ MP_ROM_QSTR(MP_QSTR_secp256k1), MP_ROM_PTR(&mod_trezorcrypto_secp256k1_module) }, MP_ROM_PTR(&mod_trezorcrypto_Groestl512_type)},
{ MP_ROM_QSTR(MP_QSTR_sha1), MP_ROM_PTR(&mod_trezorcrypto_Sha1_type) }, {MP_ROM_QSTR(MP_QSTR_nem), MP_ROM_PTR(&mod_trezorcrypto_nem_module)},
{ MP_ROM_QSTR(MP_QSTR_sha256), MP_ROM_PTR(&mod_trezorcrypto_Sha256_type) }, {MP_ROM_QSTR(MP_QSTR_pbkdf2), MP_ROM_PTR(&mod_trezorcrypto_Pbkdf2_type)},
{ MP_ROM_QSTR(MP_QSTR_sha512), MP_ROM_PTR(&mod_trezorcrypto_Sha512_type) }, {MP_ROM_QSTR(MP_QSTR_random), MP_ROM_PTR(&mod_trezorcrypto_random_module)},
{ MP_ROM_QSTR(MP_QSTR_sha3_256), MP_ROM_PTR(&mod_trezorcrypto_Sha3_256_type) }, {MP_ROM_QSTR(MP_QSTR_rfc6979), MP_ROM_PTR(&mod_trezorcrypto_Rfc6979_type)},
{ MP_ROM_QSTR(MP_QSTR_sha3_512), MP_ROM_PTR(&mod_trezorcrypto_Sha3_512_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 = { 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, .globals = (mp_obj_dict_t*)&mp_module_trezorcrypto_globals,
}; };

View File

@ -20,7 +20,4 @@
#include "rand.h" #include "rand.h"
#include "rng.h" #include "rng.h"
uint32_t random32(void) uint32_t random32(void) { return rng_get(); }
{
return rng_get();
}

View File

@ -31,7 +31,9 @@ typedef struct _mp_obj_FlashOTP_t {
/// def __init__(self) -> None: /// 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) { 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_arg_check_num(n_args, n_kw, 0, 0, false);
mp_obj_FlashOTP_t *o = m_new_obj(mp_obj_FlashOTP_t); mp_obj_FlashOTP_t *o = m_new_obj(mp_obj_FlashOTP_t);
o->base.type = type; o->base.type = type;
@ -42,7 +44,8 @@ STATIC mp_obj_t mod_trezorio_FlashOTP_make_new(const mp_obj_type_t *type, size_t
/// ''' /// '''
/// Writes data to OTP flash /// Writes data to OTP flash
/// ''' /// '''
STATIC mp_obj_t mod_trezorio_FlashOTP_write(size_t n_args, const mp_obj_t *args) { 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 block = trezor_obj_get_uint8(args[1]);
uint8_t offset = trezor_obj_get_uint8(args[2]); uint8_t offset = trezor_obj_get_uint8(args[2]);
mp_buffer_info_t data; mp_buffer_info_t data;
@ -52,13 +55,15 @@ STATIC mp_obj_t mod_trezorio_FlashOTP_write(size_t n_args, const mp_obj_t *args)
} }
return mp_const_none; 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: /// def FlashOTP.read(self, block: int, offset: int, data: bytearray) -> None:
/// ''' /// '''
/// Reads data from OTP flash /// Reads data from OTP flash
/// ''' /// '''
STATIC mp_obj_t mod_trezorio_FlashOTP_read(size_t n_args, const mp_obj_t *args) { 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 block = trezor_obj_get_uint8(args[1]);
uint8_t offset = trezor_obj_get_uint8(args[2]); uint8_t offset = trezor_obj_get_uint8(args[2]);
mp_buffer_info_t data; mp_buffer_info_t data;
@ -68,7 +73,8 @@ STATIC mp_obj_t mod_trezorio_FlashOTP_read(size_t n_args, const mp_obj_t *args)
} }
return mp_const_none; 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: /// def FlashOTP.lock(self, block: int) -> None:
/// ''' /// '''
@ -81,7 +87,8 @@ STATIC mp_obj_t mod_trezorio_FlashOTP_lock(mp_obj_t self, mp_obj_t block) {
} }
return mp_const_none; 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: /// def FlashOTP.is_locked(self, block: int) -> bool:
/// ''' /// '''
@ -91,19 +98,22 @@ 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); uint8_t b = trezor_obj_get_uint8(block);
return (sectrue == flash_otp_is_locked(b)) ? mp_const_true : mp_const_false; 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[] = { 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_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_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_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_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 = { STATIC const mp_obj_type_t mod_trezorio_FlashOTP_type = {
{ &mp_type_type }, {&mp_type_type},
.name = MP_QSTR_FlashOTP, .name = MP_QSTR_FlashOTP,
.make_new = mod_trezorio_FlashOTP_make_new, .make_new = mod_trezorio_FlashOTP_make_new,
.locals_dict = (void*)&mod_trezorio_FlashOTP_locals_dict, .locals_dict = (void *)&mod_trezorio_FlashOTP_locals_dict,
}; };

View File

@ -37,20 +37,30 @@ typedef struct _mp_obj_HID_t {
/// max_packet_len: int = 64) -> None: /// 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[] = { 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_iface_num,
{ MP_QSTR_ep_in, MP_ARG_REQUIRED | MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = 0} }, MP_ARG_REQUIRED | MP_ARG_KW_ONLY | MP_ARG_INT,
{ MP_QSTR_ep_out, MP_ARG_REQUIRED | MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = 0} }, {.u_int = 0}},
{ MP_QSTR_subclass, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = 0} }, {MP_QSTR_ep_in,
{ MP_QSTR_protocol, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = 0} }, MP_ARG_REQUIRED | MP_ARG_KW_ONLY | MP_ARG_INT,
{ MP_QSTR_polling_interval, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = 1} }, {.u_int = 0}},
{ MP_QSTR_max_packet_len, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = 64} }, {MP_QSTR_ep_out,
{ MP_QSTR_report_desc, MP_ARG_REQUIRED | MP_ARG_KW_ONLY | MP_ARG_OBJ, {.u_obj = MP_OBJ_NULL} }, 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_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_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 iface_num = vals[0].u_int;
const mp_int_t ep_in = vals[1].u_int; const mp_int_t ep_in = vals[1].u_int;
@ -62,7 +72,8 @@ STATIC mp_obj_t mod_trezorio_HID_make_new(const mp_obj_type_t *type, size_t n_ar
mp_buffer_info_t report_desc; mp_buffer_info_t report_desc;
mp_get_buffer_raise(vals[7].u_obj, &report_desc, MP_BUFFER_READ); 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) { if (report_desc.buf == NULL || report_desc.len == 0 ||
report_desc.len > 255) {
mp_raise_ValueError("report_desc is invalid"); mp_raise_ValueError("report_desc is invalid");
} }
CHECK_PARAM_RANGE(iface_num, 0, 32) CHECK_PARAM_RANGE(iface_num, 0, 32)
@ -98,7 +109,8 @@ STATIC mp_obj_t mod_trezorio_HID_iface_num(mp_obj_t self) {
mp_obj_HID_t *o = MP_OBJ_TO_PTR(self); mp_obj_HID_t *o = MP_OBJ_TO_PTR(self);
return MP_OBJ_NEW_SMALL_INT(o->info.iface_num); 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: /// def write(self, msg: bytes) -> int:
/// ''' /// '''
@ -111,17 +123,20 @@ STATIC mp_obj_t mod_trezorio_HID_write(mp_obj_t self, mp_obj_t msg) {
ssize_t r = usb_hid_write(o->info.iface_num, buf.buf, buf.len); ssize_t r = usb_hid_write(o->info.iface_num, buf.buf, buf.len);
return MP_OBJ_NEW_SMALL_INT(r); 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[] = { 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_iface_num),
{ MP_ROM_QSTR(MP_QSTR_write), MP_ROM_PTR(&mod_trezorio_HID_write_obj) }, 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 = { STATIC const mp_obj_type_t mod_trezorio_HID_type = {
{ &mp_type_type }, {&mp_type_type},
.name = MP_QSTR_HID, .name = MP_QSTR_HID,
.make_new = mod_trezorio_HID_make_new, .make_new = mod_trezorio_HID_make_new,
.locals_dict = (void*)&mod_trezorio_HID_locals_dict, .locals_dict = (void *)&mod_trezorio_HID_locals_dict,
}; };

View File

@ -18,21 +18,13 @@
*/ */
#include <string.h> #include <string.h>
#include <unistd.h>
#include "embed/extmod/trezorobj.h" #include "embed/extmod/trezorobj.h"
#include "usb.h"
#define TOUCH_IFACE (255) #define TOUCH_IFACE (255)
#define POLL_READ (0x0000) #define POLL_READ (0x0000)
#define POLL_WRITE (0x0100) #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: /// 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 /// Wait until one of `ifaces` is ready to read or write (using masks
@ -40,12 +32,14 @@
/// `list_ref`: /// `list_ref`:
/// ///
/// `list_ref[0]` - the interface number, including the mask /// `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 /// - for USB read event, received bytes
/// ///
/// If timeout occurs, False is returned, True otherwise. /// 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) { 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); mp_obj_list_t *ret = MP_OBJ_TO_PTR(list_ref);
if (!MP_OBJ_IS_TYPE(list_ref, &mp_type_list) || ret->len < 2) { if (!MP_OBJ_IS_TYPE(list_ref, &mp_type_list) || ret->len < 2) {
mp_raise_TypeError("invalid list_ref"); mp_raise_TypeError("invalid list_ref");
@ -67,15 +61,16 @@ STATIC mp_obj_t mod_trezorio_poll(mp_obj_t ifaces, mp_obj_t list_ref, mp_obj_t t
const uint32_t evt = touch_read(); const uint32_t evt = touch_read();
if (evt) { if (evt) {
mp_obj_tuple_t *tuple = MP_OBJ_TO_PTR(mp_obj_new_tuple(3, NULL)); 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[0] =
tuple->items[1] = MP_OBJ_NEW_SMALL_INT((evt >> 12) & 0xFFFU); // x position 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 tuple->items[2] = MP_OBJ_NEW_SMALL_INT(evt & 0xFFFU); // y position
ret->items[0] = MP_OBJ_NEW_SMALL_INT(i); ret->items[0] = MP_OBJ_NEW_SMALL_INT(i);
ret->items[1] = MP_OBJ_FROM_PTR(tuple); ret->items[1] = MP_OBJ_FROM_PTR(tuple);
return mp_const_true; return mp_const_true;
} }
} else } else if (mode == POLL_READ) {
if (mode == POLL_READ) {
if (sectrue == usb_hid_can_read(iface)) { if (sectrue == usb_hid_can_read(iface)) {
uint8_t buf[64]; uint8_t buf[64];
int len = usb_hid_read(iface, buf, sizeof(buf)); int len = usb_hid_read(iface, buf, sizeof(buf));
@ -93,8 +88,7 @@ STATIC mp_obj_t mod_trezorio_poll(mp_obj_t ifaces, mp_obj_t list_ref, mp_obj_t t
return mp_const_true; return mp_const_true;
} }
} }
} else } else if (mode == POLL_WRITE) {
if (mode == POLL_WRITE) {
if (sectrue == usb_hid_can_write(iface)) { if (sectrue == usb_hid_can_write(iface)) {
ret->items[0] = MP_OBJ_NEW_SMALL_INT(i); ret->items[0] = MP_OBJ_NEW_SMALL_INT(i);
ret->items[1] = mp_const_none; ret->items[1] = mp_const_none;

View File

@ -29,7 +29,9 @@ typedef struct _mp_obj_SBU_t {
/// def __init__(self) -> None: /// 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) { 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_arg_check_num(n_args, n_kw, 0, 0, false);
mp_obj_SBU_t *o = m_new_obj(mp_obj_SBU_t); mp_obj_SBU_t *o = m_new_obj(mp_obj_SBU_t);
o->base.type = type; o->base.type = type;
@ -41,20 +43,23 @@ STATIC mp_obj_t mod_trezorio_SBU_make_new(const mp_obj_type_t *type, size_t n_ar
/// ''' /// '''
/// Sets SBU wires to sbu1 and sbu2 values respectively /// 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) { 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)); sbu_set(sectrue * mp_obj_is_true(sbu1), sectrue * mp_obj_is_true(sbu2));
return mp_const_none; 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[] = { 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 = { STATIC const mp_obj_type_t mod_trezorio_SBU_type = {
{ &mp_type_type }, {&mp_type_type},
.name = MP_QSTR_SBU, .name = MP_QSTR_SBU,
.make_new = mod_trezorio_SBU_make_new, .make_new = mod_trezorio_SBU_make_new,
.locals_dict = (void*)&mod_trezorio_SBU_locals_dict, .locals_dict = (void *)&mod_trezorio_SBU_locals_dict,
}; };

View File

@ -31,7 +31,9 @@ typedef struct _mp_obj_SDCard_t {
/// def __init__(self) -> None: /// 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) { 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_arg_check_num(n_args, n_kw, 0, 0, false);
mp_obj_SDCard_t *o = m_new_obj(mp_obj_SDCard_t); mp_obj_SDCard_t *o = m_new_obj(mp_obj_SDCard_t);
o->base.type = type; o->base.type = type;
@ -48,7 +50,8 @@ STATIC mp_obj_t mod_trezorio_SDCard_make_new(const mp_obj_type_t *type, size_t n
STATIC mp_obj_t mod_trezorio_SDCard_present(mp_obj_t self) { 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: /// def power(self, state: bool) -> bool:
/// ''' /// '''
@ -63,7 +66,8 @@ STATIC mp_obj_t mod_trezorio_SDCard_power(mp_obj_t self, mp_obj_t state) {
return mp_const_true; 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: /// def capacity(self) -> int:
/// ''' /// '''
@ -72,49 +76,59 @@ STATIC MP_DEFINE_CONST_FUN_OBJ_2(mod_trezorio_SDCard_power_obj, mod_trezorio_SDC
STATIC mp_obj_t mod_trezorio_SDCard_capacity(mp_obj_t self) { 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: /// def read(self, block_num: int, buf: bytearray) -> bool:
/// ''' /// '''
/// Reads blocks starting with block_num from the SD card into buf. /// 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. /// Number of bytes read is length of buf rounded down to multiply of
/// Returns True if in case of success, False otherwise. /// 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) { 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); uint32_t block = trezor_obj_get_uint(block_num);
mp_buffer_info_t bufinfo; mp_buffer_info_t bufinfo;
mp_get_buffer_raise(buf, &bufinfo, MP_BUFFER_WRITE); 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)); 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: /// def write(self, block_num: int, buf: bytes) -> bool:
/// ''' /// '''
/// Writes blocks starting with block_num from buf to the SD card. /// 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. /// Number of bytes written is length of buf rounded down to multiply of
/// Returns True if in case of success, False otherwise. /// 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) { 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); uint32_t block = trezor_obj_get_uint(block_num);
mp_buffer_info_t bufinfo; mp_buffer_info_t bufinfo;
mp_get_buffer_raise(buf, &bufinfo, MP_BUFFER_READ); 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)); 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[] = { 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_present),
{ MP_ROM_QSTR(MP_QSTR_power), MP_ROM_PTR(&mod_trezorio_SDCard_power_obj) }, MP_ROM_PTR(&mod_trezorio_SDCard_present_obj)},
{ MP_ROM_QSTR(MP_QSTR_capacity), MP_ROM_PTR(&mod_trezorio_SDCard_capacity_obj) }, {MP_ROM_QSTR(MP_QSTR_power), MP_ROM_PTR(&mod_trezorio_SDCard_power_obj)},
{ MP_ROM_QSTR(MP_QSTR_block_size), MP_OBJ_NEW_SMALL_INT(SDCARD_BLOCK_SIZE) }, {MP_ROM_QSTR(MP_QSTR_capacity),
{ MP_ROM_QSTR(MP_QSTR_read), MP_ROM_PTR(&mod_trezorio_SDCard_read_obj) }, MP_ROM_PTR(&mod_trezorio_SDCard_capacity_obj)},
{ MP_ROM_QSTR(MP_QSTR_write), MP_ROM_PTR(&mod_trezorio_SDCard_write_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 = { STATIC const mp_obj_type_t mod_trezorio_SDCard_type = {
{ &mp_type_type }, {&mp_type_type},
.name = MP_QSTR_SDCard, .name = MP_QSTR_SDCard,
.make_new = mod_trezorio_SDCard_make_new, .make_new = mod_trezorio_SDCard_make_new,
.locals_dict = (void*)&mod_trezorio_SDCard_locals_dict, .locals_dict = (void *)&mod_trezorio_SDCard_locals_dict,
}; };

View File

@ -64,24 +64,40 @@ static const char *get_0str(mp_obj_t o, size_t min_len, size_t max_len) {
/// usb21_landing: bool=True) -> None: /// 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 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[] = { STATIC const mp_arg_t allowed_args[] = {
{ MP_QSTR_device_class, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = 0} }, {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_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_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_vendor_id,
{ MP_QSTR_product_id, MP_ARG_REQUIRED | MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = 0} }, MP_ARG_REQUIRED | MP_ARG_KW_ONLY | MP_ARG_INT,
{ MP_QSTR_release_num, MP_ARG_REQUIRED | MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = 0} }, {.u_int = 0}},
{ MP_QSTR_manufacturer, MP_ARG_KW_ONLY | MP_ARG_OBJ, {.u_obj = mp_const_empty_bytes} }, {MP_QSTR_product_id,
{ MP_QSTR_product, MP_ARG_KW_ONLY | MP_ARG_OBJ, {.u_obj = mp_const_empty_bytes} }, MP_ARG_REQUIRED | MP_ARG_KW_ONLY | MP_ARG_INT,
{ MP_QSTR_serial_number, MP_ARG_KW_ONLY | MP_ARG_OBJ, {.u_obj = mp_const_empty_bytes} }, {.u_int = 0}},
{ MP_QSTR_interface, MP_ARG_KW_ONLY | MP_ARG_OBJ, {.u_obj = mp_const_empty_bytes} }, {MP_QSTR_release_num,
{ MP_QSTR_usb21_enabled, MP_ARG_KW_ONLY | MP_ARG_BOOL, {.u_bool = true} }, MP_ARG_REQUIRED | MP_ARG_KW_ONLY | MP_ARG_INT,
{ MP_QSTR_usb21_landing, MP_ARG_KW_ONLY | MP_ARG_BOOL, {.u_bool = true} }, {.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_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_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_class = vals[0].u_int;
const mp_int_t device_subclass = vals[1].u_int; const mp_int_t device_subclass = vals[1].u_int;
@ -152,7 +168,8 @@ STATIC mp_obj_t mod_trezorio_USB_add(mp_obj_t self, mp_obj_t 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: /// def open(self) -> None:
/// ''' /// '''
@ -213,7 +230,8 @@ STATIC mp_obj_t mod_trezorio_USB_open(mp_obj_t self) {
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: /// def close(self) -> None:
/// ''' /// '''
@ -239,7 +257,8 @@ STATIC mp_obj_t mod_trezorio_USB_close(mp_obj_t self) {
return mp_const_none; return mp_const_none;
} }
STATIC MP_DEFINE_CONST_FUN_OBJ_1(mod_trezorio_USB_close_obj, mod_trezorio_USB_close); 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) { STATIC mp_obj_t mod_trezorio_USB___del__(mp_obj_t self) {
mp_obj_USB_t *o = MP_OBJ_TO_PTR(self); mp_obj_USB_t *o = MP_OBJ_TO_PTR(self);
@ -250,19 +269,21 @@ STATIC mp_obj_t mod_trezorio_USB___del__(mp_obj_t self) {
} }
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[] = { 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_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_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_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___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 = { STATIC const mp_obj_type_t mod_trezorio_USB_type = {
{ &mp_type_type }, {&mp_type_type},
.name = MP_QSTR_USB, .name = MP_QSTR_USB,
.make_new = mod_trezorio_USB_make_new, .make_new = mod_trezorio_USB_make_new,
.locals_dict = (void*)&mod_trezorio_USB_locals_dict, .locals_dict = (void *)&mod_trezorio_USB_locals_dict,
}; };

View File

@ -36,17 +36,29 @@ typedef struct _mp_obj_VCP_t {
/// ep_cmd: int) -> None: /// 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[] = { 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_iface_num,
{ MP_QSTR_data_iface_num, MP_ARG_REQUIRED | MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = 0} }, MP_ARG_REQUIRED | MP_ARG_KW_ONLY | MP_ARG_INT,
{ MP_QSTR_ep_in, MP_ARG_REQUIRED | MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = 0} }, {.u_int = 0}},
{ MP_QSTR_ep_out, MP_ARG_REQUIRED | MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = 0} }, {MP_QSTR_data_iface_num,
{ MP_QSTR_ep_cmd, MP_ARG_REQUIRED | MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = 0} }, 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_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_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 iface_num = vals[0].u_int;
const mp_int_t data_iface_num = vals[1].u_int; const mp_int_t data_iface_num = vals[1].u_int;
@ -93,16 +105,19 @@ STATIC mp_obj_t mod_trezorio_VCP_iface_num(mp_obj_t self) {
mp_obj_VCP_t *o = MP_OBJ_TO_PTR(self); mp_obj_VCP_t *o = MP_OBJ_TO_PTR(self);
return MP_OBJ_NEW_SMALL_INT(o->info.iface_num); 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[] = { 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 = { STATIC const mp_obj_type_t mod_trezorio_VCP_type = {
{ &mp_type_type }, {&mp_type_type},
.name = MP_QSTR_VCP, .name = MP_QSTR_VCP,
.make_new = mod_trezorio_VCP_make_new, .make_new = mod_trezorio_VCP_make_new,
.locals_dict = (void*)&mod_trezorio_VCP_locals_dict, .locals_dict = (void *)&mod_trezorio_VCP_locals_dict,
}; };

View File

@ -36,19 +36,27 @@ typedef struct _mp_obj_WebUSB_t {
/// max_packet_len: int = 64) -> None: /// 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[] = { 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_iface_num,
{ MP_QSTR_ep_in, MP_ARG_REQUIRED | MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = 0} }, MP_ARG_REQUIRED | MP_ARG_KW_ONLY | MP_ARG_INT,
{ MP_QSTR_ep_out, MP_ARG_REQUIRED | MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = 0} }, {.u_int = 0}},
{ MP_QSTR_subclass, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = 0} }, {MP_QSTR_ep_in,
{ MP_QSTR_protocol, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = 0} }, MP_ARG_REQUIRED | MP_ARG_KW_ONLY | MP_ARG_INT,
{ MP_QSTR_polling_interval, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = 1} }, {.u_int = 0}},
{ MP_QSTR_max_packet_len, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = 64} }, {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_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_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 iface_num = vals[0].u_int;
const mp_int_t ep_in = vals[1].u_int; const mp_int_t ep_in = vals[1].u_int;
@ -89,7 +97,8 @@ STATIC mp_obj_t mod_trezorio_WebUSB_iface_num(mp_obj_t self) {
mp_obj_WebUSB_t *o = MP_OBJ_TO_PTR(self); mp_obj_WebUSB_t *o = MP_OBJ_TO_PTR(self);
return MP_OBJ_NEW_SMALL_INT(o->info.iface_num); 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: /// def write(self, msg: bytes) -> int:
/// ''' /// '''
@ -102,17 +111,20 @@ STATIC mp_obj_t mod_trezorio_WebUSB_write(mp_obj_t self, mp_obj_t msg) {
ssize_t r = usb_webusb_write(o->info.iface_num, buf.buf, buf.len); ssize_t r = usb_webusb_write(o->info.iface_num, buf.buf, buf.len);
return MP_OBJ_NEW_SMALL_INT(r); 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[] = { 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_iface_num),
{ MP_ROM_QSTR(MP_QSTR_write), MP_ROM_PTR(&mod_trezorio_WebUSB_write_obj) }, 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 = { STATIC const mp_obj_type_t mod_trezorio_WebUSB_type = {
{ &mp_type_type }, {&mp_type_type},
.name = MP_QSTR_WebUSB, .name = MP_QSTR_WebUSB,
.make_new = mod_trezorio_WebUSB_make_new, .make_new = mod_trezorio_WebUSB_make_new,
.locals_dict = (void*)&mod_trezorio_WebUSB_locals_dict, .locals_dict = (void *)&mod_trezorio_WebUSB_locals_dict,
}; };

View File

@ -17,51 +17,65 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>. * along with this program. If not, see <http://www.gnu.org/licenses/>.
*/ */
#include "py/runtime.h"
#include "py/mphal.h" #include "py/mphal.h"
#include "py/objstr.h" #include "py/objstr.h"
#include "py/runtime.h"
#if MICROPY_PY_TREZORIO #if MICROPY_PY_TREZORIO
#include "touch.h" #include <unistd.h>
#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-flash.h"
#include "modtrezorio-hid.h"
#include "modtrezorio-poll.h"
#include "modtrezorio-sbu.h" #include "modtrezorio-sbu.h"
#include "modtrezorio-sdcard.h" #include "modtrezorio-sdcard.h"
#include "modtrezorio-poll.h"
#include "modtrezorio-hid.h"
#include "modtrezorio-vcp.h" #include "modtrezorio-vcp.h"
#include "modtrezorio-webusb.h" #include "modtrezorio-webusb.h"
#include "modtrezorio-usb.h" #include "modtrezorio-usb.h"
// clang-format on
STATIC const mp_rom_map_elem_t mp_module_trezorio_globals_table[] = { 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_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_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_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_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), 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_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_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), 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_START),
{ MP_ROM_QSTR(MP_QSTR_TOUCH_MOVE), MP_OBJ_NEW_SMALL_INT((TOUCH_MOVE >> 24) & 0xFFU) }, MP_OBJ_NEW_SMALL_INT((TOUCH_START >> 24) & 0xFFU)},
{ MP_ROM_QSTR(MP_QSTR_TOUCH_END), MP_OBJ_NEW_SMALL_INT((TOUCH_END >> 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 = { 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, .globals = (mp_obj_dict_t*)&mp_module_trezorio_globals,
}; };

View File

@ -20,7 +20,7 @@
#include STM32_HAL_H #include STM32_HAL_H
#define OLED_BUFSIZE (DISPLAY_RESX * DISPLAY_RESY / 8) #define OLED_BUFSIZE (DISPLAY_RESX * DISPLAY_RESY / 8)
#define OLED_OFFSET(x, y) (OLED_BUFSIZE - 1 - (x) - ((y)/8) * DISPLAY_RESX) #define OLED_OFFSET(x, y) (OLED_BUFSIZE - 1 - (x) - ((y) / 8) * DISPLAY_RESX)
#define OLED_MASK(x, y) (1 << (7 - (y) % 8)) #define OLED_MASK(x, y) (1 << (7 - (y) % 8))
#define OLED_SETCONTRAST 0x81 #define OLED_SETCONTRAST 0x81
@ -67,14 +67,17 @@ static struct {
} PIXELWINDOW; } PIXELWINDOW;
void PIXELDATA(uint16_t c) { void PIXELDATA(uint16_t c) {
if (PIXELWINDOW.pos.x <= PIXELWINDOW.end.x && PIXELWINDOW.pos.y <= PIXELWINDOW.end.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 // set to white if highest bits of all R, G, B values are set to 1
// bin(10000 100000 10000) = hex(0x8410) // bin(10000 100000 10000) = hex(0x8410)
// otherwise set to black // otherwise set to black
if (c & 0x8410) { if (c & 0x8410) {
OLED_BUFFER[OLED_OFFSET(PIXELWINDOW.pos.x, PIXELWINDOW.pos.y)] |= OLED_MASK(PIXELWINDOW.pos.x, PIXELWINDOW.pos.y); OLED_BUFFER[OLED_OFFSET(PIXELWINDOW.pos.x, PIXELWINDOW.pos.y)] |=
OLED_MASK(PIXELWINDOW.pos.x, PIXELWINDOW.pos.y);
} else { } else {
OLED_BUFFER[OLED_OFFSET(PIXELWINDOW.pos.x, PIXELWINDOW.pos.y)] &= ~OLED_MASK(PIXELWINDOW.pos.x, PIXELWINDOW.pos.y); OLED_BUFFER[OLED_OFFSET(PIXELWINDOW.pos.x, PIXELWINDOW.pos.y)] &=
~OLED_MASK(PIXELWINDOW.pos.x, PIXELWINDOW.pos.y);
} }
} }
PIXELWINDOW.pos.x++; PIXELWINDOW.pos.x++;
@ -84,26 +87,23 @@ void PIXELDATA(uint16_t c) {
} }
} }
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) {
PIXELWINDOW.start.x = x0; PIXELWINDOW.start.y = y0; PIXELWINDOW.start.x = x0;
PIXELWINDOW.end.x = x1; PIXELWINDOW.end.y = y1; PIXELWINDOW.start.y = y0;
PIXELWINDOW.pos.x = x0; PIXELWINDOW.pos.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) static void display_set_orientation(int degrees) { display_refresh(); }
{
display_refresh();
}
static void display_set_backlight(int val) static void display_set_backlight(int val) {}
{
}
SPI_HandleTypeDef spi_handle; SPI_HandleTypeDef spi_handle;
static inline void spi_send(const uint8_t *data, int len) static inline void spi_send(const uint8_t *data, int len) {
{
HAL_Delay(1); HAL_Delay(1);
if (HAL_OK != HAL_SPI_Transmit(&spi_handle, (uint8_t *)data, len, 1000)) { if (HAL_OK != HAL_SPI_Transmit(&spi_handle, (uint8_t *)data, len, 1000)) {
// TODO: error // TODO: error
@ -113,8 +113,7 @@ static inline void spi_send(const uint8_t *data, int len)
} }
} }
void display_init(void) void display_init(void) {
{
__HAL_RCC_GPIOA_CLK_ENABLE(); __HAL_RCC_GPIOA_CLK_ENABLE();
__HAL_RCC_GPIOB_CLK_ENABLE(); __HAL_RCC_GPIOB_CLK_ENABLE();
__HAL_RCC_SPI1_CLK_ENABLE(); __HAL_RCC_SPI1_CLK_ENABLE();
@ -160,8 +159,7 @@ void display_init(void)
// initialize display // initialize display
static const uint8_t s[25] = { static const uint8_t s[25] = {OLED_DISPLAYOFF,
OLED_DISPLAYOFF,
OLED_SETDISPLAYCLOCKDIV, OLED_SETDISPLAYCLOCKDIV,
0x80, 0x80,
OLED_SETMULTIPLEX, OLED_SETMULTIPLEX,
@ -185,8 +183,7 @@ void display_init(void)
0x40, 0x40,
OLED_DISPLAYALLON_RESUME, OLED_DISPLAYALLON_RESUME,
OLED_NORMALDISPLAY, OLED_NORMALDISPLAY,
OLED_DISPLAYON OLED_DISPLAYON};
};
HAL_GPIO_WritePin(OLED_DC_PORT, OLED_DC_PIN, GPIO_PIN_RESET); // set to CMD 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 HAL_GPIO_WritePin(OLED_CS_PORT, OLED_CS_PIN, GPIO_PIN_SET); // SPI deselect
@ -214,8 +211,7 @@ static inline uint8_t reverse_byte(uint8_t b) {
return b; return b;
} }
static void rotate_oled_buffer(void) static void rotate_oled_buffer(void) {
{
for (int i = 0; i < OLED_BUFSIZE / 2; i++) { for (int i = 0; i < OLED_BUFSIZE / 2; i++) {
uint8_t b = OLED_BUFFER[i]; uint8_t b = OLED_BUFFER[i];
OLED_BUFFER[i] = reverse_byte(OLED_BUFFER[OLED_BUFSIZE - i]); OLED_BUFFER[i] = reverse_byte(OLED_BUFFER[OLED_BUFSIZE - i]);
@ -223,9 +219,10 @@ static void rotate_oled_buffer(void)
} }
} }
void display_refresh(void) void display_refresh(void) {
{ static const uint8_t s[3] = {OLED_SETLOWCOLUMN | 0x00,
static const uint8_t s[3] = {OLED_SETLOWCOLUMN | 0x00, OLED_SETHIGHCOLUMN | 0x00, OLED_SETSTARTLINE | 0x00}; OLED_SETHIGHCOLUMN | 0x00,
OLED_SETSTARTLINE | 0x00};
HAL_GPIO_WritePin(OLED_CS_PORT, OLED_CS_PIN, GPIO_PIN_RESET); // SPI select HAL_GPIO_WritePin(OLED_CS_PORT, OLED_CS_PIN, GPIO_PIN_RESET); // SPI select
spi_send(s, 3); spi_send(s, 3);
@ -244,6 +241,4 @@ void display_refresh(void)
HAL_GPIO_WritePin(OLED_DC_PORT, OLED_DC_PIN, GPIO_PIN_RESET); // set to CMD 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) {}
{
}

View File

@ -24,29 +24,40 @@
#define DISPLAY_MEMORY_PIN 16 #define DISPLAY_MEMORY_PIN 16
#define CMD(X) (*((__IO uint8_t *)((uint32_t)(DISPLAY_MEMORY_BASE))) = (X)) #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 ADDR \
(*((__IO uint8_t *)((uint32_t)(DISPLAY_MEMORY_BASE | \
(1 << DISPLAY_MEMORY_PIN)))))
#define DATA(X) (ADDR) = (X) #define DATA(X) (ADDR) = (X)
#define PIXELDATA(X) DATA((X) >> 8); DATA((X) & 0xFF) #define PIXELDATA(X) \
DATA((X) >> 8); \
DATA((X)&0xFF)
#define LED_PWM_TIM_PERIOD (10000) #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_ST7789V \
#define DISPLAY_ID_GC9307 0x009307U // section "6.2.1. Read display identification information (04h)" of GC9307 datasheet 0x858552U // section "9.1.3 RDDID (04h): Read Display ID" of ST7789V
#define DISPLAY_ID_ILI9341V 0x009341U // section "8.3.23 Read ID4 (D3h)" of ILI9341V datasheet // 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) { static uint32_t read_display_id(uint8_t command) {
volatile uint8_t c; volatile uint8_t c;
uint32_t id = 0; uint32_t id = 0;
CMD(command); CMD(command);
c = ADDR; // first returned value is a dummy value and should be discarded c = ADDR; // first returned value is a dummy value and should be discarded
c = ADDR; id |= (c << 16); c = ADDR;
c = ADDR; id |= (c << 8); id |= (c << 16);
c = ADDR; id |= c; c = ADDR;
id |= (c << 8);
c = ADDR;
id |= c;
return id; return id;
} }
static uint32_t display_identify(void) static uint32_t display_identify(void) {
{
static uint32_t id = 0x000000U; static uint32_t id = 0x000000U;
static char id_set = 0; static char id_set = 0;
@ -56,7 +67,8 @@ static uint32_t display_identify(void)
// the default RDDID for ILI9341 should be 0x8000. // the default RDDID for ILI9341 should be 0x8000.
// some display modules return 0x0. // some display modules return 0x0.
// the ILI9341 has an extra id, let's check it here. // 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 if ((id != DISPLAY_ID_ST7789V) &&
(id != DISPLAY_ID_GC9307)) { // if not ST7789V and not GC9307
uint32_t id4 = read_display_id(0xD3); // Read ID4 uint32_t id4 = read_display_id(0xD3); // Read ID4
if (id4 == DISPLAY_ID_ILI9341V) { // definitely found a ILI9341 if (id4 == DISPLAY_ID_ILI9341V) { // definitely found a ILI9341
id = id4; id = id4;
@ -66,51 +78,62 @@ static uint32_t display_identify(void)
return id; return id;
} }
static void __attribute__((unused)) display_sleep(void) static void __attribute__((unused)) display_sleep(void) {
{
uint32_t id = display_identify(); uint32_t id = display_identify();
if ((id == DISPLAY_ID_ILI9341V) || (id == DISPLAY_ID_GC9307) || (id == DISPLAY_ID_ST7789V)) { if ((id == DISPLAY_ID_ILI9341V) || (id == DISPLAY_ID_GC9307) ||
(id == DISPLAY_ID_ST7789V)) {
CMD(0x28); // DISPOFF: Display Off CMD(0x28); // DISPOFF: Display Off
CMD(0x10); // SLPIN: Sleep in CMD(0x10); // SLPIN: Sleep in
HAL_Delay(5); // need to wait 5 milliseconds after "sleep in" before sending any new commands HAL_Delay(5); // need to wait 5 milliseconds after "sleep in" before
// sending any new commands
} }
} }
static void display_unsleep(void) static void display_unsleep(void) {
{
uint32_t id = display_identify(); uint32_t id = display_identify();
if ((id == DISPLAY_ID_ILI9341V) || (id == DISPLAY_ID_GC9307) || (id == DISPLAY_ID_ST7789V)) { if ((id == DISPLAY_ID_ILI9341V) || (id == DISPLAY_ID_GC9307) ||
(id == DISPLAY_ID_ST7789V)) {
CMD(0x11); // SLPOUT: Sleep Out CMD(0x11); // SLPOUT: Sleep Out
HAL_Delay(5); // need to wait 5 milliseconds after "sleep out" before sending any new commands HAL_Delay(5); // need to wait 5 milliseconds after "sleep out" before
// sending any new commands
CMD(0x29); // DISPON: Display On CMD(0x29); // DISPON: Display On
} }
} }
static struct { static struct { uint16_t x, y; } BUFFER_OFFSET;
uint16_t x, y;
} BUFFER_OFFSET;
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) {
x0 += BUFFER_OFFSET.x; x1 += BUFFER_OFFSET.x; x0 += BUFFER_OFFSET.x;
y0 += BUFFER_OFFSET.y; y1 += BUFFER_OFFSET.y; x1 += BUFFER_OFFSET.x;
y0 += BUFFER_OFFSET.y;
y1 += BUFFER_OFFSET.y;
uint32_t id = display_identify(); uint32_t id = display_identify();
if ((id == DISPLAY_ID_ILI9341V) || (id == DISPLAY_ID_GC9307) || (id == DISPLAY_ID_ST7789V)) { if ((id == DISPLAY_ID_ILI9341V) || (id == DISPLAY_ID_GC9307) ||
CMD(0x2A); DATA(x0 >> 8); DATA(x0 & 0xFF); DATA(x1 >> 8); DATA(x1 & 0xFF); // column addr set (id == DISPLAY_ID_ST7789V)) {
CMD(0x2B); DATA(y0 >> 8); DATA(y0 & 0xFF); DATA(y1 >> 8); DATA(y1 & 0xFF); // row addr set 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); CMD(0x2C);
} }
} }
static void display_set_orientation(int degrees) static void display_set_orientation(int degrees) {
{
char BX = 0, BY = 0; char BX = 0, BY = 0;
uint32_t id = display_identify(); uint32_t id = display_identify();
if ((id == DISPLAY_ID_ILI9341V) || (id == DISPLAY_ID_GC9307) || (id == DISPLAY_ID_ST7789V)) { if ((id == DISPLAY_ID_ILI9341V) || (id == DISPLAY_ID_GC9307) ||
#define RGB (1 << 3) (id == DISPLAY_ID_ST7789V)) {
#define MV (1 << 5) #define RGB (1 << 3)
#define MX (1 << 6) #define MV (1 << 5)
#define MY (1 << 7) #define MX (1 << 6)
#define MY (1 << 7)
// MADCTL: Memory Data Access Control - reference: // MADCTL: Memory Data Access Control - reference:
// section 9.3 in the ILI9341 manual // section 9.3 in the ILI9341 manual
// section 6.2.18 in the GC9307 manual // section 6.2.18 in the GC9307 manual
@ -137,32 +160,34 @@ static void display_set_orientation(int degrees)
if (id == DISPLAY_ID_GC9307) { if (id == DISPLAY_ID_GC9307) {
display_command_parameter ^= RGB | MY; // XOR RGB and MY settings display_command_parameter ^= RGB | MY; // XOR RGB and MY settings
} }
CMD(0x36); DATA(display_command_parameter); CMD(0x36);
display_set_window(0, 0, DISPLAY_RESX - 1, DISPLAY_RESY - 1); // reset the column and page extents 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.x = BX ? (MAX_DISPLAY_RESY - DISPLAY_RESY) : 0;
BUFFER_OFFSET.y = BY ? (MAX_DISPLAY_RESY - DISPLAY_RESY) : 0; BUFFER_OFFSET.y = BY ? (MAX_DISPLAY_RESY - DISPLAY_RESY) : 0;
} }
static void display_set_backlight(int val) static void display_set_backlight(int val) {
{
TIM1->CCR1 = LED_PWM_TIM_PERIOD * val / 255; TIM1->CCR1 = LED_PWM_TIM_PERIOD * val / 255;
} }
static void display_hardware_reset(void) static void display_hardware_reset(void) {
{
HAL_GPIO_WritePin(GPIOC, GPIO_PIN_14, GPIO_PIN_RESET); // LCD_RST/PC14 HAL_GPIO_WritePin(GPIOC, GPIO_PIN_14, GPIO_PIN_RESET); // LCD_RST/PC14
// wait 10 milliseconds. only needs to be low for 10 microseconds. // wait 10 milliseconds. only needs to be low for 10 microseconds.
// my dev display module ties display reset and touch panel reset together. // 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. // keeping this low for max(display_reset_time, ctpm_reset_time) aids
// development and does not hurt.
HAL_Delay(10); HAL_Delay(10);
HAL_GPIO_WritePin(GPIOC, GPIO_PIN_14, GPIO_PIN_SET); // LCD_RST/PC14 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) 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 // identify the controller we will communicate with
} }
void display_init(void) void display_init(void) {
{
// init peripherials // init peripherials
__HAL_RCC_GPIOE_CLK_ENABLE(); __HAL_RCC_GPIOE_CLK_ENABLE();
__HAL_RCC_TIM1_CLK_ENABLE(); __HAL_RCC_TIM1_CLK_ENABLE();
@ -182,7 +207,8 @@ void display_init(void)
TIM_HandleTypeDef TIM1_Handle; TIM_HandleTypeDef TIM1_Handle;
TIM1_Handle.Instance = TIM1; TIM1_Handle.Instance = TIM1;
TIM1_Handle.Init.Period = LED_PWM_TIM_PERIOD - 1; TIM1_Handle.Init.Period = LED_PWM_TIM_PERIOD - 1;
// TIM1/APB2 source frequency equals to SystemCoreClock in our configuration, we want 1 MHz // TIM1/APB2 source frequency equals to SystemCoreClock in our configuration,
// we want 1 MHz
TIM1_Handle.Init.Prescaler = SystemCoreClock / 1000000 - 1; TIM1_Handle.Init.Prescaler = SystemCoreClock / 1000000 - 1;
TIM1_Handle.Init.ClockDivision = TIM_CLOCKDIVISION_DIV1; TIM1_Handle.Init.ClockDivision = TIM_CLOCKDIVISION_DIV1;
TIM1_Handle.Init.CounterMode = TIM_COUNTERMODE_UP; TIM1_Handle.Init.CounterMode = TIM_COUNTERMODE_UP;
@ -210,7 +236,8 @@ void display_init(void)
GPIO_InitStructure.Speed = GPIO_SPEED_FREQ_LOW; GPIO_InitStructure.Speed = GPIO_SPEED_FREQ_LOW;
GPIO_InitStructure.Alternate = 0; GPIO_InitStructure.Alternate = 0;
GPIO_InitStructure.Pin = GPIO_PIN_14; GPIO_InitStructure.Pin = GPIO_PIN_14;
HAL_GPIO_WritePin(GPIOC, GPIO_PIN_14, GPIO_PIN_RESET); // default to keeping display in reset HAL_GPIO_WritePin(GPIOC, GPIO_PIN_14,
GPIO_PIN_RESET); // default to keeping display in reset
HAL_GPIO_Init(GPIOC, &GPIO_InitStructure); HAL_GPIO_Init(GPIOC, &GPIO_InitStructure);
// LCD_FMARK/PD12 (tearing effect) // LCD_FMARK/PD12 (tearing effect)
@ -225,33 +252,41 @@ void display_init(void)
GPIO_InitStructure.Pull = GPIO_NOPULL; GPIO_InitStructure.Pull = GPIO_NOPULL;
GPIO_InitStructure.Speed = GPIO_SPEED_FREQ_VERY_HIGH; GPIO_InitStructure.Speed = GPIO_SPEED_FREQ_VERY_HIGH;
GPIO_InitStructure.Alternate = GPIO_AF12_FMC; GPIO_InitStructure.Alternate = GPIO_AF12_FMC;
// LCD_CS/PD7 LCD_RS/PD11 LCD_RD/PD4 LCD_WR/PD5 // 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; GPIO_InitStructure.Pin = GPIO_PIN_7 | GPIO_PIN_11 | GPIO_PIN_4 | GPIO_PIN_5;
HAL_GPIO_Init(GPIOD, &GPIO_InitStructure); HAL_GPIO_Init(GPIOD, &GPIO_InitStructure);
// LCD_D0/PD14 LCD_D1/PD15 LCD_D2/PD0 LCD_D3/PD1 // 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; GPIO_InitStructure.Pin = GPIO_PIN_14 | GPIO_PIN_15 | GPIO_PIN_0 | GPIO_PIN_1;
HAL_GPIO_Init(GPIOD, &GPIO_InitStructure); HAL_GPIO_Init(GPIOD, &GPIO_InitStructure);
// LCD_D4/PE7 LCD_D5/PE8 LCD_D6/PE9 LCD_D7/PE10 // 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; GPIO_InitStructure.Pin = GPIO_PIN_7 | GPIO_PIN_8 | GPIO_PIN_9 | GPIO_PIN_10;
HAL_GPIO_Init(GPIOE, &GPIO_InitStructure); HAL_GPIO_Init(GPIOE, &GPIO_InitStructure);
// Reference UM1725 "Description of STM32F4 HAL and LL drivers", section 64.2.1 "How to use this driver" // Reference UM1725 "Description of STM32F4 HAL and LL drivers",
// section 64.2.1 "How to use this driver"
SRAM_HandleTypeDef external_display_data_sram; SRAM_HandleTypeDef external_display_data_sram;
external_display_data_sram.Instance = FMC_NORSRAM_DEVICE; external_display_data_sram.Instance = FMC_NORSRAM_DEVICE;
external_display_data_sram.Init.NSBank = FMC_NORSRAM_BANK1; 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.DataAddressMux = FMC_DATA_ADDRESS_MUX_DISABLE;
external_display_data_sram.Init.MemoryType = FMC_MEMORY_TYPE_SRAM; 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.MemoryDataWidth = FMC_NORSRAM_MEM_BUS_WIDTH_8;
external_display_data_sram.Init.BurstAccessMode = FMC_BURST_ACCESS_MODE_DISABLE; external_display_data_sram.Init.BurstAccessMode =
external_display_data_sram.Init.WaitSignalPolarity = FMC_WAIT_SIGNAL_POLARITY_LOW; 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.WrapMode = FMC_WRAP_MODE_DISABLE;
external_display_data_sram.Init.WaitSignalActive = FMC_WAIT_TIMING_BEFORE_WS; 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.WriteOperation = FMC_WRITE_OPERATION_ENABLE;
external_display_data_sram.Init.WaitSignal = FMC_WAIT_SIGNAL_DISABLE; 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.ExtendedMode = FMC_EXTENDED_MODE_DISABLE;
external_display_data_sram.Init.AsynchronousWait = FMC_ASYNCHRONOUS_WAIT_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.WriteBurst = FMC_WRITE_BURST_DISABLE;
external_display_data_sram.Init.ContinuousClock = FMC_CONTINUOUS_CLOCK_SYNC_ONLY; external_display_data_sram.Init.ContinuousClock =
FMC_CONTINUOUS_CLOCK_SYNC_ONLY;
external_display_data_sram.Init.PageSize = FMC_PAGE_SIZE_NONE; 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 // reference RM0090 section 37.5 Table 259, 37.5.4, Mode 1 SRAM, and 37.5.6
@ -272,80 +307,195 @@ void display_init(void)
if (id == DISPLAY_ID_GC9307) { if (id == DISPLAY_ID_GC9307) {
CMD(0xFE); // Inter Register Enable1 CMD(0xFE); // Inter Register Enable1
CMD(0xEF); // Inter Register Enable2 CMD(0xEF); // Inter Register Enable2
CMD(0x35); DATA(0x00); // TEON: Tearing Effect Line On; V-blanking only CMD(0x35);
CMD(0x3A); DATA(0x55); // COLMOD: Interface Pixel format; 65K color: 16-bit/pixel (RGB 5-6-5 bits input) 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(0xE8); DATA(0x12); DATA(0x00); // Frame Rate
CMD(0xC3); DATA(0x27); // Power Control 2 CMD(0xC3);
CMD(0xC4); DATA(0x18); // Power Control 3 DATA(0x27); // Power Control 2
CMD(0xC9); DATA(0x1F); // Power Control 4 CMD(0xC4);
CMD(0xC5); DATA(0x0F); DATA(0x18); // Power Control 3
CMD(0xC6); DATA(0x00); CMD(0xC9);
CMD(0xC7); DATA(0x10); DATA(0x1F); // Power Control 4
CMD(0xC8); DATA(0x01); CMD(0xC5);
CMD(0xFF); DATA(0x62); DATA(0x0F);
CMD(0x99); DATA(0x3E); CMD(0xC6);
CMD(0x9D); DATA(0x4B); DATA(0x00);
CMD(0x8E); DATA(0x0F); 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 // SET_GAMMA1
CMD(0xF0); DATA(0x8F); DATA(0x1B); DATA(0x05); DATA(0x06); DATA(0x07); DATA(0x42); CMD(0xF0);
DATA(0x8F);
DATA(0x1B);
DATA(0x05);
DATA(0x06);
DATA(0x07);
DATA(0x42);
// SET_GAMMA3 // SET_GAMMA3
CMD(0xF2); DATA(0x5C); DATA(0x1F); DATA(0x12); DATA(0x10); DATA(0x07); DATA(0x43); CMD(0xF2);
DATA(0x5C);
DATA(0x1F);
DATA(0x12);
DATA(0x10);
DATA(0x07);
DATA(0x43);
// SET_GAMMA2 // SET_GAMMA2
CMD(0xF1); DATA(0x59); DATA(0xCF); DATA(0xCF); DATA(0x35); DATA(0x37); DATA(0x8F); CMD(0xF1);
DATA(0x59);
DATA(0xCF);
DATA(0xCF);
DATA(0x35);
DATA(0x37);
DATA(0x8F);
// SET_GAMMA4 // SET_GAMMA4
CMD(0xF3); DATA(0x58); DATA(0xCF); DATA(0xCF); DATA(0x35); DATA(0x37); DATA(0x8F); CMD(0xF3);
} else DATA(0x58);
if (id == DISPLAY_ID_ST7789V) { DATA(0xCF);
CMD(0x35); DATA(0x00); // TEON: Tearing Effect Line On; V-blanking only DATA(0xCF);
CMD(0x3A); DATA(0x55); // COLMOD: Interface Pixel format; 65K color: 16-bit/pixel (RGB 5-6-5 bits input) DATA(0x35);
CMD(0xDF); DATA(0x5A); DATA(0x69); DATA(0x02); DATA(0x01); // CMD2EN: Commands in command table 2 can be executed when EXTC level is Low DATA(0x37);
CMD(0xC0); DATA(0x20); // LCMCTRL: LCM Control: XOR RGB setting DATA(0x8F);
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 } 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 // the above config is the most important and definitely necessary
CMD(0xD0); DATA(0xA4); DATA(0xA1); // PWCTRL1: Power Control 1 CMD(0xD0);
DATA(0xA4);
DATA(0xA1); // PWCTRL1: Power Control 1
// gamma curve 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); // CMD(0xE0); DATA(0x70); DATA(0x2C); DATA(0x2E); DATA(0x15); DATA(0x10);
// gamma curve 2 // DATA(0x09); DATA(0x48); DATA(0x33); DATA(0x53); DATA(0x0B); DATA(0x19);
// 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); // DATA(0x18); DATA(0x20); DATA(0x25); gamma curve 2 CMD(0xE1); DATA(0x70);
} else // DATA(0x2C); DATA(0x2E); DATA(0x15); DATA(0x10); DATA(0x09); DATA(0x48);
if (id == DISPLAY_ID_ILI9341V) { // 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 // most recent manual: https://www.newhavendisplay.com/app_notes/ILI9341.pdf
CMD(0x35); DATA(0x00); // TEON: Tearing Effect Line On; V-blanking only CMD(0x35);
CMD(0x3A); DATA(0x55); // COLMOD: Interface Pixel format; 65K color: 16-bit/pixel (RGB 5-6-5 bits input) DATA(0x00); // TEON: Tearing Effect Line On; V-blanking only
CMD(0xB6); DATA(0x0A); DATA(0xC2); DATA(0x27); DATA(0x00); // Display Function Control: gate scan direction 319 -> 0 CMD(0x3A);
CMD(0xF6); DATA(0x09); DATA(0x30); DATA(0x00); // Interface Control: XOR BGR as ST7789V does 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 // the above config is the most important and definitely necessary
CMD(0xCF); DATA(0x00); DATA(0xC1); DATA(0x30); CMD(0xCF);
CMD(0xED); DATA(0x64); DATA(0x03); DATA(0x12); DATA(0x81); DATA(0x00);
CMD(0xE8); DATA(0x85); DATA(0x10); DATA(0x7A); DATA(0xC1);
CMD(0xF7); DATA(0x20); DATA(0x30);
CMD(0xEA); DATA(0x00); DATA(0x00); CMD(0xED);
CMD(0xC0); DATA(0x23); // power control VRH[5:0] DATA(0x64);
CMD(0xC1); DATA(0x12); // power control SAP[2:0] BT[3:0] DATA(0x03);
CMD(0xC5); DATA(0x60); DATA(0x44); // vcm control 1 DATA(0x12);
CMD(0xC7); DATA(0x8A); // vcm control 2 DATA(0x81);
CMD(0xB1); DATA(0x00); DATA(0x18); // framerate CMD(0xE8);
CMD(0xF2); DATA(0x00); // 3 gamma func disable 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 // 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); 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 // 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); 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_clear();
display_unsleep(); display_unsleep();
} }
void display_refresh(void) void display_refresh(void) {
{
uint32_t id = display_identify(); uint32_t id = display_identify();
if (id && (id != DISPLAY_ID_GC9307)) { if (id && (id != DISPLAY_ID_GC9307)) {
// synchronize with the panel synchronization signal in order to avoid visual tearing effects // synchronize with the panel synchronization signal in order to avoid
while (GPIO_PIN_RESET == HAL_GPIO_ReadPin(GPIOD, GPIO_PIN_12)) { } // visual tearing effects
while (GPIO_PIN_SET == HAL_GPIO_ReadPin(GPIOD, GPIO_PIN_12)) { } 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) {}
{
}

View File

@ -78,8 +78,11 @@ void PIXELDATA(uint16_t c) {
if (!RENDERER) { if (!RENDERER) {
display_init(); display_init();
} }
if (PIXELWINDOW.pos.x <= PIXELWINDOW.end.x && PIXELWINDOW.pos.y <= PIXELWINDOW.end.y) { if (PIXELWINDOW.pos.x <= PIXELWINDOW.end.x &&
((uint16_t *)BUFFER->pixels)[PIXELWINDOW.pos.x + PIXELWINDOW.pos.y * BUFFER->pitch / sizeof(uint16_t)] = c; 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++; PIXELWINDOW.pos.x++;
if (PIXELWINDOW.pos.x > PIXELWINDOW.end.x) { if (PIXELWINDOW.pos.x > PIXELWINDOW.end.x) {
@ -91,15 +94,16 @@ void PIXELDATA(uint16_t c) {
#define PIXELDATA(X) (void)(X) #define PIXELDATA(X) (void)(X)
#endif #endif
void display_init(void) void display_init(void) {
{
#ifndef TREZOR_EMULATOR_NOUI #ifndef TREZOR_EMULATOR_NOUI
if (SDL_Init(SDL_INIT_VIDEO) != 0) { if (SDL_Init(SDL_INIT_VIDEO) != 0) {
printf("%s\n", SDL_GetError()); printf("%s\n", SDL_GetError());
ensure(secfalse, "SDL_Init error"); ensure(secfalse, "SDL_Init error");
} }
atexit(SDL_Quit); atexit(SDL_Quit);
SDL_Window *win = SDL_CreateWindow("TREZOR Emulator", SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED, WINDOW_WIDTH, WINDOW_HEIGHT, SDL_Window *win =
SDL_CreateWindow("TREZOR Emulator", SDL_WINDOWPOS_UNDEFINED,
SDL_WINDOWPOS_UNDEFINED, WINDOW_WIDTH, WINDOW_HEIGHT,
#ifdef TREZOR_EMULATOR_RASPI #ifdef TREZOR_EMULATOR_RASPI
SDL_WINDOW_SHOWN | SDL_WINDOW_FULLSCREEN SDL_WINDOW_SHOWN | SDL_WINDOW_FULLSCREEN
#else #else
@ -118,8 +122,11 @@ void display_init(void)
} }
SDL_SetRenderDrawColor(RENDERER, 0, 0, 0, 255); SDL_SetRenderDrawColor(RENDERER, 0, 0, 0, 255);
SDL_RenderClear(RENDERER); SDL_RenderClear(RENDERER);
BUFFER = SDL_CreateRGBSurface(0, MAX_DISPLAY_RESX, MAX_DISPLAY_RESY, 16, 0xF800, 0x07E0, 0x001F, 0x0000); BUFFER = SDL_CreateRGBSurface(0, MAX_DISPLAY_RESX, MAX_DISPLAY_RESY, 16,
TEXTURE = SDL_CreateTexture(RENDERER, SDL_PIXELFORMAT_RGB565, SDL_TEXTUREACCESS_STREAMING, DISPLAY_RESX, DISPLAY_RESY); 0xF800, 0x07E0, 0x001F, 0x0000);
TEXTURE = SDL_CreateTexture(RENDERER, SDL_PIXELFORMAT_RGB565,
SDL_TEXTUREACCESS_STREAMING, DISPLAY_RESX,
DISPLAY_RESY);
SDL_SetTextureBlendMode(TEXTURE, SDL_BLENDMODE_BLEND); SDL_SetTextureBlendMode(TEXTURE, SDL_BLENDMODE_BLEND);
#ifdef __APPLE__ #ifdef __APPLE__
// macOS Mojave SDL black screen workaround // macOS Mojave SDL black screen workaround
@ -130,14 +137,16 @@ void display_init(void)
#ifdef TREZOR_EMULATOR_RASPI #ifdef TREZOR_EMULATOR_RASPI
BACKGROUND = IMG_LoadTexture(RENDERER, "../embed/unix/background_raspi.jpg"); BACKGROUND = IMG_LoadTexture(RENDERER, "../embed/unix/background_raspi.jpg");
#else #else
BACKGROUND = IMG_LoadTexture(RENDERER, "../embed/unix/background_" XSTR(TREZOR_MODEL) ".jpg"); BACKGROUND = IMG_LoadTexture(
RENDERER, "../embed/unix/background_" XSTR(TREZOR_MODEL) ".jpg");
#endif #endif
if (BACKGROUND) { if (BACKGROUND) {
SDL_SetTextureBlendMode(BACKGROUND, SDL_BLENDMODE_NONE); SDL_SetTextureBlendMode(BACKGROUND, SDL_BLENDMODE_NONE);
sdl_touch_offset_x = TOUCH_OFFSET_X; sdl_touch_offset_x = TOUCH_OFFSET_X;
sdl_touch_offset_y = TOUCH_OFFSET_Y; sdl_touch_offset_y = TOUCH_OFFSET_Y;
} else { } else {
SDL_SetWindowSize(win, DISPLAY_RESX + 2 * EMULATOR_BORDER, DISPLAY_RESY + 2 * EMULATOR_BORDER); SDL_SetWindowSize(win, DISPLAY_RESX + 2 * EMULATOR_BORDER,
DISPLAY_RESY + 2 * EMULATOR_BORDER);
sdl_touch_offset_x = EMULATOR_BORDER; sdl_touch_offset_x = EMULATOR_BORDER;
sdl_touch_offset_y = EMULATOR_BORDER; sdl_touch_offset_y = EMULATOR_BORDER;
} }
@ -151,20 +160,22 @@ void display_init(void)
#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 #ifndef TREZOR_EMULATOR_NOUI
if (!RENDERER) { if (!RENDERER) {
display_init(); display_init();
} }
PIXELWINDOW.start.x = x0; PIXELWINDOW.start.y = y0; PIXELWINDOW.start.x = x0;
PIXELWINDOW.end.x = x1; PIXELWINDOW.end.y = y1; PIXELWINDOW.start.y = y0;
PIXELWINDOW.pos.x = x0; PIXELWINDOW.pos.y = y0; PIXELWINDOW.end.x = x1;
PIXELWINDOW.end.y = y1;
PIXELWINDOW.pos.x = x0;
PIXELWINDOW.pos.y = y0;
#endif #endif
} }
void display_refresh(void) void display_refresh(void) {
{
#ifndef TREZOR_EMULATOR_NOUI #ifndef TREZOR_EMULATOR_NOUI
if (!RENDERER) { if (!RENDERER) {
display_init(); display_init();
@ -176,30 +187,26 @@ void display_refresh(void)
} }
SDL_UpdateTexture(TEXTURE, NULL, BUFFER->pixels, BUFFER->pitch); SDL_UpdateTexture(TEXTURE, NULL, BUFFER->pixels, BUFFER->pitch);
#define BACKLIGHT_NORMAL 150 #define BACKLIGHT_NORMAL 150
SDL_SetTextureAlphaMod(TEXTURE, MIN(255, 255 * DISPLAY_BACKLIGHT / BACKLIGHT_NORMAL)); SDL_SetTextureAlphaMod(TEXTURE,
MIN(255, 255 * DISPLAY_BACKLIGHT / BACKLIGHT_NORMAL));
if (BACKGROUND) { if (BACKGROUND) {
const SDL_Rect r = {TOUCH_OFFSET_X, TOUCH_OFFSET_Y, DISPLAY_RESX, DISPLAY_RESY}; const SDL_Rect r = {TOUCH_OFFSET_X, TOUCH_OFFSET_Y, DISPLAY_RESX,
DISPLAY_RESY};
SDL_RenderCopyEx(RENDERER, TEXTURE, NULL, &r, DISPLAY_ORIENTATION, NULL, 0); SDL_RenderCopyEx(RENDERER, TEXTURE, NULL, &r, DISPLAY_ORIENTATION, NULL, 0);
} else { } else {
const SDL_Rect r = {EMULATOR_BORDER, EMULATOR_BORDER, DISPLAY_RESX, DISPLAY_RESY}; const SDL_Rect r = {EMULATOR_BORDER, EMULATOR_BORDER, DISPLAY_RESX,
DISPLAY_RESY};
SDL_RenderCopyEx(RENDERER, TEXTURE, NULL, &r, DISPLAY_ORIENTATION, NULL, 0); SDL_RenderCopyEx(RENDERER, TEXTURE, NULL, &r, DISPLAY_ORIENTATION, NULL, 0);
} }
SDL_RenderPresent(RENDERER); SDL_RenderPresent(RENDERER);
#endif #endif
} }
static void display_set_orientation(int degrees) static void display_set_orientation(int degrees) { display_refresh(); }
{
display_refresh();
}
static void display_set_backlight(int val) static void display_set_backlight(int val) { display_refresh(); }
{
display_refresh();
}
void display_save(const char *prefix) void display_save(const char *prefix) {
{
#ifndef TREZOR_EMULATOR_NOUI #ifndef TREZOR_EMULATOR_NOUI
if (!RENDERER) { if (!RENDERER) {
display_init(); display_init();
@ -208,7 +215,10 @@ void display_save(const char *prefix)
char fname[256]; char fname[256];
snprintf(fname, sizeof(fname), "%s%08d.png", prefix, cnt); snprintf(fname, sizeof(fname), "%s%08d.png", prefix, cnt);
const SDL_Rect rect = {0, 0, DISPLAY_RESX, DISPLAY_RESY}; 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_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); SDL_BlitSurface(BUFFER, &rect, crop, NULL);
IMG_SavePNG(crop, fname); IMG_SavePNG(crop, fname);
SDL_FreeSurface(crop); SDL_FreeSurface(crop);

View File

@ -17,8 +17,8 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>. * along with this program. If not, see <http://www.gnu.org/licenses/>.
*/ */
#include "inflate.h"
#include "font_bitmap.h" #include "font_bitmap.h"
#include "inflate.h"
#ifdef TREZOR_FONT_NORMAL_ENABLE #ifdef TREZOR_FONT_NORMAL_ENABLE
#include "font_roboto_regular_20.h" #include "font_roboto_regular_20.h"
#endif #endif
@ -37,17 +37,15 @@
#include "common.h" #include "common.h"
#include "display.h" #include "display.h"
#include <string.h>
#include <stdarg.h> #include <stdarg.h>
#include <string.h>
#include "memzero.h" #include "memzero.h"
static int DISPLAY_BACKLIGHT = -1; static int DISPLAY_BACKLIGHT = -1;
static int DISPLAY_ORIENTATION = -1; static int DISPLAY_ORIENTATION = -1;
static struct { static struct { int x, y; } DISPLAY_OFFSET;
int x, y;
} DISPLAY_OFFSET;
#ifdef TREZOR_EMULATOR #ifdef TREZOR_EMULATOR
#include "display-unix.h" #include "display-unix.h"
@ -61,44 +59,52 @@ static struct {
// common display functions // common display functions
static inline uint16_t interpolate_color(uint16_t color0, uint16_t color1, uint8_t step) static inline uint16_t interpolate_color(uint16_t color0, uint16_t color1,
{ uint8_t step) {
uint8_t cr, cg, cb; uint8_t cr, cg, cb;
cr = (((color0 & 0xF800) >> 11) * step + ((color1 & 0xF800) >> 11) * (15 - step)) / 15; cr = (((color0 & 0xF800) >> 11) * step +
cg = (((color0 & 0x07E0) >> 5) * step + ((color1 & 0x07E0) >> 5) * (15 - step)) / 15; ((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; cb = ((color0 & 0x001F) * step + (color1 & 0x001F) * (15 - step)) / 15;
return (cr << 11) | (cg << 5) | cb; return (cr << 11) | (cg << 5) | cb;
} }
static inline void set_color_table(uint16_t colortable[16], uint16_t fgcolor, uint16_t bgcolor) static inline void set_color_table(uint16_t colortable[16], uint16_t fgcolor,
{ uint16_t bgcolor) {
for (int i = 0; i < 16; i++) { for (int i = 0; i < 16; i++) {
colortable[i] = interpolate_color(fgcolor, bgcolor, 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) 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); *x0 = MAX(x, 0);
*y0 = MAX(y, 0); *y0 = MAX(y, 0);
*x1 = MIN(x + w - 1, DISPLAY_RESX - 1); *x1 = MIN(x + w - 1, DISPLAY_RESX - 1);
*y1 = MIN(y + h - 1, DISPLAY_RESY - 1); *y1 = MIN(y + h - 1, DISPLAY_RESY - 1);
} }
void display_clear(void) void display_clear(void) {
{
const int saved_orientation = DISPLAY_ORIENTATION; const int saved_orientation = DISPLAY_ORIENTATION;
display_orientation(0); // set MADCTL first so that we can set the window correctly next display_orientation(
display_set_window(0, 0, MAX_DISPLAY_RESX - 1, MAX_DISPLAY_RESY - 1); // address the complete frame memory 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++) { 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 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_set_window(0, 0, DISPLAY_RESX - 1,
display_orientation(saved_orientation); // if valid, go back to the saved orientation 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) void display_bar(int x, int y, int w, int h, uint16_t c) {
{
x += DISPLAY_OFFSET.x; x += DISPLAY_OFFSET.x;
y += DISPLAY_OFFSET.y; y += DISPLAY_OFFSET.y;
int x0, y0, x1, y1; int x0, y0, x1, y1;
@ -112,26 +118,24 @@ void display_bar(int x, int y, int w, int h, uint16_t c)
#define CORNER_RADIUS 16 #define CORNER_RADIUS 16
static const uint8_t cornertable[CORNER_RADIUS * CORNER_RADIUS] = { 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, 0, 0, 1, 5, 9, 12, 14, 15, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 3, 9, 15, 15, 15, 15, 15, 15, 0, 0, 0, 0, 0, 3, 9, 15, 15, 15, 15, 15, 15, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 8, 15, 15, 15, 15, 15, 15, 15, 15, 0, 8, 15, 15, 15, 15, 15, 15, 15, 15, 0, 0, 0, 0, 0, 3, 12, 15, 15,
0, 0, 0, 0, 0, 3, 12, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 0, 0, 0, 0, 3, 14, 15, 15, 15, 15, 15, 15,
0, 0, 0, 0, 3, 14, 15, 15, 15, 15, 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,
0, 0, 0, 3, 14, 15, 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,
0, 0, 0, 12, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 8, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 0, 3, 15, 15, 15,
0, 0, 8, 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, 9, 15, 15, 15, 15, 15, 15,
0, 3, 15, 15, 15, 15, 15, 15, 15, 15, 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,
0, 9, 15, 15, 15, 15, 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,
1, 15, 15, 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,
5, 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, 14, 15, 15, 15,
9, 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, 15, 15, 15,
12, 15, 15, 15, 15, 15, 15, 15, 15, 15, 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) 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) { if (r != 2 && r != 4 && r != 8 && r != 16) {
return; return;
} else { } else {
@ -151,17 +155,15 @@ void display_bar_radius(int x, int y, int w, int h, uint16_t c, uint16_t b, uint
if (rx < CORNER_RADIUS / r && ry < CORNER_RADIUS / r) { if (rx < CORNER_RADIUS / r && ry < CORNER_RADIUS / r) {
uint8_t c = cornertable[rx * r + ry * r * CORNER_RADIUS]; uint8_t c = cornertable[rx * r + ry * r * CORNER_RADIUS];
PIXELDATA(colortable[c]); PIXELDATA(colortable[c]);
} else } else if (rx < CORNER_RADIUS / r && ry >= h - CORNER_RADIUS / r) {
if (rx < CORNER_RADIUS / r && ry >= h - CORNER_RADIUS / r) {
uint8_t c = cornertable[rx * r + (h - 1 - ry) * r * CORNER_RADIUS]; uint8_t c = cornertable[rx * r + (h - 1 - ry) * r * CORNER_RADIUS];
PIXELDATA(colortable[c]); PIXELDATA(colortable[c]);
} else } else if (rx >= w - CORNER_RADIUS / r && ry < CORNER_RADIUS / r) {
if (rx >= w - CORNER_RADIUS / r && ry < CORNER_RADIUS / r) {
uint8_t c = cornertable[(w - 1 - rx) * r + ry * r * CORNER_RADIUS]; uint8_t c = cornertable[(w - 1 - rx) * r + ry * r * CORNER_RADIUS];
PIXELDATA(colortable[c]); PIXELDATA(colortable[c]);
} else } else if (rx >= w - CORNER_RADIUS / r && ry >= h - CORNER_RADIUS / r) {
if (rx >= w - CORNER_RADIUS / r && ry >= h - CORNER_RADIUS / r) { uint8_t c =
uint8_t c = cornertable[(w - 1 - rx) * r + (h - 1 - ry) * r * CORNER_RADIUS]; cornertable[(w - 1 - rx) * r + (h - 1 - ry) * r * CORNER_RADIUS];
PIXELDATA(colortable[c]); PIXELDATA(colortable[c]);
} else { } else {
PIXELDATA(c); PIXELDATA(c);
@ -172,8 +174,8 @@ void display_bar_radius(int x, int y, int w, int h, uint16_t c, uint16_t b, uint
#if TREZOR_MODEL == T #if TREZOR_MODEL == T
static void inflate_callback_image(uint8_t byte1, uint32_t pos, void *userdata) static void inflate_callback_image(uint8_t byte1, uint32_t pos,
{ void *userdata) {
static uint8_t byte0; static uint8_t byte0;
if (pos % 2 == 0) { if (pos % 2 == 0) {
byte0 = byte1; byte0 = byte1;
@ -193,8 +195,7 @@ static void inflate_callback_image(uint8_t byte1, uint32_t pos, void *userdata)
#endif #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 #if TREZOR_MODEL == T
x += DISPLAY_OFFSET.x; x += DISPLAY_OFFSET.x;
y += DISPLAY_OFFSET.y; y += DISPLAY_OFFSET.y;
@ -208,10 +209,12 @@ void display_image(int x, int y, int w, int h, const void *data, int datalen)
#if TREZOR_MODEL == T #if TREZOR_MODEL == T
static void inflate_callback_avatar(uint8_t byte1, uint32_t pos, void *userdata) static void inflate_callback_avatar(uint8_t byte1, uint32_t pos,
{ void *userdata) {
#define AVATAR_BORDER_SIZE 4 #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_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_BORDER_HIGH (AVATAR_IMAGE_SIZE / 2) * (AVATAR_IMAGE_SIZE / 2)
#define AVATAR_ANTIALIAS 1 #define AVATAR_ANTIALIAS 1
static uint8_t byte0; static uint8_t byte0;
@ -240,12 +243,13 @@ static void inflate_callback_avatar(uint8_t byte1, uint32_t pos, void *userdata)
// border area // border area
} else { } else {
#if AVATAR_ANTIALIAS #if AVATAR_ANTIALIAS
d = 31 * (d - AVATAR_BORDER_LOW) / (AVATAR_BORDER_HIGH - AVATAR_BORDER_LOW); d = 31 * (d - AVATAR_BORDER_LOW) /
(AVATAR_BORDER_HIGH - AVATAR_BORDER_LOW);
uint16_t c; uint16_t c;
if (d >= 16) { if (d >= 16) {
c = interpolate_color(bgcolor, fgcolor, d - 16); c = interpolate_color(bgcolor, fgcolor, d - 16);
} else { } else {
c = interpolate_color(fgcolor, (byte0 << 8) | byte1 , d); c = interpolate_color(fgcolor, (byte0 << 8) | byte1, d);
} }
PIXELDATA(c); PIXELDATA(c);
#else #else
@ -257,21 +261,21 @@ static void inflate_callback_avatar(uint8_t byte1, uint32_t pos, void *userdata)
#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 #if TREZOR_MODEL == T
x += DISPLAY_OFFSET.x; x += DISPLAY_OFFSET.x;
y += DISPLAY_OFFSET.y; y += DISPLAY_OFFSET.y;
int x0, y0, x1, y1; int x0, y0, x1, y1;
clamp_coords(x, y, AVATAR_IMAGE_SIZE, AVATAR_IMAGE_SIZE, &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); display_set_window(x0, y0, x1, y1);
int userdata[7] = {AVATAR_IMAGE_SIZE, x0 - x, x1 - x, y0 - y, y1 - y, fgcolor, bgcolor}; int userdata[7] = {AVATAR_IMAGE_SIZE, x0 - x, x1 - x, y0 - y, y1 - y,
fgcolor, bgcolor};
sinf_inflate(data, datalen, inflate_callback_avatar, userdata); sinf_inflate(data, datalen, inflate_callback_avatar, userdata);
#endif #endif
} }
static void inflate_callback_icon(uint8_t byte, uint32_t pos, void *userdata) 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 uint16_t *colortable = (const uint16_t *)(((const int *)userdata) + 5);
const int w = ((const int *)userdata)[0]; const int w = ((const int *)userdata)[0];
const int x0 = ((const int *)userdata)[1]; const int x0 = ((const int *)userdata)[1];
@ -286,15 +290,16 @@ static void inflate_callback_icon(uint8_t byte, uint32_t pos, void *userdata)
} }
} }
void display_icon(int x, int y, int w, int h, 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) {
x += DISPLAY_OFFSET.x; x += DISPLAY_OFFSET.x;
y += DISPLAY_OFFSET.y; y += DISPLAY_OFFSET.y;
x &= ~1; // cannot draw at odd coordinate x &= ~1; // cannot draw at odd coordinate
int x0, y0, x1, y1; int x0, y0, x1, y1;
clamp_coords(x, y, w, h, &x0, &y0, &x1, &y1); clamp_coords(x, y, w, h, &x0, &y0, &x1, &y1);
display_set_window(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}; 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); set_color_table((uint16_t *)(userdata + 5), fgcolor, bgcolor);
sinf_inflate(data, datalen, inflate_callback_icon, userdata); sinf_inflate(data, datalen, inflate_callback_icon, userdata);
} }
@ -303,16 +308,17 @@ void display_icon(int x, int y, int w, int h, const void *data, int datalen, uin
#include "loader.h" #include "loader.h"
static void inflate_callback_loader(uint8_t byte, uint32_t pos, void *userdata) static void inflate_callback_loader(uint8_t byte, uint32_t pos,
{ void *userdata) {
uint8_t *out = (uint8_t *)userdata; uint8_t *out = (uint8_t *)userdata;
out[pos] = byte; out[pos] = byte;
} }
#endif #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 #if TREZOR_MODEL == T
uint16_t colortable[16], iconcolortable[16]; uint16_t colortable[16], iconcolortable[16];
set_color_table(colortable, fgcolor, bgcolor); set_color_table(colortable, fgcolor, bgcolor);
@ -323,8 +329,14 @@ void display_loader(uint16_t progress, int yoffset, uint16_t fgcolor, uint16_t b
(DISPLAY_RESY / 2 + img_loader_size - 1 + yoffset >= DISPLAY_RESY)) { (DISPLAY_RESY / 2 + img_loader_size - 1 + yoffset >= DISPLAY_RESY)) {
return; 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); display_set_window(DISPLAY_RESX / 2 - img_loader_size,
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)) { 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]; uint8_t icondata[LOADER_ICON_SIZE * LOADER_ICON_SIZE / 2];
sinf_inflate(icon + 12, iconlen - 12, inflate_callback_loader, icondata); sinf_inflate(icon + 12, iconlen - 12, inflate_callback_loader, icondata);
icon = icondata; icon = icondata;
@ -339,21 +351,24 @@ void display_loader(uint16_t progress, int yoffset, uint16_t fgcolor, uint16_t b
mx = img_loader_size * 2 - 1 - x; mx = img_loader_size * 2 - 1 - x;
my = img_loader_size * 2 - 1 - y; my = img_loader_size * 2 - 1 - y;
a = 499 - (img_loader[my][mx] >> 8); a = 499 - (img_loader[my][mx] >> 8);
} else } else if (mx >= img_loader_size) {
if (mx >= img_loader_size) {
mx = img_loader_size * 2 - 1 - x; mx = img_loader_size * 2 - 1 - x;
a = img_loader[my][mx] >> 8; a = img_loader[my][mx] >> 8;
} else } else if (my >= img_loader_size) {
if (my >= img_loader_size) {
my = img_loader_size * 2 - 1 - y; my = img_loader_size * 2 - 1 - y;
a = 500 + (img_loader[my][mx] >> 8); a = 500 + (img_loader[my][mx] >> 8);
} else { } else {
a = 999 - (img_loader[my][mx] >> 8); a = 999 - (img_loader[my][mx] >> 8);
} }
// inside of circle - draw glyph // inside of circle - draw glyph
#define LOADER_ICON_CORNER_CUT 2 #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)) { if (icon &&
int i = (x - (img_loader_size - (LOADER_ICON_SIZE / 2))) + (y - (img_loader_size - (LOADER_ICON_SIZE / 2))) * LOADER_ICON_SIZE; 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; uint8_t c;
if (i % 2) { if (i % 2) {
c = icon[i / 2] & 0x0F; c = icon[i / 2] & 0x0F;
@ -380,18 +395,17 @@ void display_loader(uint16_t progress, int yoffset, uint16_t fgcolor, uint16_t b
#define DISPLAY_PRINT_COLS (DISPLAY_RESX / 6) #define DISPLAY_PRINT_COLS (DISPLAY_RESX / 6)
#define DISPLAY_PRINT_ROWS (DISPLAY_RESY / 8) #define DISPLAY_PRINT_ROWS (DISPLAY_RESY / 8)
static char display_print_buf[DISPLAY_PRINT_ROWS][DISPLAY_PRINT_COLS]; 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 // set colors for display_print function
void display_print_color(uint16_t fgcolor, uint16_t bgcolor) void display_print_color(uint16_t fgcolor, uint16_t bgcolor) {
{
display_print_fgcolor = fgcolor; display_print_fgcolor = fgcolor;
display_print_bgcolor = bgcolor; display_print_bgcolor = bgcolor;
} }
// display text using bitmap font // display text using bitmap font
void display_print(const char *text, int textlen) void display_print(const char *text, int textlen) {
{
static uint8_t row = 0, col = 0; static uint8_t row = 0, col = 0;
// determine text length if not provided // determine text length if not provided
@ -401,7 +415,6 @@ void display_print(const char *text, int textlen)
// print characters to internal buffer (display_print_buf) // print characters to internal buffer (display_print_buf)
for (int i = 0; i < textlen; i++) { for (int i = 0; i < textlen; i++) {
switch (text[i]) { switch (text[i]) {
case '\r': case '\r':
break; break;
@ -422,12 +435,12 @@ void display_print(const char *text, int textlen)
if (row >= DISPLAY_PRINT_ROWS) { if (row >= DISPLAY_PRINT_ROWS) {
for (int j = 0; j < DISPLAY_PRINT_ROWS - 1; j++) { for (int j = 0; j < DISPLAY_PRINT_ROWS - 1; j++) {
memcpy(display_print_buf[j], display_print_buf[j + 1], DISPLAY_PRINT_COLS); memcpy(display_print_buf[j], display_print_buf[j + 1],
DISPLAY_PRINT_COLS);
} }
memzero(display_print_buf[DISPLAY_PRINT_ROWS - 1], DISPLAY_PRINT_COLS); memzero(display_print_buf[DISPLAY_PRINT_ROWS - 1], DISPLAY_PRINT_COLS);
row = DISPLAY_PRINT_ROWS - 1; row = DISPLAY_PRINT_ROWS - 1;
} }
} }
// render buffer to display // render buffer to display
@ -435,8 +448,10 @@ void display_print(const char *text, int textlen)
for (int i = 0; i < DISPLAY_RESX * DISPLAY_RESY; i++) { for (int i = 0; i < DISPLAY_RESX * DISPLAY_RESY; i++) {
int x = (i % DISPLAY_RESX); int x = (i % DISPLAY_RESX);
int y = (i / DISPLAY_RESX); int y = (i / DISPLAY_RESX);
const int j = y % 8; y /= 8; const int j = y % 8;
const int k = x % 6; x /= 6; y /= 8;
const int k = x % 6;
x /= 6;
char c; char c;
if (x < DISPLAY_PRINT_COLS && y < DISPLAY_PRINT_ROWS) { if (x < DISPLAY_PRINT_COLS && y < DISPLAY_PRINT_ROWS) {
c = display_print_buf[y][x] & 0x7F; c = display_print_buf[y][x] & 0x7F;
@ -465,8 +480,7 @@ void display_print(const char *text, int textlen)
#endif #endif
// variadic display_print // variadic display_print
void display_printf(const char *fmt, ...) void display_printf(const char *fmt, ...) {
{
if (!strchr(fmt, '%')) { if (!strchr(fmt, '%')) {
display_print(fmt, strlen(fmt)); display_print(fmt, strlen(fmt));
} else { } else {
@ -483,8 +497,7 @@ void display_printf(const char *fmt, ...)
#if TREZOR_MODEL == T #if TREZOR_MODEL == T
static const uint8_t *get_glyph(int font, uint8_t c) static const uint8_t *get_glyph(int font, uint8_t c) {
{
if (c >= ' ' && c <= '~') { if (c >= ' ' && c <= '~') {
// do nothing - valid ASCII // do nothing - valid ASCII
} else } else
@ -521,8 +534,8 @@ static const uint8_t *get_glyph(int font, uint8_t c)
#if TREZOR_MODEL == T #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) 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 // determine text length if not provided
if (textlen < 0) { if (textlen < 0) {
textlen = strlen(text); textlen = strlen(text);
@ -551,13 +564,13 @@ static void display_text_render(int x, int y, const char *text, int textlen, int
const int rx = i - sx; const int rx = i - sx;
const int ry = j - sy; const int ry = j - sy;
const int a = rx + ry * w; const int a = rx + ry * w;
#if FONT_BPP == 2 #if FONT_BPP == 2
const uint8_t c = ((g[5 + a / 4] >> (6 - (a % 4) * 2)) & 0x03) * 5; const uint8_t c = ((g[5 + a / 4] >> (6 - (a % 4) * 2)) & 0x03) * 5;
#elif FONT_BPP == 4 #elif FONT_BPP == 4
const uint8_t c = (g[5 + a / 2] >> (4 - (a % 2) * 4)) & 0x0F; const uint8_t c = (g[5 + a / 2] >> (4 - (a % 2) * 4)) & 0x0F;
#else #else
#error Unsupported FONT_BPP value #error Unsupported FONT_BPP value
#endif #endif
PIXELDATA(colortable[c]); PIXELDATA(colortable[c]);
} }
} }
@ -568,8 +581,8 @@ static void display_text_render(int x, int y, const char *text, int textlen, int
#endif #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 #if TREZOR_MODEL == T
x += DISPLAY_OFFSET.x; x += DISPLAY_OFFSET.x;
y += DISPLAY_OFFSET.y; y += DISPLAY_OFFSET.y;
@ -577,8 +590,8 @@ void display_text(int x, int y, const char *text, int textlen, int font, uint16_
#endif #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 #if TREZOR_MODEL == T
x += DISPLAY_OFFSET.x; x += DISPLAY_OFFSET.x;
y += DISPLAY_OFFSET.y; y += DISPLAY_OFFSET.y;
@ -587,8 +600,8 @@ void display_text_center(int x, int y, const char *text, int textlen, int font,
#endif #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 #if TREZOR_MODEL == T
x += DISPLAY_OFFSET.x; x += DISPLAY_OFFSET.x;
y += DISPLAY_OFFSET.y; y += DISPLAY_OFFSET.y;
@ -598,8 +611,7 @@ void display_text_right(int x, int y, const char *text, int textlen, int font, u
} }
// compute the width of the text (in pixels) // compute the width of the text (in pixels)
int display_text_width(const char *text, int textlen, int font) int display_text_width(const char *text, int textlen, int font) {
{
int width = 0; int width = 0;
#if TREZOR_MODEL == T #if TREZOR_MODEL == T
// determine text length if not provided // determine text length if not provided
@ -628,30 +640,25 @@ int display_text_width(const char *text, int textlen, int font)
#define QR_MAX_VERSION 9 #define QR_MAX_VERSION 9
void display_qrcode(int x, int y, const char *data, int datalen, uint8_t scale) void display_qrcode(int x, int y, const char *data, int datalen,
{ uint8_t scale) {
if (scale < 1 || scale > 10) return; if (scale < 1 || scale > 10) return;
uint8_t codedata[qrcodegen_BUFFER_LEN_FOR_VERSION(QR_MAX_VERSION)]; uint8_t codedata[qrcodegen_BUFFER_LEN_FOR_VERSION(QR_MAX_VERSION)];
uint8_t tempdata[qrcodegen_BUFFER_LEN_FOR_VERSION(QR_MAX_VERSION)]; uint8_t tempdata[qrcodegen_BUFFER_LEN_FOR_VERSION(QR_MAX_VERSION)];
int side = 0; int side = 0;
if (qrcodegen_encodeText( if (qrcodegen_encodeText(data, tempdata, codedata, qrcodegen_Ecc_MEDIUM,
data, qrcodegen_VERSION_MIN, QR_MAX_VERSION,
tempdata, qrcodegen_Mask_AUTO, true)) {
codedata,
qrcodegen_Ecc_MEDIUM,
qrcodegen_VERSION_MIN,
QR_MAX_VERSION,
qrcodegen_Mask_AUTO,
true)) {
side = qrcodegen_getSize(codedata); side = qrcodegen_getSize(codedata);
} }
x += DISPLAY_OFFSET.x - (side + 2) * scale / 2; x += DISPLAY_OFFSET.x - (side + 2) * scale / 2;
y += DISPLAY_OFFSET.y - (side + 2) * scale / 2; y += DISPLAY_OFFSET.y - (side + 2) * scale / 2;
int x0, y0, x1, y1; int x0, y0, x1, y1;
clamp_coords(x, y, (side + 2) * scale, (side + 2) * scale, &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); display_set_window(x0, y0, x1, y1);
for (int j = y0; j <= y1; j++) { for (int j = y0; j <= y1; j++) {
for (int i = x0; i <= x1; i++) { for (int i = x0; i <= x1; i++) {
@ -671,8 +678,7 @@ void display_qrcode(int x, int y, const char *data, int datalen, uint8_t scale)
} }
} }
void display_offset(int set_xy[2], int *get_x, int *get_y) void display_offset(int set_xy[2], int *get_x, int *get_y) {
{
if (set_xy) { if (set_xy) {
DISPLAY_OFFSET.x = set_xy[0]; DISPLAY_OFFSET.x = set_xy[0];
DISPLAY_OFFSET.y = set_xy[1]; DISPLAY_OFFSET.y = set_xy[1];
@ -681,8 +687,7 @@ void display_offset(int set_xy[2], int *get_x, int *get_y)
*get_y = DISPLAY_OFFSET.y; *get_y = DISPLAY_OFFSET.y;
} }
int display_orientation(int degrees) int display_orientation(int degrees) {
{
if (degrees != DISPLAY_ORIENTATION) { if (degrees != DISPLAY_ORIENTATION) {
#if TREZOR_MODEL == T #if TREZOR_MODEL == T
if (degrees == 0 || degrees == 90 || degrees == 180 || degrees == 270) { if (degrees == 0 || degrees == 90 || degrees == 180 || degrees == 270) {
@ -698,8 +703,7 @@ int display_orientation(int degrees)
return DISPLAY_ORIENTATION; return DISPLAY_ORIENTATION;
} }
int display_backlight(int val) int display_backlight(int val) {
{
#if TREZOR_MODEL == 1 #if TREZOR_MODEL == 1
val = 255; val = 255;
#endif #endif
@ -710,8 +714,7 @@ int display_backlight(int val)
return DISPLAY_BACKLIGHT; return DISPLAY_BACKLIGHT;
} }
void display_fade(int start, int end, int delay) void display_fade(int start, int end, int delay) {
{
for (int i = 0; i < 100; i++) { for (int i = 0; i < 100; i++) {
display_backlight(start + i * (end - start) / 100); display_backlight(start + i * (end - start) / 100);
hal_delay(delay / 100); hal_delay(delay / 100);

View File

@ -74,22 +74,31 @@ void display_save(const char *prefix);
void display_clear(void); void display_clear(void);
void display_bar(int x, int y, int w, int h, uint16_t c); 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_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_avatar(int x, int y, const void *data, int datalen,
void display_icon(int x, int y, int w, int h, const void *data, int datalen, uint16_t fgcolor, uint16_t bgcolor); 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_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 #ifndef TREZOR_PRINT_DISABLE
void display_print_color(uint16_t fgcolor, uint16_t bgcolor); void display_print_color(uint16_t fgcolor, uint16_t bgcolor);
void display_print(const char *text, int textlen); 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 #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,
void display_text_center(int x, int y, const char *text, int textlen, int font, uint16_t fgcolor, uint16_t bgcolor); 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_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); 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); void display_qrcode(int x, int y, const char *data, int datalen, uint8_t scale);

View File

@ -1,5 +1,7 @@
#include "font_bitmap.h" #include "font_bitmap.h"
// clang-format off
const uint8_t * const Font_Bitmap = (const uint8_t * const) const uint8_t * const Font_Bitmap = (const uint8_t * const)
"\x00\x00\x00\x00\x00" "\x00\x00\x00\x00\x00"
"\x00\x00\x5f\x00\x00" "\x00\x00\x5f\x00\x00"

View File

@ -1,3 +1,3 @@
#include <stdint.h> #include <stdint.h>
extern const uint8_t * const Font_Bitmap; extern const uint8_t* const Font_Bitmap;

View File

@ -17,6 +17,8 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>. * along with this program. If not, see <http://www.gnu.org/licenses/>.
*/ */
// clang-format off
/* /*
* stream_inflate - tiny inflate library with output streaming * stream_inflate - tiny inflate library with output streaming
* *

View File

@ -22,6 +22,9 @@
#include <stdint.h> #include <stdint.h>
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 #endif

View File

@ -1,3 +1,4 @@
// clang-format off
static const int img_loader_size = 60; static const int img_loader_size = 60;
static const uint16_t img_loader[60][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,}, {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,},

View File

@ -33,7 +33,9 @@ typedef struct _mp_obj_Display_t {
/// ''' /// '''
/// Initialize the display. /// 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) { 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_arg_check_num(n_args, n_kw, 0, 0, false);
mp_obj_Display_t *o = m_new_obj(mp_obj_Display_t); mp_obj_Display_t *o = m_new_obj(mp_obj_Display_t);
o->base.type = type; o->base.type = type;
@ -48,7 +50,8 @@ STATIC mp_obj_t mod_trezorui_Display_clear(mp_obj_t self) {
display_clear(); display_clear();
return mp_const_none; 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: /// def refresh(self) -> None:
/// ''' /// '''
@ -58,11 +61,13 @@ STATIC mp_obj_t mod_trezorui_Display_refresh(mp_obj_t self) {
display_refresh(); display_refresh();
return mp_const_none; 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: /// 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) { 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 x = mp_obj_get_int(args[1]);
@ -73,14 +78,18 @@ STATIC mp_obj_t mod_trezorui_Display_bar(size_t n_args, const mp_obj_t *args) {
display_bar(x, y, w, h, c); display_bar(x, y, w, h, c);
return mp_const_none; 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: /// 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. /// Renders a rounded bar at position (x,y = upper left corner) with width w
/// Background is set to bgcolor and corners are drawn with radius radius. /// 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) { 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 x = mp_obj_get_int(args[1]);
mp_int_t y = mp_obj_get_int(args[2]); mp_int_t y = mp_obj_get_int(args[2]);
mp_int_t w = mp_obj_get_int(args[3]); mp_int_t w = mp_obj_get_int(args[3]);
@ -91,14 +100,18 @@ STATIC mp_obj_t mod_trezorui_Display_bar_radius(size_t n_args, const mp_obj_t *a
display_bar_radius(x, y, w, h, c, b, r); display_bar_radius(x, y, w, h, c, b, r);
return mp_const_none; 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: /// def image(self, x: int, y: int, image: bytes) -> None:
/// ''' /// '''
/// Renders an image at position (x,y). /// Renders an image at position (x,y).
/// The image needs to be in TREZOR Optimized Image Format (TOIF) - full-color mode. /// 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) { 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 x = mp_obj_get_int(args[1]);
mp_int_t y = mp_obj_get_int(args[2]); mp_int_t y = mp_obj_get_int(args[2]);
mp_buffer_info_t image; mp_buffer_info_t image;
@ -116,15 +129,19 @@ STATIC mp_obj_t mod_trezorui_Display_image(size_t n_args, const mp_obj_t *args)
display_image(x, y, w, h, data + 12, datalen); display_image(x, y, w, h, data + 12, datalen);
return mp_const_none; 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). /// Renders an avatar at position (x,y).
/// The image needs to be in TREZOR Optimized Image Format (TOIF) - full-color mode. /// The image needs to be in TREZOR Optimized Image Format (TOIF) -
/// Image needs to be of exactly AVATAR_IMAGE_SIZE x AVATAR_IMAGE_SIZE pixels size. /// 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) { 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 x = mp_obj_get_int(args[1]);
mp_int_t y = mp_obj_get_int(args[2]); mp_int_t y = mp_obj_get_int(args[2]);
mp_buffer_info_t image; mp_buffer_info_t image;
@ -147,12 +164,15 @@ STATIC mp_obj_t mod_trezorui_Display_avatar(size_t n_args, const mp_obj_t *args)
display_avatar(x, y, data + 12, datalen, fgcolor, bgcolor); display_avatar(x, y, data + 12, datalen, fgcolor, bgcolor);
return mp_const_none; 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. /// Renders an icon at position (x,y), fgcolor is used as foreground color,
/// The icon needs to be in TREZOR Optimized Image Format (TOIF) - gray-scale mode. /// 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) { 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 x = mp_obj_get_int(args[1]);
@ -175,15 +195,20 @@ STATIC mp_obj_t mod_trezorui_Display_icon(size_t n_args, const mp_obj_t *args) {
return mp_const_none; return mp_const_none;
} }
STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(mod_trezorui_Display_icon_obj, 6, 6, mod_trezorui_Display_icon); STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(mod_trezorui_Display_icon_obj, 6, 6,
/// def loader(self, progress: int, yoffset: int, fgcolor: int, bgcolor: int, icon: bytes = None, iconfgcolor: int = None) -> None: 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. /// Renders a rotating loader graphic.
/// Progress determines its position (0-1000), fgcolor is used as foreground color, bgcolor as background. /// Progress determines its position (0-1000), fgcolor is used as foreground
/// When icon and iconfgcolor are provided, an icon is drawn in the middle using the color specified in iconfgcolor. /// color, bgcolor as background. When icon and iconfgcolor are provided, an
/// Icon needs to be of exactly LOADER_ICON_SIZE x LOADER_ICON_SIZE pixels size. /// 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) { 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 progress = mp_obj_get_int(args[1]);
mp_int_t yoffset = mp_obj_get_int(args[2]); mp_int_t yoffset = mp_obj_get_int(args[2]);
mp_int_t fgcolor = mp_obj_get_int(args[3]); mp_int_t fgcolor = mp_obj_get_int(args[3]);
@ -210,13 +235,15 @@ STATIC mp_obj_t mod_trezorui_Display_loader(size_t n_args, const mp_obj_t *args)
} else { } else {
iconfgcolor = ~bgcolor; // invert iconfgcolor = ~bgcolor; // invert
} }
display_loader(progress, yoffset, fgcolor, bgcolor, icon.buf, icon.len, iconfgcolor); display_loader(progress, yoffset, fgcolor, bgcolor, icon.buf, icon.len,
iconfgcolor);
} else { } else {
display_loader(progress, yoffset, fgcolor, bgcolor, NULL, 0, 0); display_loader(progress, yoffset, fgcolor, bgcolor, NULL, 0, 0);
} }
return mp_const_none; 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: /// def print(self, text: str) -> None:
/// ''' /// '''
@ -230,14 +257,16 @@ STATIC mp_obj_t mod_trezorui_Display_print(mp_obj_t self, mp_obj_t text) {
} }
return mp_const_none; 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. /// Renders left-aligned text at position (x,y) where x is left position and
/// Font font is used for rendering, fgcolor is used as foreground color, bgcolor as background. /// y is baseline. Font font is used for rendering, fgcolor is used as
/// Fills at least minwidth pixels with bgcolor. /// foreground color, bgcolor as background. Fills at least minwidth pixels
/// Returns width of rendered text in 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) { 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 x = mp_obj_get_int(args[1]);
@ -256,16 +285,19 @@ STATIC mp_obj_t mod_trezorui_Display_text(size_t n_args, const mp_obj_t *args) {
display_text(x, y, text.buf, text.len, font, fgcolor, bgcolor); display_text(x, y, text.buf, text.len, font, fgcolor, bgcolor);
return mp_obj_new_int(w); 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: /// 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. /// Renders text centered at position (x,y) where x is text center and y is
/// Font font is used for rendering, fgcolor is used as foreground color, bgcolor as background. /// baseline. Font font is used for rendering, fgcolor is used as foreground
/// Fills at least minwidth pixels with bgcolor. /// color, bgcolor as background. Fills at least minwidth pixels with
/// Returns width of rendered text in pixels. /// 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) { 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 x = mp_obj_get_int(args[1]);
mp_int_t y = mp_obj_get_int(args[2]); mp_int_t y = mp_obj_get_int(args[2]);
mp_buffer_info_t text; mp_buffer_info_t text;
@ -282,16 +314,20 @@ STATIC mp_obj_t mod_trezorui_Display_text_center(size_t n_args, const mp_obj_t *
display_text_center(x, y, text.buf, text.len, font, fgcolor, bgcolor); display_text_center(x, y, text.buf, text.len, font, fgcolor, bgcolor);
return mp_obj_new_int(w); 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: /// 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. /// Renders right-aligned text at position (x,y) where x is right position
/// Font font is used for rendering, fgcolor is used as foreground color, bgcolor as background. /// and y is baseline. Font font is used for rendering, fgcolor is used as
/// Fills at least minwidth pixels with bgcolor. /// foreground color, bgcolor as background. Fills at least minwidth pixels
/// Returns width of rendered text in 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) { 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 x = mp_obj_get_int(args[1]);
mp_int_t y = mp_obj_get_int(args[2]); mp_int_t y = mp_obj_get_int(args[2]);
mp_buffer_info_t text; mp_buffer_info_t text;
@ -308,27 +344,32 @@ STATIC mp_obj_t mod_trezorui_Display_text_right(size_t n_args, const mp_obj_t *a
display_text_right(x, y, text.buf, text.len, font, fgcolor, bgcolor); display_text_right(x, y, text.buf, text.len, font, fgcolor, bgcolor);
return mp_obj_new_int(w); 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: /// def text_width(self, text: str, font: int) -> int:
/// ''' /// '''
/// Returns a width of text in pixels. Font font is used for rendering. /// 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) { 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_buffer_info_t txt;
mp_get_buffer_raise(text, &txt, MP_BUFFER_READ); mp_get_buffer_raise(text, &txt, MP_BUFFER_READ);
mp_int_t f = mp_obj_get_int(font); mp_int_t f = mp_obj_get_int(font);
int w = display_text_width(txt.buf, txt.len, f); int w = display_text_width(txt.buf, txt.len, f);
return mp_obj_new_int(w); 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: /// def qrcode(self, x: int, y: int, data: bytes, scale: int) -> None:
/// ''' /// '''
/// Renders data encoded as a QR code centered at position (x,y). /// Renders data encoded as a QR code centered at position (x,y).
/// Scale determines a zoom factor. /// Scale determines a zoom factor.
/// ''' /// '''
STATIC mp_obj_t mod_trezorui_Display_qrcode(size_t n_args, const mp_obj_t *args) { 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 x = mp_obj_get_int(args[1]);
mp_int_t y = mp_obj_get_int(args[2]); mp_int_t y = mp_obj_get_int(args[2]);
mp_int_t scale = mp_obj_get_int(args[4]); mp_int_t scale = mp_obj_get_int(args[4]);
@ -342,15 +383,18 @@ STATIC mp_obj_t mod_trezorui_Display_qrcode(size_t n_args, const mp_obj_t *args)
} }
return mp_const_none; 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: /// def orientation(self, degrees: int = None) -> int:
/// ''' /// '''
/// Sets display orientation to 0, 90, 180 or 270 degrees. /// Sets display orientation to 0, 90, 180 or 270 degrees.
/// Everything needs to be redrawn again when this function is used. /// Everything needs to be redrawn again when this function is used.
/// Call without the degrees parameter to just perform the read of the value. /// 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) { STATIC mp_obj_t mod_trezorui_Display_orientation(size_t n_args,
const mp_obj_t *args) {
mp_int_t deg; mp_int_t deg;
if (n_args > 1) { if (n_args > 1) {
deg = mp_obj_get_int(args[1]); deg = mp_obj_get_int(args[1]);
@ -363,14 +407,17 @@ STATIC mp_obj_t mod_trezorui_Display_orientation(size_t n_args, const mp_obj_t *
} }
return MP_OBJ_NEW_SMALL_INT(deg); 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: /// def backlight(self, val: int = None) -> int:
/// ''' /// '''
/// Sets backlight intensity to the value specified in val. /// Sets backlight intensity to the value specified in val.
/// Call without the val parameter to just perform the read of the value. /// 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) { STATIC mp_obj_t mod_trezorui_Display_backlight(size_t n_args,
const mp_obj_t *args) {
mp_int_t val; mp_int_t val;
if (n_args > 1) { if (n_args > 1) {
val = mp_obj_get_int(args[1]); val = mp_obj_get_int(args[1]);
@ -383,14 +430,17 @@ STATIC mp_obj_t mod_trezorui_Display_backlight(size_t n_args, const mp_obj_t *ar
} }
return MP_OBJ_NEW_SMALL_INT(val); 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]: /// def offset(self, xy: Tuple[int, int] = None) -> Tuple[int, int]:
/// ''' /// '''
/// Sets offset (x, y) for all subsequent drawing calls. /// Sets offset (x, y) for all subsequent drawing calls.
/// Call without the xy parameter to just perform the read of the value. /// 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) { STATIC mp_obj_t mod_trezorui_Display_offset(size_t n_args,
const mp_obj_t *args) {
int xy[2], x, y; int xy[2], x, y;
if (n_args > 1) { if (n_args > 1) {
size_t xy_cnt; size_t xy_cnt;
@ -414,7 +464,8 @@ STATIC mp_obj_t mod_trezorui_Display_offset(size_t n_args, const mp_obj_t *args)
tuple->items[1] = MP_OBJ_NEW_SMALL_INT(y); tuple->items[1] = MP_OBJ_NEW_SMALL_INT(y);
return MP_OBJ_FROM_PTR(tuple); 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: /// def save(self, prefix: str) -> None:
/// ''' /// '''
@ -428,40 +479,49 @@ STATIC mp_obj_t mod_trezorui_Display_save(mp_obj_t self, mp_obj_t prefix) {
} }
return mp_const_none; 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[] = { 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_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_refresh),
{ MP_ROM_QSTR(MP_QSTR_bar), MP_ROM_PTR(&mod_trezorui_Display_bar_obj) }, MP_ROM_PTR(&mod_trezorui_Display_refresh_obj)},
{ MP_ROM_QSTR(MP_QSTR_bar_radius), MP_ROM_PTR(&mod_trezorui_Display_bar_radius_obj) }, {MP_ROM_QSTR(MP_QSTR_bar), MP_ROM_PTR(&mod_trezorui_Display_bar_obj)},
{ MP_ROM_QSTR(MP_QSTR_image), MP_ROM_PTR(&mod_trezorui_Display_image_obj) }, {MP_ROM_QSTR(MP_QSTR_bar_radius),
{ MP_ROM_QSTR(MP_QSTR_avatar), MP_ROM_PTR(&mod_trezorui_Display_avatar_obj) }, MP_ROM_PTR(&mod_trezorui_Display_bar_radius_obj)},
{ MP_ROM_QSTR(MP_QSTR_icon), MP_ROM_PTR(&mod_trezorui_Display_icon_obj) }, {MP_ROM_QSTR(MP_QSTR_image), MP_ROM_PTR(&mod_trezorui_Display_image_obj)},
{ MP_ROM_QSTR(MP_QSTR_loader), MP_ROM_PTR(&mod_trezorui_Display_loader_obj) }, {MP_ROM_QSTR(MP_QSTR_avatar), MP_ROM_PTR(&mod_trezorui_Display_avatar_obj)},
{ MP_ROM_QSTR(MP_QSTR_print), MP_ROM_PTR(&mod_trezorui_Display_print_obj) }, {MP_ROM_QSTR(MP_QSTR_icon), MP_ROM_PTR(&mod_trezorui_Display_icon_obj)},
{ MP_ROM_QSTR(MP_QSTR_text), MP_ROM_PTR(&mod_trezorui_Display_text_obj) }, {MP_ROM_QSTR(MP_QSTR_loader), MP_ROM_PTR(&mod_trezorui_Display_loader_obj)},
{ MP_ROM_QSTR(MP_QSTR_text_center), MP_ROM_PTR(&mod_trezorui_Display_text_center_obj) }, {MP_ROM_QSTR(MP_QSTR_print), MP_ROM_PTR(&mod_trezorui_Display_print_obj)},
{ MP_ROM_QSTR(MP_QSTR_text_right), MP_ROM_PTR(&mod_trezorui_Display_text_right_obj) }, {MP_ROM_QSTR(MP_QSTR_text), MP_ROM_PTR(&mod_trezorui_Display_text_obj)},
{ MP_ROM_QSTR(MP_QSTR_text_width), MP_ROM_PTR(&mod_trezorui_Display_text_width_obj) }, {MP_ROM_QSTR(MP_QSTR_text_center),
{ MP_ROM_QSTR(MP_QSTR_qrcode), MP_ROM_PTR(&mod_trezorui_Display_qrcode_obj) }, MP_ROM_PTR(&mod_trezorui_Display_text_center_obj)},
{ MP_ROM_QSTR(MP_QSTR_orientation), MP_ROM_PTR(&mod_trezorui_Display_orientation_obj) }, {MP_ROM_QSTR(MP_QSTR_text_right),
{ MP_ROM_QSTR(MP_QSTR_backlight), MP_ROM_PTR(&mod_trezorui_Display_backlight_obj) }, MP_ROM_PTR(&mod_trezorui_Display_text_right_obj)},
{ MP_ROM_QSTR(MP_QSTR_offset), MP_ROM_PTR(&mod_trezorui_Display_offset_obj) }, {MP_ROM_QSTR(MP_QSTR_text_width),
{ MP_ROM_QSTR(MP_QSTR_save), MP_ROM_PTR(&mod_trezorui_Display_save_obj) }, MP_ROM_PTR(&mod_trezorui_Display_text_width_obj)},
{ MP_ROM_QSTR(MP_QSTR_WIDTH), MP_OBJ_NEW_SMALL_INT(DISPLAY_RESX) }, {MP_ROM_QSTR(MP_QSTR_qrcode), MP_ROM_PTR(&mod_trezorui_Display_qrcode_obj)},
{ MP_ROM_QSTR(MP_QSTR_HEIGHT), MP_OBJ_NEW_SMALL_INT(DISPLAY_RESY) }, {MP_ROM_QSTR(MP_QSTR_orientation),
{ MP_ROM_QSTR(MP_QSTR_FONT_SIZE), MP_OBJ_NEW_SMALL_INT(FONT_SIZE) }, MP_ROM_PTR(&mod_trezorui_Display_orientation_obj)},
{ MP_ROM_QSTR(MP_QSTR_FONT_NORMAL), MP_OBJ_NEW_SMALL_INT(FONT_NORMAL) }, {MP_ROM_QSTR(MP_QSTR_backlight),
{ MP_ROM_QSTR(MP_QSTR_FONT_BOLD), MP_OBJ_NEW_SMALL_INT(FONT_BOLD) }, MP_ROM_PTR(&mod_trezorui_Display_backlight_obj)},
{ MP_ROM_QSTR(MP_QSTR_FONT_MONO), MP_OBJ_NEW_SMALL_INT(FONT_MONO) }, {MP_ROM_QSTR(MP_QSTR_offset), MP_ROM_PTR(&mod_trezorui_Display_offset_obj)},
{ MP_ROM_QSTR(MP_QSTR_FONT_MONO_BOLD), MP_OBJ_NEW_SMALL_INT(FONT_MONO_BOLD) }, {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 = { STATIC const mp_obj_type_t mod_trezorui_Display_type = {
{ &mp_type_type }, {&mp_type_type},
.name = MP_QSTR_Display, .name = MP_QSTR_Display,
.make_new = mod_trezorui_Display_make_new, .make_new = mod_trezorui_Display_make_new,
.locals_dict = (void*)&mod_trezorui_Display_locals_dict, .locals_dict = (void *)&mod_trezorui_Display_locals_dict,
}; };

View File

@ -17,9 +17,9 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>. * along with this program. If not, see <http://www.gnu.org/licenses/>.
*/ */
#include <stdint.h>
#include <stdio.h> #include <stdio.h>
#include <string.h> #include <string.h>
#include <stdint.h>
#include "py/runtime.h" #include "py/runtime.h"
@ -28,14 +28,15 @@
#include "modtrezorui-display.h" #include "modtrezorui-display.h"
STATIC const mp_rom_map_elem_t mp_module_trezorui_globals_table[] = { 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___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_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 = { 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, .globals = (mp_obj_dict_t*)&mp_module_trezorui_globals,
}; };

View File

@ -54,7 +54,8 @@ STATIC mp_obj_t mod_trezorutils_consteq(mp_obj_t sec, mp_obj_t pub) {
return mp_const_false; 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, /// def memcpy(dst: bytearray, dst_ofs: int,
/// src: bytearray, src_ofs: int, /// src: bytearray, src_ofs: int,
@ -81,11 +82,12 @@ STATIC mp_obj_t mod_trezorutils_memcpy(size_t n_args, const mp_obj_t *args) {
size_t src_rem = (src_ofs < src.len) ? src.len - src_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 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: /// def halt(msg: str = None) -> None:
/// ''' /// '''
@ -100,7 +102,8 @@ STATIC mp_obj_t mod_trezorutils_halt(size_t n_args, const mp_obj_t *args) {
} }
return mp_const_none; 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: /// 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) { STATIC mp_obj_t mod_trezorutils_set_mode_unprivileged(void) {
#ifndef TREZOR_EMULATOR #ifndef TREZOR_EMULATOR
__asm__ volatile("msr control, %0" :: "r" (0x1)); __asm__ volatile("msr control, %0" ::"r"(0x1));
__asm__ volatile("isb"); __asm__ volatile("isb");
#endif #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) #define MP_QSTR(s) PASTER(s)
STATIC const mp_rom_map_elem_t mp_module_trezorutils_globals_table[] = { 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___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_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_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_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_set_mode_unprivileged),
MP_ROM_PTR(&mod_trezorutils_set_mode_unprivileged_obj)},
// various built-in constants // various built-in constants
{ MP_ROM_QSTR(MP_QSTR_GITREV), MP_ROM_QSTR(MP_QSTR(GITREV)) }, {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_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_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_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_MODEL), MP_ROM_QSTR(MP_QSTR(TREZOR_MODEL))},
#ifdef TREZOR_EMULATOR #ifdef TREZOR_EMULATOR
{ MP_ROM_QSTR(MP_QSTR_EMULATOR), mp_const_true }, {MP_ROM_QSTR(MP_QSTR_EMULATOR), mp_const_true},
#else #else
{ MP_ROM_QSTR(MP_QSTR_EMULATOR), mp_const_false }, {MP_ROM_QSTR(MP_QSTR_EMULATOR), mp_const_false},
#endif #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 = { const mp_obj_module_t mp_module_trezorutils = {
.base = { &mp_type_module }, .base = {&mp_type_module},
.globals = (mp_obj_dict_t*)&mp_module_trezorutils_globals, .globals = (mp_obj_dict_t *)&mp_module_trezorutils_globals,
}; };
#endif // MICROPY_PY_TREZORUTILS #endif // MICROPY_PY_TREZORUTILS

View File

@ -17,8 +17,8 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>. * along with this program. If not, see <http://www.gnu.org/licenses/>.
*/ */
#include "py/runtime.h"
#include "py/objint.h" #include "py/objint.h"
#include "py/runtime.h"
#ifndef __TREZOROBJ_H__ #ifndef __TREZOROBJ_H__
#define __TREZOROBJ_H__ #define __TREZOROBJ_H__
@ -33,16 +33,15 @@ static inline mp_int_t trezor_obj_get_int(mp_obj_t obj) {
if (MP_OBJ_IS_SMALL_INT(obj)) { if (MP_OBJ_IS_SMALL_INT(obj)) {
mp_int_t i = MP_OBJ_SMALL_INT_VALUE(obj); mp_int_t i = MP_OBJ_SMALL_INT_VALUE(obj);
return i; return i;
} } else if (MP_OBJ_IS_TYPE(obj, &mp_type_int)) {
else if (MP_OBJ_IS_TYPE(obj, &mp_type_int)) {
mp_int_t i = 0; mp_int_t i = 0;
mp_obj_int_t *self = MP_OBJ_TO_PTR(obj); mp_obj_int_t *self = MP_OBJ_TO_PTR(obj);
if (!mpz_as_int_checked(&self->mpz, &i)) { if (!mpz_as_int_checked(&self->mpz, &i)) {
mp_raise_msg(&mp_type_OverflowError, "value does not fit into signed int type"); mp_raise_msg(&mp_type_OverflowError,
"value does not fit into signed int type");
} }
return i; return i;
} } else {
else {
mp_raise_TypeError("value is not int"); mp_raise_TypeError("value is not int");
} }
} }
@ -55,16 +54,15 @@ static inline mp_uint_t trezor_obj_get_uint(mp_obj_t obj) {
mp_int_t i = MP_OBJ_SMALL_INT_VALUE(obj); mp_int_t i = MP_OBJ_SMALL_INT_VALUE(obj);
mp_uint_t u = i; mp_uint_t u = i;
return u; return u;
} } else if (MP_OBJ_IS_TYPE(obj, &mp_type_int)) {
else if (MP_OBJ_IS_TYPE(obj, &mp_type_int)) {
mp_uint_t u = 0; mp_uint_t u = 0;
mp_obj_int_t *self = MP_OBJ_TO_PTR(obj); mp_obj_int_t *self = MP_OBJ_TO_PTR(obj);
if (!mpz_as_uint_checked(&self->mpz, &u)) { if (!mpz_as_uint_checked(&self->mpz, &u)) {
mp_raise_msg(&mp_type_OverflowError, "value does not fit into unsigned int type"); mp_raise_msg(&mp_type_OverflowError,
"value does not fit into unsigned int type");
} }
return u; return u;
} } else {
else {
mp_raise_TypeError("value is not int"); mp_raise_TypeError("value is not int");
} }
} }

View File

@ -19,9 +19,9 @@
#include <stdint.h> #include <stdint.h>
#include <string.h> #include <string.h>
#include "blake2s.h"
#include "common.h" #include "common.h"
#include "flash.h" #include "flash.h"
#include "blake2s.h"
// symbols from bootloader.bin => bootloader.o // symbols from bootloader.bin => bootloader.o
extern const uint32_t _binary_embed_firmware_bootloader_bin_start; extern const uint32_t _binary_embed_firmware_bootloader_bin_start;
@ -31,32 +31,52 @@ extern const uint32_t _binary_embed_firmware_bootloader_bin_size;
static secbool known_bootloader(const uint8_t *hash, int len) { static secbool known_bootloader(const uint8_t *hash, int len) {
if (len != 32) return secfalse; if (len != 32) return secfalse;
// bootloader-2.0.1.bin (padded with 0x00) // 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) // 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) // 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) // 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) // 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) // 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; if (0 == memcmp(hash,
return secfalse; "\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) { static secbool latest_bootloader(const uint8_t *hash, int len) {
if (len != 32) return secfalse; if (len != 32) return secfalse;
// bootloader.bin (padded with 0x00) // 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; 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) // 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; 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; return secfalse;
} }
void check_and_replace_bootloader(void) void check_and_replace_bootloader(void) {
{
// compute current bootloader hash // compute current bootloader hash
uint8_t hash[BLAKE2S_DIGEST_LENGTH]; uint8_t hash[BLAKE2S_DIGEST_LENGTH];
const uint32_t bl_len = 128 * 1024; const uint32_t bl_len = 128 * 1024;
@ -64,7 +84,8 @@ void check_and_replace_bootloader(void)
blake2s(bl_data, bl_len, hash, BLAKE2S_DIGEST_LENGTH); blake2s(bl_data, bl_len, hash, BLAKE2S_DIGEST_LENGTH);
// don't whitelist the valid bootloaders for now // don't whitelist the valid bootloaders for now
// ensure(known_bootloader(hash, BLAKE2S_DIGEST_LENGTH), "Unknown bootloader detected"); // ensure(known_bootloader(hash, BLAKE2S_DIGEST_LENGTH), "Unknown bootloader
// detected");
// do we have the latest bootloader? // do we have the latest bootloader?
if (sectrue == latest_bootloader(hash, BLAKE2S_DIGEST_LENGTH)) { if (sectrue == latest_bootloader(hash, BLAKE2S_DIGEST_LENGTH)) {
@ -72,15 +93,21 @@ void check_and_replace_bootloader(void)
} }
// replace bootloader with the latest one // replace bootloader with the latest one
const uint32_t *data = (const uint32_t *)&_binary_embed_firmware_bootloader_bin_start; const uint32_t *data =
const uint32_t len = (const uint32_t)&_binary_embed_firmware_bootloader_bin_size; (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_erase(FLASH_SECTOR_BOOTLOADER), NULL);
ensure(flash_unlock_write(), NULL); ensure(flash_unlock_write(), NULL);
for (int i = 0; i < len / sizeof(uint32_t); i++) { for (int i = 0; i < len / sizeof(uint32_t); i++) {
ensure(flash_write_word(FLASH_SECTOR_BOOTLOADER, i * sizeof(uint32_t), data[i]), NULL); 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++) { 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_write_word(FLASH_SECTOR_BOOTLOADER, i * sizeof(uint32_t),
0x00000000),
NULL);
} }
ensure(flash_lock_write(), NULL); ensure(flash_lock_write(), NULL);
} }

View File

@ -21,18 +21,19 @@
#include <stdio.h> #include <stdio.h>
#include <string.h> #include <string.h>
#include "py/nlr.h" #include "lib/utils/pyexec.h"
#include "py/compile.h" #include "py/compile.h"
#include "py/runtime.h"
#include "py/stackctrl.h"
#include "py/repl.h"
#include "py/gc.h" #include "py/gc.h"
#include "py/mperrno.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/gccollect.h"
#include "ports/stm32/pendsv.h" #include "ports/stm32/pendsv.h"
#include "bl_check.h"
#include "common.h" #include "common.h"
#include "display.h" #include "display.h"
#include "flash.h" #include "flash.h"
@ -40,10 +41,8 @@
#include "rng.h" #include "rng.h"
#include "sdcard.h" #include "sdcard.h"
#include "touch.h" #include "touch.h"
#include "bl_check.h"
int main(void) int main(void) {
{
// reinitialize HAL for Trezor One // reinitialize HAL for Trezor One
#if TREZOR_MODEL == 1 #if TREZOR_MODEL == 1
HAL_Init(); HAL_Init();
@ -77,7 +76,7 @@ int main(void)
// Stack limit should be less than real stack size, so we have a chance // Stack limit should be less than real stack size, so we have a chance
// to recover from limit hit. // to recover from limit hit.
mp_stack_set_top(&_estack); mp_stack_set_top(&_estack);
mp_stack_set_limit((char*)&_estack - (char*)&_heap_end - 1024); mp_stack_set_limit((char *)&_estack - (char *)&_heap_end - 1024);
// GC init // GC init
printf("CORE: Starting GC\n"); printf("CORE: Starting GC\n");
@ -88,7 +87,9 @@ int main(void)
mp_init(); mp_init();
mp_obj_list_init(mp_sys_argv, 0); mp_obj_list_init(mp_sys_argv, 0);
mp_obj_list_init(mp_sys_path, 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) 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 // Execute the main script
printf("CORE: Executing main script\n"); printf("CORE: Executing main script\n");
@ -107,9 +108,7 @@ void __attribute__((noreturn)) nlr_jump_fail(void *val) {
ensure(secfalse, "uncaught exception"); ensure(secfalse, "uncaught exception");
} }
void PendSV_Handler(void) { void PendSV_Handler(void) { pendsv_isr_handler(); }
pendsv_isr_handler();
}
// MicroPython builtin stubs // MicroPython builtin stubs

View File

@ -27,21 +27,21 @@
#include "extmod/utime_mphal.h" #include "extmod/utime_mphal.h"
STATIC const mp_rom_map_elem_t time_module_globals_table[] = { 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), 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_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_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_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_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_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_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_ticks_diff), MP_ROM_PTR(&mp_utime_ticks_diff_obj)},
}; };
STATIC MP_DEFINE_CONST_DICT(time_module_globals, time_module_globals_table); STATIC MP_DEFINE_CONST_DICT(time_module_globals, time_module_globals_table);
const mp_obj_module_t mp_module_utime = { const mp_obj_module_t mp_module_utime = {
.base = { &mp_type_module }, .base = {&mp_type_module},
.globals = (mp_obj_dict_t*)&time_module_globals, .globals = (mp_obj_dict_t*)&time_module_globals,
}; };

View File

@ -1,3 +1,5 @@
// clang-format off
/* /*
* This file is part of the MicroPython project, http://micropython.org/ * This file is part of the MicroPython project, http://micropython.org/
* *

View File

@ -17,9 +17,9 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>. * along with this program. If not, see <http://www.gnu.org/licenses/>.
*/ */
#include "common.h"
#include "py/mphal.h" #include "py/mphal.h"
#include "usb.h" #include "usb.h"
#include "common.h"
static int vcp_iface_num = -1; static int vcp_iface_num = -1;
@ -38,6 +38,4 @@ void mp_hal_stdout_tx_strn(const char *str, size_t len) {
} }
} }
void mp_hal_set_vcp_iface(int iface_num) { void mp_hal_set_vcp_iface(int iface_num) { vcp_iface_num = iface_num; }
vcp_iface_num = iface_num;
}

View File

@ -19,8 +19,6 @@
#include "lib/utils/interrupt_char.h" #include "lib/utils/interrupt_char.h"
static inline mp_uint_t mp_hal_ticks_cpu(void) { static inline mp_uint_t mp_hal_ticks_cpu(void) { return 0; }
return 0;
}
void mp_hal_set_vcp_iface(int iface_num); void mp_hal_set_vcp_iface(int iface_num);

View File

@ -1,3 +1,5 @@
// clang-format off
/* /*
* This file is part of the TREZOR project, https://trezor.io/ * This file is part of the TREZOR project, https://trezor.io/
* *

View File

@ -17,8 +17,8 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>. * along with this program. If not, see <http://www.gnu.org/licenses/>.
*/ */
#include <string.h>
#include <stdlib.h> #include <stdlib.h>
#include <string.h>
#include <sys/types.h> #include <sys/types.h>
#include STM32_HAL_H #include STM32_HAL_H
@ -38,28 +38,24 @@
enum { VCP_IFACE = 0x00 }; enum { VCP_IFACE = 0x00 };
static void vcp_intr(void) static void vcp_intr(void) {
{
display_clear(); display_clear();
ensure(secfalse, "vcp_intr"); ensure(secfalse, "vcp_intr");
} }
static void vcp_puts(const char *s, size_t len) static void vcp_puts(const char *s, size_t len) {
{ int r = usb_vcp_write_blocking(VCP_IFACE, (const uint8_t *)s, len, -1);
int r = usb_vcp_write_blocking(VCP_IFACE, (const uint8_t *) s, len, -1);
(void)r; (void)r;
} }
static char vcp_getchar(void) static char vcp_getchar(void) {
{
uint8_t c = 0; uint8_t c = 0;
int r = usb_vcp_read_blocking(VCP_IFACE, &c, 1, -1); int r = usb_vcp_read_blocking(VCP_IFACE, &c, 1, -1);
(void)r; (void)r;
return (char)c; return (char)c;
} }
static void vcp_readline(char *buf, size_t len) static void vcp_readline(char *buf, size_t len) {
{
for (;;) { for (;;) {
char c = vcp_getchar(); char c = vcp_getchar();
if (c == '\r') { if (c == '\r') {
@ -81,8 +77,7 @@ static void vcp_readline(char *buf, size_t len)
} }
} }
static void vcp_printf(const char *fmt, ...) static void vcp_printf(const char *fmt, ...) {
{
static char buf[128]; static char buf[128];
va_list va; va_list va;
va_start(va, fmt); va_start(va, fmt);
@ -92,8 +87,7 @@ static void vcp_printf(const char *fmt, ...)
vcp_puts("\r\n", 2); vcp_puts("\r\n", 2);
} }
static void usb_init_all(void) static void usb_init_all(void) {
{
enum { enum {
VCP_PACKET_LEN = 64, VCP_PACKET_LEN = 64,
VCP_BUFFER_LEN = 1024, VCP_BUFFER_LEN = 1024,
@ -142,8 +136,7 @@ static void usb_init_all(void)
usb_start(); usb_start();
} }
static void draw_border(int width, int padding) static void draw_border(int width, int padding) {
{
const int W = width, P = padding, RX = DISPLAY_RESX, RY = DISPLAY_RESY; const int W = width, P = padding, RX = DISPLAY_RESX, RY = DISPLAY_RESY;
display_clear(); display_clear();
display_bar(P, P, RX - 2 * P, RY - 2 * P, 0xFFFF); display_bar(P, P, RX - 2 * P, RY - 2 * P, 0xFFFF);
@ -151,14 +144,12 @@ static void draw_border(int width, int padding)
display_refresh(); display_refresh();
} }
static void test_border(void) static void test_border(void) {
{
draw_border(2, 0); draw_border(2, 0);
vcp_printf("OK"); vcp_printf("OK");
} }
static void test_display(const char *colors) static void test_display(const char *colors) {
{
display_clear(); display_clear();
size_t l = strlen(colors); size_t l = strlen(colors);
@ -167,10 +158,18 @@ static void test_display(const char *colors)
for (size_t i = 0; i < l; i++) { for (size_t i = 0; i < l; i++) {
uint16_t c = 0x0000; // black uint16_t c = 0x0000; // black
switch (colors[i]) { switch (colors[i]) {
case 'R': c = 0xF800; break; case 'R':
case 'G': c = 0x07E0; break; c = 0xF800;
case 'B': c = 0x001F; break; break;
case 'W': c = 0xFFFF; 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); display_bar(i * w, 0, i * w + w, 240, c);
} }
@ -178,35 +177,43 @@ static void test_display(const char *colors)
vcp_printf("OK"); vcp_printf("OK");
} }
static secbool touch_click_timeout(uint32_t *touch, uint32_t timeout_ms) static secbool touch_click_timeout(uint32_t *touch, uint32_t timeout_ms) {
{
uint32_t deadline = HAL_GetTick() + timeout_ms; uint32_t deadline = HAL_GetTick() + timeout_ms;
uint32_t r = 0; uint32_t r = 0;
while (touch_read()); while (touch_read())
;
while ((touch_read() & TOUCH_START) == 0) { while ((touch_read() & TOUCH_START) == 0) {
if (HAL_GetTick() > deadline) return secfalse; if (HAL_GetTick() > deadline) return secfalse;
} }
while (((r = touch_read()) & TOUCH_END) == 0) { while (((r = touch_read()) & TOUCH_END) == 0) {
if (HAL_GetTick() > deadline) return secfalse; if (HAL_GetTick() > deadline) return secfalse;
} }
while (touch_read()); while (touch_read())
;
*touch = r; *touch = r;
return sectrue; return sectrue;
} }
static void test_touch(const char *args) static void test_touch(const char *args) {
{
int column = args[0] - '0'; int column = args[0] - '0';
int timeout = args[1] - '0'; int timeout = args[1] - '0';
display_clear(); display_clear();
switch (column) { switch (column) {
case 1: display_bar(0, 0, 120, 120, 0xFFFF); break; case 1:
case 2: display_bar(120, 0, 120, 120, 0xFFFF); break; display_bar(0, 0, 120, 120, 0xFFFF);
case 3: display_bar(120, 120, 120, 120, 0xFFFF); break; break;
default: display_bar(0, 120, 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(); display_refresh();
@ -226,8 +233,7 @@ static void test_touch(const char *args)
touch_power_off(); touch_power_off();
} }
static void test_sensitivity(const char *args) static void test_sensitivity(const char *args) {
{
int v = atoi(args); int v = atoi(args);
touch_power_on(); touch_power_on();
@ -253,8 +259,7 @@ static void test_sensitivity(const char *args)
touch_power_off(); touch_power_off();
} }
static void test_pwm(const char *args) static void test_pwm(const char *args) {
{
int v = atoi(args); int v = atoi(args);
display_backlight(v); display_backlight(v);
@ -262,8 +267,7 @@ static void test_pwm(const char *args)
vcp_printf("OK"); vcp_printf("OK");
} }
static void test_sd(void) static void test_sd(void) {
{
#define BLOCK_SIZE (32 * 1024) #define BLOCK_SIZE (32 * 1024)
static uint32_t buf1[BLOCK_SIZE / sizeof(uint32_t)]; static uint32_t buf1[BLOCK_SIZE / sizeof(uint32_t)];
static uint32_t buf2[BLOCK_SIZE / sizeof(uint32_t)]; static uint32_t buf2[BLOCK_SIZE / sizeof(uint32_t)];
@ -282,12 +286,14 @@ static void test_sd(void)
for (int i = 0; i < BLOCK_SIZE / sizeof(uint32_t); i++) { for (int i = 0; i < BLOCK_SIZE / sizeof(uint32_t); i++) {
buf1[i] ^= 0xFFFFFFFF; buf1[i] ^= 0xFFFFFFFF;
} }
if (sectrue != sdcard_write_blocks(buf1, 0, BLOCK_SIZE / SDCARD_BLOCK_SIZE)) { if (sectrue !=
sdcard_write_blocks(buf1, 0, BLOCK_SIZE / SDCARD_BLOCK_SIZE)) {
vcp_printf("ERROR sdcard_write_blocks (%d)", j); vcp_printf("ERROR sdcard_write_blocks (%d)", j);
goto power_off; goto power_off;
} }
HAL_Delay(1000); HAL_Delay(1000);
if (sectrue != sdcard_read_blocks(buf2, 0, BLOCK_SIZE / SDCARD_BLOCK_SIZE)) { if (sectrue !=
sdcard_read_blocks(buf2, 0, BLOCK_SIZE / SDCARD_BLOCK_SIZE)) {
vcp_printf("ERROR sdcard_read_blocks (%d)", j); vcp_printf("ERROR sdcard_read_blocks (%d)", j);
goto power_off; goto power_off;
} }
@ -302,30 +308,30 @@ power_off:
sdcard_power_off(); sdcard_power_off();
} }
static void test_wipe(void) static void test_wipe(void) {
{
// erase start of the firmware (metadata) -> invalidate FW // erase start of the firmware (metadata) -> invalidate FW
ensure(flash_unlock_write(), NULL); ensure(flash_unlock_write(), NULL);
for (int i = 0; i < 1024 / sizeof(uint32_t); i++) { 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_write_word(FLASH_SECTOR_FIRMWARE_START, i * sizeof(uint32_t),
0x00000000),
NULL);
} }
ensure(flash_lock_write(), NULL); ensure(flash_lock_write(), NULL);
display_clear(); display_clear();
display_text_center(DISPLAY_RESX / 2, DISPLAY_RESY / 2 + 10, "WIPED", -1, FONT_BOLD, COLOR_WHITE, COLOR_BLACK); display_text_center(DISPLAY_RESX / 2, DISPLAY_RESY / 2 + 10, "WIPED", -1,
FONT_BOLD, COLOR_WHITE, COLOR_BLACK);
display_refresh(); display_refresh();
vcp_printf("OK"); vcp_printf("OK");
} }
static void test_sbu(const char *args) static void test_sbu(const char *args) {
{
secbool sbu1 = sectrue * (args[0] == '1'); secbool sbu1 = sectrue * (args[0] == '1');
secbool sbu2 = sectrue * (args[1] == '1'); secbool sbu2 = sectrue * (args[1] == '1');
sbu_set(sbu1, sbu2); sbu_set(sbu1, sbu2);
vcp_printf("OK"); vcp_printf("OK");
} }
static void test_otp_read(void) static void test_otp_read(void) {
{
uint8_t data[32]; uint8_t data[32];
memzero(data, sizeof(data)); memzero(data, sizeof(data));
ensure(flash_otp_read(FLASH_OTP_BLOCK_BATCH, 0, data, sizeof(data)), NULL); ensure(flash_otp_read(FLASH_OTP_BLOCK_BATCH, 0, data, sizeof(data)), NULL);
@ -342,29 +348,28 @@ static void test_otp_read(void)
if (data[0] == 0x00) { if (data[0] == 0x00) {
vcp_printf("OK (null)"); vcp_printf("OK (null)");
} else { } else {
vcp_printf("OK %s", (const char *) data); vcp_printf("OK %s", (const char *)data);
} }
} }
static void test_otp_write(const char *args) static void test_otp_write(const char *args) {
{
char data[32]; char data[32];
memzero(data, sizeof(data)); memzero(data, sizeof(data));
strncpy(data, args, sizeof(data) - 1); 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_write(FLASH_OTP_BLOCK_BATCH, 0, (const uint8_t *)data,
sizeof(data)),
NULL);
ensure(flash_otp_lock(FLASH_OTP_BLOCK_BATCH), NULL); ensure(flash_otp_lock(FLASH_OTP_BLOCK_BATCH), NULL);
vcp_printf("OK"); vcp_printf("OK");
} }
static secbool startswith(const char *s, const char *prefix) static secbool startswith(const char *s, const char *prefix) {
{
return sectrue * (0 == strncmp(s, prefix, strlen(prefix))); return sectrue * (0 == strncmp(s, prefix, strlen(prefix)));
} }
#define BACKLIGHT_NORMAL 150 #define BACKLIGHT_NORMAL 150
int main(void) int main(void) {
{
display_orientation(0); display_orientation(0);
sdcard_init(); sdcard_init();
touch_init(); touch_init();
@ -376,9 +381,11 @@ int main(void)
char dom[32]; char dom[32];
// format: TREZOR2-YYMMDD // 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) { 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_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); display_text_center(DISPLAY_RESX / 2, DISPLAY_RESY - 30, dom + 8, -1,
FONT_BOLD, COLOR_WHITE, COLOR_BLACK);
} }
display_fade(0, BACKLIGHT_NORMAL, 1000); display_fade(0, BACKLIGHT_NORMAL, 1000);

View File

@ -17,8 +17,8 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>. * along with this program. If not, see <http://www.gnu.org/licenses/>.
*/ */
#include <string.h>
#include <stdlib.h> #include <stdlib.h>
#include <string.h>
#include <sys/types.h> #include <sys/types.h>
#include STM32_HAL_H #include STM32_HAL_H
@ -33,37 +33,32 @@
#include "secbool.h" #include "secbool.h"
#include "touch.h" #include "touch.h"
static void progress_callback(int pos, int len) static void progress_callback(int pos, int len) { display_printf("."); }
{
display_printf(".");
}
static void flash_from_sdcard(uint8_t sector, uint32_t source, uint32_t length) 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 uint32_t buf[SDCARD_BLOCK_SIZE / sizeof(uint32_t)];
ensure( ensure(sectrue * (source % SDCARD_BLOCK_SIZE == 0),
sectrue * (source % SDCARD_BLOCK_SIZE == 0),
"source not a multiple of block size"); "source not a multiple of block size");
ensure( ensure(sectrue * (length % SDCARD_BLOCK_SIZE == 0),
sectrue * (length % SDCARD_BLOCK_SIZE == 0),
"length not a multiple of block size"); "length not a multiple of block size");
for (uint32_t i = 0; i < length / SDCARD_BLOCK_SIZE; i++) { for (uint32_t i = 0; i < length / SDCARD_BLOCK_SIZE; i++) {
display_printf("read %d\n", (unsigned int)(i + source / SDCARD_BLOCK_SIZE)); display_printf("read %d\n", (unsigned int)(i + source / SDCARD_BLOCK_SIZE));
ensure( ensure(sdcard_read_blocks(buf, i + source / SDCARD_BLOCK_SIZE, 1),
sdcard_read_blocks(buf, i + source / SDCARD_BLOCK_SIZE, 1),
"sdcard_read_blocks"); "sdcard_read_blocks");
for (uint32_t j = 0; j < SDCARD_BLOCK_SIZE / sizeof(uint32_t); j++) { 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); ensure(flash_write_word(
sector, i * SDCARD_BLOCK_SIZE + j * sizeof(uint32_t), buf[j]),
NULL);
} }
} }
} }
int main(void) int main(void) {
{
sdcard_init(); sdcard_init();
touch_init(); touch_init();
@ -71,9 +66,7 @@ int main(void)
display_clear(); display_clear();
display_backlight(255); display_backlight(255);
ensure( ensure(sdcard_is_present(), "sdcard_is_present");
sdcard_is_present(),
"sdcard_is_present");
display_printf("updating boardloader + bootloader\n"); display_printf("updating boardloader + bootloader\n");
@ -84,7 +77,8 @@ int main(void)
FLASH_SECTOR_BOOTLOADER, FLASH_SECTOR_BOOTLOADER,
}; };
display_printf("erasing sectors"); display_printf("erasing sectors");
ensure(flash_erase_sectors(sectors, sizeof(sectors), progress_callback), "flash_erase_sectors"); ensure(flash_erase_sectors(sectors, sizeof(sectors), progress_callback),
"flash_erase_sectors");
display_printf("\n"); display_printf("\n");
display_printf("erased\n"); display_printf("erased\n");
@ -96,10 +90,13 @@ int main(void)
#define BOARDLOADER_TOTAL_SIZE (3 * BOARDLOADER_CHUNK_SIZE) #define BOARDLOADER_TOTAL_SIZE (3 * BOARDLOADER_CHUNK_SIZE)
#define BOOTLOADER_TOTAL_SIZE (128 * 1024) #define BOOTLOADER_TOTAL_SIZE (128 * 1024)
flash_from_sdcard(FLASH_SECTOR_BOARDLOADER_START, 0 * BOARDLOADER_CHUNK_SIZE, BOARDLOADER_CHUNK_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(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_BOARDLOADER_END, 2 * BOARDLOADER_CHUNK_SIZE,
flash_from_sdcard(FLASH_SECTOR_BOOTLOADER, BOARDLOADER_TOTAL_SIZE, BOOTLOADER_TOTAL_SIZE); BOARDLOADER_CHUNK_SIZE);
flash_from_sdcard(FLASH_SECTOR_BOOTLOADER, BOARDLOADER_TOTAL_SIZE,
BOOTLOADER_TOTAL_SIZE);
display_printf("done\n"); display_printf("done\n");
sdcard_power_off(); sdcard_power_off();

View File

@ -23,9 +23,9 @@
#include "common.h" #include "common.h"
#include "display.h" #include "display.h"
#include "rng.h"
#include "rand.h"
#include "flash.h" #include "flash.h"
#include "rand.h"
#include "rng.h"
#include "stm32f4xx_ll_utils.h" #include "stm32f4xx_ll_utils.h"
@ -34,7 +34,9 @@ extern void shutdown(void);
#define COLOR_FATAL_ERROR RGB16(0x7F, 0x00, 0x00) #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) { void __attribute__((noreturn))
__fatal_error(const char *expr, const char *msg, const char *file, int line,
const char *func) {
display_orientation(0); display_orientation(0);
display_backlight(255); display_backlight(255);
display_print_color(COLOR_WHITE, COLOR_FATAL_ERROR); display_print_color(COLOR_WHITE, COLOR_FATAL_ERROR);
@ -56,11 +58,13 @@ void __attribute__((noreturn)) __fatal_error(const char *expr, const char *msg,
#endif #endif
display_printf("\nPlease contact TREZOR support.\n"); display_printf("\nPlease contact TREZOR support.\n");
shutdown(); shutdown();
for (;;); for (;;)
;
} }
void __attribute__((noreturn)) error_shutdown(const char *line1, const char *line2, const char *line3, const char *line4) void __attribute__((noreturn))
{ error_shutdown(const char *line1, const char *line2, const char *line3,
const char *line4) {
display_orientation(0); display_orientation(0);
#ifdef TREZOR_FONT_NORMAL_ENABLE #ifdef TREZOR_FONT_NORMAL_ENABLE
display_clear(); display_clear();
@ -83,7 +87,8 @@ void __attribute__((noreturn)) error_shutdown(const char *line1, const char *lin
y += 32; y += 32;
} }
y += 32; y += 32;
display_text(8, y, "Please unplug the device.", -1, FONT_NORMAL, COLOR_WHITE, COLOR_FATAL_ERROR); display_text(8, y, "Please unplug the device.", -1, FONT_NORMAL, COLOR_WHITE,
COLOR_FATAL_ERROR);
#else #else
display_print_color(COLOR_WHITE, COLOR_FATAL_ERROR); display_print_color(COLOR_WHITE, COLOR_FATAL_ERROR);
if (line1) { if (line1) {
@ -102,22 +107,20 @@ void __attribute__((noreturn)) error_shutdown(const char *line1, const char *lin
#endif #endif
display_backlight(255); display_backlight(255);
shutdown(); shutdown();
for (;;); for (;;)
;
} }
#ifndef NDEBUG #ifndef NDEBUG
void __assert_func(const char *file, int line, const char *func, const char *expr) { void __assert_func(const char *file, int line, const char *func,
const char *expr) {
__fatal_error(expr, "assert failed", file, line, func); __fatal_error(expr, "assert failed", file, line, func);
} }
#endif #endif
void hal_delay(uint32_t ms) void hal_delay(uint32_t ms) { HAL_Delay(ms); }
{
HAL_Delay(ms);
}
void delay_random(void) void delay_random(void) {
{
int wait = rng_get() & 0xff; int wait = rng_get() & 0xff;
volatile int i = 0; volatile int i = 0;
volatile int j = wait; volatile int j = wait;
@ -138,25 +141,28 @@ void delay_random(void)
#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) #define USB_OTG_HS_DATA_FIFO_SIZE (4096U)
void clear_otg_hs_memory(void) void clear_otg_hs_memory(void) {
{
// use the HAL version due to section 2.1.6 of STM32F42xx Errata sheet // 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 __HAL_RCC_USB_OTG_HS_CLK_ENABLE(); // enable USB_OTG_HS peripheral clock so
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); // that the peripheral memory is
__HAL_RCC_USB_OTG_HS_CLK_DISABLE(); // disable USB OTG_HS peripheral clock as the peripheral is not needed right now // 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; uint32_t __stack_chk_guard = 0;
void __attribute__((noreturn)) __stack_chk_fail(void) void __attribute__((noreturn)) __stack_chk_fail(void) {
{
ensure(secfalse, "Stack smashing detected"); ensure(secfalse, "Stack smashing detected");
} }
uint8_t HW_ENTROPY_DATA[HW_ENTROPY_LEN]; uint8_t HW_ENTROPY_DATA[HW_ENTROPY_LEN];
void collect_hw_entropy(void) void collect_hw_entropy(void) {
{
// collect entropy from UUID // collect entropy from UUID
uint32_t w = LL_GetUID_Word0(); uint32_t w = LL_GetUID_Word0();
memcpy(HW_ENTROPY_DATA, &w, 4); memcpy(HW_ENTROPY_DATA, &w, 4);
@ -169,9 +175,13 @@ void collect_hw_entropy(void)
if (secfalse == flash_otp_is_locked(FLASH_OTP_BLOCK_RANDOMNESS)) { if (secfalse == flash_otp_is_locked(FLASH_OTP_BLOCK_RANDOMNESS)) {
uint8_t entropy[FLASH_OTP_BLOCK_SIZE]; uint8_t entropy[FLASH_OTP_BLOCK_SIZE];
random_buffer(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_write(FLASH_OTP_BLOCK_RANDOMNESS, 0, entropy,
FLASH_OTP_BLOCK_SIZE),
NULL);
ensure(flash_otp_lock(FLASH_OTP_BLOCK_RANDOMNESS), NULL); ensure(flash_otp_lock(FLASH_OTP_BLOCK_RANDOMNESS), NULL);
} }
// collect entropy from OTP randomness block // collect entropy from OTP randomness block
ensure(flash_otp_read(FLASH_OTP_BLOCK_RANDOMNESS, 0, HW_ENTROPY_DATA + 12, FLASH_OTP_BLOCK_SIZE), NULL); ensure(flash_otp_read(FLASH_OTP_BLOCK_RANDOMNESS, 0, HW_ENTROPY_DATA + 12,
FLASH_OTP_BLOCK_SIZE),
NULL);
} }

View File

@ -27,19 +27,41 @@
#define STR(s) #s #define STR(s) #s
#ifndef MIN_8bits #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 #endif
#ifndef MIN #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 #endif
#ifndef MAX #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 #endif
void __attribute__((noreturn)) __fatal_error(const char *expr, const char *msg, const char *file, int line, const char *func); void __attribute__((noreturn))
void __attribute__((noreturn)) error_shutdown(const char *line1, const char *line2, const char *line3, const char *line4); __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); void hal_delay(uint32_t ms);

View File

@ -27,16 +27,16 @@
// see docs/memory.md for more information // see docs/memory.md for more information
static const uint32_t FLASH_SECTOR_TABLE[FLASH_SECTOR_COUNT + 1] = { static const uint32_t FLASH_SECTOR_TABLE[FLASH_SECTOR_COUNT + 1] = {
[ 0] = 0x08000000, // - 0x08003FFF | 16 KiB [0] = 0x08000000, // - 0x08003FFF | 16 KiB
[ 1] = 0x08004000, // - 0x08007FFF | 16 KiB [1] = 0x08004000, // - 0x08007FFF | 16 KiB
[ 2] = 0x08008000, // - 0x0800BFFF | 16 KiB [2] = 0x08008000, // - 0x0800BFFF | 16 KiB
[ 3] = 0x0800C000, // - 0x0800FFFF | 16 KiB [3] = 0x0800C000, // - 0x0800FFFF | 16 KiB
[ 4] = 0x08010000, // - 0x0801FFFF | 64 KiB [4] = 0x08010000, // - 0x0801FFFF | 64 KiB
[ 5] = 0x08020000, // - 0x0803FFFF | 128 KiB [5] = 0x08020000, // - 0x0803FFFF | 128 KiB
[ 6] = 0x08040000, // - 0x0805FFFF | 128 KiB [6] = 0x08040000, // - 0x0805FFFF | 128 KiB
[ 7] = 0x08060000, // - 0x0807FFFF | 128 KiB [7] = 0x08060000, // - 0x0807FFFF | 128 KiB
[ 8] = 0x08080000, // - 0x0809FFFF | 128 KiB [8] = 0x08080000, // - 0x0809FFFF | 128 KiB
[ 9] = 0x080A0000, // - 0x080BFFFF | 128 KiB [9] = 0x080A0000, // - 0x080BFFFF | 128 KiB
[10] = 0x080C0000, // - 0x080DFFFF | 128 KiB [10] = 0x080C0000, // - 0x080DFFFF | 128 KiB
[11] = 0x080E0000, // - 0x080FFFFF | 128 KiB [11] = 0x080E0000, // - 0x080FFFFF | 128 KiB
[12] = 0x08100000, // - 0x08103FFF | 16 KiB [12] = 0x08100000, // - 0x08103FFF | 16 KiB
@ -54,7 +54,7 @@ static const uint32_t FLASH_SECTOR_TABLE[FLASH_SECTOR_COUNT + 1] = {
[24] = 0x08200000, // last element - not a valid sector [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, FLASH_SECTOR_FIRMWARE_START,
7, 7,
8, 8,
@ -75,25 +75,20 @@ const uint8_t STORAGE_SECTORS[STORAGE_SECTORS_COUNT] = {
FLASH_SECTOR_STORAGE_2, FLASH_SECTOR_STORAGE_2,
}; };
void flash_init(void) void flash_init(void) {}
{
}
secbool flash_unlock_write(void) secbool flash_unlock_write(void) {
{
HAL_FLASH_Unlock(); HAL_FLASH_Unlock();
FLASH->SR |= FLASH_STATUS_ALL_FLAGS; // clear all status flags FLASH->SR |= FLASH_STATUS_ALL_FLAGS; // clear all status flags
return sectrue; return sectrue;
} }
secbool flash_lock_write(void) secbool flash_lock_write(void) {
{
HAL_FLASH_Lock(); HAL_FLASH_Lock();
return sectrue; return sectrue;
} }
const void *flash_get_address(uint8_t sector, uint32_t offset, uint32_t size) const void *flash_get_address(uint8_t sector, uint32_t offset, uint32_t size) {
{
if (sector >= FLASH_SECTOR_COUNT) { if (sector >= FLASH_SECTOR_COUNT) {
return NULL; return NULL;
} }
@ -105,8 +100,8 @@ const void *flash_get_address(uint8_t sector, uint32_t offset, uint32_t size)
return (const void *)addr; return (const void *)addr;
} }
secbool flash_erase_sectors(const uint8_t *sectors, int len, void (*progress)(int pos, int len)) secbool flash_erase_sectors(const uint8_t *sectors, int len,
{ void (*progress)(int pos, int len)) {
ensure(flash_unlock_write(), NULL); ensure(flash_unlock_write(), NULL);
FLASH_EraseInitTypeDef EraseInitStruct; FLASH_EraseInitTypeDef EraseInitStruct;
EraseInitStruct.TypeErase = FLASH_TYPEERASE_SECTORS; EraseInitStruct.TypeErase = FLASH_TYPEERASE_SECTORS;
@ -123,7 +118,8 @@ secbool flash_erase_sectors(const uint8_t *sectors, int len, void (*progress)(in
return secfalse; return secfalse;
} }
// check whether the sector was really deleted (contains only 0xFF) // 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]; 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) { for (uint32_t addr = addr_start; addr < addr_end; addr += 4) {
if (*((const uint32_t *)addr) != 0xFFFFFFFF) { if (*((const uint32_t *)addr) != 0xFFFFFFFF) {
ensure(flash_lock_write(), NULL); ensure(flash_lock_write(), NULL);
@ -138,8 +134,7 @@ secbool flash_erase_sectors(const uint8_t *sectors, int len, void (*progress)(in
return sectrue; return sectrue;
} }
secbool flash_write_byte(uint8_t sector, uint32_t offset, uint8_t data) secbool flash_write_byte(uint8_t sector, uint32_t offset, uint8_t data) {
{
uint32_t address = (uint32_t)flash_get_address(sector, offset, 1); uint32_t address = (uint32_t)flash_get_address(sector, offset, 1);
if (address == 0) { if (address == 0) {
return secfalse; return secfalse;
@ -156,8 +151,7 @@ secbool flash_write_byte(uint8_t sector, uint32_t offset, uint8_t data)
return sectrue; return sectrue;
} }
secbool flash_write_word(uint8_t sector, uint32_t offset, uint32_t data) secbool flash_write_word(uint8_t sector, uint32_t offset, uint32_t data) {
{
uint32_t address = (uint32_t)flash_get_address(sector, offset, 4); uint32_t address = (uint32_t)flash_get_address(sector, offset, 4);
if (address == 0) { if (address == 0) {
return secfalse; return secfalse;
@ -179,43 +173,48 @@ secbool flash_write_word(uint8_t sector, uint32_t offset, uint32_t data)
#define FLASH_OTP_LOCK_BASE 0x1FFF7A00U #define FLASH_OTP_LOCK_BASE 0x1FFF7A00U
secbool flash_otp_read(uint8_t block, uint8_t offset, uint8_t *data, uint8_t datalen) 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) { if (block >= FLASH_OTP_NUM_BLOCKS ||
offset + datalen > FLASH_OTP_BLOCK_SIZE) {
return secfalse; return secfalse;
} }
for (uint8_t i = 0; i < datalen; i++) { for (uint8_t i = 0; i < datalen; i++) {
data[i] = *(__IO uint8_t *)(FLASH_OTP_BASE + block * FLASH_OTP_BLOCK_SIZE + offset + i); data[i] = *(__IO uint8_t *)(FLASH_OTP_BASE + block * FLASH_OTP_BLOCK_SIZE +
offset + i);
} }
return sectrue; return sectrue;
} }
secbool flash_otp_write(uint8_t block, uint8_t offset, const uint8_t *data, uint8_t datalen) 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) { if (block >= FLASH_OTP_NUM_BLOCKS ||
offset + datalen > FLASH_OTP_BLOCK_SIZE) {
return secfalse; return secfalse;
} }
ensure(flash_unlock_write(), NULL); ensure(flash_unlock_write(), NULL);
for (uint8_t i = 0; i < datalen; i++) { for (uint8_t i = 0; i < datalen; i++) {
uint32_t address = FLASH_OTP_BASE + block * FLASH_OTP_BLOCK_SIZE + offset + i; uint32_t address =
ensure(sectrue * (HAL_OK == HAL_FLASH_Program(FLASH_TYPEPROGRAM_BYTE, address, data[i])), NULL); 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); ensure(flash_lock_write(), NULL);
return sectrue; return sectrue;
} }
secbool flash_otp_lock(uint8_t block) secbool flash_otp_lock(uint8_t block) {
{
if (block >= FLASH_OTP_NUM_BLOCKS) { if (block >= FLASH_OTP_NUM_BLOCKS) {
return secfalse; return secfalse;
} }
ensure(flash_unlock_write(), NULL); ensure(flash_unlock_write(), NULL);
HAL_StatusTypeDef ret = HAL_FLASH_Program(FLASH_TYPEPROGRAM_BYTE, FLASH_OTP_LOCK_BASE + block, 0x00); HAL_StatusTypeDef ret = HAL_FLASH_Program(FLASH_TYPEPROGRAM_BYTE,
FLASH_OTP_LOCK_BASE + block, 0x00);
ensure(flash_lock_write(), NULL); ensure(flash_lock_write(), NULL);
return sectrue * (ret == HAL_OK); return sectrue * (ret == HAL_OK);
} }
secbool flash_otp_is_locked(uint8_t block) secbool flash_otp_is_locked(uint8_t block) {
{
return sectrue * (0x00 == *(__IO uint8_t *)(FLASH_OTP_LOCK_BASE + block)); return sectrue * (0x00 == *(__IO uint8_t *)(FLASH_OTP_LOCK_BASE + block));
} }

View File

@ -67,12 +67,15 @@
extern const uint8_t STORAGE_SECTORS[STORAGE_SECTORS_COUNT]; extern const uint8_t STORAGE_SECTORS[STORAGE_SECTORS_COUNT];
extern const uint8_t FIRMWARE_SECTORS[FIRMWARE_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 #ifndef STM32F427xx
#define FLASH_SR_RDERR 0 #define FLASH_SR_RDERR 0
#endif #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); void flash_init(void);
@ -81,8 +84,11 @@ secbool __wur flash_lock_write(void);
const void *flash_get_address(uint8_t sector, uint32_t offset, uint32_t size); 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)); secbool __wur flash_erase_sectors(const uint8_t *sectors, int len,
static inline secbool flash_erase(uint8_t sector) { return flash_erase_sectors(&sector, 1, NULL); } void (*progress)(int pos, int len));
static inline secbool flash_erase(uint8_t sector) {
return flash_erase_sectors(&sector, 1, NULL);
}
secbool __wur flash_write_byte(uint8_t sector, uint32_t offset, uint8_t data); 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); secbool __wur flash_write_word(uint8_t sector, uint32_t offset, uint32_t data);
@ -95,8 +101,10 @@ secbool __wur flash_write_word(uint8_t sector, uint32_t offset, uint32_t data);
#define FLASH_OTP_BLOCK_VENDOR_KEYS_LOCK 2 #define FLASH_OTP_BLOCK_VENDOR_KEYS_LOCK 2
#define FLASH_OTP_BLOCK_RANDOMNESS 3 #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_read(uint8_t block, uint8_t offset, uint8_t *data,
secbool __wur flash_otp_write(uint8_t block, uint8_t offset, const uint8_t *data, uint8_t datalen); 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_lock(uint8_t block);
secbool __wur flash_otp_is_locked(uint8_t block); secbool __wur flash_otp_is_locked(uint8_t block);

View File

@ -26,8 +26,9 @@
#include "flash.h" #include "flash.h"
#include "image.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) 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 (0 == sig_m || 0 == sig_n) return secfalse;
if (sig_m > sig_n) return secfalse; if (sig_m > sig_n) return secfalse;
@ -49,8 +50,9 @@ static secbool compute_pubkey(uint8_t sig_m, uint8_t sig_n, const uint8_t * cons
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) 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); memcpy(&hdr->magic, data, 4);
if (hdr->magic != magic) return secfalse; if (hdr->magic != magic) return secfalse;
@ -59,7 +61,8 @@ secbool load_image_header(const uint8_t * const data, const uint32_t magic, cons
memcpy(&hdr->expiry, data + 8, 4); memcpy(&hdr->expiry, data + 8, 4);
// TODO: expiry mechanism needs to be ironed out before production or those // TODO: expiry mechanism needs to be ironed out before production or those
// devices won't accept expiring bootloaders (due to boardloader write protection). // devices won't accept expiring bootloaders (due to boardloader write
// protection).
if (hdr->expiry != 0) return secfalse; if (hdr->expiry != 0) return secfalse;
memcpy(&hdr->codelen, data + 12, 4); memcpy(&hdr->codelen, data + 12, 4);
@ -74,7 +77,8 @@ secbool load_image_header(const uint8_t * const data, const uint32_t magic, cons
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
@ -87,13 +91,17 @@ secbool load_image_header(const uint8_t * const data, const uint32_t magic, cons
blake2s_Final(&ctx, hdr->fingerprint, BLAKE2S_DIGEST_LENGTH); blake2s_Final(&ctx, hdr->fingerprint, BLAKE2S_DIGEST_LENGTH);
ed25519_public_key pub; ed25519_public_key pub;
if (sectrue != compute_pubkey(key_m, key_n, keys, hdr->sigmask, pub)) return secfalse; 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) 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); memcpy(&vhdr->magic, data, 4);
if (vhdr->magic != 0x565A5254) return secfalse; // TRZV if (vhdr->magic != 0x565A5254) return secfalse; // TRZV
@ -130,7 +138,8 @@ secbool load_vendor_header(const uint8_t * const data, uint8_t key_m, uint8_t ke
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
@ -144,13 +153,15 @@ secbool load_vendor_header(const uint8_t * const data, uint8_t key_m, uint8_t ke
blake2s_Final(&ctx, hash, BLAKE2S_DIGEST_LENGTH); blake2s_Final(&ctx, hash, BLAKE2S_DIGEST_LENGTH);
ed25519_public_key pub; ed25519_public_key pub;
if (sectrue != compute_pubkey(key_m, key_n, keys, vhdr->sigmask, pub)) return secfalse; 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) void vendor_keys_hash(const vendor_header *const vhdr, uint8_t *hash) {
{
BLAKE2S_CTX ctx; BLAKE2S_CTX ctx;
blake2s_Init(&ctx, BLAKE2S_DIGEST_LENGTH); blake2s_Init(&ctx, BLAKE2S_DIGEST_LENGTH);
blake2s_Update(&ctx, &(vhdr->vsig_m), sizeof(vhdr->vsig_m)); blake2s_Update(&ctx, &(vhdr->vsig_m), sizeof(vhdr->vsig_m));
@ -159,30 +170,37 @@ void vendor_keys_hash(const vendor_header * const vhdr, uint8_t *hash)
if (vhdr->vpub[i] != 0) { if (vhdr->vpub[i] != 0) {
blake2s_Update(&ctx, vhdr->vpub[i], 32); blake2s_Update(&ctx, vhdr->vpub[i], 32);
} else { } 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_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) secbool check_single_hash(const uint8_t *const hash, const uint8_t *const data,
{ int len) {
uint8_t h[BLAKE2S_DIGEST_LENGTH]; uint8_t h[BLAKE2S_DIGEST_LENGTH];
blake2s(data, len, h, BLAKE2S_DIGEST_LENGTH); blake2s(data, len, h, BLAKE2S_DIGEST_LENGTH);
return sectrue * (0 == memcmp(h, hash, 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) secbool check_image_contents(const image_header *const hdr, uint32_t firstskip,
{ const uint8_t *sectors, int blocks) {
if (0 == sectors || blocks < 1) { if (0 == sectors || blocks < 1) {
return secfalse; return secfalse;
} }
const void *data = flash_get_address(sectors[0], firstskip, IMAGE_CHUNK_SIZE - firstskip); const void *data =
flash_get_address(sectors[0], firstskip, IMAGE_CHUNK_SIZE - firstskip);
if (!data) { if (!data) {
return secfalse; return secfalse;
} }
int remaining = hdr->codelen; int remaining = hdr->codelen;
if (sectrue != check_single_hash(hdr->hashes, data, MIN(remaining, IMAGE_CHUNK_SIZE - firstskip))) { if (sectrue !=
check_single_hash(hdr->hashes, data,
MIN(remaining, IMAGE_CHUNK_SIZE - firstskip))) {
return secfalse; return secfalse;
} }
int block = 1; int block = 1;
@ -195,7 +213,8 @@ secbool check_image_contents(const image_header * const hdr, uint32_t firstskip,
if (!data) { if (!data) {
return secfalse; return secfalse;
} }
if (sectrue != check_single_hash(hdr->hashes + block * 32, data, MIN(remaining, IMAGE_CHUNK_SIZE))) { if (sectrue != check_single_hash(hdr->hashes + block * 32, data,
MIN(remaining, IMAGE_CHUNK_SIZE))) {
return secfalse; return secfalse;
} }
block++; block++;

View File

@ -77,14 +77,22 @@ typedef struct {
uint8_t sig[64]; uint8_t sig[64];
} vendor_header; } 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 #endif

View File

@ -19,74 +19,84 @@
#include STM32_HAL_H #include STM32_HAL_H
#include "flash.h"
#include "lowlevel.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 #if PRODUCTION
#define WANT_RDP_LEVEL (OB_RDP_LEVEL_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) #define WANT_WRP_SECTORS (OB_WRP_SECTOR_0 | OB_WRP_SECTOR_1 | OB_WRP_SECTOR_2)
#else #else
#define WANT_RDP_LEVEL (OB_RDP_LEVEL_0) #define WANT_RDP_LEVEL (OB_RDP_LEVEL_0)
#define WANT_WRP_SECTORS (0) #define WANT_WRP_SECTORS (0)
#endif #endif
// BOR LEVEL 3: Reset level threshold is around 2.5 V // BOR LEVEL 3: Reset level threshold is around 2.5 V
#define WANT_BOR_LEVEL (OB_BOR_LEVEL3) #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; // reference RM0090 section 3.9.10; SPRMOD is 0 meaning PCROP disabled.; DB1M is
#define FLASH_OPTCR_VALUE ( (((~WANT_WRP_SECTORS) << FLASH_OPTCR_nWRP_Pos) & FLASH_OPTCR_nWRP_Msk) | \ // 0 because we use 2MB dual-bank; BFB2 is 0 allowing boot from flash;
(WANT_RDP_LEVEL << FLASH_OPTCR_RDP_Pos) | FLASH_OPTCR_nRST_STDBY | FLASH_OPTCR_nRST_STOP | FLASH_OPTCR_WDG_SW | WANT_BOR_LEVEL ) #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 // 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_RDP_USER_VALUE \
#define OPTION_BYTES_BANK1_WRP_VALUE ((uint16_t) ((~WANT_WRP_SECTORS) & 0xFFFU)) ((uint16_t)((WANT_RDP_LEVEL << FLASH_OPTCR_RDP_Pos) | \
#define OPTION_BYTES_BANK2_WRP_VALUE ((uint16_t) 0xFFFU) 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. // reference RM0090 section 3.7.1 table 16. use 16 bit pointers because the top
#define OPTION_BYTES_RDP_USER (*(volatile uint16_t * const) 0x1FFFC000U) // 48 bits are all reserved.
#define OPTION_BYTES_BANK1_WRP (*(volatile uint16_t * const) 0x1FFFC008U) #define OPTION_BYTES_RDP_USER (*(volatile uint16_t* const)0x1FFFC000U)
#define OPTION_BYTES_BANK2_WRP (*(volatile uint16_t * const) 0x1FFEC008U) #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) uint32_t flash_wait_and_clear_status_flags(void) {
{ while (FLASH->SR & FLASH_SR_BSY)
while(FLASH->SR & FLASH_SR_BSY); // wait for all previous flash operations to complete ; // wait for all previous flash operations to complete
const uint32_t result = FLASH->SR & FLASH_STATUS_ALL_FLAGS; // get the current status flags 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 FLASH->SR |= FLASH_STATUS_ALL_FLAGS; // clear all status flags
return result; return result;
} }
secbool flash_check_option_bytes(void) secbool flash_check_option_bytes(void) {
{
flash_wait_and_clear_status_flags(); flash_wait_and_clear_status_flags();
// check values stored in flash interface registers // check values stored in flash interface registers
if ((FLASH->OPTCR & ~3) != FLASH_OPTCR_VALUE) { // ignore bits 0 and 1 because they are control bits if ((FLASH->OPTCR & ~3) !=
FLASH_OPTCR_VALUE) { // ignore bits 0 and 1 because they are control bits
return secfalse; return secfalse;
} }
if (FLASH->OPTCR1 != FLASH_OPTCR1_nWRP) { if (FLASH->OPTCR1 != FLASH_OPTCR1_nWRP) {
return secfalse; return secfalse;
} }
// check values stored in flash memory // check values stored in flash memory
if ((OPTION_BYTES_RDP_USER & ~3) != OPTION_BYTES_RDP_USER_VALUE) { // bits 0 and 1 are unused if ((OPTION_BYTES_RDP_USER & ~3) !=
OPTION_BYTES_RDP_USER_VALUE) { // bits 0 and 1 are unused
return secfalse; return secfalse;
} }
if ((OPTION_BYTES_BANK1_WRP & 0xCFFFU) != OPTION_BYTES_BANK1_WRP_VALUE) { // bits 12 and 13 are unused if ((OPTION_BYTES_BANK1_WRP & 0xCFFFU) !=
OPTION_BYTES_BANK1_WRP_VALUE) { // bits 12 and 13 are unused
return secfalse; return secfalse;
} }
if ((OPTION_BYTES_BANK2_WRP & 0xFFFU) != OPTION_BYTES_BANK2_WRP_VALUE) { // bits 12, 13, 14, and 15 are unused if ((OPTION_BYTES_BANK2_WRP & 0xFFFU) !=
OPTION_BYTES_BANK2_WRP_VALUE) { // bits 12, 13, 14, and 15 are unused
return secfalse; return secfalse;
} }
return sectrue; return sectrue;
} }
void flash_lock_option_bytes(void) void flash_lock_option_bytes(void) {
{
FLASH->OPTCR |= FLASH_OPTCR_OPTLOCK; // lock the option bytes FLASH->OPTCR |= FLASH_OPTCR_OPTLOCK; // lock the option bytes
} }
void flash_unlock_option_bytes(void) void flash_unlock_option_bytes(void) {
{
if ((FLASH->OPTCR & FLASH_OPTCR_OPTLOCK) == 0) { if ((FLASH->OPTCR & FLASH_OPTCR_OPTLOCK) == 0) {
return; // already unlocked return; // already unlocked
} }
@ -94,38 +104,40 @@ void flash_unlock_option_bytes(void)
// write the special sequence to unlock // write the special sequence to unlock
FLASH->OPTKEYR = FLASH_OPT_KEY1; FLASH->OPTKEYR = FLASH_OPT_KEY1;
FLASH->OPTKEYR = FLASH_OPT_KEY2; FLASH->OPTKEYR = FLASH_OPT_KEY2;
while (FLASH->OPTCR & FLASH_OPTCR_OPTLOCK); // wait until the flash option control register is unlocked while (FLASH->OPTCR & FLASH_OPTCR_OPTLOCK)
; // wait until the flash option control register is unlocked
} }
uint32_t flash_set_option_bytes(void) uint32_t flash_set_option_bytes(void) {
{
// reference RM0090 section 3.7.2 // reference RM0090 section 3.7.2
flash_wait_and_clear_status_flags(); flash_wait_and_clear_status_flags();
flash_unlock_option_bytes(); flash_unlock_option_bytes();
flash_wait_and_clear_status_flags(); flash_wait_and_clear_status_flags();
FLASH->OPTCR1 = FLASH_OPTCR1_nWRP; // no write protection on any sectors in bank 2 FLASH->OPTCR1 =
FLASH->OPTCR = FLASH_OPTCR_VALUE; // WARNING: dev board safe unless you compile for PRODUCTION or change this value!!! 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 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 const uint32_t result =
flash_wait_and_clear_status_flags(); // wait until changes are committed
flash_lock_option_bytes(); flash_lock_option_bytes();
return result; return result;
} }
secbool flash_configure_option_bytes(void) secbool flash_configure_option_bytes(void) {
{
if (sectrue == flash_check_option_bytes()) { if (sectrue == flash_check_option_bytes()) {
return sectrue; // we DID NOT have to change the option bytes return sectrue; // we DID NOT have to change the option bytes
} }
do { do {
flash_set_option_bytes(); flash_set_option_bytes();
} while(sectrue != flash_check_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) void periph_init(void) {
{
// STM32F4xx HAL library initialization: // STM32F4xx HAL library initialization:
// - configure the Flash prefetch, instruction and data caches // - configure the Flash prefetch, instruction and data caches
// - configure the Systick to generate an interrupt each 1 msec // - configure the Systick to generate an interrupt each 1 msec
@ -152,13 +164,15 @@ void periph_init(void)
NVIC_EnableIRQ(PVD_IRQn); NVIC_EnableIRQ(PVD_IRQn);
} }
secbool reset_flags_check(void) secbool reset_flags_check(void) {
{
#if PRODUCTION #if PRODUCTION
// this is effective enough that it makes development painful, so only use it for production. // this is effective enough that it makes development painful, so only use it
// check the reset flags to assure that we arrive here due to a regular full power-on event, // for production. check the reset flags to assure that we arrive here due to
// and not as a result of a lesser reset. // 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)) { 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; return secfalse;
} }
#endif #endif

View File

@ -1,3 +1,5 @@
// clang-format off
/* /*
* The Minimal snprintf() implementation * The Minimal snprintf() implementation
* *

View File

@ -1,3 +1,5 @@
// clang-format off
/* /*
* The Minimal snprintf() implementation * The Minimal snprintf() implementation
* *

View File

@ -27,14 +27,12 @@
#define MPU_SUBREGION_DISABLE(X) ((X) << MPU_RASR_SRD_Pos) #define MPU_SUBREGION_DISABLE(X) ((X) << MPU_RASR_SRD_Pos)
void mpu_config_off(void) void mpu_config_off(void) {
{
// Disable MPU // Disable MPU
HAL_MPU_Disable(); HAL_MPU_Disable();
} }
void mpu_config_bootloader(void) void mpu_config_bootloader(void) {
{
// Disable MPU // Disable MPU
HAL_MPU_Disable(); HAL_MPU_Disable();
@ -43,34 +41,44 @@ void mpu_config_bootloader(void)
// Everything (0x00000000 - 0xFFFFFFFF, 4 GiB, read-write) // Everything (0x00000000 - 0xFFFFFFFF, 4 GiB, read-write)
MPU->RNR = MPU_REGION_NUMBER0; MPU->RNR = MPU_REGION_NUMBER0;
MPU->RBAR = 0; MPU->RBAR = 0;
MPU->RASR = MPU_RASR_ENABLE_Msk | MPU_RASR_ATTR_FLASH | LL_MPU_REGION_SIZE_4GB | LL_MPU_REGION_FULL_ACCESS; 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) // Flash (0x0800C000 - 0x0800FFFF, 16 KiB, no access)
MPU->RNR = MPU_REGION_NUMBER1; MPU->RNR = MPU_REGION_NUMBER1;
MPU->RBAR = FLASH_BASE + 0xC000; 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; 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) // Flash (0x0810C000 - 0x0810FFFF, 16 KiB, no access)
MPU->RNR = MPU_REGION_NUMBER2; MPU->RNR = MPU_REGION_NUMBER2;
MPU->RBAR = FLASH_BASE + 0x10C000; 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; 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) // SRAM (0x20000000 - 0x2002FFFF, 192 KiB = 256 KiB except 2/8 at end,
// read-write, execute never)
MPU->RNR = MPU_REGION_NUMBER3; MPU->RNR = MPU_REGION_NUMBER3;
MPU->RBAR = SRAM_BASE; 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); 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) // Peripherals (0x40000000 - 0x5FFFFFFF, read-write, execute never)
// External RAM (0x60000000 - 0x7FFFFFFF, read-write, execute never) // External RAM (0x60000000 - 0x7FFFFFFF, read-write, execute never)
MPU->RNR = MPU_REGION_NUMBER4; MPU->RNR = MPU_REGION_NUMBER4;
MPU->RBAR = PERIPH_BASE; 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; 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 #ifdef STM32F427xx
// CCMRAM (0x10000000 - 0x1000FFFF, read-write, execute never) // CCMRAM (0x10000000 - 0x1000FFFF, read-write, execute never)
MPU->RNR = MPU_REGION_NUMBER5; MPU->RNR = MPU_REGION_NUMBER5;
MPU->RBAR = CCMDATARAM_BASE; 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; 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 #elif STM32F405xx
// no CCMRAM // no CCMRAM
#else #else
@ -81,60 +89,77 @@ void mpu_config_bootloader(void)
HAL_MPU_Enable(LL_MPU_CTRL_HARDFAULT_NMI); HAL_MPU_Enable(LL_MPU_CTRL_HARDFAULT_NMI);
} }
void mpu_config_firmware(void) {
void mpu_config_firmware(void)
{
// Disable MPU // Disable MPU
HAL_MPU_Disable(); HAL_MPU_Disable();
// Note: later entries overwrite previous ones // Note: later entries overwrite previous ones
/* /*
// Boardloader (0x08000000 - 0x0800FFFF, 64 KiB, read-only, execute never) // Boardloader (0x08000000 - 0x0800FFFF, 64 KiB, read-only, execute never)
MPU->RBAR = FLASH_BASE | MPU_REGION_NUMBER0; 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; 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) // Bootloader (0x08020000 - 0x0803FFFF, 64 KiB, read-only)
MPU->RNR = MPU_REGION_NUMBER0; MPU->RNR = MPU_REGION_NUMBER0;
MPU->RBAR = FLASH_BASE + 0x20000; 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; 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) // Storage#1 (0x08010000 - 0x0801FFFF, 64 KiB, read-write, execute never)
MPU->RNR = MPU_REGION_NUMBER1; MPU->RNR = MPU_REGION_NUMBER1;
MPU->RBAR = FLASH_BASE + 0x10000; 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; 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) // Storage#2 (0x08110000 - 0x0811FFFF, 64 KiB, read-write, execute never)
MPU->RNR = MPU_REGION_NUMBER2; MPU->RNR = MPU_REGION_NUMBER2;
MPU->RBAR = FLASH_BASE + 0x110000; 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; 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) // Firmware (0x08040000 - 0x080FFFFF, 6 * 128 KiB = 1024 KiB except 2/8 at
// start = 768 KiB, read-only)
MPU->RNR = MPU_REGION_NUMBER3; MPU->RNR = MPU_REGION_NUMBER3;
MPU->RBAR = FLASH_BASE; 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); 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) // Firmware extra (0x08120000 - 0x081FFFFF, 7 * 128 KiB = 1024 KiB except 1/8
// at start = 896 KiB, read-only)
MPU->RNR = MPU_REGION_NUMBER4; MPU->RNR = MPU_REGION_NUMBER4;
MPU->RBAR = FLASH_BASE + 0x100000; 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); 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) // SRAM (0x20000000 - 0x2002FFFF, 192 KiB = 256 KiB except 2/8 at end,
// read-write, execute never)
MPU->RNR = MPU_REGION_NUMBER5; MPU->RNR = MPU_REGION_NUMBER5;
MPU->RBAR = SRAM_BASE; 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); 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) // Peripherals (0x40000000 - 0x5FFFFFFF, read-write, execute never)
// External RAM (0x60000000 - 0x7FFFFFFF, read-write, execute never) // External RAM (0x60000000 - 0x7FFFFFFF, read-write, execute never)
MPU->RNR = MPU_REGION_NUMBER6; MPU->RNR = MPU_REGION_NUMBER6;
MPU->RBAR = PERIPH_BASE; 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; 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 #ifdef STM32F427xx
// CCMRAM (0x10000000 - 0x1000FFFF, read-write, execute never) // CCMRAM (0x10000000 - 0x1000FFFF, read-write, execute never)
MPU->RNR = MPU_REGION_NUMBER7; MPU->RNR = MPU_REGION_NUMBER7;
MPU->RBAR = CCMDATARAM_BASE; 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; 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 #elif STM32F405xx
// no CCMRAM // no CCMRAM
#else #else

View File

@ -21,10 +21,10 @@
#include "rng.h" #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) void rng_init(void) {
{
// enable TRNG peripheral clock // enable TRNG peripheral clock
// use the HAL version due to section 2.1.6 of STM32F42xx Errata sheet // use the HAL version due to section 2.1.6 of STM32F42xx Errata sheet
// "Delay after an RCC peripheral clock enabling" // "Delay after an RCC peripheral clock enabling"
@ -32,19 +32,21 @@ void rng_init(void)
RNG->CR = RNG_CR_RNGEN; // enable TRNG RNG->CR = RNG_CR_RNGEN; // enable TRNG
} }
uint32_t rng_read(const uint32_t previous, const uint32_t compare_previous) uint32_t rng_read(const uint32_t previous, const uint32_t compare_previous) {
{
uint32_t temp = previous; uint32_t temp = previous;
do { do {
while ((RNG->SR & (RNG_SR_SECS | RNG_SR_CECS | RNG_SR_DRDY)) != RNG_SR_DRDY); // wait until TRNG is ready 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 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 } while (compare_previous &&
(temp == previous)); // RM0090 section 24.3.1 FIPS continuous random
// number generator test
return temp; return temp;
} }
uint32_t rng_get(void) uint32_t rng_get(void) {
{ // reason for keeping history: RM0090 section 24.3.1 FIPS continuous random
// reason for keeping history: RM0090 section 24.3.1 FIPS continuous random number generator test // number generator test
static uint32_t previous = 0, current = 0; static uint32_t previous = 0, current = 0;
if (previous == current) { if (previous == current) {
previous = rng_read(previous, 0); previous = rng_read(previous, 0);

View File

@ -36,6 +36,8 @@ void sbu_init(void) {
} }
void sbu_set(secbool sbu1, secbool sbu2) { 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_2,
HAL_GPIO_WritePin(GPIOA, GPIO_PIN_3, sbu2 == sectrue ? GPIO_PIN_SET : GPIO_PIN_RESET); sbu1 == sectrue ? GPIO_PIN_SET : GPIO_PIN_RESET);
HAL_GPIO_WritePin(GPIOA, GPIO_PIN_3,
sbu2 == sectrue ? GPIO_PIN_SET : GPIO_PIN_RESET);
} }

View File

@ -73,7 +73,8 @@ static inline void sdcard_default_pin_state(void) {
GPIO_InitStructure.Mode = GPIO_MODE_OUTPUT_PP; GPIO_InitStructure.Mode = GPIO_MODE_OUTPUT_PP;
GPIO_InitStructure.Pull = GPIO_NOPULL; GPIO_InitStructure.Pull = GPIO_NOPULL;
GPIO_InitStructure.Speed = GPIO_SPEED_FREQ_LOW; 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; GPIO_InitStructure.Pin =
GPIO_PIN_8 | GPIO_PIN_9 | GPIO_PIN_10 | GPIO_PIN_11 | GPIO_PIN_12;
HAL_GPIO_Init(GPIOC, &GPIO_InitStructure); HAL_GPIO_Init(GPIOC, &GPIO_InitStructure);
GPIO_InitStructure.Pin = GPIO_PIN_2; GPIO_InitStructure.Pin = GPIO_PIN_2;
HAL_GPIO_Init(GPIOD, &GPIO_InitStructure); HAL_GPIO_Init(GPIOD, &GPIO_InitStructure);
@ -97,15 +98,14 @@ static inline void sdcard_active_pin_state(void) {
GPIO_InitStructure.Pull = GPIO_PULLUP; GPIO_InitStructure.Pull = GPIO_PULLUP;
GPIO_InitStructure.Speed = GPIO_SPEED_FREQ_VERY_HIGH; GPIO_InitStructure.Speed = GPIO_SPEED_FREQ_VERY_HIGH;
GPIO_InitStructure.Alternate = GPIO_AF12_SDIO; GPIO_InitStructure.Alternate = GPIO_AF12_SDIO;
GPIO_InitStructure.Pin = GPIO_PIN_8 | GPIO_PIN_9 | GPIO_PIN_10 | GPIO_PIN_11 | GPIO_PIN_12; GPIO_InitStructure.Pin =
GPIO_PIN_8 | GPIO_PIN_9 | GPIO_PIN_10 | GPIO_PIN_11 | GPIO_PIN_12;
HAL_GPIO_Init(GPIOC, &GPIO_InitStructure); HAL_GPIO_Init(GPIOC, &GPIO_InitStructure);
GPIO_InitStructure.Pin = GPIO_PIN_2; GPIO_InitStructure.Pin = GPIO_PIN_2;
HAL_GPIO_Init(GPIOD, &GPIO_InitStructure); HAL_GPIO_Init(GPIOD, &GPIO_InitStructure);
} }
void sdcard_init(void) { void sdcard_init(void) { sdcard_default_pin_state(); }
sdcard_default_pin_state();
}
void HAL_SD_MspInit(SD_HandleTypeDef *hsd) { void HAL_SD_MspInit(SD_HandleTypeDef *hsd) {
// enable SDIO clock // enable SDIO clock
@ -113,9 +113,7 @@ void HAL_SD_MspInit(SD_HandleTypeDef *hsd) {
// GPIO have already been initialised by sdcard_init // GPIO have already been initialised by sdcard_init
} }
void HAL_SD_MspDeInit(SD_HandleTypeDef *hsd) { void HAL_SD_MspDeInit(SD_HandleTypeDef *hsd) { __HAL_RCC_SDIO_CLK_DISABLE(); }
__HAL_RCC_SDIO_CLK_DISABLE();
}
secbool sdcard_power_on(void) { secbool sdcard_power_on(void) {
if (sectrue != sdcard_is_present()) { if (sectrue != sdcard_is_present()) {
@ -182,7 +180,8 @@ uint64_t sdcard_get_capacity_in_bytes(void) {
return (uint64_t)cardinfo.LogBlockNbr * (uint64_t)cardinfo.LogBlockSize; return (uint64_t)cardinfo.LogBlockNbr * (uint64_t)cardinfo.LogBlockSize;
} }
static HAL_StatusTypeDef sdcard_wait_finished(SD_HandleTypeDef *sd, uint32_t 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) // Wait for HAL driver to be ready (eg for DMA to finish)
uint32_t start = HAL_GetTick(); uint32_t start = HAL_GetTick();
while (sd->State == HAL_SD_STATE_BUSY) { while (sd->State == HAL_SD_STATE_BUSY) {
@ -196,7 +195,8 @@ static HAL_StatusTypeDef sdcard_wait_finished(SD_HandleTypeDef *sd, uint32_t tim
if (state == HAL_SD_CARD_TRANSFER) { 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)) { if (!(state == HAL_SD_CARD_SENDING || state == HAL_SD_CARD_RECEIVING ||
state == HAL_SD_CARD_PROGRAMMING)) {
return HAL_ERROR; return HAL_ERROR;
} }
if (HAL_GetTick() - start >= timeout) { if (HAL_GetTick() - start >= timeout) {
@ -206,7 +206,8 @@ static HAL_StatusTypeDef sdcard_wait_finished(SD_HandleTypeDef *sd, uint32_t tim
return HAL_OK; return HAL_OK;
} }
secbool sdcard_read_blocks(uint32_t *dest, uint32_t block_num, uint32_t num_blocks) { secbool sdcard_read_blocks(uint32_t *dest, uint32_t block_num,
uint32_t num_blocks) {
// check that SD card is initialised // check that SD card is initialised
if (sd_handle.Instance == NULL) { if (sd_handle.Instance == NULL) {
return secfalse; return secfalse;
@ -219,7 +220,8 @@ secbool sdcard_read_blocks(uint32_t *dest, uint32_t block_num, uint32_t num_bloc
HAL_StatusTypeDef err = HAL_OK; HAL_StatusTypeDef err = HAL_OK;
err = HAL_SD_ReadBlocks(&sd_handle, (uint8_t *)dest, block_num, num_blocks, 60000); err = HAL_SD_ReadBlocks(&sd_handle, (uint8_t *)dest, block_num, num_blocks,
60000);
if (err == HAL_OK) { if (err == HAL_OK) {
err = sdcard_wait_finished(&sd_handle, 60000); err = sdcard_wait_finished(&sd_handle, 60000);
} }
@ -227,7 +229,8 @@ secbool sdcard_read_blocks(uint32_t *dest, uint32_t block_num, uint32_t num_bloc
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) { secbool sdcard_write_blocks(const uint32_t *src, uint32_t block_num,
uint32_t num_blocks) {
// check that SD card is initialised // check that SD card is initialised
if (sd_handle.Instance == NULL) { if (sd_handle.Instance == NULL) {
return secfalse; return secfalse;
@ -240,7 +243,8 @@ secbool sdcard_write_blocks(const uint32_t *src, uint32_t block_num, uint32_t nu
HAL_StatusTypeDef err = HAL_OK; HAL_StatusTypeDef err = HAL_OK;
err = HAL_SD_WriteBlocks(&sd_handle, (uint8_t *)src, block_num, num_blocks, 60000); err = HAL_SD_WriteBlocks(&sd_handle, (uint8_t *)src, block_num, num_blocks,
60000);
if (err == HAL_OK) { if (err == HAL_OK) {
err = sdcard_wait_finished(&sd_handle, 60000); err = sdcard_wait_finished(&sd_handle, 60000);
} }

View File

@ -56,7 +56,9 @@ secbool __wur sdcard_power_on(void);
void sdcard_power_off(void); void sdcard_power_off(void);
secbool __wur sdcard_is_present(void); secbool __wur sdcard_is_present(void);
uint64_t sdcard_get_capacity_in_bytes(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_read_blocks(uint32_t *dest, uint32_t block_num,
secbool __wur sdcard_write_blocks(const uint32_t *src, uint32_t block_num, uint32_t num_blocks); uint32_t num_blocks);
secbool __wur sdcard_write_blocks(const uint32_t *src, uint32_t block_num,
uint32_t num_blocks);
#endif #endif

View File

@ -27,7 +27,7 @@ typedef uint32_t secbool;
#define secfalse 0x00000000U #define secfalse 0x00000000U
#ifndef __wur #ifndef __wur
#define __wur __attribute__ ((warn_unused_result)) #define __wur __attribute__((warn_unused_result))
#endif #endif
#endif #endif

View File

@ -21,7 +21,8 @@
#include "rng.h" #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}; const uint8_t APBPrescTable[8] = {0, 0, 0, 0, 1, 2, 3, 4};
#ifdef STM32F427xx #ifdef STM32F427xx
@ -34,46 +35,60 @@ const uint8_t APBPrescTable[8] = {0, 0, 0, 0, 1, 2, 3, 4};
uint32_t SystemCoreClock = CORE_CLOCK_MHZ * 1000000U; 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) void SystemInit(void) {
{ // set flash wait states for an increasing HCLK frequency -- reference RM0090
// set flash wait states for an increasing HCLK frequency -- reference RM0090 section 3.5.1 // section 3.5.1
FLASH->ACR = FLASH_ACR_LATENCY_5WS; FLASH->ACR = FLASH_ACR_LATENCY_5WS;
// wait until the new wait state config takes effect -- per section 3.5.1 guidance // wait until the new wait state config takes effect -- per section 3.5.1
while ((FLASH->ACR & FLASH_ACR_LATENCY) != FLASH_ACR_LATENCY_5WS); // guidance
// configure main PLL; assumes HSE is 8 MHz; this should evaluate to 0x27402a04 -- reference RM0090 section 7.3.2 while ((FLASH->ACR & FLASH_ACR_LATENCY) != FLASH_ACR_LATENCY_5WS)
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 // 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 | RCC_PLLCFGR_PLLSRC_HSE // PLLSRC = HSE
| (0U << RCC_PLLCFGR_PLLP_Pos) // P = 2 (two bits, 00 means PLLP = 2) | (0U << RCC_PLLCFGR_PLLP_Pos) // P = 2 (two bits, 00 means PLLP = 2)
| (CORE_CLOCK_MHZ << RCC_PLLCFGR_PLLN_Pos) // N = CORE_CLOCK_MHZ | (CORE_CLOCK_MHZ << RCC_PLLCFGR_PLLN_Pos) // N = CORE_CLOCK_MHZ
| (4U << RCC_PLLCFGR_PLLM_Pos); // M = 4 | (4U << RCC_PLLCFGR_PLLM_Pos); // M = 4
// enable spread spectrum clock for main PLL // enable spread spectrum clock for main PLL
RCC->SSCGR = RCC_SSCGR_SSCGEN | (44 << RCC_SSCGR_INCSTEP_Pos) | (250 << RCC_SSCGR_MODPER_Pos); RCC->SSCGR = RCC_SSCGR_SSCGEN | (44 << RCC_SSCGR_INCSTEP_Pos) |
(250 << RCC_SSCGR_MODPER_Pos);
// enable clock security system, HSE clock, and main PLL // enable clock security system, HSE clock, and main PLL
RCC->CR |= RCC_CR_CSSON | RCC_CR_HSEON | RCC_CR_PLLON; RCC->CR |= RCC_CR_CSSON | RCC_CR_HSEON | RCC_CR_PLLON;
// wait until PLL and HSE ready // wait until PLL and HSE ready
while((RCC->CR & (RCC_CR_PLLRDY | RCC_CR_HSERDY)) != (RCC_CR_PLLRDY | RCC_CR_HSERDY)); 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 // 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; const uint32_t cfgr = RCC_CFGR_PPRE2_DIV2 | RCC_CFGR_PPRE1_DIV4 |
RCC_CFGR_HPRE_DIV1 | RCC_CFGR_SW_PLL;
RCC->CFGR = cfgr; RCC->CFGR = cfgr;
// wait until PLL is system clock and also verify that the pre-scalers were set // wait until PLL is system clock and also verify that the pre-scalers were
while(RCC->CFGR != (RCC_CFGR_SWS_PLL | cfgr)); // set
// turn off the HSI as it is now unused (it will be turned on again automatically if a clock security failure occurs) 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; RCC->CR &= ~RCC_CR_HSION;
// wait until ths HSI is off // wait until ths HSI is off
while((RCC->CR & RCC_CR_HSION) == RCC_CR_HSION); while ((RCC->CR & RCC_CR_HSION) == RCC_CR_HSION)
;
// init the TRNG peripheral // init the TRNG peripheral
rng_init(); rng_init();
// set CP10 and CP11 to enable full access to the fpu coprocessor; ARMv7-M Architecture Reference Manual section B3.2.20 // 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)); SCB->CPACR |= ((3U << 22) | (3U << 20));
} }
extern volatile uint32_t uwTick; extern volatile uint32_t uwTick;
void SysTick_Handler(void) void SysTick_Handler(void) {
{
// this is a millisecond tick counter that wraps after approximately // this is a millisecond tick counter that wraps after approximately
// 49.71 days = (0xffffffff / (24 * 60 * 60 * 1000)) // 49.71 days = (0xffffffff / (24 * 60 * 60 * 1000))
uwTick++; uwTick++;
@ -82,8 +97,7 @@ void SysTick_Handler(void)
// from util.s // from util.s
extern void shutdown(void); extern void shutdown(void);
void PVD_IRQHandler(void) void PVD_IRQHandler(void) {
{
TIM1->CCR1 = 0; // turn off display backlight TIM1->CCR1 = 0; // turn off display backlight
shutdown(); shutdown();
} }

View File

@ -1,3 +1,5 @@
// clang-format off
/** /**
****************************************************************************** ******************************************************************************
* @file stm32f4xx_hal_conf.h * @file stm32f4xx_hal_conf.h

View File

@ -1,3 +1,5 @@
// clang-format off
/* /*
* This file is part of the TREZOR project, https://trezor.io/ * This file is part of the TREZOR project, https://trezor.io/
* *

View File

@ -28,17 +28,20 @@
#error Unknown TREZOR Model #error Unknown TREZOR Model
#endif #endif
uint32_t touch_click(void) uint32_t touch_click(void) {
{
uint32_t r = 0; uint32_t r = 0;
// flush touch events if any // flush touch events if any
while (touch_read()) { } while (touch_read()) {
}
// wait for TOUCH_START // wait for TOUCH_START
while ((touch_read() & TOUCH_START) == 0) { } while ((touch_read() & TOUCH_START) == 0) {
}
// wait for TOUCH_END // wait for TOUCH_END
while (((r = touch_read()) & TOUCH_END) == 0) { } while (((r = touch_read()) & TOUCH_END) == 0) {
}
// flush touch events if any // flush touch events if any
while (touch_read()) { } while (touch_read()) {
}
// return last touch coordinate // return last touch coordinate
return r; return r;
} }

View File

@ -33,8 +33,14 @@ void touch_sensitivity(uint8_t value);
uint32_t touch_read(void); uint32_t touch_read(void);
uint32_t touch_click(void); uint32_t touch_click(void);
uint32_t touch_is_detected(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_x(uint32_t evt) {
static inline uint16_t touch_unpack_y(uint32_t evt) { return (evt >> 0) & 0xFFF; } return (evt >> 12) & 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_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 #endif

View File

@ -19,14 +19,13 @@ void touch_init(void) {
HAL_GPIO_Init(GPIOC, &GPIO_InitStructure); 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; } void touch_sensitivity(uint8_t value) { (void)value; }
uint32_t touch_read(void) uint32_t touch_read(void) {
{
static char last_left = 0, last_right = 0; static char last_left = 0, last_right = 0;
char left = (GPIO_PIN_RESET == HAL_GPIO_ReadPin(GPIOC, BTN_PIN_LEFT)); char left = (GPIO_PIN_RESET == HAL_GPIO_ReadPin(GPIOC, BTN_PIN_LEFT));
char right = (GPIO_PIN_RESET == HAL_GPIO_ReadPin(GPIOC, BTN_PIN_RIGHT)); char right = (GPIO_PIN_RESET == HAL_GPIO_ReadPin(GPIOC, BTN_PIN_RIGHT));
@ -49,7 +48,7 @@ uint32_t touch_read(void)
return 0; return 0;
} }
uint32_t touch_is_detected(void) uint32_t touch_is_detected(void) {
{ return (GPIO_PIN_RESET == HAL_GPIO_ReadPin(GPIOC, BTN_PIN_LEFT)) ||
return (GPIO_PIN_RESET == HAL_GPIO_ReadPin(GPIOC, BTN_PIN_LEFT)) || (GPIO_PIN_RESET == HAL_GPIO_ReadPin(GPIOC, BTN_PIN_RIGHT)); (GPIO_PIN_RESET == HAL_GPIO_ReadPin(GPIOC, BTN_PIN_RIGHT));
} }

View File

@ -3,7 +3,8 @@
#include "common.h" #include "common.h"
#include "secbool.h" #include "secbool.h"
#define TOUCH_ADDRESS (0x38U << 1) // the HAL requires the 7-bit address to be shifted by one bit #define TOUCH_ADDRESS \
(0x38U << 1) // the HAL requires the 7-bit address to be shifted by one bit
#define TOUCH_PACKET_SIZE 7U #define TOUCH_PACKET_SIZE 7U
#define EVENT_PRESS_DOWN 0x00U #define EVENT_PRESS_DOWN 0x00U
#define EVENT_CONTACT 0x80U #define EVENT_CONTACT 0x80U
@ -19,11 +20,18 @@ static I2C_HandleTypeDef i2c_handle;
static void touch_default_pin_state(void) { static void touch_default_pin_state(void) {
// set power off and other pins as per section 3.5 of FT6236 datasheet // 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_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_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(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(
HAL_GPIO_WritePin(GPIOC, GPIO_PIN_5, GPIO_PIN_RESET); // CTP_REST/PC5 (active low) i.e.- CTPM held in reset until released 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 // set above pins to OUTPUT / NOPULL
GPIO_InitTypeDef GPIO_InitStructure; GPIO_InitTypeDef GPIO_InitStructure;
@ -38,7 +46,8 @@ static void touch_default_pin_state(void) {
// in-case power was on, or CTPM was active make sure to wait long enough // 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 // 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). // a minimum of 5ms. also wait for power circuitry to stabilize (if it
// changed).
HAL_Delay(100); // 100ms (being conservative) HAL_Delay(100); // 100ms (being conservative)
} }
@ -51,7 +60,9 @@ static void touch_active_pin_state(void) {
// configure CTP I2C SCL and SDA GPIO lines (PB6 & PB7) // configure CTP I2C SCL and SDA GPIO lines (PB6 & PB7)
GPIO_InitStructure.Mode = GPIO_MODE_AF_OD; GPIO_InitStructure.Mode = GPIO_MODE_AF_OD;
GPIO_InitStructure.Pull = GPIO_NOPULL; 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.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.Alternate = GPIO_AF4_I2C1;
GPIO_InitStructure.Pin = GPIO_PIN_6 | GPIO_PIN_7; GPIO_InitStructure.Pin = GPIO_PIN_6 | GPIO_PIN_7;
HAL_GPIO_Init(GPIOB, &GPIO_InitStructure); HAL_GPIO_Init(GPIOB, &GPIO_InitStructure);
@ -64,12 +75,11 @@ static void touch_active_pin_state(void) {
HAL_GPIO_Init(GPIOC, &GPIO_InitStructure); HAL_GPIO_Init(GPIOC, &GPIO_InitStructure);
HAL_GPIO_WritePin(GPIOC, GPIO_PIN_5, GPIO_PIN_SET); // release CTPM reset 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_Delay(310); // "Time of starting to report point after resetting" min is
// 300ms, giving an extra 10ms
} }
void touch_init(void) { void touch_init(void) { touch_default_pin_state(); }
touch_default_pin_state();
}
void HAL_I2C_MspInit(I2C_HandleTypeDef *hi2c) { void HAL_I2C_MspInit(I2C_HandleTypeDef *hi2c) {
// enable I2C clock // enable I2C clock
@ -106,9 +116,14 @@ void touch_power_on(void) {
return; 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. // 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}; 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); ensure(
sectrue * (HAL_OK == HAL_I2C_Master_Transmit(
&i2c_handle, TOUCH_ADDRESS, touch_panel_config,
sizeof(touch_panel_config), 10)),
NULL);
touch_sensitivity(0x06); touch_sensitivity(0x06);
} }
@ -126,11 +141,14 @@ void touch_power_off(void) {
void touch_sensitivity(uint8_t value) { void touch_sensitivity(uint8_t value) {
// set panel threshold (TH_GROUP) - default value is 0x12 // set panel threshold (TH_GROUP) - default value is 0x12
uint8_t touch_panel_threshold[] = {0x80, value}; 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); 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) uint32_t touch_is_detected(void) {
{
// check the interrupt line coming in from the CTPM. // check the interrupt line coming in from the CTPM.
// the line goes low when a touch event is actively detected. // the line goes low when a touch event is actively detected.
// reference section 1.2 of "Application Note for FT6x06 CTPM". // reference section 1.2 of "Application Note for FT6x06 CTPM".
@ -138,9 +156,9 @@ uint32_t touch_is_detected(void)
return GPIO_PIN_RESET == HAL_GPIO_ReadPin(GPIOC, GPIO_PIN_4); return GPIO_PIN_RESET == HAL_GPIO_ReadPin(GPIOC, GPIO_PIN_4);
} }
uint32_t touch_read(void) uint32_t touch_read(void) {
{ static uint8_t touch_data[TOUCH_PACKET_SIZE],
static uint8_t touch_data[TOUCH_PACKET_SIZE], previous_touch_data[TOUCH_PACKET_SIZE]; previous_touch_data[TOUCH_PACKET_SIZE];
static uint32_t xy; static uint32_t xy;
static int touching; static int touching;
@ -157,11 +175,13 @@ uint32_t touch_read(void)
} }
uint8_t outgoing[] = {0x00}; // start reading from address 0x00 uint8_t outgoing[] = {0x00}; // start reading from address 0x00
if (HAL_OK != HAL_I2C_Master_Transmit(&i2c_handle, TOUCH_ADDRESS, outgoing, sizeof(outgoing), 1)) { if (HAL_OK != HAL_I2C_Master_Transmit(&i2c_handle, TOUCH_ADDRESS, outgoing,
sizeof(outgoing), 1)) {
return 0; return 0;
} }
if (HAL_OK != HAL_I2C_Master_Receive(&i2c_handle, TOUCH_ADDRESS, touch_data, TOUCH_PACKET_SIZE, 1)) { if (HAL_OK != HAL_I2C_Master_Receive(&i2c_handle, TOUCH_ADDRESS, touch_data,
TOUCH_PACKET_SIZE, 1)) {
return 0; // read failure return 0; // read failure
} }
@ -171,10 +191,13 @@ uint32_t touch_read(void)
memcpy(previous_touch_data, touch_data, TOUCH_PACKET_SIZE); 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 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; const uint32_t event_flag = touch_data[3] & 0xC0;
if (touch_data[1] == GESTURE_NO_GESTURE) { 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); 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)) { if ((number_of_touch_points == 1) && (event_flag == EVENT_PRESS_DOWN)) {
touching = 1; touching = 1;
return TOUCH_START | xy; return TOUCH_START | xy;
@ -187,8 +210,8 @@ uint32_t touch_read(void)
} }
if (last_packet) { if (last_packet) {
// interrupt line is inactive, we didn't read valid touch data, and as far as // interrupt line is inactive, we didn't read valid touch data, and as far
// we know, we never sent a TOUCH_END event. // as we know, we never sent a TOUCH_END event.
touching = 0; touching = 0;
return TOUCH_END | xy; return TOUCH_END | xy;
} }

View File

@ -19,8 +19,8 @@
#include STM32_HAL_H #include STM32_HAL_H
#include "common.h"
#include "usb.h" #include "usb.h"
#include "common.h"
#include "usbd_core.h" #include "usbd_core.h"
#define USB_MAX_CONFIG_DESC_SIZE 256 #define USB_MAX_CONFIG_DESC_SIZE 256
@ -35,8 +35,12 @@
#error Unable to determine proper USB_PHY_ID to use #error Unable to determine proper USB_PHY_ID to use
#endif #endif
#define USB_WINUSB_VENDOR_CODE '!' // arbitrary, but must be equivalent to the last character in extra string #define USB_WINUSB_VENDOR_CODE \
#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! '!' // 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_EXTRA_STRING_INDEX 0xEE
#define USB_WINUSB_REQ_GET_COMPATIBLE_ID_FEATURE_DESCRIPTOR 0x04 #define USB_WINUSB_REQ_GET_COMPATIBLE_ID_FEATURE_DESCRIPTOR 0x04
#define USB_WINUSB_REQ_GET_EXTENDED_PROPERTIES_OS_FEATURE_DESCRIPTOR 0x05 #define USB_WINUSB_REQ_GET_EXTENDED_PROPERTIES_OS_FEATURE_DESCRIPTOR 0x05
@ -46,8 +50,10 @@
static usb_device_descriptor_t usb_dev_desc; static usb_device_descriptor_t usb_dev_desc;
// Config descriptor // Config descriptor
static uint8_t usb_config_buf[USB_MAX_CONFIG_DESC_SIZE] __attribute__((aligned(4))); static uint8_t usb_config_buf[USB_MAX_CONFIG_DESC_SIZE]
static usb_config_descriptor_t *usb_config_desc = (usb_config_descriptor_t *)(usb_config_buf); __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; static usb_interface_descriptor_t *usb_next_iface_desc;
// String descriptor // String descriptor
@ -70,7 +76,6 @@ static secbool __wur check_desc_str(const char *s) {
} }
void usb_init(const usb_dev_info_t *dev_info) { void usb_init(const usb_dev_info_t *dev_info) {
// enable/disable USB 2.1 features // enable/disable USB 2.1 features
usb21_enabled = dev_info->usb21_enabled; usb21_enabled = dev_info->usb21_enabled;
usb21_landing = dev_info->usb21_landing; usb21_landing = dev_info->usb21_landing;
@ -78,7 +83,8 @@ void usb_init(const usb_dev_info_t *dev_info) {
// Device descriptor // Device descriptor
usb_dev_desc.bLength = sizeof(usb_device_descriptor_t); usb_dev_desc.bLength = sizeof(usb_device_descriptor_t);
usb_dev_desc.bDescriptorType = USB_DESC_TYPE_DEVICE; 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.bcdUSB =
(sectrue == usb21_enabled) ? 0x0210 : 0x0200; // USB 2.1 or USB 2.0
usb_dev_desc.bDeviceClass = dev_info->device_class; usb_dev_desc.bDeviceClass = dev_info->device_class;
usb_dev_desc.bDeviceSubClass = dev_info->device_subclass; usb_dev_desc.bDeviceSubClass = dev_info->device_subclass;
usb_dev_desc.bDeviceProtocol = dev_info->device_protocol; usb_dev_desc.bDeviceProtocol = dev_info->device_protocol;
@ -86,9 +92,11 @@ void usb_init(const usb_dev_info_t *dev_info) {
usb_dev_desc.idVendor = dev_info->vendor_id; usb_dev_desc.idVendor = dev_info->vendor_id;
usb_dev_desc.idProduct = dev_info->product_id; usb_dev_desc.idProduct = dev_info->product_id;
usb_dev_desc.bcdDevice = dev_info->release_num; usb_dev_desc.bcdDevice = dev_info->release_num;
usb_dev_desc.iManufacturer = USBD_IDX_MFC_STR; // Index of manufacturer string 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.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.iSerialNumber =
USBD_IDX_SERIAL_STR; // Index of serial number string
usb_dev_desc.bNumConfigurations = 1; usb_dev_desc.bNumConfigurations = 1;
// String table // String table
@ -105,18 +113,31 @@ void usb_init(const usb_dev_info_t *dev_info) {
// Configuration descriptor // Configuration descriptor
usb_config_desc->bLength = sizeof(usb_config_descriptor_t); usb_config_desc->bLength = sizeof(usb_config_descriptor_t);
usb_config_desc->bDescriptorType = USB_DESC_TYPE_CONFIGURATION; 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->wTotalLength =
usb_config_desc->bNumInterfaces = 0; // will be updated later via usb_desc_add_iface() 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->bConfigurationValue = 0x01;
usb_config_desc->iConfiguration = 0; usb_config_desc->iConfiguration = 0;
usb_config_desc->bmAttributes = 0x80; // 0x80 = bus powered; 0xC0 = self powered usb_config_desc->bmAttributes =
0x80; // 0x80 = bus powered; 0xC0 = self powered
usb_config_desc->bMaxPower = 0x32; // Maximum Power Consumption in 2mA units usb_config_desc->bMaxPower = 0x32; // Maximum Power Consumption in 2mA units
// Pointer to interface descriptor data // Pointer to interface descriptor data
usb_next_iface_desc = (usb_interface_descriptor_t *)(usb_config_buf + usb_config_desc->wTotalLength); 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 *
ensure(sectrue * (USBD_OK == USBD_RegisterClass(&usb_dev_handle, (USBD_ClassTypeDef*)&usb_class)), NULL); (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) { void usb_deinit(void) {
@ -126,13 +147,9 @@ void usb_deinit(void) {
} }
} }
void usb_start(void) { void usb_start(void) { USBD_Start(&usb_dev_handle); }
USBD_Start(&usb_dev_handle);
}
void usb_stop(void) { void usb_stop(void) { USBD_Stop(&usb_dev_handle); }
USBD_Stop(&usb_dev_handle);
}
/* /*
* Utility functions for USB interfaces * Utility functions for USB interfaces
@ -157,7 +174,9 @@ static void *usb_desc_alloc_iface(size_t desc_len) {
static void usb_desc_add_iface(size_t desc_len) { static void usb_desc_add_iface(size_t desc_len) {
usb_config_desc->bNumInterfaces++; usb_config_desc->bNumInterfaces++;
usb_config_desc->wTotalLength += desc_len; usb_config_desc->wTotalLength += desc_len;
usb_next_iface_desc = (usb_interface_descriptor_t *)(usb_config_buf + usb_config_desc->wTotalLength); 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) { static uint8_t usb_ep_set_nak(USBD_HandleTypeDef *dev, uint8_t ep_num) {
@ -186,12 +205,14 @@ static uint8_t usb_ep_clear_nak(USBD_HandleTypeDef *dev, uint8_t ep_num) {
* USB configuration (device & string descriptors) * USB configuration (device & string descriptors)
*/ */
static uint8_t *usb_get_dev_descriptor(USBD_SpeedTypeDef speed, uint16_t *length) { static uint8_t *usb_get_dev_descriptor(USBD_SpeedTypeDef speed,
uint16_t *length) {
*length = sizeof(usb_dev_desc); *length = sizeof(usb_dev_desc);
return (uint8_t *)(&usb_dev_desc); return (uint8_t *)(&usb_dev_desc);
} }
static uint8_t *usb_get_langid_str_descriptor(USBD_SpeedTypeDef speed, uint16_t *length) { static uint8_t *usb_get_langid_str_descriptor(USBD_SpeedTypeDef speed,
uint16_t *length) {
static const usb_langid_descriptor_t usb_langid_str_desc = { static const usb_langid_descriptor_t usb_langid_str_desc = {
.bLength = USB_LEN_LANGID_STR_DESC, .bLength = USB_LEN_LANGID_STR_DESC,
.bDescriptorType = USB_DESC_TYPE_STRING, .bDescriptorType = USB_DESC_TYPE_STRING,
@ -201,32 +222,38 @@ static uint8_t *usb_get_langid_str_descriptor(USBD_SpeedTypeDef speed, uint16_t
return UNCONST(&usb_langid_str_desc); return UNCONST(&usb_langid_str_desc);
} }
static uint8_t *usb_get_manufacturer_str_descriptor(USBD_SpeedTypeDef speed, uint16_t *length) { 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); USBD_GetString((uint8_t *)usb_str_table.manufacturer, usb_str_buf, length);
return usb_str_buf; return usb_str_buf;
} }
static uint8_t *usb_get_product_str_descriptor(USBD_SpeedTypeDef speed, uint16_t *length) { 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); USBD_GetString((uint8_t *)usb_str_table.product, usb_str_buf, length);
return usb_str_buf; return usb_str_buf;
} }
static uint8_t *usb_get_serial_str_descriptor(USBD_SpeedTypeDef speed, uint16_t *length) { 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); USBD_GetString((uint8_t *)usb_str_table.serial_number, usb_str_buf, length);
return usb_str_buf; return usb_str_buf;
} }
static uint8_t *usb_get_configuration_str_descriptor(USBD_SpeedTypeDef speed, uint16_t *length) { static uint8_t *usb_get_configuration_str_descriptor(USBD_SpeedTypeDef speed,
uint16_t *length) {
USBD_GetString((uint8_t *)"", usb_str_buf, length); USBD_GetString((uint8_t *)"", usb_str_buf, length);
return usb_str_buf; return usb_str_buf;
} }
static uint8_t *usb_get_interface_str_descriptor(USBD_SpeedTypeDef speed, uint16_t *length) { 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); USBD_GetString((uint8_t *)usb_str_table.interface, usb_str_buf, length);
return usb_str_buf; return usb_str_buf;
} }
static uint8_t *usb_get_bos_descriptor(USBD_SpeedTypeDef speed, uint16_t *length) { static uint8_t *usb_get_bos_descriptor(USBD_SpeedTypeDef speed,
uint16_t *length) {
if (sectrue == usb21_enabled) { if (sectrue == usb21_enabled) {
static uint8_t bos[] = { static uint8_t bos[] = {
// usb_bos_descriptor { // usb_bos_descriptor {
@ -240,7 +267,8 @@ static uint8_t *usb_get_bos_descriptor(USBD_SpeedTypeDef speed, uint16_t *length
USB_DESC_TYPE_DEVICE_CAPABILITY, // uint8_t bDescriptorType USB_DESC_TYPE_DEVICE_CAPABILITY, // uint8_t bDescriptorType
USB_DEVICE_CAPABILITY_PLATFORM, // uint8_t bDevCapabilityType USB_DEVICE_CAPABILITY_PLATFORM, // uint8_t bDevCapabilityType
0x00, // uint8_t bReserved 0x00, // uint8_t bReserved
0x38, 0xb6, 0x08, 0x34, 0xa9, 0x09, 0xa0, 0x47, 0x8b, 0xfd, 0xa0, 0x76, 0x88, 0x15, 0xb6, 0x65, // uint128_t platformCompatibilityUUID 0x38, 0xb6, 0x08, 0x34, 0xa9, 0x09, 0xa0, 0x47, 0x8b, 0xfd, 0xa0, 0x76,
0x88, 0x15, 0xb6, 0x65, // uint128_t platformCompatibilityUUID
0x00, 0x01, // uint16_t bcdVersion 0x00, 0x01, // uint16_t bcdVersion
USB_WEBUSB_VENDOR_CODE, // uint8_t bVendorCode USB_WEBUSB_VENDOR_CODE, // uint8_t bVendorCode
USB_WEBUSB_LANDING_PAGE, // uint8_t iLandingPage USB_WEBUSB_LANDING_PAGE, // uint8_t iLandingPage
@ -313,7 +341,8 @@ static uint8_t usb_class_deinit(USBD_HandleTypeDef *dev, uint8_t cfg_idx) {
#define USB_WEBUSB_URL_SCHEME_HTTP 0 #define USB_WEBUSB_URL_SCHEME_HTTP 0
#define USB_WEBUSB_URL_SCHEME_HTTPS 1 #define USB_WEBUSB_URL_SCHEME_HTTPS 1
static uint8_t usb_class_setup(USBD_HandleTypeDef *dev, USBD_SetupReqTypedef *req) { static uint8_t usb_class_setup(USBD_HandleTypeDef *dev,
USBD_SetupReqTypedef *req) {
delay_random(); delay_random();
if (((req->bmRequest & USB_REQ_TYPE_MASK) != USB_REQ_TYPE_CLASS) && 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_STANDARD) &&
@ -324,23 +353,39 @@ static uint8_t usb_class_setup(USBD_HandleTypeDef *dev, USBD_SetupReqTypedef *re
if ((req->bmRequest & USB_REQ_TYPE_MASK) == USB_REQ_TYPE_VENDOR) { if ((req->bmRequest & USB_REQ_TYPE_MASK) == USB_REQ_TYPE_VENDOR) {
if ((req->bmRequest & USB_REQ_RECIPIENT_MASK) == USB_REQ_RECIPIENT_DEVICE) { if ((req->bmRequest & USB_REQ_RECIPIENT_MASK) == USB_REQ_RECIPIENT_DEVICE) {
if (sectrue == usb21_enabled && req->bRequest == USB_WEBUSB_VENDOR_CODE) { if (sectrue == usb21_enabled && req->bRequest == USB_WEBUSB_VENDOR_CODE) {
if (req->wIndex == USB_WEBUSB_REQ_GET_URL && req->wValue == USB_WEBUSB_LANDING_PAGE) { if (req->wIndex == USB_WEBUSB_REQ_GET_URL &&
req->wValue == USB_WEBUSB_LANDING_PAGE) {
static const char webusb_url[] = { static const char webusb_url[] = {
3 + 15, // uint8_t bLength 3 + 15, // uint8_t bLength
USB_WEBUSB_DESCRIPTOR_TYPE_URL, // uint8_t bDescriptorType USB_WEBUSB_DESCRIPTOR_TYPE_URL, // uint8_t bDescriptorType
USB_WEBUSB_URL_SCHEME_HTTPS, // uint8_t bScheme USB_WEBUSB_URL_SCHEME_HTTPS, // uint8_t bScheme
't', 'r', 'e', 'z', 'o', 'r', '.', 'i', 'o', '/', 's', 't', 'a', 'r', 't', // char URL[] '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))); USBD_CtlSendData(dev, UNCONST(webusb_url),
MIN_8bits(req->wLength, sizeof(webusb_url)));
return USBD_OK; return USBD_OK;
} else { } else {
USBD_CtlError(dev, req); USBD_CtlError(dev, req);
return USBD_FAIL; return USBD_FAIL;
} }
} } else if (sectrue == usb21_enabled &&
else req->bRequest == USB_WINUSB_VENDOR_CODE) {
if (sectrue == usb21_enabled && req->bRequest == USB_WINUSB_VENDOR_CODE) { if (req->wIndex ==
if (req->wIndex == USB_WINUSB_REQ_GET_COMPATIBLE_ID_FEATURE_DESCRIPTOR) { USB_WINUSB_REQ_GET_COMPATIBLE_ID_FEATURE_DESCRIPTOR) {
static const uint8_t winusb_wcid[] = { static const uint8_t winusb_wcid[] = {
// header // header
0x28, 0x00, 0x00, 0x00, // dwLength 0x28, 0x00, 0x00, 0x00, // dwLength
@ -349,13 +394,16 @@ static uint8_t usb_class_setup(USBD_HandleTypeDef *dev, USBD_SetupReqTypedef *re
0x01, // bNumSections 0x01, // bNumSections
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // reserved 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // reserved
// functions // functions
0x00, // bInterfaceNumber - HACK: we present only interface 0 as WinUSB 0x00, // bInterfaceNumber - HACK: we present only interface 0 as
// WinUSB
0x01, // reserved 0x01, // reserved
'W', 'I', 'N', 'U', 'S', 'B', 0x00, 0x00, // compatibleId 'W', 'I', 'N', 'U', 'S', 'B', 0x00, 0x00, // compatibleId
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // subCompatibleId 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, // subCompatibleId
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // reserved 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // reserved
}; };
USBD_CtlSendData(dev, UNCONST(winusb_wcid), MIN_8bits(req->wLength, sizeof(winusb_wcid))); USBD_CtlSendData(dev, UNCONST(winusb_wcid),
MIN_8bits(req->wLength, sizeof(winusb_wcid)));
return USBD_OK; return USBD_OK;
} else { } else {
USBD_CtlError(dev, req); USBD_CtlError(dev, req);
@ -363,9 +411,11 @@ static uint8_t usb_class_setup(USBD_HandleTypeDef *dev, USBD_SetupReqTypedef *re
} }
} }
} }
if ((req->bmRequest & USB_REQ_RECIPIENT_MASK) == USB_REQ_RECIPIENT_INTERFACE) { if ((req->bmRequest & USB_REQ_RECIPIENT_MASK) ==
USB_REQ_RECIPIENT_INTERFACE) {
if (sectrue == usb21_enabled && req->bRequest == USB_WINUSB_VENDOR_CODE) { if (sectrue == usb21_enabled && req->bRequest == USB_WINUSB_VENDOR_CODE) {
if (req->wIndex == USB_WINUSB_REQ_GET_EXTENDED_PROPERTIES_OS_FEATURE_DESCRIPTOR && if (req->wIndex ==
USB_WINUSB_REQ_GET_EXTENDED_PROPERTIES_OS_FEATURE_DESCRIPTOR &&
(req->wValue & 0xFF) == 0) { // reply only if interface is 0 (req->wValue & 0xFF) == 0) { // reply only if interface is 0
static const uint8_t winusb_guid[] = { static const uint8_t winusb_guid[] = {
// header // header
@ -377,11 +427,21 @@ static uint8_t usb_class_setup(USBD_HandleTypeDef *dev, USBD_SetupReqTypedef *re
0x88, 0x00, 0x00, 0x00, // dwLength 0x88, 0x00, 0x00, 0x00, // dwLength
0x07, 0x00, 0x00, 0x00, // dwPropertyDataType 0x07, 0x00, 0x00, 0x00, // dwPropertyDataType
0x2A, 0x00, // wNameLength 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 '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 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 '{', 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))); USBD_CtlSendData(dev, UNCONST(winusb_guid),
MIN_8bits(req->wLength, sizeof(winusb_guid)));
return USBD_OK; return USBD_OK;
} else { } else {
USBD_CtlError(dev, req); USBD_CtlError(dev, req);
@ -389,8 +449,8 @@ static uint8_t usb_class_setup(USBD_HandleTypeDef *dev, USBD_SetupReqTypedef *re
} }
} }
} }
} else } else if ((req->bmRequest & USB_REQ_RECIPIENT_MASK) ==
if ((req->bmRequest & USB_REQ_RECIPIENT_MASK) == USB_REQ_RECIPIENT_INTERFACE) { USB_REQ_RECIPIENT_INTERFACE) {
if (req->wIndex >= USBD_MAX_NUM_INTERFACES) { if (req->wIndex >= USBD_MAX_NUM_INTERFACES) {
USBD_CtlError(dev, req); USBD_CtlError(dev, req);
return USBD_FAIL; return USBD_FAIL;
@ -401,7 +461,8 @@ static uint8_t usb_class_setup(USBD_HandleTypeDef *dev, USBD_SetupReqTypedef *re
case USB_IFACE_TYPE_VCP: case USB_IFACE_TYPE_VCP:
return usb_vcp_class_setup(dev, &usb_ifaces[req->wIndex].vcp, req); return usb_vcp_class_setup(dev, &usb_ifaces[req->wIndex].vcp, req);
case USB_IFACE_TYPE_WEBUSB: case USB_IFACE_TYPE_WEBUSB:
return usb_webusb_class_setup(dev, &usb_ifaces[req->wIndex].webusb, req); return usb_webusb_class_setup(dev, &usb_ifaces[req->wIndex].webusb,
req);
default: default:
USBD_CtlError(dev, req); USBD_CtlError(dev, req);
return USBD_FAIL; return USBD_FAIL;
@ -469,7 +530,8 @@ static uint8_t *usb_class_get_cfg_desc(uint16_t *length) {
return usb_config_buf; return usb_config_buf;
} }
static uint8_t *usb_class_get_usrstr_desc(USBD_HandleTypeDef *dev, uint8_t index, uint16_t *length) { 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) { if (sectrue == usb21_enabled && index == USB_WINUSB_EXTRA_STRING_INDEX) {
static const uint8_t winusb_string_descriptor[] = { static const uint8_t winusb_string_descriptor[] = {
0x12, // bLength 0x12, // bLength

View File

@ -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_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_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_read_blocking(uint8_t iface_num, uint8_t *buf, uint32_t len,
int __wur usb_hid_write_blocking(uint8_t iface_num, const uint8_t *buf, uint32_t len, int timeout); int timeout);
int __wur usb_hid_write_blocking(uint8_t iface_num, const uint8_t *buf,
uint32_t len, int timeout);

View File

@ -30,7 +30,6 @@
/* usb_hid_add adds and configures new USB HID interface according to /* usb_hid_add adds and configures new USB HID interface according to
* configuration options passed in `info`. */ * configuration options passed in `info`. */
secbool usb_hid_add(const usb_hid_info_t *info) { secbool usb_hid_add(const usb_hid_info_t *info) {
usb_iface_t *iface = usb_get_iface(info->iface_num); usb_iface_t *iface = usb_get_iface(info->iface_num);
if (iface == NULL) { if (iface == NULL) {
@ -40,7 +39,8 @@ secbool usb_hid_add(const usb_hid_info_t *info) {
return secfalse; // Interface is already enabled return secfalse; // Interface is already enabled
} }
usb_hid_descriptor_block_t *d = usb_desc_alloc_iface(sizeof(usb_hid_descriptor_block_t)); usb_hid_descriptor_block_t *d =
usb_desc_alloc_iface(sizeof(usb_hid_descriptor_block_t));
if (d == NULL) { if (d == NULL) {
return secfalse; // Not enough space in the configuration descriptor return secfalse; // Not enough space in the configuration descriptor
@ -206,7 +206,8 @@ int usb_hid_read_select(uint32_t timeout) {
return -1; // Timeout return -1; // Timeout
} }
int usb_hid_read_blocking(uint8_t iface_num, uint8_t *buf, uint32_t len, int timeout) { int usb_hid_read_blocking(uint8_t iface_num, uint8_t *buf, uint32_t len,
int timeout) {
const uint32_t start = HAL_GetTick(); const uint32_t start = HAL_GetTick();
while (sectrue != usb_hid_can_read(iface_num)) { while (sectrue != usb_hid_can_read(iface_num)) {
if (timeout >= 0 && HAL_GetTick() - start >= timeout) { if (timeout >= 0 && HAL_GetTick() - start >= timeout) {
@ -217,7 +218,8 @@ int usb_hid_read_blocking(uint8_t iface_num, uint8_t *buf, uint32_t len, int tim
return usb_hid_read(iface_num, buf, len); 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) { int usb_hid_write_blocking(uint8_t iface_num, const uint8_t *buf, uint32_t len,
int timeout) {
const uint32_t start = HAL_GetTick(); const uint32_t start = HAL_GetTick();
while (sectrue != usb_hid_can_write(iface_num)) { while (sectrue != usb_hid_can_write(iface_num)) {
if (timeout >= 0 && HAL_GetTick() - start >= timeout) { if (timeout >= 0 && HAL_GetTick() - start >= timeout) {
@ -228,7 +230,8 @@ int usb_hid_write_blocking(uint8_t iface_num, const uint8_t *buf, uint32_t len,
return usb_hid_write(iface_num, buf, len); 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) { static void usb_hid_class_init(USBD_HandleTypeDef *dev, usb_hid_state_t *state,
uint8_t cfg_idx) {
// Open endpoints // Open endpoints
USBD_LL_OpenEP(dev, state->ep_in, USBD_EP_TYPE_INTR, state->max_packet_len); 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); USBD_LL_OpenEP(dev, state->ep_out, USBD_EP_TYPE_INTR, state->max_packet_len);
@ -241,10 +244,12 @@ static void usb_hid_class_init(USBD_HandleTypeDef *dev, usb_hid_state_t *state,
state->ep_in_is_idle = 1; state->ep_in_is_idle = 1;
// Prepare the OUT EP to receive next packet // Prepare the OUT EP to receive next packet
USBD_LL_PrepareReceive(dev, state->ep_out, state->rx_buffer, state->max_packet_len); 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) { static void usb_hid_class_deinit(USBD_HandleTypeDef *dev,
usb_hid_state_t *state, uint8_t cfg_idx) {
// Flush endpoints // Flush endpoints
USBD_LL_FlushEP(dev, state->ep_in); USBD_LL_FlushEP(dev, state->ep_in);
USBD_LL_FlushEP(dev, state->ep_out); USBD_LL_FlushEP(dev, state->ep_out);
@ -253,13 +258,12 @@ static void usb_hid_class_deinit(USBD_HandleTypeDef *dev, usb_hid_state_t *state
USBD_LL_CloseEP(dev, state->ep_out); USBD_LL_CloseEP(dev, state->ep_out);
} }
static int usb_hid_class_setup(USBD_HandleTypeDef *dev, usb_hid_state_t *state, USBD_SetupReqTypedef *req) { static int usb_hid_class_setup(USBD_HandleTypeDef *dev, usb_hid_state_t *state,
USBD_SetupReqTypedef *req) {
switch (req->bmRequest & USB_REQ_TYPE_MASK) { switch (req->bmRequest & USB_REQ_TYPE_MASK) {
// Class request // Class request
case USB_REQ_TYPE_CLASS: case USB_REQ_TYPE_CLASS:
switch (req->bRequest) { switch (req->bRequest) {
case USB_HID_REQ_SET_PROTOCOL: case USB_HID_REQ_SET_PROTOCOL:
state->protocol = req->wValue; state->protocol = req->wValue;
USBD_CtlSendStatus(dev); USBD_CtlSendStatus(dev);
@ -287,25 +291,27 @@ static int usb_hid_class_setup(USBD_HandleTypeDef *dev, usb_hid_state_t *state,
// Interface & Endpoint request // Interface & Endpoint request
case USB_REQ_TYPE_STANDARD: case USB_REQ_TYPE_STANDARD:
switch (req->bRequest) { switch (req->bRequest) {
case USB_REQ_SET_INTERFACE: case USB_REQ_SET_INTERFACE:
state->alt_setting = req->wValue; state->alt_setting = req->wValue;
USBD_CtlSendStatus(dev); USBD_CtlSendStatus(dev);
return USBD_OK; return USBD_OK;
case USB_REQ_GET_INTERFACE: case USB_REQ_GET_INTERFACE:
USBD_CtlSendData(dev, &state->alt_setting, sizeof(state->alt_setting)); USBD_CtlSendData(dev, &state->alt_setting,
sizeof(state->alt_setting));
return USBD_OK; return USBD_OK;
case USB_REQ_GET_DESCRIPTOR: case USB_REQ_GET_DESCRIPTOR:
switch (req->wValue >> 8) { switch (req->wValue >> 8) {
case USB_DESC_TYPE_HID: case USB_DESC_TYPE_HID:
USBD_CtlSendData(dev, UNCONST(&state->desc_block->hid), MIN_8bits(req->wLength, sizeof(state->desc_block->hid))); USBD_CtlSendData(
dev, UNCONST(&state->desc_block->hid),
MIN_8bits(req->wLength, sizeof(state->desc_block->hid)));
return USBD_OK; return USBD_OK;
case USB_DESC_TYPE_REPORT: case USB_DESC_TYPE_REPORT:
USBD_CtlSendData(dev, UNCONST(state->report_desc), MIN_8bits(req->wLength, state->report_desc_len)); USBD_CtlSendData(dev, UNCONST(state->report_desc),
MIN_8bits(req->wLength, state->report_desc_len));
return USBD_OK; return USBD_OK;
default: default:
@ -324,19 +330,23 @@ static int usb_hid_class_setup(USBD_HandleTypeDef *dev, usb_hid_state_t *state,
return USBD_OK; return USBD_OK;
} }
static void usb_hid_class_data_in(USBD_HandleTypeDef *dev, usb_hid_state_t *state, uint8_t ep_num) { 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) { if ((ep_num | USB_EP_DIR_IN) == state->ep_in) {
state->ep_in_is_idle = 1; 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) { 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) { if (ep_num == state->ep_out) {
state->last_read_len = USBD_LL_GetRxDataSize(dev, ep_num); state->last_read_len = USBD_LL_GetRxDataSize(dev, ep_num);
// Prepare the OUT EP to receive next packet // Prepare the OUT EP to receive next packet
// User should provide state->rx_buffer that is big enough for state->max_packet_len bytes // User should provide state->rx_buffer that is big enough for
USBD_LL_PrepareReceive(dev, ep_num, state->rx_buffer, state->max_packet_len); // state->max_packet_len bytes
USBD_LL_PrepareReceive(dev, ep_num, state->rx_buffer,
state->max_packet_len);
if (state->last_read_len > 0) { if (state->last_read_len > 0) {
// Block the OUT EP until we process received data // Block the OUT EP until we process received data

View File

@ -52,9 +52,11 @@ typedef struct __attribute__((packed)) {
typedef struct __attribute__((packed)) { typedef struct __attribute__((packed)) {
usb_interface_assoc_descriptor_t assoc; usb_interface_assoc_descriptor_t assoc;
usb_interface_descriptor_t iface_cdc; usb_interface_descriptor_t iface_cdc;
usb_vcp_header_descriptor_t fheader; // Class-Specific Descriptor Header Format usb_vcp_header_descriptor_t
fheader; // Class-Specific Descriptor Header Format
usb_vcp_cm_descriptor_t fcm; // Call Management Functional Descriptor usb_vcp_cm_descriptor_t fcm; // Call Management Functional Descriptor
usb_vcp_acm_descriptor_t facm; // Abstract Control 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_vcp_union_descriptor_t funion; // Union Interface Functional Descriptor
usb_endpoint_descriptor_t ep_cmd; usb_endpoint_descriptor_t ep_cmd;
usb_interface_descriptor_t iface_data; usb_interface_descriptor_t iface_data;
@ -87,21 +89,28 @@ typedef enum {
* passed pointers need to live at least until the interface is disabled * passed pointers need to live at least until the interface is disabled
* (usb_stop is called). */ * (usb_stop is called). */
typedef struct { typedef struct {
uint8_t *tx_packet; // Buffer for one packet, with length of at least max_packet_len bytes uint8_t *tx_packet; // Buffer for one packet, with length of at least
uint8_t *tx_buffer; // Buffer for IN EP ring buffer, with length of at least tx_buffer_len bytes // max_packet_len bytes
uint8_t *rx_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
uint8_t *rx_buffer; // Buffer for OUT EP ring buffer, with length of at least rx_buffer_len bytes // 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 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 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 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 rx_intr_byte; // Value matched against every received byte
uint8_t iface_num; // Address of this VCP interface 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 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_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_in; // Address of IN endpoint (with the highest bit set)
uint8_t ep_out; // Address of OUT endpoint uint8_t ep_out; // Address of OUT endpoint
uint8_t polling_interval; // In units of 1ms 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 max_packet_len; // Length of the biggest packet, and of tx_packet and
// rx_packet
} usb_vcp_info_t; } usb_vcp_info_t;
/* usb_rbuf_t is used internally for the RX/TX buffering. */ /* usb_rbuf_t is used internally for the RX/TX buffering. */
@ -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_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_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_read_blocking(uint8_t iface_num, uint8_t *buf, uint32_t len,
int __wur usb_vcp_write_blocking(uint8_t iface_num, const uint8_t *buf, uint32_t len, int timeout); int timeout);
int __wur usb_vcp_write_blocking(uint8_t iface_num, const uint8_t *buf,
uint32_t len, int timeout);

View File

@ -26,7 +26,8 @@
// Class Subclass Code (bFunctionSubClass, bInterfaceSubClass) // 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) // Communications Interface Class Control Protocol Codes (bFunctionProtocol,
// bInterfaceProtocol)
#define USB_CDC_PROTOCOL_AT 0x01 #define USB_CDC_PROTOCOL_AT 0x01
// Descriptor Types (bDescriptorType) // Descriptor Types (bDescriptorType)
@ -52,7 +53,6 @@
/* usb_vcp_add adds and configures new USB VCP interface according to /* usb_vcp_add adds and configures new USB VCP interface according to
* configuration options passed in `info`. */ * configuration options passed in `info`. */
secbool usb_vcp_add(const usb_vcp_info_t *info) { secbool usb_vcp_add(const usb_vcp_info_t *info) {
usb_iface_t *iface = usb_get_iface(info->iface_num); usb_iface_t *iface = usb_get_iface(info->iface_num);
if (iface == NULL) { if (iface == NULL) {
@ -62,7 +62,8 @@ secbool usb_vcp_add(const usb_vcp_info_t *info) {
return secfalse; // Interface is already enabled return secfalse; // Interface is already enabled
} }
usb_vcp_descriptor_block_t *d = usb_desc_alloc_iface(sizeof(usb_vcp_descriptor_block_t)); usb_vcp_descriptor_block_t *d =
usb_desc_alloc_iface(sizeof(usb_vcp_descriptor_block_t));
if (d == NULL) { if (d == NULL) {
return secfalse; // Not enough space in the configuration descriptor return secfalse; // Not enough space in the configuration descriptor
@ -77,10 +78,12 @@ secbool usb_vcp_add(const usb_vcp_info_t *info) {
if ((info->ep_out & USB_EP_DIR_MASK) != USB_EP_DIR_OUT) { if ((info->ep_out & USB_EP_DIR_MASK) != USB_EP_DIR_OUT) {
return secfalse; // OUT EP is invalid return secfalse; // OUT EP is invalid
} }
if ((info->rx_buffer_len == 0) || (info->rx_buffer_len & (info->rx_buffer_len - 1)) != 0) { 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 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) { 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 return secfalse; // Capacity needs to be a power of 2
} }
if (info->rx_buffer == NULL) { if (info->rx_buffer == NULL) {
@ -121,14 +124,16 @@ secbool usb_vcp_add(const usb_vcp_info_t *info) {
d->fheader.bFunctionLength = sizeof(usb_vcp_header_descriptor_t); d->fheader.bFunctionLength = sizeof(usb_vcp_header_descriptor_t);
d->fheader.bDescriptorType = USB_DESC_TYPE_CS_INTERACE; d->fheader.bDescriptorType = USB_DESC_TYPE_CS_INTERACE;
d->fheader.bDescriptorSubtype = USB_DESC_TYPE_HEADER; d->fheader.bDescriptorSubtype = USB_DESC_TYPE_HEADER;
d->fheader.bcdCDC = 0x1001; // USB Class Definitions for Communication Devices Specification release number. d->fheader.bcdCDC = 0x1001; // USB Class Definitions for Communication
// Devices Specification release number.
// Call Management Functional Descriptor // Call Management Functional Descriptor
d->fcm.bFunctionLength = sizeof(usb_vcp_cm_descriptor_t); d->fcm.bFunctionLength = sizeof(usb_vcp_cm_descriptor_t);
d->fcm.bDescriptorType = USB_DESC_TYPE_CS_INTERACE; d->fcm.bDescriptorType = USB_DESC_TYPE_CS_INTERACE;
d->fcm.bDescriptorSubtype = USB_DESC_TYPE_CM; d->fcm.bDescriptorSubtype = USB_DESC_TYPE_CM;
// Device sends/receives call management information only over the Communication Class interface. // Device sends/receives call management information only over the
// Device does not handle call management itself. // Communication Class interface. Device does not handle call management
// itself.
d->fcm.bmCapabilities = 0x00; d->fcm.bmCapabilities = 0x00;
d->fcm.bDataInterface = info->data_iface_num; d->fcm.bDataInterface = info->data_iface_num;
@ -136,8 +141,8 @@ secbool usb_vcp_add(const usb_vcp_info_t *info) {
d->facm.bFunctionLength = sizeof(usb_vcp_acm_descriptor_t); d->facm.bFunctionLength = sizeof(usb_vcp_acm_descriptor_t);
d->facm.bDescriptorType = USB_DESC_TYPE_CS_INTERACE; d->facm.bDescriptorType = USB_DESC_TYPE_CS_INTERACE;
d->facm.bDescriptorSubtype = USB_DESC_TYPE_ACM; d->facm.bDescriptorSubtype = USB_DESC_TYPE_ACM;
// Device supports the request combination of Set_Line_Coding, Set_Control_Line_State, // Device supports the request combination of Set_Line_Coding,
// Get_Line_Coding, and the notification Serial_State. // Set_Control_Line_State, Get_Line_Coding, and the notification Serial_State.
d->facm.bmCapabilities = 0x02; d->facm.bmCapabilities = 0x02;
// Union Functional Descriptor // Union Functional Descriptor
@ -184,7 +189,8 @@ secbool usb_vcp_add(const usb_vcp_info_t *info) {
// Config descriptor // Config descriptor
usb_desc_add_iface(sizeof(usb_vcp_descriptor_block_t)); usb_desc_add_iface(sizeof(usb_vcp_descriptor_block_t));
usb_config_desc->bNumInterfaces++; // usb_vcp_descriptor_block_t contains 2 interfaces usb_config_desc
->bNumInterfaces++; // usb_vcp_descriptor_block_t contains 2 interfaces
// Interface state // Interface state
@ -217,17 +223,11 @@ secbool usb_vcp_add(const usb_vcp_info_t *info) {
return sectrue; return sectrue;
} }
static inline size_t ring_length(usb_rbuf_t *b) { static inline size_t ring_length(usb_rbuf_t *b) { return (b->write - b->read); }
return (b->write - b->read);
}
static inline int ring_empty(usb_rbuf_t *b) { static inline int ring_empty(usb_rbuf_t *b) { return ring_length(b) == 0; }
return ring_length(b) == 0;
}
static inline int ring_full(usb_rbuf_t *b) { static inline int ring_full(usb_rbuf_t *b) { return ring_length(b) == b->cap; }
return ring_length(b) == b->cap;
}
secbool usb_vcp_can_read(uint8_t iface_num) { secbool usb_vcp_can_read(uint8_t iface_num) {
usb_iface_t *iface = usb_get_iface(iface_num); usb_iface_t *iface = usb_get_iface(iface_num);
@ -300,7 +300,8 @@ int usb_vcp_write(uint8_t iface_num, const uint8_t *buf, uint32_t len) {
return len; return len;
} }
int usb_vcp_read_blocking(uint8_t iface_num, uint8_t *buf, uint32_t len, int timeout) { int usb_vcp_read_blocking(uint8_t iface_num, uint8_t *buf, uint32_t len,
int timeout) {
uint32_t start = HAL_GetTick(); uint32_t start = HAL_GetTick();
while (sectrue != usb_vcp_can_read(iface_num)) { while (sectrue != usb_vcp_can_read(iface_num)) {
if (timeout >= 0 && HAL_GetTick() - start >= timeout) { if (timeout >= 0 && HAL_GetTick() - start >= timeout) {
@ -311,7 +312,8 @@ int usb_vcp_read_blocking(uint8_t iface_num, uint8_t *buf, uint32_t len, int tim
return usb_vcp_read(iface_num, buf, len); 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) { int usb_vcp_write_blocking(uint8_t iface_num, const uint8_t *buf, uint32_t len,
int timeout) {
uint32_t start = HAL_GetTick(); uint32_t start = HAL_GetTick();
while (sectrue != usb_vcp_can_write(iface_num)) { while (sectrue != usb_vcp_can_write(iface_num)) {
if (timeout >= 0 && HAL_GetTick() - start >= timeout) { if (timeout >= 0 && HAL_GetTick() - start >= timeout) {
@ -322,11 +324,13 @@ int usb_vcp_write_blocking(uint8_t iface_num, const uint8_t *buf, uint32_t len,
return usb_vcp_write(iface_num, buf, len); 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) { static void usb_vcp_class_init(USBD_HandleTypeDef *dev, usb_vcp_state_t *state,
uint8_t cfg_idx) {
// Open endpoints // Open endpoints
USBD_LL_OpenEP(dev, state->ep_in, USBD_EP_TYPE_BULK, state->max_packet_len); 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_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); USBD_LL_OpenEP(dev, state->ep_cmd, USBD_EP_TYPE_INTR,
USB_CDC_MAX_CMD_PACKET_LEN);
// Reset the state // Reset the state
state->rx_ring.read = 0; state->rx_ring.read = 0;
@ -336,10 +340,12 @@ static void usb_vcp_class_init(USBD_HandleTypeDef *dev, usb_vcp_state_t *state,
state->ep_in_is_idle = 1; state->ep_in_is_idle = 1;
// Prepare the OUT EP to receive next packet // Prepare the OUT EP to receive next packet
USBD_LL_PrepareReceive(dev, state->ep_out, state->rx_packet, state->max_packet_len); 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) { static void usb_vcp_class_deinit(USBD_HandleTypeDef *dev,
usb_vcp_state_t *state, uint8_t cfg_idx) {
// Flush endpoints // Flush endpoints
USBD_LL_FlushEP(dev, state->ep_in); USBD_LL_FlushEP(dev, state->ep_in);
USBD_LL_FlushEP(dev, state->ep_out); USBD_LL_FlushEP(dev, state->ep_out);
@ -350,7 +356,8 @@ static void usb_vcp_class_deinit(USBD_HandleTypeDef *dev, usb_vcp_state_t *state
USBD_LL_CloseEP(dev, state->ep_cmd); 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 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 = { static const usb_cdc_line_coding_t line_coding = {
.dwDTERate = 115200, .dwDTERate = 115200,
.bCharFormat = USB_CDC_1_STOP_BITS, .bCharFormat = USB_CDC_1_STOP_BITS,
@ -364,26 +371,31 @@ static int usb_vcp_class_setup(USBD_HandleTypeDef *dev, usb_vcp_state_t *state,
if ((req->bmRequest & USB_REQ_DIR_MASK) == USB_REQ_DIR_D2H) { if ((req->bmRequest & USB_REQ_DIR_MASK) == USB_REQ_DIR_D2H) {
if (req->bRequest == USB_CDC_GET_LINE_CODING) { if (req->bRequest == USB_CDC_GET_LINE_CODING) {
USBD_CtlSendData(dev, UNCONST(&line_coding), MIN_8bits(req->wLength, sizeof(line_coding))); USBD_CtlSendData(dev, UNCONST(&line_coding),
MIN_8bits(req->wLength, sizeof(line_coding)));
} else { } else {
USBD_CtlSendData(dev, state->cmd_buffer, MIN_8bits(req->wLength, USB_CDC_MAX_CMD_PACKET_LEN)); USBD_CtlSendData(dev, state->cmd_buffer,
MIN_8bits(req->wLength, USB_CDC_MAX_CMD_PACKET_LEN));
} }
} else { // USB_REQ_DIR_H2D } else { // USB_REQ_DIR_H2D
if (req->wLength > 0) { if (req->wLength > 0) {
USBD_CtlPrepareRx(dev, state->cmd_buffer, MIN_8bits(req->wLength, USB_CDC_MAX_CMD_PACKET_LEN)); USBD_CtlPrepareRx(dev, state->cmd_buffer,
MIN_8bits(req->wLength, USB_CDC_MAX_CMD_PACKET_LEN));
} }
} }
return USBD_OK; return USBD_OK;
} }
static void usb_vcp_class_data_in(USBD_HandleTypeDef *dev, usb_vcp_state_t *state, uint8_t ep_num) { 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) { if ((ep_num | USB_EP_DIR_IN) == state->ep_in) {
state->ep_in_is_idle = 1; state->ep_in_is_idle = 1;
} }
} }
static void usb_vcp_class_data_out(USBD_HandleTypeDef *dev, usb_vcp_state_t *state, uint8_t ep_num) { 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) { if (ep_num == state->ep_out) {
uint32_t len = USBD_LL_GetRxDataSize(dev, ep_num); uint32_t len = USBD_LL_GetRxDataSize(dev, ep_num);
@ -404,7 +416,8 @@ static void usb_vcp_class_data_out(USBD_HandleTypeDef *dev, usb_vcp_state_t *sta
} }
// Prepare the OUT EP to receive next packet // Prepare the OUT EP to receive next packet
USBD_LL_PrepareReceive(dev, state->ep_out, state->rx_packet, state->max_packet_len); USBD_LL_PrepareReceive(dev, state->ep_out, state->rx_packet,
state->max_packet_len);
} }
} }

View File

@ -26,8 +26,8 @@ typedef struct __attribute__((packed)) {
usb_endpoint_descriptor_t ep_out; usb_endpoint_descriptor_t ep_out;
} usb_webusb_descriptor_block_t; } usb_webusb_descriptor_block_t;
/* usb_webusb_info_t contains all information for setting up a WebUSB interface. All /* usb_webusb_info_t contains all information for setting up a WebUSB interface.
* passed pointers need to live at least until the interface is disabled * All passed pointers need to live at least until the interface is disabled
* (usb_stop is called). */ * (usb_stop is called). */
typedef struct { typedef struct {
uint8_t *rx_buffer; // With length of max_packet_len bytes uint8_t *rx_buffer; // With length of max_packet_len bytes
@ -40,10 +40,10 @@ typedef struct {
uint8_t max_packet_len; // Length of the biggest report and of rx_buffer uint8_t max_packet_len; // Length of the biggest report and of rx_buffer
} usb_webusb_info_t; } usb_webusb_info_t;
/* usb_webusb_state_t encapsulates all state used by enabled WebUSB interface. It /* usb_webusb_state_t encapsulates all state used by enabled WebUSB interface.
* needs to be completely initialized in usb_webusb_add and reset in * 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 * usb_webusb_class_init. See usb_webusb_info_t for details of the
* fields. */ * configuration fields. */
typedef struct { typedef struct {
const usb_webusb_descriptor_block_t *desc_block; const usb_webusb_descriptor_block_t *desc_block;
uint8_t *rx_buffer; uint8_t *rx_buffer;
@ -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_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_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_read_blocking(uint8_t iface_num, uint8_t *buf,
int __wur usb_webusb_write_blocking(uint8_t iface_num, const uint8_t *buf, uint32_t len, int timeout); uint32_t len, int timeout);
int __wur usb_webusb_write_blocking(uint8_t iface_num, const uint8_t *buf,
uint32_t len, int timeout);

View File

@ -22,7 +22,6 @@
/* usb_webusb_add adds and configures new USB WebUSB interface according to /* usb_webusb_add adds and configures new USB WebUSB interface according to
* configuration options passed in `info`. */ * configuration options passed in `info`. */
secbool usb_webusb_add(const usb_webusb_info_t *info) { secbool usb_webusb_add(const usb_webusb_info_t *info) {
usb_iface_t *iface = usb_get_iface(info->iface_num); usb_iface_t *iface = usb_get_iface(info->iface_num);
if (iface == NULL) { if (iface == NULL) {
@ -32,7 +31,8 @@ secbool usb_webusb_add(const usb_webusb_info_t *info) {
return secfalse; // Interface is already enabled return secfalse; // Interface is already enabled
} }
usb_webusb_descriptor_block_t *d = usb_desc_alloc_iface(sizeof(usb_webusb_descriptor_block_t)); usb_webusb_descriptor_block_t *d =
usb_desc_alloc_iface(sizeof(usb_webusb_descriptor_block_t));
if (d == NULL) { if (d == NULL) {
return secfalse; // Not enough space in the configuration descriptor return secfalse; // Not enough space in the configuration descriptor
@ -182,7 +182,8 @@ int usb_webusb_read_select(uint32_t timeout) {
return -1; // Timeout return -1; // Timeout
} }
int usb_webusb_read_blocking(uint8_t iface_num, uint8_t *buf, uint32_t len, int timeout) { int usb_webusb_read_blocking(uint8_t iface_num, uint8_t *buf, uint32_t len,
int timeout) {
const uint32_t start = HAL_GetTick(); const uint32_t start = HAL_GetTick();
while (sectrue != usb_webusb_can_read(iface_num)) { while (sectrue != usb_webusb_can_read(iface_num)) {
if (timeout >= 0 && HAL_GetTick() - start >= timeout) { if (timeout >= 0 && HAL_GetTick() - start >= timeout) {
@ -193,7 +194,8 @@ int usb_webusb_read_blocking(uint8_t iface_num, uint8_t *buf, uint32_t len, int
return usb_webusb_read(iface_num, buf, len); 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) { int usb_webusb_write_blocking(uint8_t iface_num, const uint8_t *buf,
uint32_t len, int timeout) {
const uint32_t start = HAL_GetTick(); const uint32_t start = HAL_GetTick();
while (sectrue != usb_webusb_can_write(iface_num)) { while (sectrue != usb_webusb_can_write(iface_num)) {
if (timeout >= 0 && HAL_GetTick() - start >= timeout) { if (timeout >= 0 && HAL_GetTick() - start >= timeout) {
@ -204,7 +206,8 @@ int usb_webusb_write_blocking(uint8_t iface_num, const uint8_t *buf, uint32_t le
return usb_webusb_write(iface_num, buf, len); 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) { static void usb_webusb_class_init(USBD_HandleTypeDef *dev,
usb_webusb_state_t *state, uint8_t cfg_idx) {
// Open endpoints // Open endpoints
USBD_LL_OpenEP(dev, state->ep_in, USBD_EP_TYPE_INTR, state->max_packet_len); 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); USBD_LL_OpenEP(dev, state->ep_out, USBD_EP_TYPE_INTR, state->max_packet_len);
@ -215,10 +218,13 @@ static void usb_webusb_class_init(USBD_HandleTypeDef *dev, usb_webusb_state_t *s
state->ep_in_is_idle = 1; state->ep_in_is_idle = 1;
// Prepare the OUT EP to receive next packet // Prepare the OUT EP to receive next packet
USBD_LL_PrepareReceive(dev, state->ep_out, state->rx_buffer, state->max_packet_len); 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) { static void usb_webusb_class_deinit(USBD_HandleTypeDef *dev,
usb_webusb_state_t *state,
uint8_t cfg_idx) {
// Flush endpoints // Flush endpoints
USBD_LL_FlushEP(dev, state->ep_in); USBD_LL_FlushEP(dev, state->ep_in);
USBD_LL_FlushEP(dev, state->ep_out); USBD_LL_FlushEP(dev, state->ep_out);
@ -227,14 +233,14 @@ static void usb_webusb_class_deinit(USBD_HandleTypeDef *dev, usb_webusb_state_t
USBD_LL_CloseEP(dev, state->ep_out); USBD_LL_CloseEP(dev, state->ep_out);
} }
static int usb_webusb_class_setup(USBD_HandleTypeDef *dev, usb_webusb_state_t *state, USBD_SetupReqTypedef *req) { 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) { if ((req->bmRequest & USB_REQ_TYPE_MASK) != USB_REQ_TYPE_STANDARD) {
return USBD_OK; return USBD_OK;
} }
switch (req->bRequest) { switch (req->bRequest) {
case USB_REQ_SET_INTERFACE: case USB_REQ_SET_INTERFACE:
state->alt_setting = req->wValue; state->alt_setting = req->wValue;
USBD_CtlSendStatus(dev); USBD_CtlSendStatus(dev);
@ -250,19 +256,25 @@ static int usb_webusb_class_setup(USBD_HandleTypeDef *dev, usb_webusb_state_t *s
} }
} }
static void usb_webusb_class_data_in(USBD_HandleTypeDef *dev, usb_webusb_state_t *state, uint8_t ep_num) { 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) { if ((ep_num | USB_EP_DIR_IN) == state->ep_in) {
state->ep_in_is_idle = 1; 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) { 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) { if (ep_num == state->ep_out) {
state->last_read_len = USBD_LL_GetRxDataSize(dev, ep_num); state->last_read_len = USBD_LL_GetRxDataSize(dev, ep_num);
// Prepare the OUT EP to receive next packet // Prepare the OUT EP to receive next packet
// User should provide state->rx_buffer that is big enough for state->max_packet_len bytes // User should provide state->rx_buffer that is big enough for
USBD_LL_PrepareReceive(dev, ep_num, state->rx_buffer, state->max_packet_len); // state->max_packet_len bytes
USBD_LL_PrepareReceive(dev, ep_num, state->rx_buffer,
state->max_packet_len);
if (state->last_read_len > 0) { if (state->last_read_len > 0) {
// Block the OUT EP until we process received data // Block the OUT EP until we process received data

View File

@ -1,3 +1,5 @@
// clang-format off
/* /*
* This file is part of the Micro Python project, http://micropython.org/ * This file is part of the Micro Python project, http://micropython.org/
*/ */

Some files were not shown because too many files have changed in this diff Show More