Skip to content

Commit

Permalink
Try to prevent duplicate keys
Browse files Browse the repository at this point in the history
It is possible for the 'signatures' field of metadata to contain duplicates.  Same key, but different KEYIDs due to multiple hash algorithms being used to generate their keyid.
  • Loading branch information
vladimir-v-diaz committed Mar 3, 2017
1 parent 9772462 commit 1a00d87
Show file tree
Hide file tree
Showing 2 changed files with 32 additions and 6 deletions.
13 changes: 12 additions & 1 deletion tests/test_sig.py
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@

import unittest
import logging
import copy

import tuf
import tuf.log
Expand Down Expand Up @@ -201,16 +202,26 @@ def test_get_signature_status_below_threshold(self):
signable = {'signed' : 'test', 'signatures' : []}

signable['signatures'].append(securesystemslib.keys.create_signature(
KEYS[0], signable['signed']))
KEYS[0], signable['signed']))

copy_of_key = copy.deepcopy(KEYS[0])
copy_of_key['keyid'] = '123456'

signable['signatures'].append(securesystemslib.keys.create_signature(
copy_of_key, signable['signed']))
print('signable signatures: ' + repr(signable['signatures']))

tuf.keydb.add_key(KEYS[0])
tuf.keydb.add_key(copy_of_key)

threshold = 2
roleinfo = tuf.formats.make_role_metadata(
[KEYS[0]['keyid'],
KEYS[2]['keyid']], threshold)
tuf.roledb.add_role('Root', roleinfo)

sig_status = tuf.sig.get_signature_status(signable, 'Root')
print('sig_status: ' + repr(sig_status))

self.assertEqual(2, sig_status['threshold'])
self.assertEqual([KEYS[0]['keyid']], sig_status['good_sigs'])
Expand Down
25 changes: 20 additions & 5 deletions tuf/sig.py
Original file line number Diff line number Diff line change
Expand Up @@ -67,10 +67,11 @@ def get_signature_status(signable, role=None, repository_name='default',
<Purpose>
Return a dictionary representing the status of the signatures listed in
'signable'. Given an object conformant to SIGNABLE_SCHEMA, a set of public
keys in 'tuf.keydb', a set of roles in 'tuf.roledb', and a role,
the status of these signatures can be determined. This method will iterate
the signatures in 'signable' and enumerate all the keys that are valid,
invalid, unrecognized, unauthorized, or generated using an unknown method.
keys in 'tuf.keydb', a set of roles in 'tuf.roledb', and a role, the status
of these signatures can be determined. This method will iterate the
signatures in 'signable' and enumerate all of the unique keys that are
valid, invalid, unrecognized, unauthorized, or generated using an unknown
method.
<Arguments>
signable:
Expand Down Expand Up @@ -151,7 +152,12 @@ def get_signature_status(signable, role=None, repository_name='default',
signed = signable['signed']
signatures = signable['signatures']

# Iterate the signatures and enumerate the signature_status fields.
# To avoid duplicates, maintain a list of unique keys that are loaded.
# Duplicates might occur if the same key (a valid, but different keyid) is
# loaded with a different KEYID hash algorithm.
loaded_keys = []

# Iterate signatures and enumerate the signature_status fields.
# (i.e., good_sigs, bad_sigs, etc.).
for signature in signatures:
sig = signature['sig']
Expand All @@ -166,12 +172,17 @@ def get_signature_status(signable, role=None, repository_name='default',
unknown_sigs.append(keyid)
continue

# Has 'key' already been processed (via the same, or different, KEYID)?
if key['keyval'] in loaded_keys:
continue

# Does the signature use an unknown key signing method?
try:
valid_sig = securesystemslib.keys.verify_signature(key, signature, signed)

except securesystemslib.exceptions.UnknownMethodError:
unknown_method_sigs.append(keyid)
loaded_keys.append(key['keyval'])
continue

# We are now dealing with either a trusted or untrusted key...
Expand All @@ -185,6 +196,7 @@ def get_signature_status(signable, role=None, repository_name='default',

if keyid not in keyids:
untrusted_sigs.append(keyid)
loaded_keys.append(key['keyval'])
continue

# Unknown role, re-raise exception.
Expand All @@ -194,14 +206,17 @@ def get_signature_status(signable, role=None, repository_name='default',
# This is an unset role, thus an unknown signature.
else:
unknown_sigs.append(keyid)
loaded_keys.append(key['keyval'])
continue

# Identify good/authorized key.
good_sigs.append(keyid)
loaded_keys.append(key['keyval'])

else:
# This is a bad signature for a trusted key.
bad_sigs.append(keyid)
loaded_keys.append(key['keyval'])

# Retrieve the threshold value for 'role'. Raise
# securesystemslib.exceptions.UnknownRoleError if we were given an invalid
Expand Down

0 comments on commit 1a00d87

Please sign in to comment.