Nitrokey / trussed-secrets-app

Secrets App: OTP and PWS application for the Nitrokey 3
Apache License 2.0
7 stars 4 forks source link

Confirm Credential removal with a touch #92

Closed szszszsz closed 11 months ago

szszszsz commented 11 months ago

By design all state changes (exception: HOTP counter) should be confirmed by touch. Currently removal of the credential does not have such. To add it.

Connected: https://github.com/Nitrokey/nitrokey-3-firmware/issues/303

image

https://github.com/Nitrokey/trussed-secrets-app/blob/d1b083dc47d48e40fbec4477b3b2f1d0248a666e/src/authenticator.rs#L436-L464

peterwilli commented 11 months ago

Wow, I love that diagram. Is it something I can try and fix? I want to contribute to the firmware and this seems to be a good start! I have done embedded security hardware before (Ledger, in C) but am working fulltime in Rust now.

szszszsz commented 11 months ago

Sure! This is a one-line change, but it needs to be tested / checked for potential implications. Feel free to take it :-) Let me know if you need any directions. Quick crash course - you can test all changes live using USB/IP simulation:

$ env RUST_LOG=debug cargo run --example usbip --features "ctaphid devel"
$ make -f examples/Makefile attach
# run tests
$ cd ../pynitrokey && make secrets-test
# or with pynitrokey as usual
$ pynitrokey nk3 secrets list
# disconnect from the USB server once done
$ make -f examples/Makefile stop
# kill the usb/ip client run by the cargo
# <ctrl+c> or killall

Edit: added RUST_LOG=debug

peterwilli commented 11 months ago

I'll get on it right away! So this means you don't need to flash your NitroKey with the firmware to test it out?

szszszsz commented 11 months ago

Great! Yes, you can run it locally, and it could behave like a real connected device. For the real hardware test you would need a "Hacker" variant to flash your build, since only signed firmware is accepted in the sold Nitrokey 3 devices. The USB/IP Simulation has one disadvantage currently however - it auto-accepts all touch requests, hence it does not allow to test touch-based test cases. It's logged though, so you can see whether it shows up or not. Former is not a technical limitation though - this should be relatively simple to implement, e.g. using a TCP/IP supplementary app for that.

Edit: alternatively maybe the DevKits would do, but this target was removed recently

szszszsz commented 11 months ago

I forgot to mention, that you need USB/IP kernel modules and tools available in your Linux system. I have not tested that with Windows/macOS, but perhaps it would work there too.

robin-nitrokey commented 11 months ago

If you want to develop with real hardware, this would be the starting point: https://github.com/Nitrokey/nitrokey-3-firmware/blob/main/docs/lpc55-quickstart.md

peterwilli commented 11 months ago

I forgot to mention, that you need USB/IP kernel modules and tools available in your Linux system. I have not tested that with Windows/macOS, but perhaps it would work there too.

I run Linux so it should be fine. If not, I'll be able to install them I'm sure!

peterwilli commented 11 months ago

Yes, you can run it locally, and it could behave like a real connected device. For the real hardware test you would need a "Hacker" variant to flash your build, since only signed firmware is accepted in the sold Nitrokey 3 devices.

Ah that's kinda sad, I was hoping to add more features to the firmware when I would get more experienced, I assumed that since the firmware was open source it would be possible to flash a custom build in some way or another

robin-nitrokey commented 11 months ago

Ah that's kinda sad, I was hoping to add more features to the firmware when I would get more experienced, I assumed that since the firmware was open source it would be possible to flash a custom build in some way or another

This is not possible for normal Nitrokey 3 devices because they are shipped with secure boot. But if you order a Nitrokey 3 Hacker device from shop@nitrokey.com, you will get the same hardware without secure boot and can run any firmware you want on it.

peterwilli commented 11 months ago

Ah that's kinda sad, I was hoping to add more features to the firmware when I would get more experienced, I assumed that since the firmware was open source it would be possible to flash a custom build in some way or another

This is not possible for normal Nitrokey 3 devices because they are shipped with secure boot. But if you order a Nitrokey 3 Hacker device from shop@nitrokey.com, you will get the same hardware without secure boot and can run any firmware you want on it.

I might get back about that later then 👍🏼

peterwilli commented 11 months ago

I did get the error about USB/IP. I managed to install the driver and now tests seem to run well, so I can begin make the change

peterwilli commented 11 months ago

I seem to have done it! It was really easy in hindsight, I will make a PR now and we'll see from there. The logs were very clear on where a button was supposed to be pressed.

Also, this USB/IP thing is very new to me but very pleasant to work like this, it this possible on any Rust based embedded hardware/software project? Like using it on a firmware written in Rust for STM32 or something.

peterwilli commented 11 months ago

Here we go: https://github.com/Nitrokey/trussed-secrets-app/pull/93

Ironically, this is my first commit signed with a Nitrokey

robin-nitrokey commented 11 months ago

Wow, that was quick! :)

Also, this USB/IP thing is very new to me but very pleasant to work like this, it this possible on any Rust based embedded hardware/software project? Like using it on a firmware written in Rust for STM32 or something.

This is not related to Rust at all. You just need a driver that wraps the USB packets in IP packets and sends them to the correct socket. Rust’s abstractions make it easy to switch out the real USB driver with the usbip driver, but the same principle works for all languages.

szszszsz commented 11 months ago

@peterwilli I am glad you like it! We are using this one: https://github.com/sawchord/usbip-device You may find the examples there interesting. As @robin-nitrokey said you need a proper abstraction, but once this is set up its a breeze.

peterwilli commented 11 months ago

Wow, that was quick! :)

Also, this USB/IP thing is very new to me but very pleasant to work like this, it this possible on any Rust based embedded hardware/software project? Like using it on a firmware written in Rust for STM32 or something.

This is not related to Rust at all. You just need a driver that wraps the USB packets in IP packets and sends them to the correct socket. Rust’s abstractions make it easy to switch out the real USB driver with the usbip driver, but the same principle works for all languages.

Oh, so you use an abstraction layer in Rust to switch to USB/IP. From what I understand, there's no "emulator" in place that ran the firmware I just tested?

robin-nitrokey commented 11 months ago

From what I understand, there's no "emulator" in place that ran the firmware I just tested?

Exactly. The bigger picture is: We use the Trussed framework for our firmware. This framework provides abstractions that can be used by applications like the secrets app. Then there is a runner that provides implementations for these abstractions and defines the available applications.

To run the firmware on hardware, you would use a runner that uses hardware-specific code to implement these abstractions, e. g. accessing the flash chip or the touch button. But for the usbip simulation, we just use the standard library and the file system to implement them and compile to a native binary. The advantage is that it is very easy to test, the downside is that we don’t test the low-level components of the firmware. But for application development, this is typically sufficient.

peterwilli commented 11 months ago

Oh, that makes sense, so it's a good Swiss Army knife for development, but for testing out actual hardware elements you'd still need a different way to test on an actual device.