3f9f88500bfb13b4117eac1cf7da41b18491fdb6
[gnupg-doc.git] / misc / blog.gnupg.org / 20171005-gnupg-ccid-card-daemon-UbuntuPhone.org
1 #+TITLE: Using an OpenPGP card in the UbuntuPhone BQ E4.5
2 #+STARTUP: showall
3 #+AUTHOR: Matthias
4 #+DATE: October 5, 2017
5
6 ** Using an OpenPGP card in the UbuntuPhone BQ E4.5
7
8 #+CAPTION: The device BQ E4.5 with the attached OpenPGP card
9 #+ATTR_HTML: :class right :style max-width: 350px
10 [[file:img/UbuntuPhone-GnuPG-card.png]]
11
12 This small tutorial describes how to setup and use GnuPG together with
13 an OpenPGP card in the mobile device BQ E4.5, running Ubuntu 15-04. The device
14 root file system is for good reason mounted read-only. I.e. one can not
15 just install any other piece of software into it. The way used here is
16 an additional Linux system inside the phones system and *chroot*-ing into it
17 for the to be installed software, and later calling the software from outside
18 the chroot'ed file system.
19
20 When you login into the phone, either by SSH or via the terminal-app, your
21 ~HOME~ directory is ~/home/phablet~. ~phablet~ is the default user in the
22 phone. I have created there an additional directory ~/home/phablet/myRoot~
23 and below this untar'ed a complete Debian based Linux.
24 How to do this is described in a small
25 [[https://gurucubano.gitbooks.io/bq-aquaris-e-4-5-ubuntu-phone/content/en/chapter27.html][Gitbook about the BQ E4.5]].
26
27 In the following text as naming convention the shell
28 prompt =$= means, we are in the phones file system and something
29 like =root@ubuntu-phablet:/#= or
30 =phablet@ubuntu-phablet:~$= means,
31 we are in the chroot'ed file system, best to understand with these commands:
32
33 #+begin_src sh
34 $ ssh phablet@10.42.0.1
35
36 Welcome to Ubuntu 15.04 (GNU/Linux 3.4.67 armv7l)
37
38 Last login: Mon Sep 25 07:45:37 2017 from 10.42.0.152
39
40 phablet@ubuntu-phablet-bq:~$
41
42 phablet@ubuntu-phablet-bq:~$ PS1='$ '
43
44 $ sudo chroot /home/phablet/myRoot
45 [sudo] password for phablet:
46 root@ubuntu-phablet:/# su phablet
47 phablet@ubuntu-phablet:/$ cd
48 phablet@ubuntu-phablet:~$ pwd
49 /home/phablet
50 phablet@ubuntu-phablet:~$
51 #+end_src
52
53 *** Installing GnuPG 2.2.1 into the 'myRoot' system
54
55 In the chroot'ed system we install some additional packages:
56
57 #+begin_src sh
58 phablet@ubuntu-phablet:~$ sudo apt-get install pinentry-curses
59 phablet@ubuntu-phablet:~$ sudo apt-get install pass
60 phablet@ubuntu-phablet:~$ sudo apt-get install libudev-dev
61 phablet@ubuntu-phablet:~$ sudo apt-get install libusb-dev
62 phablet@ubuntu-phablet:~$ sudo apt-get install libusb-1.0-0-dev
63 #+end_src
64
65 ~pass~ is a small password-storage manager which we will later use for our
66 GnuPG encrypted tree of password, for example for websites or any other
67 purpose, bank account PIN, ...
68
69 ~pinentry-curses~ is used by the ~gpg-agent~ to ask for the OpenPGP card
70 PIN, i.e. all the usage is later done or in a SSH session or in the
71 terminal-app.
72
73 We now compile the following pieces of GnuPG software in that order:
74
75 #+begin_example
76 libgpg-error-1.27
77 libassuan-2.4.3
78 libksba-1.3.5
79 npth-1.5
80 libgcrypt-1.8.1
81 gnupg-2.2.1
82 #+end_example
83
84 always with ~./configure && make && sudo make install~ The compiled
85 software ends up below ~/usr/local~ (i.e. below
86 ~/home/phablet/myRoot/usr/local~ when one looks from outside the
87 chroot'ed phone system);
88
89 Now in the phone system we configure for GnuPG the following config
90 files:
91
92 #+begin_src sh
93 $ mkdir ~/.gnupg
94
95 $ cat .gnupg/gpg.conf
96 #
97 agent-program  /home/phablet/myRoot/usr/local/bin/gpg-agent
98
99 $ cat .gnupg/gpg-agent.conf
100 pinentry-program /home/phablet/myRoot/usr/bin/pinentry-curses
101 scdaemon-program /home/phablet/myRoot/usr/local/libexec/scdaemon
102 log-file /home/phablet/gpg-agent.log
103 log-file /dev/null
104 debug-level guru
105 #+end_src
106
107 Due to the nature of the installation in the chroot'ed system we
108 need small wrapper scripts to set ~PATH~, ~LD_LIBRARY_PATH~, ... and
109 other stuff;
110
111 #+begin_src sh
112 $ cat ~/gpg.sh
113 #!/bin/sh
114 LD_LIBRARY_PATH=/home/phablet/myRoot/usr/local/lib export LD_LIBRARY_PATH
115 PATH=/home/phablet/myRoot/usr/local/bin:$PATH      export PATH
116 GNUPGHOME=/home/phablet/.gnupg    export GNUPGHOME
117 GPG_TTY=$(tty)                    export GPG_TTY
118 /home/phablet/myRoot/usr/local/bin/gpg-agent    \
119             --homedir /home/phablet/.gnupg      \
120             --daemon                            \
121             --pinentry-program /home/phablet/myRoot/usr/bin/pinentry-curses
122 /home/phablet/myRoot/usr/local/bin/gpg-connect-agent /bye
123 /home/phablet/myRoot/usr/local/bin/gpg $*
124 #+end_src
125
126 run and create for test a key pair (later we want to use the OpenPGP card key pair
127 for instead of this)
128
129 #+begin_src sh
130 $ ~/gpg.sh --full-generate-key
131 gpg-agent[2973]: enabled debug flags: mpi crypto memory cache memstat hashing ipc
132 gpg (GnuPG) 2.2.1; Copyright (C) 2017 Free Software Foundation, Inc.
133 This is free software: you are free to change and redistribute it.
134 There is NO WARRANTY, to the extent permitted by law.
135
136 Please select what kind of key you want:
137    (1) RSA and RSA (default)
138    (2) DSA and Elgamal
139    (3) DSA (sign only)
140    (4) RSA (sign only)
141 Your selection?
142 ...
143 #+end_src
144
145 This starts the gpg-agent as:
146
147 #+begin_src sh
148 $ ps ax | grep gpg-a
149  2974 ?        Ss     0:00 /home/phablet/myRoot/usr/local/bin/gpg-agent --homedir /home/phablet/.gnupg --daemon --pinentry-program /home/phablet/myRoot/usr/bin/pinentry-curses
150 #+end_src
151
152
153 Now we can use the 'pass' command we installed in the chroot'es system
154 with
155
156 #+begin_src sh
157 $ cat pass.sh
158 #!/bin/sh
159 LD_LIBRARY_PATH=/home/phablet/myRoot/usr/local/lib export LD_LIBRARY_PATH
160 PATH=/home/phablet/myRoot/usr/local/bin:$PATH      export PATH
161 GNUPGHOME=/home/phablet/.gnupg    export GNUPGHOME
162 GPG_TTY=$(tty)                    export GPG_TTY
163 unset GPG_AGENT_INFO
164 /home/phablet/myRoot/usr/bin/pass $*
165 #+end_src
166
167
168 Init the pass storage as:
169
170 #+begin_src sh
171 $ ./pass.sh init Matthias
172
173                  ┌────────────────────────────────────────────────────────────────┐
174                  │ Please enter the passphrase to unlock the OpenPGP secret key:  │
175                  │ "Matthias Apitz (test) <guru@sisis.de>"                        │
176                  │ 2048-bit RSA key, ID 93A6FBF52FA76DB0,                         │
177                  │ created 2017-09-22 (main key ID 3FECB79DDDA409E4).             │
178                  │                                                                │
179                  │                                                                │
180                  │ Passphrase: ***_______________________________________________ │
181                  │                                                                │
182                  │         <OK>                                    <Cancel>       │
183                  └────────────────────────────────────────────────────────────────┘
184
185 $ find .password-store/
186 .password-store/
187 .password-store/.gpg-id
188 #+end_src
189
190 Insert some password for test:
191
192 #+begin_src sh
193 $ ./pass.sh insert -m web/bla
194 Enter contents of web/bla and press Ctrl+D when finished:
195
196 password
197 Username: guru
198
199 $ ./pass.sh web/bla
200 password
201 Username: guru
202 #+end_src
203
204
205 Final step is getting support for the OpenPGP card. We need the 'pcscd' daemon.
206 Its build is a bit tricky because it must later, on start from outside the
207 chroot'ed syste, find the ccid driver.
208
209 We compile the following pieces inside the chroot'ed system:
210
211 pcsc-lite-1.8.20
212 ccid-1.4.25
213
214 with the following options set on ~./configure~ ...
215
216 #+begin_src sh
217 phablet@ubuntu-phablet-bq:~$ cd pcsc-lite-1.8.20
218 phablet@ubuntu-phablet-bq:~/pcsc-lite-1.8.20$ ./configure --enable-usbdropdir=/home/phablet/myRoot/usr/local/lib/pcsc/drivers --enable-confdir=/home/phablet/myRoot/etc/reader.conf.d
219
220 ...
221 PC/SC lite has been configured with following options:
222
223 Version:             1.8.20
224 System binaries:     /usr/local/sbin
225 Configuration dir:   /usr/local/etc/reader.conf.d
226
227
228 Host:                armv7l-unknown-linux-gnueabihf
229 Compiler:            gcc
230 Preprocessor flags:  -I${top_srcdir}/src
231 Compiler flags:      -Wall -fno-common -g -O2
232 Preprocessor flags:  -I${top_srcdir}/src
233 Linker flags:
234 Libraries:           -ldl  -lrt
235
236 PTHREAD_CFLAGS:      -pthread
237 PTHREAD_LIBS:
238 PCSC_ARCH:           Linux
239
240 pcscd binary            /usr/local/sbin/pcscd
241 polkit support:         no
242 polkit policy dir:
243 libudev support:        yes
244 libusb support:         no
245 USB drop directory:     /home/phablet/myRoot/usr/local/lib/pcsc/drivers
246 ATR parsing messages:   false
247 ipcdir:                 /var/run/pcscd
248 use serial:             yes
249 use usb:                yes
250 systemd unit directory: /lib/systemd/system
251 serial config dir.:     /home/phablet/myRoot/etc/reader.conf.d
252 filter:                 no
253
254 PCSCLITE_FEATURES:       Linux armv7l-unknown-linux-gnueabihf serial usb libudev usbdropdir=/home/phablet/myRoot/usr/local/lib/pcsc/drivers ipcdir=/var/run/pcscd configdir=/home/phablet/myRoot/etc/reader.conf.d
255
256 checking that generated files are newer than configure... done
257 ...
258
259 phablet@ubuntu-phablet-bq:~/ccid-1.4.25$ make
260 phablet@ubuntu-phablet-bq:~/ccid-1.4.25$ sudo make install
261 #+end_src
262
263
264 ok, now the 'ccid' driver, installed (copied) to be seen by the daemon:
265
266 #+begin_src sh
267
268 phablet@ubuntu-phablet-bq:~$ cd ccid-1.4.25
269 phablet@ubuntu-phablet:~/ccid-1.4.25$ ./configure -enable-usbdropdir=/home/phablet/myRoot/usr/local/lib/pcsc/drivers
270 ...
271 libccid has been configured with following options:
272
273 Version:             1.4.25
274 User binaries:       /usr/local/bin
275 Configuration files: /usr/local/etc
276
277
278 Host:                armv7l-unknown-linux-gnueabihf
279 Compiler:            gcc
280 Preprocessor flags:
281 Compiler flags:      -g -O2
282 Preprocessor flags:
283 Linker flags:
284 Libraries:
285
286 PCSC_CFLAGS:         -pthread -I/usr/local/include/PCSC
287 PCSC_LIBS:           -L/usr/local/lib -lpcsclite
288 PTHREAD_CFLAGS:      -pthread
289 PTHREAD_LIBS:
290 BUNDLE_HOST:         Linux
291 DYN_LIB_EXT:         so
292 LIBUSB_CFLAGS:       -I/usr/include/libusb-1.0
293 LIBUSB_LIBS:         -lusb-1.0
294 SYMBOL_VISIBILITY:   -fvisibility=hidden
295 NOCLASS:
296
297 libusb support:          yes
298 composite as multislot:  no
299 multi threading:         yes
300 bundle directory name:   ifd-ccid.bundle
301 USB drop directory:      /home/phablet/myRoot/usr/local/lib/pcsc/drivers
302 serial Twin support:     no
303 serial twin install dir: /home/phablet/myRoot/usr/local/lib/pcsc/drivers/serial
304 serial config directory: /home/phablet/myRoot/etc/reader.conf.d
305 compiled for pcsc-lite:  yes
306 syslog debug:            no
307 class driver:            yes
308
309 ...
310
311 phablet@ubuntu-phablet:~/ccid-1.4.25$ make
312 phablet@ubuntu-phablet:~/ccid-1.4.25$ sudo make install
313 #+end_src
314
315 the driver ~libccid.so~ and its control file ~Info.plist~ ended up as configured in:
316
317 #+begin_src sh
318 phablet@ubuntu-phablet:~$ find /home/phablet/myRoot/usr/local/lib/pcsc/drivers/ifd-ccid.bundle/Contents/
319 /home/phablet/myRoot/usr/local/lib/pcsc/drivers/ifd-ccid.bundle/Contents/
320 /home/phablet/myRoot/usr/local/lib/pcsc/drivers/ifd-ccid.bundle/Contents/Linux
321 /home/phablet/myRoot/usr/local/lib/pcsc/drivers/ifd-ccid.bundle/Contents/Linux/libccid.so
322 /home/phablet/myRoot/usr/local/lib/pcsc/drivers/ifd-ccid.bundle/Contents/Info.plist
323 #+end_src
324
325 This is fine,
326 but if we run the daemon from outside the chroot'ed system, the files must be in
327 some other place because ~/home/phablet/myRoot~ is added in front; so
328 we copy them over to the correct place:
329
330 #+begin_src sh
331 phablet@ubuntu-phablet:~$ sudo mkdir -p /usr/local/lib/pcsc/drivers/ifd-ccid.bundle
332 phablet@ubuntu-phablet:~$ sudo cp -rp /home/phablet/myRoot/usr/local/lib/pcsc/drivers/ifd-ccid.bundle/Contents /usr/local/lib/pcsc/drivers/ifd-ccid.bundle
333 phablet@ubuntu-phablet:~$ find /usr/local/lib/pcsc/drivers/ifd-ccid.bundle
334 /usr/local/lib/pcsc/drivers/ifd-ccid.bundle
335 /usr/local/lib/pcsc/drivers/ifd-ccid.bundle/Contents
336 /usr/local/lib/pcsc/drivers/ifd-ccid.bundle/Contents/Linux
337 /usr/local/lib/pcsc/drivers/ifd-ccid.bundle/Contents/Linux/libccid.so
338 /usr/local/lib/pcsc/drivers/ifd-ccid.bundle/Contents/Info.plist
339 #+end_src
340
341 From outside the chroot'ed system we can now start the daemon as:
342
343 #+begin_src sh
344 $ sudo /home/phablet/myRoot/usr/local/sbin/pcscd --foreground --debug | tee pcscd.log
345 #+end_src
346
347 and check the log file ~pcscd.log~ to see if it sees the card attaching (see at the very
348 end of the write-up);
349
350 Now we start in the phone the pcscd daemon as:
351
352 #+begin_src sh
353 $ sudo /home/phablet/myRoot/usr/local/sbin/pcscd
354 $ ps ax | grep pcscd
355 31669 pts/53   Sl     0:00 /home/phablet/myRoot/usr/local/sbin/pcscd
356 #+end_src
357
358 and run the gpg --card-status to see if it finds the card on attach:
359
360 #+begin_src sh
361 $ ./gpg.sh --card-status
362 gpg-agent[20254]: enabled debug flags: mpi crypto memory cache memstat hashing ipc
363 gpg-agent: a gpg-agent is already running - not starting a new one
364 gpg-agent: random usage: poolsize=600 mixed=0 polls=0/0 added=0/0
365               outmix=0 getlvl1=0/0 getlvl2=0/0
366 gpg-agent: secmem usage: 0/32768 bytes in 0 blocks
367 Reader ...........: Identiv uTrust 3512 SAM slot Token [CCID Interface] (55511514602745) 00 00
368 Application ID ...: D27600012401020100050000532B0000
369 Version ..........: 2.1
370 Manufacturer .....: ZeitControl
371 Serial number ....: 0000532B
372 Name of cardholder: Matthias Apitz
373 Language prefs ...: en
374 Sex ..............: unspecified
375 URL of public key : http://www.unixarea.de/ccid--export-key-guru.pub
376 Login data .......: [not set]
377 Signature PIN ....: not forced
378 Key attributes ...: rsa4096 rsa4096 rsa4096
379 Max. PIN lengths .: 32 32 32
380 PIN retry counter : 3 0 3
381 Signature counter : 457
382 Signature key ....: 5E69 FBAC 1618 562C B3CB  FBC1 47CC F7E4 76FE 9D11
383       created ....: 2017-05-14 18:20:07
384 Encryption key....: EB62 00DA 13A1 9E80 679B  1A13 61F1 ECB6 25C9 A6C3
385       created ....: 2017-05-14 18:20:07
386 Authentication key: E51D D2D6 C727 35D6 651D  EA4B 6AA5 C5C4 51A1 CD1C
387       created ....: 2017-05-14 18:20:07
388 General key info..: [none]
389 #+end_src
390
391
392 Now we removed ~/home/phablet/.gnupg~ (saving the ~*.conf~ files) and copied over from my
393 real netbook the ~/.password-store~ and the key material for the
394 OpenPGP card;
395 let's see if 'pass' can unlock the card (via the gpg-agent) and decipher the
396 crypted information (uncrypted shown here as ~XXXXXXXX-XXXXXX~). The ~gpg-agent~
397 will first ask for the card to be inserted and then for its PIN.
398
399 #+begin_src sh
400 $ ./pass.sh askubuntu.com/guru@unixarea.de
401 #+end_src
402
403 #+html: <div class="figure-left">
404 #+CAPTION: The request for the card
405 #+ATTR_HTML: :class center :style max-width: 400px
406 [[file:img/gnupg-card-insert-card.png]]
407
408 #+html: </div>
409 #+html: <p style="clear: both"/>
410
411 #+html: <div class="figure-left">
412 #+CAPTION: The request for the PIN
413 #+ATTR_HTML: :class center :style max-width: 400px
414 [[file:img/gnupg-card-insert-pin.png]]
415
416 #+html: </div>
417 #+html: <p style="clear: both"/>
418
419 #+begin_src sh
420 XXXXXXXX-XXXXXX
421 $
422 #+end_src
423
424
425 on the 2nd run it does not need anymore the PIN:
426
427 #+begin_src sh
428 $ ./pass.sh askubuntu.com/guru@unixarea.de
429 XXXXXXXX-XXXXXX
430 #+end_src
431
432 i.e. all is fine!
433
434
435 This is only the debug log of the pcscd daemon for reference.
436
437 #+begin_example
438 00000000 debuglog.c:289:DebugLogSetLevel() debug level=debug
439 00001760 configfile.l:282:DBGetReaderListDir() Parsing conf directory: /home/phablet/myRoot/etc/reader.conf.d
440 00000840 configfile.l:319:DBGetReaderListDir() Skipping non regular file: .
441 00000349 configfile.l:319:DBGetReaderListDir() Skipping non regular file: ..
442 00000364 configfile.l:358:DBGetReaderList() Parsing conf file: /home/phablet/myRoot/etc/reader.conf.d/libccidtwin
443 00000568 pcscdaemon.c:655:main() pcsc-lite 1.8.20 daemon ready.
444 00007279 hotplug_libudev.c:294:get_driver() Looking for a driver for VID: 0x1D6B, PID: 0x0002, path: /dev/bus/usb/001/001
445 07475463 hotplug_libudev.c:648:HPEstablishUSBNotifications() USB Device add
446 00005501 hotplug_libudev.c:294:get_driver() Looking for a driver for VID: 0x04E6, PID: 0x5816, path: /dev/bus/usb/001/009
447 00000555 hotplug_libudev.c:433:HPAddDevice() Adding USB device: Identiv uTrust 3512 SAM slot Token
448 00000673 readerfactory.c:1079:RFInitializeReader() Attempting startup of Identiv uTrust 3512 SAM slot Token [CCID Interface] (55511514602745) 00 00 using /home/phablet/myRoot/usr/local/lib/pcsc/drivers/ifd-ccid.bundle/Contents/Linux/libccid.so
449 00001129 readerfactory.c:954:RFBindFunctions() Loading IFD Handler 3.0
450 00013183 ifdhandler.c:1953:init_driver() Driver version: 1.4.25
451 00004027 ifdhandler.c:1970:init_driver() LogLevel: 0x0003
452 00004427 ifdhandler.c:1981:init_driver() DriverOptions: 0x0000
453 00001127 ifdhandler.c:110:CreateChannelByNameOrChannel() Lun: 0, device: usb:04e6/5816:libudev:0:/dev/bus/usb/001/009
454 00001212 ccid_usb.c:287:OpenUSBByName() Using: /home/phablet/myRoot/usr/local/lib/pcsc/drivers/ifd-ccid.bundle/Contents/Info.plist
455 00005565 ccid_usb.c:305:OpenUSBByName() ifdManufacturerString: Ludovic Rousseau (ludovic.rousseau@free.fr)
456 00001479 ccid_usb.c:306:OpenUSBByName() ifdProductString: Generic CCID driver
457 00000362 ccid_usb.c:307:OpenUSBByName() Copyright: This driver is protected by terms of the GNU Lesser General Public License version 2.1, or (at your option) any later version.
458 00003937 ccid_usb.c:621:OpenUSBByName() Found Vendor/Product: 04E6/5816 (Identiv uTrust 3512 SAM slot Token)
459 00000667 ccid_usb.c:623:OpenUSBByName() Using USB bus/device: 1/9
460 00000337 ccid_usb.c:680:OpenUSBByName() bNumDataRatesSupported is 0
461 00010195 ifdhandler.c:379:IFDHGetCapabilities() tag: 0xFB3, usb:04e6/5816:libudev:0:/dev/bus/usb/001/009 (lun: 0)
462 00000626 readerfactory.c:395:RFAddReader() Using the reader polling thread
463 00000838 ifdhandler.c:379:IFDHGetCapabilities() tag: 0xFAE, usb:04e6/5816:libudev:0:/dev/bus/usb/001/009 (lun: 0)
464 00000470 ifdhandler.c:470:IFDHGetCapabilities() Reader supports 1 slot(s)
465 00001264 ifdhandler.c:1146:IFDHPowerICC() action: PowerUp, usb:04e6/5816:libudev:0:/dev/bus/usb/001/009 (lun: 0)
466 00032378 eventhandler.c:286:EHStatusHandlerThread() powerState: POWER_STATE_POWERED
467 00000596 Card ATR: 3B DA 18 FF 81 B1 FE 75 1F 03 00 31 C5 73 C0 01 40 00 90 00 0C
468 05001478 ifdhandler.c:1146:IFDHPowerICC() action: PowerDown, usb:04e6/5816:libudev:0:/dev/bus/usb/001/009 (lun: 0)
469 00003148 eventhandler.c:479:EHStatusHandlerThread() powerState: POWER_STATE_UNPOWERED
470 14774363 hotplug_libudev.c:642:HPEstablishUSBNotifications() USB Device removed
471 00000796 hotplug_libudev.c:360:HPRemoveDevice() Removing USB device[0]: Identiv uTrust 3512 SAM slot Token [CCID Interface] (55511514602745) at /dev/bus/usb/001/009
472 00000053 readerfactory.c:608:RFRemoveReader() UnrefReader() count was: 1
473 00000024 eventhandler.c:176:EHDestroyEventHandler() Stomping thread.
474 00000026 ifdhandler.c:379:IFDHGetCapabilities() tag: 0xFB1, usb:04e6/5816:libudev:0:/dev/bus/usb/001/009 (lun: 0)
475 00000024 ifdhandler.c:379:IFDHGetCapabilities() tag: 0xFB2, usb:04e6/5816:libudev:0:/dev/bus/usb/001/009 (lun: 0)
476 00000018 eventhandler.c:201:EHDestroyEventHandler() Request stopping of polling thread
477 00000020 ifdhandler.c:344:IFDHStopPolling() usb:04e6/5816:libudev:0:/dev/bus/usb/001/009 (lun: 0)
478 00397726 eventhandler.c:502:EHStatusHandlerThread() Die
479 00001909 eventhandler.c:216:EHDestroyEventHandler() Thread stomped.
480 00000049 readerfactory.c:1130:RFUnInitializeReader() Attempting shutdown of Identiv uTrust 3512 SAM slot Token [CCID Interface] (55511514602745) 00 00.
481 00000039 ifdhandler.c:282:IFDHCloseChannel() usb:04e6/5816:libudev:0:/dev/bus/usb/001/009 (lun: 0)
482 00000101 ccid_usb.c:797:WriteUSB() write failed (1/9): -4 LIBUSB_ERROR_NO_DEVICE
483 00000147 ccid_usb.c:189:close_libusb_if_needed() libusb_exit
484 00001864 readerfactory.c:991:RFUnloadReader() Unloading reader driver.
485 #+end_example