WICG / webusb

Connecting hardware to the web.
https://wicg.github.io/webusb/
Other
1.31k stars 130 forks source link

How to handle legacy permissions for FTDI/Prolific/etc USB-Serial interfaces #56

Closed gfwilliams closed 5 years ago

gfwilliams commented 8 years ago

Have you considered what happens with USB-Serial devices like FTDI and Prolific? If FTDI decided to allow access publicly, they would effectively claim ownership of any device that used their chips (or was connected by a cable containing their chips), regardless of whether it was theirs or not? Given their history of bricking counterfeit devices, that's a bit scary.

It works the other way too - many older Arduino boards would be unusable because they use FTDI chips and so have their VID and PID, and FTDI wouldn't want to risk putting another company's URL into allowed origins. It'd be really nice to have some 'advanced' way to override it, perhaps by having the option to specify which 'Public URLs' contained the descriptors for legacy devices.

Also many devices now have a USB DFU bootloader burnt into the device. I'm not saying it should be a 'single click' to enable it (that'd be a security disaster) but it'd be nice for people who knew what they were doing to be able to work around it (if only with chrome://flags/)

Background

I develop Espruino (an Open Source JavaScript interpreter for microcontrollers) and most users have been dependent on the Chrome Serial API via a Chrome app for years - while it works fine now, driver support is always a nightmare and there's no support on Android.

I'm using Web Bluetooth in a new product specifically because of the promise of communication directly from a website. Adding Web USB too would be amazing.

Given the driver issue, I was lazy and have my devices the PID and VID that ST used for the USB CDC examples for the microcontrollers I was using, as they provided a set of drivers that 'just worked' - obviously that would now cause my users problems (unless I can update the firmware to serve up descriptors).

larsgk commented 8 years ago

+1, there needs to be a better solution for legacy devices than a yet to be defined online repo of trusted devices. IMO, it needs to (also) be possible to do it by e.g. system certificate (installed on the machine in question) for offline use - or if the connection to said repo is down for some other reason. My biggest concern is the lack of adoption from larger industry vendors (still using legacy USB chips for comms) who are then forced to go other ways - especially now that Chrome apps are phased out for win/lin/osx.

gfwilliams commented 8 years ago

I'd really like to see an update on this. I have thousands of users, and have sold around 20,000 Espruino-based boards to date - these rely on the Chrome Web App USB support ('Espruino Web IDE' on the Chrome store) but it now looks like that will be going away, and there is currently no solution to replace it.

If I have to build a new native app for USB support on Mac, Windows and Linux, the only loser here will be Chrome OS, which I'll have to drop support for - so you're really shooting yourself in the foot.

beaufortfrancois commented 8 years ago

gentle ping @reillyeon

larsgk commented 8 years ago

@beaufortfrancois @reillyeon Suggestion: Why don't we make and maintain some reference apps in this repo (both Chrome App and WebUSB WebApps) that cover the cases we can think of to move things from speculation to actual code and solution?

A few that come to mind:

  1. Communication with USB-Serial Legacy devices/chips, where it's NOT possible to add WebUSB headers. Offline and online case (it has to work without the online DB/repo of trusted sites available at execution time)
  2. Reference WebUSB addition implementation to arduino, mbed.org, etc. controller code (could be upstreamed eventually for all of these to work out of the box)
  3. ALL should work on Windows 7/8.1/10, OSX and Linux - and we might want to do some collaboration with modemmanager (linux) to let WebUSB compliant devices be blacklisted (not to be grabbed and probed as a potential modem) by default.

more?

gfwilliams commented 8 years ago

+1 - a 'reference' USB CDC implementation for WebUSB would be extremely handy

Wrt upstream changes - there are literally millions boards out there already. Even if they can have firmware updated, it kind of defeats the point if the user has to install a native application in order to perform the update first!

larsgk commented 8 years ago

Slightly offtopic but still related (can someone help me ;)):

To test the current state of things, I tried to get my legacy device (FTDI chip, I assume, VID/PID=0x0483/0x5740) at least listed in a call to navigator.usb.getDevices - but the list keeps turning up empty.

Tried: Windows and Linux, Chrome Stable and Dev + enabled WebUSB & ExperimentalFeatures & added --disable-webusb-security to the command line. On windows, the chrome device-log seems to not add the usbser devices to the "user" list (on linux it seems to do that just fine and fast). Neither system allows me to see them in the usb.getDevices list OR give me any options in the "manage USB devices" in popup (and under settings).

I'd like to help participate in the feedback on this - but need some help to get the ball rolling ;)

BTW: The same hardware works perfectly fine with chrome.serial (same browsers, same machine - just a Chrome App .. ;))

reillyeon commented 8 years ago

Supporting existing USB CDC devices (as well as the proprietary FTDI and other vendor protocols) with WebUSB presents more issues than just getting the devices to return the correct descriptors. There is an Arduino library that presents a modified version of Arduino's normal USB CDC interface in a WebUSB compatible way. To do this it:

  1. Adds a WebUSB descriptors so that browsers will apply the correct security policy.
  2. Changes the bInterfaceClass so that the device is not claimed by the system's USB CDC driver.
  3. Adds Microsoft OS 2.0 Descriptors so that Windows 8.1+ will load WinUSB.sys as the kernel driver for the device.

These last two points are actually the most critical challenge for existing devices migrating to WebUSB. With the --disable-webusb-security flag (and the chrome://usb-internals page that will soon replace it with a less drastically insecure method) or the public device registry discussed in the spec one can fake the device returning the right descriptors. The next step is getting the host OS to allow the browser to talk to the device. On OS X and Windows this is essentially impossible if a kernel driver has already claimed the device. On Linux it can be done but Chrome tries not to disturb any existing users of the device if possible. This is why the Arduino library changes the interface class so that it isn't recognized by the USB CDC driver. This isn't an issue for devices already speaking proprietary protocols without kernel drivers as they are already unclaimed and are ready for user-space applications to connect.

The migration path I see for FTDI and Prolific is to write a web app that through the public device registry (which doesn't have to be an on-line only solution, it can be embedded like the HSTS preload list) can reprogram the firmware to respond with WebUSB descriptors pointing to a particular manufacturer's site. The key observation here is that when not going through the public registry the vendor ID does not have to match the origin sent by the device.

larsgk commented 8 years ago

Supporting existing USB CDC devices will be needed if the packaged Chrome Web Apps are killed (as announced). I work with a major vendor of medical related devices already in the market - and even many devices to come - with off-the-shelf USB comm chips for USB serial communication. One thing is the hobby projects that could probably get around the problem with hacks but that is not the case with expensive products launched in larger scale (I am sure there are many other vendors who will face the same problem). If a clean WebUSB solution will not cater for those, the only solutions that come to mind would be:

  1. Packaged Chrome App - dead soon
  2. Not relying on WebUSB but throwing a lot of effort after WebSerial for the rescue
  3. Installing a small proxy service app, e.g. USB Serial <-> WebSockets + some localhost cert to be trusted by the system... (would hate that)

We need a solution that will work as well as chrome.serial/usb before they are gone - or large industry vendors will just not be able to migrate to pure web apps any time soon. Even if the will and knowledge was there, many vendors have piles of pre-ordered/bought components in their HW pipeline, not allowing for HW changes (and most probably no USB chip FW updates for a long time to come).

I know the currently proposed security model was made for the future and flexible USB FW in mind - but please consider some viable solution for everyone else :).

Another note on devices that do get the WebUSB header treatment: I know at least one vendor who does B2B sales of their devices and lets other portals/hosts communicate with their USB hardware. In this case, even knowing the original vendor's trusted URLs would not be enough as their customers are running the solution from their own In that case, it would be much more convenient with a solution that tied trust to something else - like a certificate or some shared secret over the USB CDC wire (which could also be used for legacy non-WebUSB header enabled devices, as higher level protocol modifications would be easier to do than changing the USB communication chips in produced hardware).

gfwilliams commented 8 years ago

The Web USB + driver clash is a big issue (IMO). Pretty much all hardware will want to be able to be controlled from other software, especially if Chrome is the only browser to support WebUSB initially.

You're saying that in order for a device to be usable with Chrome, it actually can't have drivers using it on WIndows or Mac? So the only applications that could use it are ones that access it in the same way Chrome does - via low-level USB? So for serial ports especially, you'd have to modify the firmware on your device such that it was incompatible with any other serial-based application, just so you could use it on Chrome.

I guess the one solution to this would be to have two separate interfaces - one for Chrome, and one for standard drivers - but that's quite a big ask for hardware manufacturers.

As I guess USB CDC will be one of the biggest use cases where this is an issue, perhaps Chrome could actually 'fake' USB devices that have drivers installed. It could provide a USB interface and descriptors, but would actually send data through the OS's serial port APIs instead.

larsgk commented 8 years ago

hmmm.. from all this input and after trying my best to get something to show up from my USB Serial devices (that I now understand will probably never work), we should push really hard for chrome.serial to be at least one of the Packaged App APIs to be ported ASAP (to be available and stable before packaged apps die). WebUSB sounds like a nice idea for future hardware with future chipsets but it doesn't sound like a feasible path for all the existing USB CDC hardware out there at the moment.

So - 2 possible solutions:

  1. extend WebUSB to also handle USB Serial devices in general (especially to cover off the shelf FTDI chips in existing hardware
  2. get chrome.serial (which works very well and stable on Win/Lin/OSX/ChromeOS at the moment) on the top of the list of APIs that need to become a standard and into Chrome (pure web apps) ASAP

Am I missing something?

larsgk commented 7 years ago

Just an idea: Would it make sense to embed simple and restricted (e.g. certificate - providing trust that this host is trusted to use this VID/PID from this manifest/app) access to pure USB Serial devices - in case WebSerial in it's currently proposed form would not pass the security concerns by google/mozilla/ms ?

Looking at all the big traditional industry with a lot of hardware out there using e.g. FTDI/STM32 (or the like), it would cut off SOO many important players if WebUSB will only support (in practice) a few indie/maker projects + potential future vendors who are 100% sure about the hosting domain of their app for years to come.

larsgk commented 7 years ago

@gfwilliams our current proxy/hack solutions https://github.com/larsgk/go-webserial and https://github.com/Tronil/go-webserial-native-msg (but that's just a temp solution)

gfwilliams commented 7 years ago

@larsgk yeah - it feels like you need to support FTDI/Prolific out of the box for any Web USB system to really get people excited... But then you have the permissions issue.

I suggested an Option 3: When WebUSB detects a USB serial device it could present a 'fake' low level USB CDC device that channelled requests through the platform's high level serial API. That would allow the existing APIs to support USB serial devices that have drivers installed, and might work for other types of device in the future.

Personally, I think a flag in chrome://flags and an 'Origin Trial Token' would be a big help to avoid security concerns. I don't mind telling my users to change a few options in their web browser - it's just installing things that is a pain.

Just FYI, New releases of NW.js support the chrome.* APIs - including serial - out of the box. So if you need to keep a web app running, just bundle it up alongside nw.js and distribute it for each platform.

reillyeon commented 5 years ago

The solution for this issue is the Serial API which I am working on implementing in Chrome. Between the two of them a page should be able to connect to a device whether or not there is a serial driver loaded.

paulobarcelos commented 5 years ago

@reillyeon would you care to elaborate a bit on the Serial API? Are you saying this is something Chrome is officially working on?

Since the depreciation of Chrome apps (and consequently, the web serial api), I have wondering if Chrome would provide some sort of alternative to it, and a signal that a public Serial API is on the way would be great news!

reillyeon commented 5 years ago

Yes, Chrome is officially working on implementing the Serial API. Intent to implement.