OpenPGP card: Waiting for the first reader

I have inserted and configured the OpenPGP card es described here:

$ cat guru/OpenPGP.txt 

https://puri.sm/posts/openpgp-in-your-pocket/
(includes video about inserting the card)

https://source.puri.sm/angus.ainslie/ttxs-firmware/-/blob/purism/PURISM.md

install and get the software:

sudo apt install stm32flash git
git clone https://source.puri.sm/angus.ainslie/ttxs-firmware

cd ttxs-firmware

Upgrade the smart card reader firmware:

./scripts/stm_reflash.sh

And set up the smart card:

./scripts/smartcard_setup.sh

When I now run the test pcsc_scan it only says:

purism@pureos:~$ pcsc_scan
Using reader plug'n play mechanism
Scanning present readers...
Waiting for the first reader... |   

UPDATE:

When I now run the flash of the firmware again, it says:

+ sleep 1
+ sudo stm32flash -w /tmp/tmp.DQD29pKyIC/ttxs.bin /dev/ttymxc2
stm32flash 0.5

http://stm32flash.sourceforge.net/

Using Parser : Raw BINARY
Interface serial_posix: 57600 8E1
Failed to read ACK byte
...

In addition: I have here the low level dialog of the flash tool with the card captured with strace:

openat(AT_FDCWD, "/dev/ttymxc2", O_RDWR|O_NOCTTY|O_NONBLOCK) = 5
fcntl(5, F_SETLK, {l_type=F_WRLCK, l_whence=SEEK_CUR, l_start=0, l_len=0}) = 0
fcntl(5, F_SETFL, O_RDONLY)             = 0
ioctl(5, TCGETS, {B115200 -opost -isig -icanon -echo ...}) = 0
ioctl(5, TCGETS, {B115200 -opost -isig -icanon -echo ...}) = 0
ioctl(5, TCGETS, {B115200 -opost -isig -icanon -echo ...}) = 0
ioctl(5, TCFLSH, TCIFLUSH)              = 0
ioctl(5, TCGETS, {B115200 -opost -isig -icanon -echo ...}) = 0
ioctl(5, SNDCTL_TMR_START or TCSETS, {B57600 -opost -isig -icanon -echo ...}) = 0
ioctl(5, TCGETS, {B57600 -opost -isig -icanon -echo ...}) = 0
ioctl(5, TCGETS, {B57600 -opost -isig -icanon -echo ...}) = 0
write(1, "Interface serial_posix: 57600 8E"..., 34) = 34
ioctl(5, TCFLSH, TCIFLUSH)              = 0
write(5, "\177", 1)                     = 1
read(5, "y", 1)                         = 1
write(5, "\1\376", 2)                   = 2
read(5, "y", 1)                         = 1
read(5, "\0", 3)                        = 1
read(5, "\0", 2)                        = 1
read(5, "\0", 1)                        = 1
read(5, "", 1)                          = 0
write(2, "Failed to read ACK byte\n", 24) = 24
close(4)                                = 0

If I pullout the OpenPG card and reboot the L5 without the card, the flashing works fine.

./scripts/stm_reflash.sh

...
stm32flash 0.5

http://stm32flash.sourceforge.net/

Using Parser : Raw BINARY
Interface serial_posix: 57600 8E1
Version      : 0x31
Option 1     : 0x00
Option 2     : 0x00
Device ID    : 0x0435 (STM32L43xxx/44xxx)
- RAM        : Up to 48KiB  (12544b reserved by bootloader)
- Flash      : Up to 256KiB (size first sector: 1x2048)

- Option RAM : 16b
- System RAM : 28KiB
Write to memory
Erasing memory
Wrote address 0x08002388 (100.00%) Done.

The card later after insert and reboot does not work. I restarted the pccard from shell: it can not initialize the card through the /dev/ttymxc2 device file.

Maybe the card is broken. I’ve got it together with my L5 and inserted it correctly and for the very first time.

@angus.ainslie ^^^^

So something has broken this since Sep 29. I’m looking into the kernel changes now.

I got it working once starting the daemon from shell:

Last login: Fri Oct 29 19:14:29 2021 from 192.168.178.39

purism@pureos:~$ sudo pcscd -f --debug &

purism@pureos:~$ gpg --card-status
Reader ...........: TTXS serial 00 00
Application ID ...: D27600012401030400050000A6FE0000
Application type .: OpenPGP
Version ..........: 3.4
Manufacturer .....: ZeitControl
Serial number ....: 0000A6FE
Name of cardholder: [not set]
Language prefs ...: de
Salutation .......:
URL of public key : [not set]
Login data .......: [not set]
Signature PIN ....: forced
Key attributes ...: rsa2048 rsa2048 rsa2048
Max. PIN lengths .: 64 64 64
PIN retry counter : 3 0 3
Signature counter : 0
KDF setting ......: off
Signature key ....: [none]
Encryption key....: [none]
Authentication key: [none]
General key info..: [none]


purism@pureos:~$ pcsc_scan
Using reader plug'n play mechanism
Scanning present readers...
0: TTXS serial 00 00
1: TTXS serial 00 01


Fri Oct 29 19:27:10 2021
 Reader 0: TTXS serial 00 00
  Event number: 0
  Card state: Card inserted, Exclusive Mode,
  ATR: 3B DA 18 FF 81 B1 FE 75 1F 03 00 31 F5 73 C0 01 60 00 90 00 1C

ATR: 3B DA 18 FF 81 B1 FE 75 1F 03 00 31 F5 73 C0 01 60 00 90 00 1C
+ TS = 3B --> Direct Convention
+ T0 = DA, Y(1): 1101, K: 10 (historical bytes)
  TA(1) = 18 --> Fi=372, Di=12, 31 cycles/ETU
    129032 bits/s at 4 MHz, fMax for Fi = 5 MHz => 161290 bits/s
  TC(1) = FF --> Extra guard time: 255 (special value)
  TD(1) = 81 --> Y(i+1) = 1000, Protocol T = 1
-----
  TD(2) = B1 --> Y(i+1) = 1011, Protocol T = 1
-----
  TA(3) = FE --> IFSC: 254
  TB(3) = 75 --> Block Waiting Integer: 7 - Character Waiting Integer: 5
  TD(3) = 1F --> Y(i+1) = 0001, Protocol T = 15 - Global interface bytes following
-----
  TA(4) = 03 --> Clock stop: not supported - Class accepted by the card: (3G) A 5V B 3V
+ Historical bytes: 00 31 F5 73 C0 01 60 00 90 00
  Category indicator byte: 00 (compact TLV data object)
    Tag: 3, len: 1 (card service data byte)
      Card service data byte: F5
        - Application selection: by full DF name
        - Application selection: by partial DF name
        - BER-TLV data objects available in EF.DIR
        - BER-TLV data objects available in EF.ATR
        - EF.DIR and EF.ATR access services: by GET DATA command
        - Card without MF
    Tag: 7, len: 3 (card capabilities)
      Selection methods: C0
        - DF selection by full DF name
        - DF selection by partial DF name
      Data coding byte: 01
        - Behaviour of write functions: one-time write
        - Value 'FF' for the first byte of BER-TLV tag fields: invalid
        - Data unit in quartets: 2
      Command chaining, length fields and logical channels: 60
        - Extended Lc and Le fields
        - RFU (should not happen)
        - Logical channel number assignment: No logical channel
        - Maximum number of logical channels: 1
    Mandatory status indicator (3 last bytes)
      LCS (life card cycle): 00 (No information given)
      SW: 9000 (Normal processing.)
+ TCK = 1C (correct checksum)

Possibly identified card (using /usr/share/pcsc/smartcard_list.txt):
3B DA 18 FF 81 B1 FE 75 1F 03 00 31 F5 73 C0 01 60 00 90 00 1C
	OpenPGP Card V3
 Reader 1: TTXS serial 00 01
  Event number: 0
  Card state: Card inserted, Unresponsive card,
 /
purism@pureos:~$
purism@pureos:~$ gpg --card-status
Reader ...........: TTXS serial 00 00
Application ID ...: D27600012401030400050000A6FE0000
Application type .: OpenPGP
Version ..........: 3.4
Manufacturer .....: ZeitControl
Serial number ....: 0000A6FE
Name of cardholder: [not set]
Language prefs ...: de
Salutation .......:
URL of public key : [not set]
Login data .......: [not set]
Signature PIN ....: forced
Key attributes ...: rsa2048 rsa2048 rsa2048
Max. PIN lengths .: 64 64 64
PIN retry counter : 3 0 3
Signature counter : 0
KDF setting ......: off
Signature key ....: [none]
Encryption key....: [none]
Authentication key: [none]
General key info..: [none]
purism@pureos:~$ gpg --card-status
Reader ...........: TTXS serial 00 00
Application ID ...: D27600012401030400050000A6FE0000
Application type .: OpenPGP
Version ..........: 3.4
Manufacturer .....: ZeitControl
Serial number ....: 0000A6FE
Name of cardholder: [not set]
Language prefs ...: de
Salutation .......:
URL of public key : [not set]
Login data .......: [not set]
Signature PIN ....: forced
Key attributes ...: rsa2048 rsa2048 rsa2048
Max. PIN lengths .: 64 64 64
PIN retry counter : 3 0 3
Signature counter : 0
KDF setting ......: off
Signature key ....: [none]
Encryption key....: [none]
Authentication key: [none]
General key info..: [none]

But now the daemon always can’t open the device saying:

...
00000021 ifdhandler.c:2053:init_driver() DriverOptions: 0x0000
00000621 ifdhandler.c:110:CreateChannelByNameOrChannel() Lun: 0, device: /dev/ttymxc2
00000227 ccid_serial.c:838:OpenSerialByName() Set serial port baudrate to 115200 and correct configuration
02002721 ccid_serial.c:864:OpenSerialByName() Get firmware failed. Maybe the reader is not connected
00000432 ifdhandler.c:160:CreateChannelByNameOrChannel() failed
00000017 readerfactory.c:1120:RFInitializeReader() Open Port 0x0 Failed (/dev/ttymxc2)
00000011 readerfactory.c:380:RFAddReader() TTXS serial init failed.

I tried to figure out, even by looking into the driver code


what could go wrong during initializing the card. At the end I did:
# stty -F /dev/ttymxc2 raw cstopb -parenb cs8 115200
# pcscd -f --debug

and after this pcscd could work with the card and a gpg --card-status was happy as well.

It works now even across a reboot. Don’t know why. Will watch further and at the end I could insert the above stty ... in /lib/systemd/system/pcscd.service in the ExecStartPre= ... commands.

2 Likes

See also my comment in https://source.puri.sm/Librem5/OS-issues/-/issues/119 why we use pcscd at all for accessing the card?

Since the yesterday (March 22, 2022) kernel update the problem returned:

stm32flash 0.5

http://stm32flash.sourceforge.net/

Using Parser : Raw BINARY
Interface serial_posix: 57600 8E1
Failed to read ACK byte

Please help, I need my OpenPGP card.

UPDATE
When I pull out the OpenPGP card, the flashing works:

+ sudo stm32flash -w /tmp/tmp.QezcW7s9E6/ttxs.bin /dev/ttymxc2
stm32flash 0.5

http://stm32flash.sourceforge.net/

Using Parser : Raw BINARY
Interface serial_posix: 57600 8E1
Version      : 0x31
Option 1     : 0x00
Option 2     : 0x00
Device ID    : 0x0435 (STM32L43xxx/44xxx)
- RAM        : Up to 48KiB  (12544b reserved by bootloader)
- Flash      : Up to 256KiB (size first sector: 1x2048)
- Option RAM : 16b
- System RAM : 28KiB
Write to memory
Erasing memory
Wrote address 0x08002388 (100.00%) Done.

But the pcscd can’t open the reader (with the card inserted again):

sudo pcscd -f --debug
00000000 debuglog.c:299:DebugLogSetLevel() debug level=debug
00000135 utils.c:81:GetDaemonPid() Can't open /run/pcscd/pcscd.pid: No such file or directory
00000288 configfile.l:293:DBGetReaderListDir() Parsing conf directory: /etc/reader.conf.d
00000053 configfile.l:329:DBGetReaderListDir() Skipping non regular file: ..
00000011 configfile.l:369:DBGetReaderList() Parsing conf file: /etc/reader.conf.d/libccidtwin
00000085 configfile.l:210:evaluatetoken() Add reader: TTXS serial
00000029 configfile.l:329:DBGetReaderListDir() Skipping non regular file: .
00000013 configfile.l:369:DBGetReaderList() Parsing conf file: /etc/reader.conf.d/libccidtwin.bak
00000111 configfile.l:369:DBGetReaderList() Parsing conf file: /etc/reader.conf.d/librem5
00000052 configfile.l:210:evaluatetoken() Add reader: TTXS serial
00000044 readerfactory.c:1079:RFInitializeReader() Attempting startup of TTXS serial 00 00 using /usr/lib/pcsc/drivers/serial/libccidtwin.so
00000239 readerfactory.c:954:RFBindFunctions() Loading IFD Handler 3.0
00000051 ifdhandler.c:2025:init_driver() Driver version: 1.4.34
00002272 ifdhandler.c:2042:init_driver() LogLevel: 0x0003
00000019 ifdhandler.c:2053:init_driver() DriverOptions: 0x0000
00000639 ifdhandler.c:110:CreateChannelByNameOrChannel() Lun: 0, device: /dev/ttymxc2:SEC1210
00000227 ccid_serial.c:838:OpenSerialByName() Set serial port baudrate to 115200 and correct configuration
02002645 ccid_serial.c:864:OpenSerialByName() Get firmware failed. Maybe the reader is not connected
00000172 ifdhandler.c:160:CreateChannelByNameOrChannel() failed
00000020 readerfactory.c:1120:RFInitializeReader() Open Port 0x0 Failed (/dev/ttymxc2)
00000013 readerfactory.c:380:RFAddReader() TTXS serial init failed.

What’s happening on the sys call level is: the pcscd opens the device successfully, writes 14 bytes and awaits a response within 2 secs which does not appear:

openat(AT_FDCWD, "/dev/ttymxc2", O_RDWR|O_NOCTTY) = 5
ioctl(5, TIOCMGET, [TIOCM_DTR|TIOCM_RTS|TIOCM_CAR|TIOCM_DSR]) = 0
ioctl(5, TIOCMSET, [TIOCM_DTR|TIOCM_CAR|TIOCM_DSR]) = 0
ioctl(5, TCFLSH, TCIOFLUSH)             = 0
ioctl(5, TCGETS, {B115200 -opost -isig -icanon -echo ...}) = 0
ioctl(5, TCGETS, {B115200 -opost -isig -icanon -echo ...}) = 0
ioctl(5, SNDCTL_TMR_START or TCSETS, {B115200 -opost -isig -icanon -echo ...}) = 0
ioctl(5, TCGETS, {B115200 -opost -isig -icanon -echo ...}) = 0
write(5, "\3\6k\1\0\0\0\0\0\0\0\0\6i", 14) = 14
pselect6(6, [5], NULL, NULL, {tv_sec=2, tv_nsec=0}, NULL) = 0 (Timeout)

Are there any changes in the kernel
-rw-r--r-- 1 root root 65262818 Mar 22 10:33 initrd.img-5.16.0-1-librem5
?

2 Likes

You don’t need to flash the reader every time, it’s a one time operation.

Since the latest update, the smartcard reader is configured automatically out-of-box. However, this can conflict with manual configuration if you done it previously, so you should remove the lines you’ve added earlier in /etc/reader.conf.d/libccidtwin.

3 Likes

I hoped that flashing the reader (with a newer sw) would solve the failing OpenPGP card, which did not helped. It seems that renaming the file /etc/reader.conf.d/libccidtwin to /etc/reader.conf.d/libccidtwin.away solved it.
Should I put the file as empty in place again?

Yeah, by default this file only contains a bunch of comments.

The file I renamed to /etc/reader.conf.d/libccidtwin.away only contained these three lines:

purism@pureos:~$ cat /etc/reader.conf.d/libccidtwin.away 
DEVICENAME        /dev/ttymxc2:SEC1210
FRIENDLYNAME      "TTXS serial"
LIBPATH           /usr/lib/pcsc/drivers/serial/libccidtwin.so

Yeah, that’s what the old instructions tell you to edit it to. For the reference, the original content of this file is:

# Gemalto reader with serial communication
#  - n is the serial port to use n in [0..3]
#  - reader is the reader name. It is needed for multi-slot readers.
#    Possible reader values are: 
#     GemCorePOSPro
#     GemCoreSIMPro
#     GemCoreSIMPro2
#     GemPCPinPad
#     GemPCTwin (default value)
#     SEC1210 (Dual slot Reader)
# example: /dev/ttyS0:GemPCPinPad
#DEVICENAME        /dev/ttySn[:reader]
#FRIENDLYNAME      "GemPCTwin serial"
#LIBPATH           /usr/lib/pcsc/drivers/serial/libccidtwin.so

so, since it’s only comments, leaving it empty is fine too.

It remains unreliable. From one moment to the other, without changing anything it says now:

purism@pureos:~$ ps ax | grep pcs
   1843 ?        Ssl    0:00 /usr/sbin/pcscd --foreground --auto-exit
   1854 pts/0    S+     0:00 grep pcs
purism@pureos:~$ gpg --card-status
gpg: selecting card failed: No such device
gpg: OpenPGP card not available: No such device

Please advice, how to debug this.

That doesn’t seem true, though.
I flashed my L5 when I got it. That was Feb 22.
And after the recent upgrades I had to reflash again, because, again, it was not finding the card.
Now it works again.

-H

There is a pitfall. While debugging pcscd with strace I saw that the daemon opens the directory /etc/reader.conf.d and then reads any file it is seeing there:

purism@pureos:~$ grep reader.conf.d pcscd.tr
openat(AT_FDCWD, "/etc/reader.conf.d", O_RDONLY|O_NONBLOCK|O_CLOEXEC|O_DIRECTORY) = 5
openat(AT_FDCWD, "/etc/reader.conf.d/libccidtwin.away", O_RDONLY) = 6
openat(AT_FDCWD, "/etc/reader.conf.d/librem5", O_RDONLY) = 6

Ofc, this is not Purism’s fault, it’s just how pcscd was written and one mus be aware of this. One has to remove the file or move it elsewhere, and not just rename it, as I did.

1 Like

I got same problems here, because i already flashed the gpg controller and configured before. I fixed now by removing all the lines on /etc/reader.conf.d/libccidtwin.
Thank you dos it working good again.

There is some more info here.
So I had a L5 sitting here which had no update since mid March.
In /etc/reader.conf.d were

- libccidtwin
- libccidtwin.bak

and gpg --card-status
would just work fine
Then I update the system with the recent updates.
part of the update was the new file

/etc/reader.conf.d/librem5

but gpg --card-status would now return

gpg: selecting card failed: No such device
gpg: OpenPGP card not available: No such device

I created /etc/reader.save.d
and moved libccidtwin and libccidtwin.bak over there.
Now it all works again.
I do not know which package was responsible for this update. apt-file currently
does not update the cache (but thats a different issue) so I cannot search for
/etc/reader.conf.d/librem5

-H

I think I have the correct configuration and only these files in:

$ ls -l /etc/reader.conf.d/
total 8
-rw-r--r-- 1 root root 719 Mar 24 18:07 libccidtwin
-rw-r--r-- 1 root root 133 Mar 25 07:11 librem5

The file libccidtwin only contains comments.

But, the access to the OpenPGP card is unreliable. This wasn’t before the update on March 22:

purism@pureos:~$ gpg --card-status > /dev/null || echo failed
gpg: OpenPGP card not available: Invalid value
failed
purism@pureos:~$ gpg --card-status > /dev/null || echo failed
purism@pureos:~$ gpg --card-status > /dev/null || echo failed

@guru Delete ‘libccidtwin’ or ‘libccidtwin.bak’ if exist then just leave ‘librem5’ file with this:

DEVICENAME /dev/ttymxc2:SEC1210
FRIENDLYNAME “TTXS serial”
LIBPATH /usr/lib/pcsc/drivers/serial/libccidtwin.so