google / OpenSK

OpenSK is an open-source implementation for security keys written in Rust that supports both FIDO U2F and FIDO2 standards.
Apache License 2.0
2.98k stars 289 forks source link

nRF52840 USB dongle can not work with source code from stable and develop branches #348

Open geofli opened 3 years ago

geofli commented 3 years ago

Expected Behavior

nRF52840 USB dongle should work with source code on stable branch or develop branch

Actual Behavior

Neither stable nor develop branch work.

Following below steps

1. ./reset.sh
2. ./setup.sh
3. ./deploy.py --board=nrf52840_dongle_dfu --opensk --programmer=nordicdfu
Have switched nrf52840 usb dongle to bootloader mode.
4. ./tools/configure.py \
    --certificate=crypto_data/opensk_cert.pem \
    --private-key=crypto_data/opensk.key

If I use source code from stable branch, step 4 reports error 0xF2.

info: Private key is valid.
info: Certificate is valid.
DEBUG:fido2.hid.macos:Found CTAP device: 4295020873
DEBUG:fido2.hid:SEND: ffffffff8600084859dd5c0a590e2f
DEBUG:fido2.hid:RECV: ffffffff8600114859dd5c0a590e2f00000001020100000500000000000000000000000000000000000000000000000000000000000000000000000000000000
DEBUG:fido2.hid:SEND: 0000000190000104
DEBUG:fido2.hid:RECV: 00000001900001f20000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
Traceback (most recent call last):
  File "./tools/configure.py", line 204, in <module>
    main(parser.parse_args())
  File "./tools/configure.py", line 134, in main
    for authenticator in tqdm(get_opensk_devices(args.batch)):
  File "./tools/configure.py", line 72, in get_opensk_devices
    return [ctap2.CTAP2(dev)]
  File "/Users/gaofeng/.pyenv/versions/3.8.8/lib/python3.8/site-packages/fido2/ctap2/base.py", line 643, in __init__
    self._info = self.get_info()
  File "/Users/gaofeng/.pyenv/versions/3.8.8/lib/python3.8/site-packages/fido2/ctap2/base.py", line 695, in get_info
    return self.send_cbor(Ctap2.CMD.GET_INFO, parse=Info)
  File "/Users/gaofeng/.pyenv/versions/3.8.8/lib/python3.8/site-packages/fido2/ctap2/base.py", line 675, in send_cbor
    raise CtapError(status)
fido2.ctap.CtapError: CTAP error: 0xF2 - UNKNOWN

If I checkout code to develop branch, after step 3, nrf52840 usb dongle behaves like

https://user-images.githubusercontent.com/10238809/126742034-fdf49cec-d0c0-4173-aeb3-64b33207f636.mp4

Even if I perform ./deploy.py --board=nrf52840_dongle_dfu --erase_storage --programmer=nordicdfu before step 3, behavior is same.

What's the matter?

Steps to Reproduce the Problem

1. ./reset.sh
2. ./setup.sh
3. ./deploy.py --board=nrf52840_dongle_dfu --opensk --programmer=nordicdfu
Have switched nrf52840 usb dongle to bootloader mode.
4. ./tools/configure.py \
    --certificate=crypto_data/opensk_cert.pem \
    --private-key=crypto_data/opensk.key

on either stable or develop branch.

kaczmarczyck commented 3 years ago

Hi, thanks for reporting. May I ask a few clarifying questions?

  1. Do you have a dev board and is the behaviour identical?
  2. When you try to configure, is the device already configured?
  3. Do you erase the storage when switching between stable and develop?
  4. So you can't deploy to the dongle on develop, even after a full erase, and you can't properly configure on stable?

The panic and error code 0xF2 hint at internal errors, but erasing should make your storage consistent to the current branch.

geofli commented 3 years ago
  1. I don't have dev board but only this USB dongle.
  2. I used this USB dongle for a long time, I often downloaded latest OpenSK firmware to it. But these days when I tried to download latest firmware, it became to this behavior.
  3. Yes, I have tried ./deploy.py --board=nrf52840_dongle_dfu --erase_storage --programmer=nordicdfu to erase the storage, but same issue happened.
  4. Yes, I tried for several days.

I have our own Feitian OpenSK dongle, some of them are same to this nrf52840 USB dongle, but some can work. I don't know from which commit this issue happened , but they all can work before. End user can only flash firmware by dfu, it is not possible for them to erase storage through J-Link.

bmbeverst commented 3 years ago

I had this issue as well. I was able to resolve it by re-flashing Tock, not sure if this is needed. ./deploy.py --board=nrf52840_dongle_dfu --programmer=nordicdfu --no-app --dont-clear-apps and then configuring the certificate again without being in bootloader mode, ./tools/configure.py --certificate=crypto_data/opensk_cert.pem --private-key=crypto_data/opensk.key

geofli commented 3 years ago

Not work for me, after

1. ./reset.sh
2. ./setup.sh
3. ./deploy.py --board=nrf52840_dongle_dfu --programmer=nordicdfu --no-app --dont-clear-apps 
    (in bootloader mode)
4. ./deploy.py --board=nrf52840_dongle_dfu --opensk --programmer=nordicdfu 
    (in bootloader mode)
5. ./tools/configure.py \
    --certificate=crypto_data/opensk_cert.pem \
    --private-key=crypto_data/opensk.key

or

1. ./reset.sh
2. ./setup.sh
3. ./deploy.py --board=nrf52840_dongle_dfu --opensk --programmer=nordicdfu 
    (in bootloader mode)
4. ./deploy.py --board=nrf52840_dongle_dfu --programmer=nordicdfu --no-app --dont-clear-apps 
    (in bootloader mode)
5. ./tools/configure.py \
    --certificate=crypto_data/opensk_cert.pem \
    --private-key=crypto_data/opensk.key

Same thing happened, LEDs blinked as above video after step 4 on develop branch, and step 5 returned 0xF2 on stable branch. On stable and develop branch, I ran the steps cleanly from step 1.

jmichelp commented 3 years ago

Looking at the packets exchanged, the firmware returns 0xF2 (vendor internal error) when receiving an authenticatorGetInfo (0x04) command. This can fail when the persistent storage fails to retrieve any of the following entries:

I can try to reproduce on a dongle on Friday.

I don't see any code change on stable branch since we introduced the configuration command so everything should be working. AAGUID is checked at compile time so I'm taking for now the assumption that the error comes from one of the other 2 values.

@ia0 and @kaczmarczyck can this be a missing/changed default value for pin_hash or min_pin_length between stable and develop? I don't know how the code would behave if you alternate between stable and develop branch while not erasing the storage.

geofli commented 3 years ago

I can not find any usb dfu way to erase code and data storage to have only MBR/bootloader left, tools from Nordic can not do either. If I can do that, maybe I can re-program the USB dongle to be a fresh one.

ia0 commented 3 years ago

I could not reproduce the issue in stable. Could you make sure to run ./deploy.py --board=nrf52840_dongle_dfu --erase_storage --programmer=nordicdfu between step 2 and 3?

However I could reproduce the issue in develop. This only happens with the dongle with DFU. I could successfully flash the dev kit with jlink. So I've run a git bisect to find the commit introducing the issue. The first problematic commit is ce0ee6c054ce822d8a5e2285d11b4c876be49dcc (#334). I'm sending #351 to fix.

geofli commented 3 years ago

./deploy.py --board=nrf52840_dongle_dfu --erase_storage --programmer=nordicdfu is only available in develop, this --erase_storage option is introduced in https://github.com/google/OpenSK/pull/247 . If this option is very helpful, please add it to stable too.

geofli commented 3 years ago

After correct Line 9 of boards/nordic/nrf52840_dongle_dfu/Cargo.toml according to https://github.com/google/OpenSK/pull/351 , our nrf52840 USB dongle can work with develop source code. But on stable branch, it still reports 0xF2 when programming attestation certificate/private key.

Check boards/nordic/nrf52840_dongle_dfu/Cargo.toml on stable branch, path = "../nrf52840_dongle/src/main.rs" directory nrf52840_dongle does not exist, is it the reason?

ia0 commented 3 years ago

erase_storage is only available in develop

Yes, we should add it to stable. But in the meantime, you can run it from develop:

git checkout develop
./reset.sh
./setup.sh
./deploy.py --board=nrf52840_dongle_dfu --programmer=nordicdfu --erase_storage
git checkout stable
./reset.sh
./setup.sh
./deploy.py --board=nrf52840_dongle_dfu --programmer=nordicdfu --opensk
./tools/configure.py --certificate=crypto_data/opensk_cert.pem --private-key=crypto_data/opensk.key

directory nrf52840_dongle does not exist

It's because the boards are in third_party/tock/boards/nordic, we just copy the ones specific to OpenSK from boards/nordic there. It's just that in develop (#334) we stopped using the ones from Tock and introduced custom ones for OpenSK and we forgot to update the reference from the DFU board to the OpenSK one.

jmichelp commented 3 years ago

I think the reason we weren't adding the --erase_storage flag to stable is because we don't expect people flash the same dongle alternating between the 2 branches. We're doing our best to ensure compatibility when moving forward in versions (i.e. stable to develop which at some point will become the new stable) and the --erase_storage is there in case the develop branch introduces changes that are incompatible and require erasing everything. But moving backward cannot be guaranteed.

ia0 commented 3 years ago

I think the reason we weren't adding the --erase_storage flag to stable is because we don't expect people flash the same dongle alternating between the 2 branches.

If this is true, then:

the --erase_storage is there in case the develop branch introduces changes that are incompatible

No, the --erase_storage is there to provide a solution for DFU users who can't use the --clear-storage flag. Besides the example use-case you describe, this can be used to fully reset a device and permit a different configuration, or just wipe an existing key to be repurposed. If those use-cases are also forbidden, this should be documented, in particular that flashing OpenSK from the stable branch locks the device to be used for OpenSK on the stable branch with that specific configuration.

geofli commented 3 years ago
1.  git checkout develop
2. ./reset.sh
3. ./setup.sh
4. ./deploy.py --board=nrf52840_dongle_dfu --programmer=nordicdfu --erase_storage
5. git checkout stable
6. ./reset.sh
7. ./setup.sh
8. ./deploy.py --board=nrf52840_dongle_dfu --programmer=nordicdfu --opensk
9. ./tools/configure.py --certificate=crypto_data/opensk_cert.pem --private-key=crypto_data/opensk.key

Yes, several hours ago, I tried these steps, changed the source code according to https://github.com/google/OpenSK/pull/351 after step2 and before step 3, but step 9 returned 0xF2 yet. But now, I try again, it works.

So, https://github.com/google/OpenSK/pull/351 can solve this issue. Great, thank you very much.

kaczmarczyck commented 3 years ago

Thanks for debugging @ia0 !

Tiebe commented 1 year ago

If I checkout code to develop branch, after step 3, nrf52840 usb dongle behaves like

nrf52840.mp4

How did you get out of this flashing mode?

kaczmarczyck commented 1 year ago

Hey, is this question related to your issue #544 ? Because the referenced video is not an MDK, and you #544 is about MDK. But if you have problems on both platforms, can you create a new issue for the dongle with your exact steps? Otherwise I will respond on #544.

geofli commented 1 year ago

Use current latest commit 8868752e37a83ccffd0149cc96d65397fcc51d33 from develop branch to test dongle on macOS ./reset.sh ./setup.sh ./deploy.py --board=nrf52840_dongle_dfu --programmer=nordicdfu --erase_storage ./deploy.py --board=nrf52840_dongle_dfu --programmer=nordicdfu --opensk

report

info: Flashing device using DFU...
  [####################################]  100%
Device programmed.
info: Configuring device.
info: Your device is not yet configured, and lacks some functionality. You can check its configuration status with:

./tools/configure.py

If you run into issues, this command might help:

./tools/configure.py \
    --certificate=crypto_data/opensk_cert.pem \
    --private-key=crypto_data/opensk.key

Please read the Certificate considerations in docs/customization.md to understand the privacy trade-off.
fatal: No device to configure found.

So no FIDO device found.

kaczmarczyck commented 1 year ago

And it's still not detected after you replug it? If you try to use it or call ./tools/configure.py after a reboot, what happens?

geofli commented 1 year ago

Cannot find FIDO device no matter reboot on macOS, even though use other tools, such as chrome://settings/securityKeys chrome://device-log/ showed as below:

USBUser[09:58:54] USB device added: vendor=6421 "Nordic Semiconductor ASA", product=21023 "OpenSK", serial="v1.0", guid=5e7cbeb0-a832-4db6-9579-cf9d5bb458ee
USBEvent[09:58:54] Failed to get active configuration: Entity not found
USBUser[09:58:52] USB device removed: guid=9ab56205-6e05-4cef-966a-2b2726e124b6

And USB Prober showed image

kaczmarczyck commented 1 year ago

@jmichelp Please reproduce when you have time.

jmichelp commented 1 year ago

Will try to reproduce this morning. But the message tends to point towards modifications on the USB stack. We shouldn't see the error regarding the USB configuration.

jmichelp commented 1 year ago

I can reproduce on OSX. OpenSK isn't detected as FIDO2 HID device by python fido2 module:

kaczmarczyck commented 1 year ago

@geofli Please pull develop and let us know if your issue is fixed.

geofli commented 1 year ago

Works on my macOS. But it seems there may still be some potential issue.

Use https://www.uwe-sieber.de/usbtreeview_e.html#download on Windows image image image

Use USB Prober.app on macOS image image

kaczmarczyck commented 1 year ago

Thanks for pointers, we will look into it!