From nobody Tue Feb 10 06:25:29 2026 Delivered-To: importer@patchew.org Received-SPF: pass (zoho.com: domain of gnu.org designates 208.118.235.17 as permitted sender) client-ip=208.118.235.17; envelope-from=qemu-devel-bounces+importer=patchew.org@nongnu.org; helo=lists.gnu.org; Authentication-Results: mx.zohomail.com; spf=pass (zoho.com: domain of gnu.org designates 208.118.235.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org Return-Path: Received: from lists.gnu.org (lists.gnu.org [208.118.235.17]) by mx.zohomail.com with SMTPS id 1500539295178508.21956093956646; Thu, 20 Jul 2017 01:28:15 -0700 (PDT) Received: from localhost ([::1]:36661 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1dY6of-0007Ma-UA for importer@patchew.org; Thu, 20 Jul 2017 04:28:13 -0400 Received: from eggs.gnu.org ([2001:4830:134:3::10]:35316) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1dY6mo-0006AL-MR for qemu-devel@nongnu.org; Thu, 20 Jul 2017 04:26:22 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1dY6mn-0004pg-RU for qemu-devel@nongnu.org; Thu, 20 Jul 2017 04:26:18 -0400 Received: from manul.sfritsch.de ([2a01:4f8:172:195f:112::2]:36930) by eggs.gnu.org with esmtps (TLS1.0:RSA_AES_128_CBC_SHA1:16) (Exim 4.71) (envelope-from ) id 1dY6mn-0004pW-Kl for qemu-devel@nongnu.org; Thu, 20 Jul 2017 04:26:17 -0400 From: Stefan Fritsch To: Gerd Hoffmann , qemu-devel@nongnu.org Date: Thu, 20 Jul 2017 10:25:19 +0200 Message-Id: <1500539123-23884-5-git-send-email-sf@sfritsch.de> X-Mailer: git-send-email 2.1.4 In-Reply-To: <1500539123-23884-1-git-send-email-sf@sfritsch.de> References: <1500539123-23884-1-git-send-email-sf@sfritsch.de> X-detected-operating-system: by eggs.gnu.org: GNU/Linux 2.2.x-3.x [generic] X-Received-From: 2a01:4f8:172:195f:112::2 Subject: [Qemu-devel] [PATCH 4/8] usb-ccid: Fix ATR parsing X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.21 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: Stefan Fritsch Errors-To: qemu-devel-bounces+importer=patchew.org@nongnu.org Sender: "Qemu-devel" X-ZohoMail: RSF_0 Z_629925259 SPT_0 Content-Transfer-Encoding: quoted-printable MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" From: Stefan Fritsch - The number of parameter set TA_i...TD_i is unlimited. The list ends if TD_i is not present or the high nibble is zero. - If at least one protocol in any of the TD bytes is non-zero, the ATR must have a checksum. - Add a missing length check before accessing TD. - Fixup a wrong checksum but accept the ATR. Signed-off-by: Stefan Fritsch Signed-off-by: Christian Ehrhardt --- hw/usb/ccid-card-passthru.c | 34 ++++++++++++++++++++++++++-------- 1 file changed, 26 insertions(+), 8 deletions(-) diff --git a/hw/usb/ccid-card-passthru.c b/hw/usb/ccid-card-passthru.c index 45d96b03c6..e2e94ac1ba 100644 --- a/hw/usb/ccid-card-passthru.c +++ b/hw/usb/ccid-card-passthru.c @@ -146,8 +146,7 @@ static void ccid_card_vscard_handle_init( =20 static int check_atr(PassthruState *card, uint8_t *data, int len) { - int historical_length, opt_bytes; - int td_count =3D 0; + int historical_length, opt_bytes, tck =3D 0; int td; =20 if (len < 2) { @@ -160,10 +159,8 @@ static int check_atr(PassthruState *card, uint8_t *dat= a, int len) data[0]); return 0; } - td_count =3D 0; td =3D data[1] >> 4; - while (td && td_count < 2 && opt_bytes + historical_length + 2 < len) { - td_count++; + while (td && opt_bytes + historical_length + 2 < len) { if (td & 0x1) { opt_bytes++; } @@ -175,16 +172,37 @@ static int check_atr(PassthruState *card, uint8_t *da= ta, int len) } if (td & 0x8) { opt_bytes++; - td =3D data[opt_bytes + 2] >> 4; + if (opt_bytes + 1 >=3D len) { + break; + } + /* Checksum byte must be present if T!=3D0 */ + if (data[opt_bytes + 1] & 0xf) { + tck =3D 1; + } + td =3D data[opt_bytes + 1] >> 4; + } else { + td =3D 0; } } - if (len < 2 + historical_length + opt_bytes) { + if (len < 2 + historical_length + opt_bytes + tck) { DPRINTF(card, D_WARN, "atr too short: len %d, but historical_len %d, T1 0x%X\n", len, historical_length, data[1]); return 0; } - if (len > 2 + historical_length + opt_bytes) { + if (tck) { + int i; + uint8_t cksum =3D 0; + for (i =3D 1; i < 2 + historical_length + opt_bytes; ++i) { + cksum ^=3D data[i]; + } + if (cksum !=3D data[i]) { + DPRINTF(card, D_WARN, "atr has bad checksum: " + "real=3D0x%x should be 0x%x (FIXED)\n", cksum, data[i]); + data[i] =3D cksum; + } + } + if (len > 2 + historical_length + opt_bytes + tck) { DPRINTF(card, D_WARN, "atr too long: len %d, but hist/opt %d/%d, T1 0x%X\n", len, historical_length, opt_bytes, data[1]); --=20 2.11.0