theupdateframework / python-tuf

Python reference implementation of The Update Framework (TUF)
https://theupdateframework.com/
Apache License 2.0
1.63k stars 272 forks source link

Updater feature request: verify chain of trust from bootstrapped root metadata #1168

Open joshuagl opened 4 years ago

joshuagl commented 4 years ago

Description of issue or feature request:

Context:

Observations:

With these considerations in mind, it feels like providing a way to verify the chain of trust from the boostrap root metadata to the trusted root metadata will provide some additional integrity protection for the client, to better detect tampering with trusted root metadata that isn't stored in OS protected locations.

Current behavior:

No verification of chain of trust from bootstrap trusted root metadata to current trusted root metadata.

Expected behavior:

Expose an optional method on tuf.client.updater.Updater, to be called before refresh(), which will walk the chain of trust from the bootstrap root metadata to the current trusted root metadata. This method will perform a similar sequence of steps as defined in 5.1 of the detailed client workflow, only it will prefer local copies of the intermediate trusted root metadata before reaching out to the repository to download intermediate root metadata file version.

jku commented 4 years ago

I'll write down the details for pip specifically as an example (like it currently works in my WIP branch):

So the issue here is that any application running as user can modify ~/.local/share/pip/. We can't prevent that but when pip starts, it could make sure that the boostrap metadata that was installed with pip is used. In some cases that boostrap metadata is more trustworthy than something in the home directory.

The easy solution is to always wipe the runtime metadata directory (or at least root.json) and start from bootstrap but that seems wasteful...

I'll add one caveat to this bug report: the pip design of using shared runtime metadata location has some downsides and might turn out to be wrong. The core problem is still there since we do want to use cached metadata even if it's not shared by multiple installs

jku commented 4 years ago

I think this changes nothing from the above descriptions, but just for the record: When the installed pip gets upgraded, the bootstrap metadata may change -- in an extreme case the new root.json may not even be in the same chain of trust as the old one.

Another thing I had not considered before: we may want to provide multiple bootstrap files (targets.json and bins.json as well as root.json). This is not really useful for verifying the chain of trust of an existing runtime metadata but the point would be to make the first run pip invocation faster: the client would not need to download the large bins.json file (assuming the included file has not expired).

mnm678 commented 4 years ago

Another thing I had not considered before: we may want to provide multiple bootstrap files (targets.json and bins.json as well as root.json). This is not really useful for verifying the chain of trust of an existing runtime metadata but the point would be to make the first run pip invocation faster: the client would not need to download the large bins.json file (assuming the included file has not expired).

This would also provide some additional rollback protection for first time clients as they could use bootstrapped targets and maybe snapshot to ensure version numbers have not decreased. The added metadata may make the initial install much larger, but it might be useful in some cases.

MVrachev commented 4 years ago

I will work on this after I push some updates on some of my already opened prs.

jku commented 4 years ago

The added metadata may make the initial install much larger, but it might be useful in some cases.

The point about rollback protection is good... but I think including large files known to be expired (snapshot) is unappealing (In that same train of thought I'm really hoping we get some version of succinct delegation in at some point so I don't have to explain to pip folks how the pip install size just grew by 1.6MB because of bins.json :grimacing:)

In fact, I think snapshot.json in the bootstrap does not bring additional benefits if timestamp is included: the snapshot version number included in timestamp.json should get checked for replay attack according to spec if I'm reading it right.

So for reference, my understanding of the potential bootstrap contents for pip:

  1. root.json (required, small size)
  2. timestamp.json (additional replay attack protection, small size, will be expired but that should not matter)
  3. maybe targets.json+bins.json (huge size currently, no security benefit but including these potentially helps first run experience)

Does that seem correct? The last point is really debatable even now and succinct delegations, if it appears, will make it more so.

jku commented 3 years ago

The original issue (chaining root trust from bootstrap root.json) should now be fairly easy to implement in ngclient:

jku commented 1 year ago

There's a first draft in https://github.com/jku/python-tuf/commits/bootstrap-root-metadata -- I don't know if I'll push this further: Feel free to take this code and turn into a PR. Needs tests (at the very least).