Skip to content

Commit

Permalink
updater: verify newly downloaded root metadata with its signatures
Browse files Browse the repository at this point in the history
Per the detailed client workflow in the specification step 1.2

"Version N+1 of the root metadata file MUST have been signed by:
(1) a threshold of keys specified in the trusted root metadata file
(version N), and
(2) a threshold of keys specified in the new root metadata file being
validated (version N+1)."

Number 2 is implemented here as this step was not being performed by the
Updater. Unfortunately we can't use existing signature verification
methods in tuf.sig, because tuf.sig.signature_status() does not verify
signatures for keys which are not listed in keydb (and tuf.sig.verify
uses tuf.sig.signature_status)

Therefore this patch introduces a method for verifying signatures with
root keys listed in the signable being verified.

Signed-off-by: Joshua Lock <[email protected]>
  • Loading branch information
joshuagl committed Aug 18, 2020
1 parent 902a025 commit 2fc25ad
Showing 1 changed file with 53 additions and 0 deletions.
53 changes: 53 additions & 0 deletions tuf/client/updater.py
Original file line number Diff line number Diff line change
Expand Up @@ -1370,6 +1370,45 @@ def verify_target_file(target_file_object):



def _verify_root_self_signed(self, signable):
"""
Verify the root metadata in signable is signed by a threshold of keys,
where the threshold and valid keys are defined by itself
"""
threshold = signable['signed']['roles']['root']['threshold']
keyids = signable['signed']['roles']['root']['keyids']
keys = signable['signed']['keys']
signatures = signable['signatures']
signed = securesystemslib.formats.encode_canonical(
signable['signed']).encode('utf-8')
validated = 0

for signature in signatures:
keyid = signature['keyid']

# At this point we are verifying that the root metadata is signed by a
# threshold of keys listed in the current root role, therefore skip
# keys with a keyid that is not listed in the current root role.
if keyid not in keyids:
continue

key = keys[keyid]
# The ANYKEY_SCHEMA check in verify_signature expects the keydict to
# include a keyid
key['keyid'] = keyid
valid_sig = securesystemslib.keys.verify_signature(key, signature, signed)

if valid_sig:
validated = validated + 1

if validated >= threshold:
return True
return False





def _verify_metadata_file(self, metadata_file_object,
metadata_role):
"""
Expand Down Expand Up @@ -1439,6 +1478,20 @@ def _verify_metadata_file(self, metadata_file_object,
if not valid:
raise securesystemslib.exceptions.BadSignatureError(metadata_role)

# For root metadata, verify the downloaded root metadata object with the
# new threshold of new signatures contained within the downloaded root
# metadata object
# NOTE: we perform the checks on root metadata here because this enables
# us to perform the check before the tempfile is persisted. Furthermore,
# by checking here we can easily perform the check for each download
# mirror. Whereas if we check after _verify_metadata_file we may be
# persisting invalid files and we cannot try copies of the file from other
# mirrors.
if valid and metadata_role == 'root':
valid = self._verify_root_self_signed(metadata_signable)
if not valid:
raise securesystemslib.exceptions.BadSignatureError(metadata_role)




Expand Down

0 comments on commit 2fc25ad

Please sign in to comment.