diff --git a/tuf/client/updater.py b/tuf/client/updater.py index 150bf376..b5514e35 100755 --- a/tuf/client/updater.py +++ b/tuf/client/updater.py @@ -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): """ @@ -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) +