From a8c500bffd890e3830094e906b1070c7d49dfa85 Mon Sep 17 00:00:00 2001 From: Andrew Kozlik Date: Sat, 16 Jan 2021 01:19:54 +0100 Subject: [PATCH] feat(core): Ensure that WebAuthn runs on port 21326 by default for both production and debug emulator. --- .../extmod/modtrezorio/modtrezorio-hid.h | 20 ++++++++++++++----- .../extmod/modtrezorio/modtrezorio-vcp.h | 10 ++++++++++ .../extmod/modtrezorio/modtrezorio-webusb.h | 18 +++++++++++++---- core/embed/trezorhal/usb_hid-defs.h | 12 +++++++---- core/embed/trezorhal/usb_vcp-defs.h | 4 ++++ core/embed/trezorhal/usb_webusb-defs.h | 12 +++++++---- core/embed/unix/usb.c | 12 +++++------ core/mocks/generated/trezorio/__init__.pyi | 3 +++ core/src/usb.py | 17 ++++++++++++++++ core/tools/hid-bridge/hid-bridge | 4 ++-- 10 files changed, 87 insertions(+), 25 deletions(-) diff --git a/core/embed/extmod/modtrezorio/modtrezorio-hid.h b/core/embed/extmod/modtrezorio/modtrezorio-hid.h index 532dc8ce5..4a13c4013 100644 --- a/core/embed/extmod/modtrezorio/modtrezorio-hid.h +++ b/core/embed/extmod/modtrezorio/modtrezorio-hid.h @@ -33,6 +33,7 @@ typedef struct _mp_obj_HID_t { /// iface_num: int, /// ep_in: int, /// ep_out: int, +/// emu_port: int, /// report_desc: bytes, /// subclass: int = 0, /// protocol: int = 0, @@ -54,6 +55,9 @@ STATIC mp_obj_t mod_trezorio_HID_make_new(const mp_obj_type_t *type, {MP_QSTR_ep_out, MP_ARG_REQUIRED | MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = 0}}, + {MP_QSTR_emu_port, + 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}}, @@ -69,12 +73,13 @@ STATIC mp_obj_t mod_trezorio_HID_make_new(const mp_obj_type_t *type, const mp_int_t iface_num = vals[0].u_int; const mp_int_t ep_in = vals[1].u_int; const mp_int_t ep_out = vals[2].u_int; - const mp_int_t subclass = vals[3].u_int; - const mp_int_t protocol = vals[4].u_int; - const mp_int_t polling_interval = vals[5].u_int; - const mp_int_t max_packet_len = vals[6].u_int; + const mp_int_t emu_port = vals[3].u_int; + const mp_int_t subclass = vals[4].u_int; + const mp_int_t protocol = vals[5].u_int; + const mp_int_t polling_interval = vals[6].u_int; + const mp_int_t max_packet_len = vals[7].u_int; mp_buffer_info_t report_desc = {0}; - mp_get_buffer_raise(vals[7].u_obj, &report_desc, MP_BUFFER_READ); + mp_get_buffer_raise(vals[8].u_obj, &report_desc, MP_BUFFER_READ); if (report_desc.buf == NULL || report_desc.len == 0 || report_desc.len > 255) { @@ -83,6 +88,7 @@ STATIC mp_obj_t mod_trezorio_HID_make_new(const mp_obj_type_t *type, CHECK_PARAM_RANGE(iface_num, 0, 32) CHECK_PARAM_RANGE(ep_in, 0, 255) CHECK_PARAM_RANGE(ep_out, 0, 255) + CHECK_PARAM_RANGE(emu_port, 0, 65535) CHECK_PARAM_RANGE(subclass, 0, 255) CHECK_PARAM_RANGE(protocol, 0, 255) CHECK_PARAM_RANGE(polling_interval, 1, 255) @@ -94,8 +100,12 @@ STATIC mp_obj_t mod_trezorio_HID_make_new(const mp_obj_type_t *type, o->info.rx_buffer = m_new(uint8_t, max_packet_len); o->info.report_desc = report_desc.buf; o->info.iface_num = (uint8_t)(iface_num); +#ifdef TREZOR_EMULATOR + o->info.emu_port = (uint16_t)(emu_port); +#else o->info.ep_in = (uint8_t)(ep_in); o->info.ep_out = (uint8_t)(ep_out); +#endif o->info.subclass = (uint8_t)(subclass); o->info.protocol = (uint8_t)(protocol); o->info.polling_interval = (uint8_t)(polling_interval); diff --git a/core/embed/extmod/modtrezorio/modtrezorio-vcp.h b/core/embed/extmod/modtrezorio/modtrezorio-vcp.h index 6a427c041..47160a569 100644 --- a/core/embed/extmod/modtrezorio/modtrezorio-vcp.h +++ b/core/embed/extmod/modtrezorio/modtrezorio-vcp.h @@ -37,6 +37,7 @@ typedef struct _mp_obj_VCP_t { /// ep_in: int, /// ep_out: int, /// ep_cmd: int, +/// emu_port: int, /// ) -> None: /// """ /// """ @@ -59,6 +60,9 @@ STATIC mp_obj_t mod_trezorio_VCP_make_new(const mp_obj_type_t *type, {MP_QSTR_ep_cmd, MP_ARG_REQUIRED | MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = 0}}, + {MP_QSTR_emu_port, + MP_ARG_REQUIRED | MP_ARG_KW_ONLY | MP_ARG_INT, + {.u_int = 0}}, }; mp_arg_val_t vals[MP_ARRAY_SIZE(allowed_args)] = {0}; mp_arg_parse_all_kw_array(n_args, n_kw, args, MP_ARRAY_SIZE(allowed_args), @@ -69,12 +73,14 @@ STATIC mp_obj_t mod_trezorio_VCP_make_new(const mp_obj_type_t *type, const mp_int_t ep_in = vals[2].u_int; const mp_int_t ep_out = vals[3].u_int; const mp_int_t ep_cmd = vals[4].u_int; + const mp_int_t emu_port = vals[5].u_int; CHECK_PARAM_RANGE(iface_num, 0, 32) CHECK_PARAM_RANGE(data_iface_num, 0, 32) CHECK_PARAM_RANGE(ep_in, 0, 255) CHECK_PARAM_RANGE(ep_out, 0, 255) CHECK_PARAM_RANGE(ep_cmd, 0, 255) + CHECK_PARAM_RANGE(emu_port, 0, 65535) const size_t vcp_buffer_len = 1024; const size_t vcp_packet_len = 64; @@ -92,9 +98,13 @@ STATIC mp_obj_t mod_trezorio_VCP_make_new(const mp_obj_type_t *type, o->info.rx_intr_byte = 3; // Ctrl-C o->info.iface_num = (uint8_t)(iface_num); o->info.data_iface_num = (uint8_t)(data_iface_num); +#ifdef TREZOR_EMULATOR + o->info.emu_port = (uint16_t)(emu_port); +#else o->info.ep_cmd = (uint8_t)(ep_cmd); o->info.ep_in = (uint8_t)(ep_in); o->info.ep_out = (uint8_t)(ep_out); +#endif o->info.polling_interval = 10; o->info.max_packet_len = (uint8_t)(vcp_packet_len); diff --git a/core/embed/extmod/modtrezorio/modtrezorio-webusb.h b/core/embed/extmod/modtrezorio/modtrezorio-webusb.h index e18ba38cf..b56be1bd5 100644 --- a/core/embed/extmod/modtrezorio/modtrezorio-webusb.h +++ b/core/embed/extmod/modtrezorio/modtrezorio-webusb.h @@ -33,6 +33,7 @@ typedef struct _mp_obj_WebUSB_t { /// iface_num: int, /// ep_in: int, /// ep_out: int, +/// emu_port: int, /// subclass: int = 0, /// protocol: int = 0, /// polling_interval: int = 1, @@ -53,6 +54,9 @@ STATIC mp_obj_t mod_trezorio_WebUSB_make_new(const mp_obj_type_t *type, {MP_QSTR_ep_out, MP_ARG_REQUIRED | MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = 0}}, + {MP_QSTR_emu_port, + 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}}, @@ -65,14 +69,16 @@ STATIC mp_obj_t mod_trezorio_WebUSB_make_new(const mp_obj_type_t *type, const mp_int_t iface_num = vals[0].u_int; const mp_int_t ep_in = vals[1].u_int; const mp_int_t ep_out = vals[2].u_int; - const mp_int_t subclass = vals[3].u_int; - const mp_int_t protocol = vals[4].u_int; - const mp_int_t polling_interval = vals[5].u_int; - const mp_int_t max_packet_len = vals[6].u_int; + const mp_int_t emu_port = vals[3].u_int; + const mp_int_t subclass = vals[4].u_int; + const mp_int_t protocol = vals[5].u_int; + const mp_int_t polling_interval = vals[6].u_int; + const mp_int_t max_packet_len = vals[7].u_int; CHECK_PARAM_RANGE(iface_num, 0, 32) CHECK_PARAM_RANGE(ep_in, 0, 255) CHECK_PARAM_RANGE(ep_out, 0, 255) + CHECK_PARAM_RANGE(emu_port, 0, 65535) CHECK_PARAM_RANGE(subclass, 0, 255) CHECK_PARAM_RANGE(protocol, 0, 255) CHECK_PARAM_RANGE(polling_interval, 1, 255) @@ -83,8 +89,12 @@ STATIC mp_obj_t mod_trezorio_WebUSB_make_new(const mp_obj_type_t *type, o->info.rx_buffer = m_new(uint8_t, max_packet_len); o->info.iface_num = (uint8_t)(iface_num); +#ifdef TREZOR_EMULATOR + o->info.emu_port = (uint16_t)(emu_port); +#else o->info.ep_in = (uint8_t)(ep_in); o->info.ep_out = (uint8_t)(ep_out); +#endif o->info.subclass = (uint8_t)(subclass); o->info.protocol = (uint8_t)(protocol); o->info.polling_interval = (uint8_t)(polling_interval); diff --git a/core/embed/trezorhal/usb_hid-defs.h b/core/embed/trezorhal/usb_hid-defs.h index d83c06381..9062d71eb 100644 --- a/core/embed/trezorhal/usb_hid-defs.h +++ b/core/embed/trezorhal/usb_hid-defs.h @@ -41,10 +41,14 @@ typedef struct { const uint8_t *report_desc; // With length of report_desc_len bytes uint8_t *rx_buffer; // With length of max_packet_len bytes uint8_t iface_num; // Address of this HID interface - uint8_t ep_in; // Address of IN endpoint (with the highest bit set) - uint8_t ep_out; // Address of OUT endpoint - uint8_t subclass; // usb_iface_subclass_t - uint8_t protocol; // usb_iface_protocol_t +#ifdef TREZOR_EMULATOR + uint16_t emu_port; // UDP port of this interface in the emulator. +#else + uint8_t ep_in; // Address of IN endpoint (with the highest bit set) + uint8_t ep_out; // Address of OUT endpoint +#endif + uint8_t subclass; // usb_iface_subclass_t + uint8_t protocol; // usb_iface_protocol_t uint8_t polling_interval; // In units of 1ms uint8_t max_packet_len; // Length of the biggest report and of rx_buffer uint8_t report_desc_len; // Length of report_desc diff --git a/core/embed/trezorhal/usb_vcp-defs.h b/core/embed/trezorhal/usb_vcp-defs.h index 67656a793..849aed06f 100644 --- a/core/embed/trezorhal/usb_vcp-defs.h +++ b/core/embed/trezorhal/usb_vcp-defs.h @@ -105,9 +105,13 @@ typedef struct { uint8_t iface_num; // Address of this VCP interface uint8_t data_iface_num; // Address of data interface of the VCP interface // association +#ifdef TREZOR_EMULATOR + uint16_t emu_port; // UDP port of this interface in the emulator. +#else uint8_t ep_cmd; // Address of IN CMD endpoint (with the highest bit set) uint8_t ep_in; // Address of IN endpoint (with the highest bit set) uint8_t ep_out; // Address of OUT endpoint +#endif 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 diff --git a/core/embed/trezorhal/usb_webusb-defs.h b/core/embed/trezorhal/usb_webusb-defs.h index 046f803cc..aa475bf36 100644 --- a/core/embed/trezorhal/usb_webusb-defs.h +++ b/core/embed/trezorhal/usb_webusb-defs.h @@ -32,10 +32,14 @@ typedef struct __attribute__((packed)) { typedef struct { uint8_t *rx_buffer; // With length of max_packet_len bytes uint8_t iface_num; // Address of this WebUSB interface - uint8_t ep_in; // Address of IN endpoint (with the highest bit set) - uint8_t ep_out; // Address of OUT endpoint - uint8_t subclass; // usb_iface_subclass_t - uint8_t protocol; // usb_iface_protocol_t +#ifdef TREZOR_EMULATOR + uint16_t emu_port; // UDP port of this interface in the emulator. +#else + uint8_t ep_in; // Address of IN endpoint (with the highest bit set) + uint8_t ep_out; // Address of OUT endpoint +#endif + uint8_t subclass; // usb_iface_subclass_t + uint8_t protocol; // usb_iface_protocol_t uint8_t polling_interval; // In units of 1ms uint8_t max_packet_len; // Length of the biggest report and of rx_buffer } usb_webusb_info_t; diff --git a/core/embed/unix/usb.c b/core/embed/unix/usb.c index 1a439a594..db7b8d389 100644 --- a/core/embed/unix/usb.c +++ b/core/embed/unix/usb.c @@ -49,6 +49,7 @@ __fatal_error(const char *expr, const char *msg, const char *file, int line, static struct { usb_iface_type_t type; + uint16_t port; int sock; struct sockaddr_in si_me, si_other; socklen_t slen; @@ -58,6 +59,7 @@ void usb_init(const usb_dev_info_t *dev_info) { (void)dev_info; for (int i = 0; i < USBD_MAX_NUM_INTERFACES; i++) { usb_ifaces[i].type = USB_IFACE_TYPE_DISABLED; + usb_ifaces[i].port = 0; usb_ifaces[i].sock = -1; memzero(&usb_ifaces[i].si_me, sizeof(struct sockaddr_in)); memzero(&usb_ifaces[i].si_other, sizeof(struct sockaddr_in)); @@ -69,7 +71,6 @@ void usb_deinit(void) {} void usb_start(void) { const char *ip = getenv("TREZOR_UDP_IP"); - const char *port = getenv("TREZOR_UDP_PORT"); // iterate interfaces for (int i = 0; i < USBD_MAX_NUM_INTERFACES; i++) { @@ -90,11 +91,7 @@ void usb_start(void) { } else { usb_ifaces[i].si_me.sin_addr.s_addr = htonl(INADDR_LOOPBACK); } - if (port) { - usb_ifaces[i].si_me.sin_port = htons(atoi(port) + i); - } else { - usb_ifaces[i].si_me.sin_port = htons(TREZOR_UDP_PORT + i); - } + usb_ifaces[i].si_me.sin_port = htons(usb_ifaces[i].port); ensure(sectrue * (0 == bind(usb_ifaces[i].sock, (struct sockaddr *)&usb_ifaces[i].si_me, @@ -109,6 +106,7 @@ secbool usb_hid_add(const usb_hid_info_t *info) { if (info->iface_num < USBD_MAX_NUM_INTERFACES && usb_ifaces[info->iface_num].type == USB_IFACE_TYPE_DISABLED) { usb_ifaces[info->iface_num].type = USB_IFACE_TYPE_HID; + usb_ifaces[info->iface_num].port = info->emu_port; } return sectrue; } @@ -117,6 +115,7 @@ secbool usb_webusb_add(const usb_webusb_info_t *info) { if (info->iface_num < USBD_MAX_NUM_INTERFACES && usb_ifaces[info->iface_num].type == USB_IFACE_TYPE_DISABLED) { usb_ifaces[info->iface_num].type = USB_IFACE_TYPE_WEBUSB; + usb_ifaces[info->iface_num].port = info->emu_port; } return sectrue; } @@ -125,6 +124,7 @@ secbool usb_vcp_add(const usb_vcp_info_t *info) { if (info->iface_num < USBD_MAX_NUM_INTERFACES && usb_ifaces[info->iface_num].type == USB_IFACE_TYPE_DISABLED) { usb_ifaces[info->iface_num].type = USB_IFACE_TYPE_VCP; + usb_ifaces[info->iface_num].port = info->emu_port; } return sectrue; } diff --git a/core/mocks/generated/trezorio/__init__.pyi b/core/mocks/generated/trezorio/__init__.pyi index 0fc6bdaf9..e9fa19038 100644 --- a/core/mocks/generated/trezorio/__init__.pyi +++ b/core/mocks/generated/trezorio/__init__.pyi @@ -42,6 +42,7 @@ class HID: iface_num: int, ep_in: int, ep_out: int, + emu_port: int, report_desc: bytes, subclass: int = 0, protocol: int = 0, @@ -148,6 +149,7 @@ class VCP: ep_in: int, ep_out: int, ep_cmd: int, + emu_port: int, ) -> None: """ """ @@ -169,6 +171,7 @@ class WebUSB: iface_num: int, ep_in: int, ep_out: int, + emu_port: int, subclass: int = 0, protocol: int = 0, polling_interval: int = 1, diff --git a/core/src/usb.py b/core/src/usb.py index cb732e618..c232bbd27 100644 --- a/core/src/usb.py +++ b/core/src/usb.py @@ -1,6 +1,19 @@ +from micropython import const + from storage.device import get_device_id from trezor import io, utils +UDP_PORT = 0 +WIRE_PORT_OFFSET = const(0) +DEBUGLINK_PORT_OFFSET = const(1) +WEBAUTHN_PORT_OFFSET = const(2) +VCP_PORT_OFFSET = const(3) + +if utils.EMULATOR: + import uos + + UDP_PORT = int(uos.getenv("TREZOR_UDP_PORT") or "21324") + _iface_iter = iter(range(5)) ENABLE_IFACE_DEBUG = __debug__ @@ -23,6 +36,7 @@ iface_wire = io.WebUSB( iface_num=id_wire, ep_in=0x81 + id_wire, ep_out=0x01 + id_wire, + emu_port=UDP_PORT + WIRE_PORT_OFFSET, ) # XXXXXXXXXXXXXXXXXXX @@ -43,6 +57,7 @@ if __debug__ and ENABLE_IFACE_DEBUG: iface_num=id_debug, ep_in=0x81 + id_debug, ep_out=0x01 + id_debug, + emu_port=UDP_PORT + DEBUGLINK_PORT_OFFSET, ) if not utils.BITCOIN_ONLY and ENABLE_IFACE_WEBAUTHN: @@ -52,6 +67,7 @@ if not utils.BITCOIN_ONLY and ENABLE_IFACE_WEBAUTHN: iface_num=id_webauthn, ep_in=0x81 + id_webauthn, ep_out=0x01 + id_webauthn, + emu_port=UDP_PORT + WEBAUTHN_PORT_OFFSET, # fmt: off report_desc=bytes([ 0x06, 0xd0, 0xf1, # USAGE_PAGE (FIDO Alliance) @@ -84,6 +100,7 @@ if __debug__ and ENABLE_IFACE_VCP: ep_in=0x81 + id_vcp, ep_out=0x01 + id_vcp, ep_cmd=0x81 + id_vcp_data, + emu_port=UDP_PORT + VCP_PORT_OFFSET, ) bus = io.USB( diff --git a/core/tools/hid-bridge/hid-bridge b/core/tools/hid-bridge/hid-bridge index 08575e6c4..424648fa0 100755 --- a/core/tools/hid-bridge/hid-bridge +++ b/core/tools/hid-bridge/hid-bridge @@ -11,10 +11,10 @@ import logger parser = argparse.ArgumentParser() parser.add_argument( "-e", - default=21325, + default=21326, metavar="port", type=int, - help="UDP port the utility communicates with, 21325 by default.", + help="UDP port the utility communicates with, 21326 by default.", ) parser.add_argument( "-l",