haskell / hackage-security

Hackage security framework based on TUF (The Update Framework)
http://hackage.haskell.org/package/hackage-security
56 stars 47 forks source link

Clarification requested: bootstrapping process #181

Closed snoyberg closed 7 years ago

snoyberg commented 7 years ago

In reviewing the workflow in the example-client executable, it appears that the standard workflow would be:

From my understanding, the bootstrap download will grab the public keys used to verify any future downloads. Once those keys are downloaded, they are used to ensure the authenticity of all future steps.

However, the bootstrap download itself has no way to verify it. Furthermore, at least in the example-client, it appears that the HTTP libraries selected do not have TLS support (I know that http-client was used without http-client-tls, as well as the HTTP package), and therefore that bootstrap download seemingly could be trivially MITMed, without even compromising a certificate authority.

What is the expected workflow here for actual clients? Is it intended that security keys be shipped with tools like cabal-install/Stack which use hackage-security? Is the intention to rely on HTTPS for the bootstrap, but the example client skips that for simplicity?

edsko commented 7 years ago

Right, initial distribution of keys is outside the purview of the spec. The intention is, as you said, that tools such as stack or cabal-install will ship with the set of root keys.

snoyberg commented 7 years ago

Thanks for the response. For the record, this isn't idle curiosity, I'm trying to figure out how to roll out this support in Stack.

Shipping the list of keys in a build tool seems like it would most easily be handled via:

Is that the plan for cabal-install as well?

I'm not a crypto expert by any means, but in a sense I'm not sure that this is actually any more secure than just downloading the root.json file over HTTPS, given that the cabal-install/stack executables themselves will be downloaded like this. The other downside I see is likely just based on a lack of knowledge: what happens if the upstream root.json file changes after the executable is shipped?

ezyang commented 7 years ago

It's a matter of minimizing TCB. Yes, if cabal-install/stack are downloaded over HTTPS, someone could compromise the root.json they ship with. But they could also compromise the entire executable, so... Whereas, if the keys are downloaded after the fact, that's another possible compromise point; now you can have a good executable but bad keys. It's also worth noting that if cabal-install/stack are shipped via your operating system distro, now the keys can be bootstrapped via the distro's keys. If there's a separate download step, the distro has to know to pre-ship keys to prevent the bootstrapping process from taking place, which is another place where failure can occur.

In any case, TUF provides a mechanism for upgrading when root.json is updated (see section 6.1 of https://github.com/theupdateframework/tuf/blob/develop/docs/tuf-spec.txt ); as a not-hackage-security-contributor I don't know if we've actually implemented it, but in principle this should work.

edsko commented 7 years ago

You're right I guess that downloading the keys over HTTPS, versus downloading the entire distribution over HTTPS, is not more secure in principle. Initial key distribution is always a thorny problems. Ideally you'd piggy back on some other kind of key validation, like for instance a distro's keys. Even that of course then piggy-backs on HTTPS keys in the end because, well, you downloaded that distribution at some point.. In practice I don't think downloading the initial set of root keys over HTTPS is a huge deal. It happens only once and although you'd have a problem if you were unlucky enough to download compromised keys, in all other situations you'd be fine from that point forward.

As regards updates to the root.json -- as Edward mentions, this is in the purview of the spec, and it has in fact been implemented as well. The root dataset contains a relatively large set of root keys (about 10 or so), but does not need to be signed with all 10 (it needs to be signed with some threshold number, which IIRC we've set to 3). So if a client has an old version of the root file, notices that a new version exists, it will download the new version, verify it with its old set of keys, and then accept the new version as the new authoritative version. This allows the root set of keys to slowly change over time.

snoyberg commented 7 years ago

Interesting about the root.json updates. Are those handled automatically by the calls to check, or would an explicit call to bootstrap be necessary to make that happen? If something explicit needs to happen, how can we tell when it's supposed to happen?

edsko commented 7 years ago

That will be handled entirely automatically by check. Verified updates to the root.json are not considered a bootstrap.

snoyberg commented 7 years ago

OK, cool, thanks for all the feedback. Here's my summary of the situation, let me know if you disagree:

edsko commented 7 years ago

Yup, that all sounds reasonable to me.

snoyberg commented 7 years ago

OK, thanks again. I've implemented the key and key threshold settings in Stack's Hackage Security configuration, and provided default values, so I think the Stack side is in good shape.

edsko commented 7 years ago

You're welcome :-)