mirror of
https://github.com/theupdateframework/python-tuf
synced 2026-05-24 10:08:28 +00:00
updater: verify newly downloaded root metadata with its signatures
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 <jlock@vmware.com>
This commit is contained in:
parent
902a025918
commit
2fc25adfad
1 changed files with 53 additions and 0 deletions
|
|
@ -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)
|
||||
|
||||
|
||||
|
||||
|
||||
|
|
|
|||
Loading…
Reference in a new issue