芯片卡接口设备(CCID)
USB CCID 设备
USB CCID 实现 CCID 规范,允许连接遵循相同规范的智能卡读卡器。规范信息如下:
Universal Serial Bus
Device Class: Smart Card
CCID
Specification for
Integrated Circuit(s) Cards Interface Devices
Revision 1.1
April 22rd, 2005
智能卡用于认证、单点登录、公私钥解密和数字签名。不能简单地将客户端读卡器 USB 直通给客户机,因为客户端将失去设备,甚至因“移除”卡而锁屏。此设备则 允许客户端和客户机同时使用智能卡,也支持不依赖物理设备的完全虚拟读卡器 和智能卡。
构建
密码运算和物理卡访问由 libcacard 完成,构建前需安装开发包。
Red Hat/Fedora:
yum install libcacard-devel
Ubuntu:
apt-get install libcacard-dev
配置并构建:
./configure --enable-smartcard && make
使用 ccid-card-emulated 访问硬件
假定当前主机用户通过 libcacard 可正常使用智能卡,QEMU 可作为另一个客户端:
qemu -usb -device usb-ccid -device ccid-card-emulated
使用 ccid-card-emulated 访问文件证书
先创建 CA 和卡证书,只需一次。这里使用 NSS:
mkdir fake-smartcard
cd fake-smartcard
certutil -N -d sql:$PWD
certutil -S -d sql:$PWD -s "CN=Fake Smart Card CA" -x -t TC,TC,TC -n fake-smartcard-ca
certutil -S -d sql:$PWD -t ,, -s "CN=John Doe" -n id-cert -c fake-smartcard-ca
certutil -S -d sql:$PWD -t ,, -s "CN=John Doe (signing)" --nsCertType smime -n signing-cert -c fake-smartcard-ca
certutil -S -d sql:$PWD -t ,, -s "CN=John Doe (encryption)" --nsCertType sslClient -n encryption-cert -c fake-smartcard-ca
注意,必须恰好有三个卡证书。
使用 certificates 后端:
qemu -usb -device usb-ccid -device ccid-card-emulated,backend=certificates,db=sql:$PWD,cert1=id-cert,cert2=signing-cert,cert3=encryption-cert
要在客户机使用,先导出 CA:
certutil -L -r -d sql:$PWD -o fake-smartcard-ca.cer -n fake-smartcard-ca
再在客户机导入:
certutil -A -d /etc/pki/nssdb -i fake-smartcard-ca.cer -t TC,TC,TC -n fake-smartcard-ca
Linux 客户机可用 CoolKey PKCS #11 模块访问:
certutil -d /etc/pki/nssdb -L -h all
它会请求 PIN,即之前证书数据库的密码,然后显示三个证书及手动导入的 CA:
Certificate Nickname Trust Attributes
fake-smartcard-ca CT,C,C
John Doe:CAC ID Certificate u,u,u
John Doe:CAC Email Signature Certificate u,u,u
John Doe:CAC Email Encryption Certificate u,u,u
若未显示,说明 CoolKey 未安装或未注册到 NSS。可通过 Firefox 或命令行注册:
modutil -dbdir /etc/pki/nssdb -add "CAC Module" -libfile /usr/lib64/pkcs11/libcoolkeypk11.so
modutil -dbdir /etc/pki/nssdb -list
使用 ccid-card-passthru 访问客户端硬件
主机上配置设备及适当 chardev:
qemu -chardev socket,server=on,host=0.0.0.0,port=2001,id=ccid,wait=off \
-usb -device usb-ccid -device ccid-card-passthru,chardev=ccid
客户端运行构建 QEMU 时生成的 vscclient:
vscclient <qemu-host> 2001
使用 ccid-card-passthru 访问客户端证书
这种方式实际用途不大,但可用于调试配置。
按前文准备,随后以下述方式运行 QEMU 和 vscclient。
QEMU 与前述一致,vscclient 在 fake-smartcard 目录运行:
qemu -chardev socket,server=on,host=0.0.0.0,port=2001,id=ccid,wait=off \
-usb -device usb-ccid -device ccid-card-passthru,chardev=ccid
vscclient -e "db=\"sql:$PWD\" use_hw=no soft=(,Test,CAC,,id-cert,signing-cert,encryption-cert)" <qemu-host> 2001
直通协议场景
下面是 passthru 卡的典型消息交互。usb-ccid 是 USB 设备,启动时默认未连接。 它需要 chardev,并通过该通道传输 cac_card/vscard_common.h 定义的协议。 设备有三种状态:
未连接
已连接但无卡
已连接且有卡
典型交互如下,箭头表示由客户端或客户机发起:
client event | vscclient | passthru | usb-ccid | guest event
------------------------------------------------------------------------------------------------
| VSC_Init | | |
| VSC_ReaderAdd | | attach |
| | | | sees new usb device.
card inserted -> | | | |
| VSC_ATR | insert | insert | see new card
| | | |
| VSC_APDU | VSC_APDU | | <- guest sends APDU
client <-> physical | | | |
card APDU exchange | | | |
client response -> | VSC_APDU | VSC_APDU | | receive APDU response
...
[APDU<->APDU repeats several times]
...
card removed -> | | | |
| VSC_CardRemove | remove | remove | card removed
...
[(card insert, apdu's, card remove) repeat]
...
kill/quit | | | |
vscclient | | | |
| VSC_ReaderRemove | | detach |
| | | | usb device removed.
libcacard
ccid-card-emulated 和 vscclient 都使用 libcacard。它实现完全虚拟的 CAC 兼容卡(美国国防部智能卡标准),并用 NSS 获取证书和执行加密。后端可为 真实读卡器和卡,也可为文件中的证书。