The CCID Rev 1.1 specification states in section 1.3, Document
Conventions, that fields larger than one byte are stored in
little-endian format. The bulk message header's dwLength field is a
four-byte field described in section 6, CCID Messages.
Decode dwLength with le32_to_cpu() before using it to assemble and
validate Bulk-OUT messages. This fixes message handling on big-endian
hosts.
Signed-off-by: Marc-André Lureau <marcandre.lureau@redhat.com>
---
hw/usb/dev-smartcard-reader.c | 10 ++++++----
1 file changed, 6 insertions(+), 4 deletions(-)
diff --git a/hw/usb/dev-smartcard-reader.c b/hw/usb/dev-smartcard-reader.c
index 9fc6bbca0f2d..3580465df368 100644
--- a/hw/usb/dev-smartcard-reader.c
+++ b/hw/usb/dev-smartcard-reader.c
@@ -989,6 +989,7 @@ static const char *ccid_message_type_to_str(uint8_t type)
static void ccid_handle_bulk_out(USBCCIDState *s, USBPacket *p)
{
CCID_Header *ccid_header;
+ uint32_t payload_len;
if (p->iov.size + s->bulk_out_pos > BULK_OUT_DATA_SIZE) {
goto err;
@@ -1001,17 +1002,18 @@ static void ccid_handle_bulk_out(USBCCIDState *s, USBPacket *p)
}
ccid_header = (CCID_Header *)s->bulk_out_data;
- if ((s->bulk_out_pos - 10 < ccid_header->dwLength) &&
+ payload_len = le32_to_cpu(ccid_header->dwLength);
+ if ((s->bulk_out_pos - 10 < payload_len) &&
(p->iov.size == CCID_MAX_PACKET_SIZE)) {
DPRINTF(s, D_VERBOSE,
"usb-ccid: bulk_in: expecting more packets (%u/%u)\n",
- s->bulk_out_pos - 10, ccid_header->dwLength);
+ s->bulk_out_pos - 10, payload_len);
return;
}
- if (s->bulk_out_pos - 10 != ccid_header->dwLength) {
+ if (s->bulk_out_pos - 10 != payload_len) {
DPRINTF(s, 1,
"usb-ccid: bulk_in: message size mismatch (got %u, expected %u)\n",
- s->bulk_out_pos - 10, ccid_header->dwLength);
+ s->bulk_out_pos - 10, payload_len);
goto err;
}
--
2.55.0