Proof of concept WebUSB based Interface Device (IFD) handler for USB based Chip Card Interface Device(s) (CCID).
To run the demo, host a (simple) web server and access it with a WebUSB compatible Browser, e.g. Chromium (based) >= 61, and a (WebUSB compatible) CCID/reader (see requirements).
+--Chromium (based) browser---+ +--> WebSocketServer.py
|-----------------------------| | (send GET CHALLENGE and
| | | output the cards result)
| demo.html +--WebSocket---+
| | | +--> WebSocketServerVICC.py
+---------------------|-------+ | (make card available via PC/SC
+-----+ +--------+ | | | | on server in virtual reader)
|Smart|<-->|USB CCID| <--WebUSB----> ifd.js <-----+ | |
|Card | |Reader | | | +--> WebSocketServerPACE.py
+-----+ +--------+ +-----------------------------+ (generate APDUs to
establish a PACE channel)
If your CCID is WebUSB compatible, you should be able to use it out of the box. In doubt, try to make it accessible using the instructions for non-WebUSB CCIDs below.
Making a traditional, non-WebUSB CCID available to WebUSB requires operating system specific actions. As of April 2018 (Chromium Build > 546309, version 67.0.3382.0) those readers are blocked for security reasons by their respective USB interface class (0x0B). If they use a different interface class, not one of [0x01,0x03,0x08,0x0B,0x0E,0x10,0xE0], they can still be made available using instructions below. Otherwise, for debugging, you can use an old Chromium Snapshot e.g. 546309 for Linux x64. To use non-WebUSB readers in production, it may be a better idea to provide a proxy WebUSB driver, which forwards messages to the hardware and does necessary security (origin) checks. Or opt for a browser extension (not plugin) approach to access respective native components.
/etc/udev/rules.d/50-Identiv-4700F.rules
and adding your user to the plugdev
group in etc/group
. A generic rule for (specific) WebUSB devices could be added to the udev project.
SUBSYSTEM=="usb", ATTR{idVendor}=="04e6", ATTR{idProduct}=="5720", GROUP="plugdev"
Vendor Id and Product Id of your CCID can be identified using lsusb
command.
Once your WebUSB device is available for the browser, in user space, you can follow the instructions to get the demos up and running. You need to enable SSL/TLS encryption, if you want to host the server on a different machine. SSL/TLS encryption is left off for debugging.
python3 HttpServer.py
)http://localhost:8000/demo.html
in Chromium/Chrome00 84 00 00 00 00 01
)setup.py
, see WebSocketServer.py
.00 84 00 00 00 00 01
)python3 WebSocketServer.py
setup.py
or manually, see WebSockerServerVICC.py
.python3 WebSocketServerVICC.py
Note: I included vicc-vpcdHost.py
, an example vpcd and app. You need Virtualsmartcard's Python files, either from the install above or manually downloaded, see setup.py
.
setup.py
, see WebSocketServerPACE.py
.python3 WebSocketServerPACE.py
Note: It is a bad idea to hand out your authentication token and its secret to a website. Compared to giving away your email address and password, you give away a stronger authentication proof of ownership of a physical device. Vervier and Orru presented a closed vulnerability of U2F tokens in combination with WebUSB, whereby the user is tricked into allowing access to his security token via WebUSB by a similar looking phishing website.
In case of the nPA, EAC (Extended Access Control) is required to access the passport's data. If the PIN instead of CAN is used as password, an attacker can use it to authenticate on your behalf at a legitimate party. He can also change the PIN. This example can be seen as a demonstration of how easier access increases the attack surface and thus the security risk associated.
Generally speaking, without technical understanding it is hard for users to distinguish a secure input method from an insecure. For example, why is it secure to enter the PIN to a security token in a browser extension, but not inside the website? Maybe browsers will implement some form of secure input method, that cannot be replicated inside a website. Perhaps by adding to the <input>
element in a similar fashion, a file has to be selected using a distinguishable, native element. Or anchored somewhere in the user interface, outside the rendering area of the website. For now, a browser extension does the job of providing such an input method. Or you own an advanced CCID, that provides a hardware PIN pad and transaction display. Which also protects against malicious software on the user's system.
See Pace.md for an overview of the PCD's implementation of the PACE protocol.
Electron provides a Chromium based framework to build native applications for Linux, Mac, and Windows. If Chromium >= 61 and <= 67 is used, it supports WebUSB. Once started (npm start
), navigator.usb
should be available in the included developer console (Ctrl+Shift+I).
Be aware that WebUSB forwards your local USB device into the browser context whose security context is the origin (protocol, host, port) of the visited website. This means once you allow a USB device using the WebUSB Browser dialog, the website's scripts can run arbitrary USB commands on your local device. In the case of a WebUSB device that is designed to operate under these conditions it's fine. Classic USB devices on the other hand were not intended to be used remote as with WebUSB and (function) abstraction layers like driver, library, and application aren't present anymore. As a result the web application host serving the web application can use USB functions of the device, which may be flash(newFirmware) or deleteSomethingImportant() [BadUSB]. In case of authentication, a website may use your (allowed) USB token as man-in-the-middle to authenticate on your behalf somewhere else. This can be recognized by the user, if the hardware token itself displays transaction information, and denied, if it has hardware based confirmation.
I implemented the CCID interface device (ifd) handler in JavaScript using the WebUSB API to allow (progressive) web applications direct access to the hardware token. I could have forwarded all WebUSB communication to a remote party, which then handles the WebUSB device. The included forwarding examples proxy the hardware token on its apdu level via WebSocket to the remote party.
This is currently a side project, I occasionally work on in my spare time.
Since this project was only possible because of my work on my diploma thesis, a special thanks goes out to my two advisors for all the consultations, time, and effort. During that time I was supported by my alma mater, Humboldt-Universität zu Berlin (Humboldt University of Berlin), and Bundesdruckerei GmbH ("Federal Printing Office").