diff options
author | Werner Koch <wk@gnupg.org> | 2021-06-22 20:41:47 +0200 |
---|---|---|
committer | Werner Koch <wk@gnupg.org> | 2021-06-22 20:41:47 +0200 |
commit | 2c6b62b3572fe43cb6b89ec5fb0bc62385a4b230 (patch) | |
tree | fa6f38698edfb55b91e66e7226e6dae265d702a7 /tools | |
parent | tests: Cope with broken Libgcrypt versions (diff) | |
download | gnupg2-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.c | 94 |
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); } |