summaryrefslogtreecommitdiffstats
path: root/tools
diff options
context:
space:
mode:
authorWerner Koch <wk@gnupg.org>2021-06-22 20:41:47 +0200
committerWerner Koch <wk@gnupg.org>2021-06-22 20:41:47 +0200
commit2c6b62b3572fe43cb6b89ec5fb0bc62385a4b230 (patch)
treefa6f38698edfb55b91e66e7226e6dae265d702a7 /tools
parenttests: Cope with broken Libgcrypt versions (diff)
downloadgnupg2-2c6b62b3572fe43cb6b89ec5fb0bc62385a4b230.tar.xz
gnupg2-2c6b62b3572fe43cb6b89ec5fb0bc62385a4b230.zip
tools: Extend ccidmon to print T=1 APDUs
* tools/ccidmon.c (print_as_ascii): New. (print_t1_block): New. (print_p2r_xfrblock): Print APDUs (print_r2p_datablock): Ditto. Signed-off-by: Werner Koch <wk@gnupg.org>
Diffstat (limited to 'tools')
-rw-r--r--tools/ccidmon.c94
1 files changed, 93 insertions, 1 deletions
diff --git a/tools/ccidmon.c b/tools/ccidmon.c
index 4e99da54d..c649913d1 100644
--- a/tools/ccidmon.c
+++ b/tools/ccidmon.c
@@ -1,5 +1,7 @@
/* ccidmon.c - CCID monitor for use with the Linux usbmon facility.
- * Copyright (C) 2009 Free Software Foundation, Inc.
+ * Copyright (C) 2009, 2016, 2019 Werner Koch
+ * Copyright (C) 2021 g10 Code GmbH
+ * Copyright (C) 2009 Free Software Foundation, Inc.
*
* This file is part of GnuPG.
*
@@ -15,6 +17,7 @@
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, see <https://www.gnu.org/licenses/>.
+ * SPDX-License-Identifier: GPL-3.0-or-later
*/
@@ -188,6 +191,85 @@ print_pr_data (const unsigned char *data, size_t datalen, size_t off)
static void
+print_as_ascii (const unsigned char *buf, unsigned int buflen,unsigned int fill)
+{
+ unsigned int n;
+
+ if (!buflen)
+ return;
+ if (buflen > 16)
+ buflen = 16;
+
+ for (n = buflen; n < fill; n++)
+ fputs (" ", stdout);
+ fputs (" |", stdout);
+ for (n = 0; n < buflen; n++, buf++)
+ if (*buf >= 32 && *buf < 127 && *buf != '|')
+ putchar (*buf);
+ else
+ putchar ('.');
+ putchar ('|');
+}
+
+
+static void
+print_t1_block (const unsigned char *msg, size_t msglen)
+{
+ unsigned int count, len;
+ unsigned char buf[16];
+
+ if (msglen < 4)
+ {
+ printf (" T=1 ..: invalid block\n");
+ return;
+ }
+ printf (" T=1 ..: NAD=%02x", msg[0]);
+ if (!(msg[1] & 0x80))
+ {
+ printf (" I-block seq=%d%s\n",
+ !!(msg[1] & 0x40), (msg[1] & 0x20)? " chaining":"");
+ len = msg[2];
+ msg += 3;
+ msglen -= 3;
+
+ printf (" APDU .:");
+ count = 0;
+ while (msglen > 1 && len)
+ {
+ if (count == 16)
+ {
+ print_as_ascii (buf, count, count);
+ printf ("\n ");
+ count = 0;
+ }
+ buf[count] = msg[0];
+ printf (" %02X", msg[0]);
+ msg++;
+ msglen--;
+ len--;
+ count++;
+ }
+ print_as_ascii (buf, count, 16);
+ putchar ('\n');
+ }
+ else if (!(msg[1] & 0x40))
+ printf (" R-block seq=%d%s\n",
+ !!(msg[1] & 0x10),
+ (msg[1] & 0x0f) == 0 ? "":
+ (msg[1] & 0x0f) == 1 ? "EDC error":
+ (msg[1] & 0x0f) == 2 ? "other error": "?");
+ else
+ printf (" S-block %s %s\n",
+ (msg[1] & 0x1f) == 0 ? "resync":
+ (msg[1] & 0x1f) == 1 ? "info_field_size":
+ (msg[1] & 0x1f) == 2 ? "abort":
+ (msg[1] & 0x1f) == 2 ? "BWT_extension":
+ (msg[1] & 0x1f) == 2 ? "VPP_error": "?",
+ (msg[1] & 0x20)? "response":"request");
+}
+
+
+static void
print_p2r_header (const char *name, const unsigned char *msg, size_t msglen)
{
printf ("%s:\n", name);
@@ -246,6 +328,11 @@ print_p2r_xfrblock (const unsigned char *msg, size_t msglen)
val == 3? " (continues+continued)":
val == 16? " (DataBlock-expected)":"");
print_pr_data (msg, msglen, 10);
+ if (msglen < 10)
+ return;
+ msg += 10;
+ msglen -= 10;
+ print_t1_block (msg, msglen);
}
@@ -454,6 +541,11 @@ print_r2p_datablock (const unsigned char *msg, size_t msglen)
msg[9] == 3? " (continues+continued)":
msg[9] == 16? " (XferBlock-expected)":"");
print_pr_data (msg, msglen, 10);
+ if (msglen < 10)
+ return;
+ msg += 10;
+ msglen -= 10;
+ print_t1_block (msg, msglen);
}