Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add support for client based device reset #199

Open
secworks opened this issue Apr 3, 2024 · 14 comments · May be fixed by #200
Open

Add support for client based device reset #199

secworks opened this issue Apr 3, 2024 · 14 comments · May be fixed by #200
Assignees
Labels
fpga Related to the FPGA design hw Related to hardware - PCB, MCU552, USB etc

Comments

@secworks
Copy link
Contributor

secworks commented Apr 3, 2024

In order to be able to switch device applications, we need a mechanism that allows the client to perform a reset of the connected TKey device. The idea is to have the USB handler, the CH552 MCU be able to receive a command from the client and notify the FPGA trough a separate channel than the serial link (UART) that a reset is requested.

We have a couple of unused connections between the CH552 and the FPGA. The idea is to commandeer one of these for this signalling.

The firmware also needs a way of identifying when a client reset has been made. It needs this signal to know if it's going to wait for a device app from the client app or boot something else.

Open questions

  • Should a client reset request should always be followed, or if it should be possible to be ignored?
    One idea is to ignore reset requests in FW-mode.
  • How do we signal status or a response back to the client that we have done the reset?
@secworks secworks self-assigned this Apr 3, 2024
@secworks secworks added fpga Related to the FPGA design hw Related to hardware - PCB, MCU552, USB etc labels Apr 3, 2024
@secworks
Copy link
Contributor Author

secworks commented Apr 3, 2024

@secworks
Copy link
Contributor Author

secworks commented Apr 3, 2024

Allocating the interface_rts signal, since it has the same intended direction as the interface_tx UART signal. And 'r' can be interpreted as reset.

@secworks
Copy link
Contributor Author

secworks commented Apr 3, 2024

First attempt at implementing the feature has been pushed to the branch and is ready for testing. The FPGA builds and should be stable (if the CH552 keeps the interface_rts signal low). And if pulled high should trigger a FPGA reset.

@secworks secworks linked a pull request Apr 3, 2024 that will close this issue
@secworks secworks linked a pull request Apr 3, 2024 that will close this issue
@tillitis tillitis deleted a comment from secworks Apr 3, 2024
@mchack-work mchack-work changed the title Add support for host based device reset Add support for client based device reset Apr 3, 2024
@secworks
Copy link
Contributor Author

secworks commented Apr 4, 2024

I've committed an updated implementation. Basically instead of pulling the reset directly at a client reset request, we instad trigger the reset loop to again be active. This will cause the reset to be asserted as it is when the bitststream has been loaded.

@mchack-work
Copy link
Member

Joachim and I discussed the API. We decided to create a first version that overrides the use of what the memory map calls TK1_SWITCH_APP, which will probably change name, into a status register with more added modes besides application mode/firmware mode:

  • Power cycle happened
  • Client reset
  • Internal reset

In this way firmware (And apps! We need to discuss if this is what we want.) will know what kind of reset has happened and how to proceed.

@secworks
Copy link
Contributor Author

secworks commented Apr 4, 2024

Commit 92a419e now updates the design by moving the reset handling logic to the tk1 core. It can now detect external request, and trigger the clk_reset module to perform a reset. The tk1 core can store the reset status (or better the reason why a reset was triggered). This status can be read out via the tk1 API.

Note that this commit changes the behavior of the ADDR_SWITCH_APP register. When written it will switch mode just as before. But when read, it does not return the fw_app-mode in all 32 bits. Instead the reset-status is returned in bit 17..16, and the fw_app-mode in bit 0 only. So one can not determine the fw_app mode by just checking if the API register is zero or not. In a future update we should change the name of the API register. For example to ADDR_SYS_CTRL_STATUS.

@cobratbq
Copy link

cobratbq commented Apr 16, 2024

  • How can I be sure that such a (client) reset is not performed unexpectedly/maliciously?
    The applications that I've seen, all check for the running firmware/application at start, then assume it is the same for the duration of the session.
  • I see benefits during development and when debugging, but not while being used. I can imagine an (desktop) application loading one of several programs depending on the needed function, but doesn't this assume single-request/short-running uses? (As opposed to loading a program, then performing a number of related actions, all of which assume the same program and previous data is loaded.)
  • What other use-cases did you have in mind?
  • Is this going to provide a DoS attack vector?

Given lack of persistence, sensitive data will likely be sent on every use. Now that a reset is possible, is there always the uncertainty of whether the loaded program has changed?

At the very least, it would be very valuable to allow the loaded program to disable this functionality. (Or vice-versa, enable it for development/debugging purposes.)

@secworks
Copy link
Contributor Author

Great comments. The main use case for this is the ability to switch apps, sessions without having to physically pull out and reinsert the TKey. But we need to think through the implications for this. And under what situations it can be accepted.

In the PR, the tk1 core includes a reset control. The purpose is to decide if a reset request should be allowed or not. It also tracks if a reset was caused by power up the device, or if it was due to a reset request. We can extend this with allowing an application to cause a reset. And could also add ability to block, deny client reset requests.

We won't merge this functionality until we know that it provides utility, is safe and works as we want it to. You feedback is very valuable for this.

@cobratbq
Copy link

cobratbq commented Apr 17, 2024

Here are some thoughts/questions, I still had in mind: the use-case involves loading sensitive data, then repeatedly using this data for several requests, which each provide some input of their own. The application counts on the program's continued execution and having the correct data in memory.

  • API-based resets (as part of TKey program-binary) are perfectly fine for me.
  • Client-side resets would be fine, if the program can control (disabling or explicitly enabling) client-side resets.

My thoughts are in the direction of avoiding unnecessary interference:

  • with the running program, or
  • having running program swapped, or
  • blocking access through repeated resets.
  • unpredictable faulty requests, (due to switching programs)

Probably not a convenient suggestion, possibly overkill: you could prefix response frames with an "identifier", some random (read-only) value assigned by firmware. Upon changing, one knows there was a reset (or some change of program). Granted, in most cases you would discover as soon as requests/commands no longer work, although not the root cause. (It's probably not practical. I'm just putting it out there.)

Question:
would this reset mean that the connection with the USB device is lost? (USB device rediscovered? Changes to USB device?) E.g. does a desktop application maintain the (exclusive) open socket, or lose its connection? This would be important in case of switching applications with a controlled reset.

@mchack-work
Copy link
Member

mchack-work commented Apr 18, 2024 via email

@mchack-work
Copy link
Member

mchack-work commented Apr 18, 2024 via email

@cobratbq
Copy link

Below my view, with some additional information.

Makes sense? [..] This might be solved in some other way, perhaps, but how? And what is
the best way?

Sure. I see where you're going. Taking a very high-level perspective, you have: client-side + internal resets, internal resets (from within program), or no resets.

If you want to support a use-case where you cannot have physical access (to disconnect and reconnect the device), you either:

  1. offer client-side resets (if you want absolute control), or
  2. offer a request-byte for asking the loaded program for the reset.

However, (2.) would be a risk, given that you don't have physical access. Assuming a sound program or physical access, then (2.) wouldn't be a problem (IMO).

Currently, [..] we don't have any way of detecting, say, a long
press [..] Possible to add?

I have little experience with hardware or embedded, but I can't think of anything. IIUC you cannot detect the touch itself, only that a touch was registered.

  1. Check for the correct device app (not very secure, I know, more below.)
    [..]
    Number 2 here is problematic in many ways.
    [..]
  2. The response is not secure in any way. It's just a pair of name strings and a version.

True. For what I need, I want to be sure of the triple (device, program-binary, USS), so I perform authentication. (I use this simple custom protocol, which seems to be enough for my case.) I use app-name and -version to check the API.

If you're only worried about speaking to the same instance [..]

Nah, it's not for that. My current prototype establishes a confidential session. I'm more worried that the random gibberish that it sends gets misinterpreted and the client won't know what's going on because of a sudden reset or app-swap. The problem with resets/app-swap is that it could potentially happen at any moment, and leaves the client guessing. That's why having control over the reset-capability would be very valuable. (Or at least, I assumed that there isn't an unmistakable sign. If the connection interrupts, then confusion isn't going to be a problem.)

The problem on how to identify to the client that it's the correct application on first start is harder, [..]

My current idea assumes physical access on first use, and then TOFU. (There's a bit more to it.)

@secworks
Copy link
Contributor Author

I have little experience with hardware or embedded, but I can't think of anything. IIUC you cannot detect the touch itself, only that a touch was registered.

The current touch_sensor HW core only supports detection of an event. But the sensor is actually simply presenting a high signal when a touch is performed. It is the core itself that does the event-thing. That is detect a low->high transition ,set at status register for SW to read and acknowledge before being able to detect a new event. There is nothing stopping us from providing the (sampled) input to SW, which could detect a finger present for x time.

@mchack-work
Copy link
Member

Changing the core is maybe a way forward. We didn't know that the touch sensor could handle this. This might mean we don't need client reset after all, but let's keep it here and think about it.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
fpga Related to the FPGA design hw Related to hardware - PCB, MCU552, USB etc
Projects
None yet
Development

Successfully merging a pull request may close this issue.

3 participants