TUFening UP Conex
2017-05-15 · Posted by: Justin Cappos · Categories: TUF · CommentsI spent this week with Hannes Mehnert figuring out how best to secure
Conex, a TUF-like system for the
OCaml community. After quite a bit of time spent pouring
over the Conex proposal, we eventually concluded the best way to secure this
system was to leverage the delegation design from TUF,
but with added functionality that can support more complete decentralization.
Delegations in TUF let a party that is trusted to perform an action grant that
ability to another party.
A lot of interesting observations emerged from our discussions, of which I would like to share three.
First, the TUF documentation really needs to be improved, especially when it comes to roles. I believe Conex’s first design may have used TUF if we had provided clearer descriptions of how to set up these roles in a realistic repository. Providing a more complete description about how different real world TUF repositories are set up will facilitate adoption. This will be a point of emphasis in the coming weeks.
Second, there are quite a few `underemphasized’ design choices in TUF that are important for security. For example, we do not discuss clearly enough why it is important to have a repository retrieve the timestamp metadata before conveying any other information about the state of the client. This is because the repository is forced to say what set of snapshot metadata (and thus all targets metadata) they will subsequently serve to the client. This prevents an attacker from learning the state of the repository, and thus being able to customize a replay attack to the specific client’s metadata state.
Rotating keys
The final obervation was about how to do key rotation. The model for Conex / OCaml is to distribute trust as much as possible. Hence, it is desirable to delegate to a threshold of developer keys rather than to a single, centrally-stored project key that could be stolen. Hannes and I discussed an interesting way to let a role rotate its keys to another role without requiring any change in delegation for that receiving role. Effectively, a key can sign a statement saying ``This key should not be trusted anymore, instead use this new key.’’ For example, foo’s delegation to bar need not change for bar to rotate their key.
Handling cycles of rotation
One interesting side effect of this new mechanism is how to handle a ``rotation loop,’’ where a series of rotations create a cycle. In this case, we believe the sane behavior is for all of those keys to be treated as revoked, and for none to be trusted. So, if bar rotates their keys back to a previous key, then all keys in the cycle, or that rotate to the cycle, are treated as invalid.
Explicitly revoking one’s own key
The nice feature of this is that a role now has an easy way to revoke trust in its own key. The role simply rotates the key to itself (creating a cycle of one). This effectively states, “Do not trust my key for any signatures in the future.” It is an option that can be used to let a user revoke trust in its key without requiring the parties that delegate to it to be involved.
Rotation beyond targets roles?
This rotation primitive is also being considered for non-targets roles. About six months ago, Docker’s security team expressed strong interest in key rotation for the timestamp role. We are eager to work with them to ensure this proposal meets their needs / goals. This primitive would likely replace the root rotation mechanism, preventing users from downloading all missing root metadata (whether the root keys changed or not). It also would allow the root roles on a repository to sign a statement revoking trust in themselves, in case a threshold of root keys were compromised. This would mean that any client that can connect to retrieve this metadata would stop trusting that repository in the future.
In closing, we are excited to continue this discussion via TAP 8. We are working together to move forward the deployment of TUF’s security for the OCaml community!