Skip to content

repository_tool: Root pre-verification during metadata writes misses possible verification failures #883

@awwad

Description

@awwad

Summary and Impact

This is a bug that occurs when root metadata is being verified before being written. This pre-write verification is intended to prevent the writing of metadata that would not be verifiable by a client. The code is flawed, and so it is readily possible to produce root metadata that will not be verifiable by a client.

Note that this bug does not result in incorrect client verification behavior, and so is not strictly a security issue. Problems can result from this behavior, however.

Background and Details

When writing new metadata (e.g. using repository_tool.write*), the write stack employs repository_lib._generate_and_write_metadata().

_generate_and_write_metadata:

  1. signs the metadata based on what keyids are noted in roledb._roledb_dict[<repo>][<role>]['signing_keyids']
  2. checks to make sure that the resulting signed metadata is correct / can be verified
  3. writes the metadata file

There is a substantial bug in step 2 that results in this verification check failing to catch root metadata that a client might reject. Note that the way that step 1 works will be altered by #846 (alters internal metadata storage to match the written metadata format) and that the bug in step 2 will also be fixed by #846. It may be worth fixing this bug in parallel, however, and it must in any case be recorded.

Root metadata is a bit special. Any other top-level metadata can be verified by simply looking at the contemporaneous root metadata. Root metadata itself dictates the keys expected for verification of root metadata, however, and that means that (e.g.) clients will use version 5 of root to verify version 6 of root. To generalize: in order to verify version V of root, you must verify that it has good signatures from BOTH:

  • at least the threshold and keyids for root from version V-1 of root
  • at least the threshold and keyids for root from version V of root (i.e. the version being verified)

We don't want users of repository_tool to write metadata that can't be verified, so we check that; however, we do the verification against expected keyids & threshold from root version V-1 incorrectly. In particular, when we use repository_tool to update root's expectations of root (using repository_tool.add_verification_key(), repository_tool.remove_verification_key(), and repository_tool.threshold()), old values are saved in roledb._roledb_dict[<repo>][<role>]['previous_threshold'] and ...['previous_keyids'], but:

  • remove_verification_key doesn't note prior values in those variables
  • add_verification_key and threshold overwrite what they last added to those variables, resulting in the wrong values if e.g. you add two verification keys between one root version and the next, or if (much less likely) you switch the threshold value twice before writing.

The Fix:

  • If there's already a value for ...['previous_keyids'], don't overwrite it. The same goes for `...['previous_threshold'].
  • Empty the values on write.

#846 should also result in a fix to this, with slightly different properties, as those values will be moved.

Metadata

Metadata

Assignees

Labels

bugrepositoryRelated to the repository implementation

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions