1
0
mirror of https://github.com/trezor/trezor-firmware.git synced 2025-01-15 09:50:57 +00:00

core/webauthn: Fix CTAP HID protocol to correctly handle invalid channel IDs and interleaving packets from different channels.

This commit is contained in:
Andrew Kozlik 2019-09-26 18:42:51 +02:00
parent 9ea8136545
commit 0495d18b1e

View File

@ -363,7 +363,7 @@ async def read_cmd(iface: io.HID) -> Optional[Cmd]:
read = loop.wait(iface.iface_num() | io.POLL_READ) read = loop.wait(iface.iface_num() | io.POLL_READ)
buf = await read buf = await read
while True:
ifrm = overlay_struct(buf, desc_init) ifrm = overlay_struct(buf, desc_init)
bcnt = ifrm.bcnt bcnt = ifrm.bcnt
data = ifrm.data data = ifrm.data
@ -376,6 +376,11 @@ async def read_cmd(iface: io.HID) -> Optional[Cmd]:
log.warning(__name__, "_TYPE_CONT") log.warning(__name__, "_TYPE_CONT")
return None return None
if ifrm.cid == 0 or ((ifrm.cid == _CID_BROADCAST) and (ifrm.cmd != _CMD_INIT)):
# CID 0 is reserved for future use and _CID_BROADCAST is reserved for channel allocation
await send_cmd(cmd_error(ifrm.cid, _ERR_INVALID_CID), iface)
return None
if bcnt > _MAX_U2FHID_MSG_PAYLOAD_LEN: if bcnt > _MAX_U2FHID_MSG_PAYLOAD_LEN:
# invalid payload length, abort current msg # invalid payload length, abort current msg
if __debug__: if __debug__:
@ -397,12 +402,10 @@ async def read_cmd(iface: io.HID) -> Optional[Cmd]:
if cfrm.seq == _CMD_INIT: if cfrm.seq == _CMD_INIT:
# _CMD_INIT frame, cancels current channel # _CMD_INIT frame, cancels current channel
ifrm = overlay_struct(buf, desc_init)
data = ifrm.data[: ifrm.bcnt]
break break
if cfrm.cid != ifrm.cid: if cfrm.cid != ifrm.cid:
# cont frame for a different channel, reply with BUSY and skip # cont frame for a different channel, reply with BUSY and abort
if __debug__: if __debug__:
log.warning(__name__, "_ERR_CHANNEL_BUSY") log.warning(__name__, "_ERR_CHANNEL_BUSY")
await send_cmd(cmd_error(cfrm.cid, _ERR_CHANNEL_BUSY), iface) await send_cmd(cmd_error(cfrm.cid, _ERR_CHANNEL_BUSY), iface)
@ -418,7 +421,7 @@ async def read_cmd(iface: io.HID) -> Optional[Cmd]:
datalen += utils.memcpy(data, datalen, cfrm.data, 0, bcnt - datalen) datalen += utils.memcpy(data, datalen, cfrm.data, 0, bcnt - datalen)
seq += 1 seq += 1
else:
return Cmd(ifrm.cid, ifrm.cmd, data) return Cmd(ifrm.cid, ifrm.cmd, data)
@ -1051,9 +1054,7 @@ def dispatch_cmd(req: Cmd, dialog_mgr: DialogManager) -> Optional[Cmd]:
def cmd_init(req: Cmd) -> Cmd: def cmd_init(req: Cmd) -> Cmd:
if req.cid == 0: if req.cid == _CID_BROADCAST:
return cmd_error(req.cid, _ERR_INVALID_CID)
elif req.cid == _CID_BROADCAST:
# uint32_t except 0 and 0xffffffff # uint32_t except 0 and 0xffffffff
resp_cid = random.uniform(0xFFFFFFFE) + 1 resp_cid = random.uniform(0xFFFFFFFE) + 1
else: else: