From 1bc176770e45113bc6d8d5a3810cc7285aa9b716 Mon Sep 17 00:00:00 2001 From: Daniel Elero Date: Wed, 21 Aug 2019 15:24:45 +0200 Subject: [PATCH 1/2] Update formats --- securesystemslib/formats.py | 107 +++++++++++++++++++++++------------- securesystemslib/keys.py | 4 +- tests/test_formats.py | 2 +- 3 files changed, 72 insertions(+), 41 deletions(-) diff --git a/securesystemslib/formats.py b/securesystemslib/formats.py index e85ca6d9..533e1ad4 100755 --- a/securesystemslib/formats.py +++ b/securesystemslib/formats.py @@ -287,35 +287,9 @@ keyid_hash_algorithms = SCHEMA.Optional(HASHALGORITHMS_SCHEMA), keyval = KEYVAL_SCHEMA) -# A single signature of an object. Indicates the signature, and the KEYID of -# the signing key. I debated making the signature schema not contain the key -# ID and instead have the signatures of a file be a dictionary with the key -# being the keyid and the value being the signature schema without the keyid. -# That would be under the argument that a key should only be able to sign a -# file once. -SIGNATURE_SCHEMA = SCHEMA.Object( - object_name = 'SIGNATURE_SCHEMA', - keyid = KEYID_SCHEMA, - sig = HEX_SCHEMA) - -SIGNATURES_SCHEMA = SCHEMA.ListOf(SIGNATURE_SCHEMA) - -# A signable object. Holds the signing role and its associated signatures. -SIGNABLE_SCHEMA = SCHEMA.Object( - object_name = 'SIGNABLE_SCHEMA', - signed = SCHEMA.Any(), - signatures = SCHEMA.ListOf(SIGNATURE_SCHEMA)) - -# A dict where the dict keys hold a keyid and the dict values a key object. -KEYDICT_SCHEMA = SCHEMA.DictOf( - key_schema = KEYID_SCHEMA, - value_schema = KEY_SCHEMA) - - - - -ANY_STRING_SCHEMA = SCHEMA.AnyString() -LIST_OF_ANY_STRING_SCHEMA = SCHEMA.ListOf(ANY_STRING_SCHEMA) +GPG_HASH_ALGORITHM_STRING = "pgp+SHA2" +GPG_RSA_PUBKEY_METHOD_STRING = "pgp+rsa-pkcsv1.5" +GPG_DSA_PUBKEY_METHOD_STRING = "pgp+dsa-fips-180-2" def _create_gpg_pubkey_with_subkey_schema(pubkey_schema): """Helper method to extend the passed public key schema with an optional @@ -335,17 +309,12 @@ def _create_gpg_pubkey_with_subkey_schema(pubkey_schema): schema._required.append(subkey_schema_tuple) # pylint: disable=protected-access return schema -GPG_HASH_ALGORITHM_STRING = "pgp+SHA2" -GPG_RSA_PUBKEY_METHOD_STRING = "pgp+rsa-pkcsv1.5" -GPG_DSA_PUBKEY_METHOD_STRING = "pgp+dsa-fips-180-2" - GPG_RSA_PUBKEYVAL_SCHEMA = SCHEMA.Object( object_name = "GPG_RSA_PUBKEYVAL_SCHEMA", e = SCHEMA.AnyString(), n = HEX_SCHEMA ) - # We have to define GPG_RSA_PUBKEY_SCHEMA in two steps, because it is # self-referential. Here we define a shallow _GPG_RSA_PUBKEY_SCHEMA, which we # use below to create the self-referential GPG_RSA_PUBKEY_SCHEMA. @@ -365,7 +334,6 @@ def _create_gpg_pubkey_with_subkey_schema(pubkey_schema): GPG_RSA_PUBKEY_SCHEMA = _create_gpg_pubkey_with_subkey_schema( _GPG_RSA_PUBKEY_SCHEMA) - GPG_DSA_PUBKEYVAL_SCHEMA = SCHEMA.Object( object_name = "GPG_DSA_PUBKEYVAL_SCHEMA", y = HEX_SCHEMA, @@ -374,7 +342,6 @@ def _create_gpg_pubkey_with_subkey_schema(pubkey_schema): g = HEX_SCHEMA ) - # We have to define GPG_DSA_PUBKEY_SCHEMA in two steps, because it is # self-referential. Here we define a shallow _GPG_DSA_PUBKEY_SCHEMA, which we # use below to create the self-referential GPG_DSA_PUBKEY_SCHEMA. @@ -391,14 +358,13 @@ def _create_gpg_pubkey_with_subkey_schema(pubkey_schema): private = SCHEMA.String("") ) ) + GPG_DSA_PUBKEY_SCHEMA = _create_gpg_pubkey_with_subkey_schema( _GPG_DSA_PUBKEY_SCHEMA) - GPG_PUBKEY_SCHEMA = SCHEMA.OneOf([GPG_RSA_PUBKEY_SCHEMA, GPG_DSA_PUBKEY_SCHEMA]) - GPG_SIGNATURE_SCHEMA = SCHEMA.Object( object_name = "SIGNATURE_SCHEMA", keyid = KEYID_SCHEMA, @@ -408,6 +374,71 @@ def _create_gpg_pubkey_with_subkey_schema(pubkey_schema): info = SCHEMA.Optional(SCHEMA.Any()), ) +# A single signature of an object. Indicates the signature, and the KEYID of +# the signing key. I debated making the signature schema not contain the key +# ID and instead have the signatures of a file be a dictionary with the key +# being the keyid and the value being the signature schema without the keyid. +# That would be under the argument that a key should only be able to sign a +# file once. +SIGNATURE_SCHEMA = SCHEMA.Object( + object_name = 'SIGNATURE_SCHEMA', + keyid = KEYID_SCHEMA, + sig = HEX_SCHEMA) + +# A schema holding the result of checking the signatures of a particular +# 'SIGNABLE_SCHEMA' role. +# For example, how many of the signatures for the 'Target' role are +# valid? This SCHEMA holds this information. See 'sig.py' for +# more information. +SIGNATURESTATUS_SCHEMA = SCHEMA.Object( + object_name = 'SIGNATURESTATUS_SCHEMA', + threshold = SCHEMA.Integer(), + good_sigs = KEYIDS_SCHEMA, + bad_sigs = KEYIDS_SCHEMA, + unknown_sigs = KEYIDS_SCHEMA, + untrusted_sigs = KEYIDS_SCHEMA) + +# A dict where the dict keys hold a keyid and the dict values a key object. +KEYDICT_SCHEMA = SCHEMA.DictOf( + key_schema = KEYID_SCHEMA, + value_schema = KEY_SCHEMA) + +ANY_SIGNATURE_SCHEMA = securesystemslib.schema.OneOf([SIGNATURE_SCHEMA, + GPG_SIGNATURE_SCHEMA]) + +# List of ANY_SIGNATURE_SCHEMA. +SIGNATURES_SCHEMA = SCHEMA.ListOf(ANY_SIGNATURE_SCHEMA) + +# A signable object. Holds the signing role and its associated signatures. +SIGNABLE_SCHEMA = SCHEMA.Object( + object_name = 'SIGNABLE_SCHEMA', + signed = SCHEMA.Any(), + signatures = SIGNATURES_SCHEMA) + +# Note: Verification keys can have private portions but in case of GPG we +# only have a PUBKEY_SCHEMA (because we never export private gpg keys from +# the gpg keyring) +ANY_VERIFICATION_KEY_SCHEMA = SCHEMA.OneOf([ANYKEY_SCHEMA, + GPG_PUBKEY_SCHEMA]) + +VERIFICATION_KEY_DICT_SCHEMA = SCHEMA.DictOf( + key_schema = KEYID_SCHEMA, + value_schema = ANY_VERIFICATION_KEY_SCHEMA) + +ANY_KEYDICT_SCHEMA = SCHEMA.OneOf([KEYDICT_SCHEMA, + VERIFICATION_KEY_DICT_SCHEMA]) + +ANY_PUBKEY_SCHEMA = SCHEMA.OneOf([PUBLIC_KEY_SCHEMA, GPG_PUBKEY_SCHEMA]) + +ANY_PUBKEY_DICT_SCHEMA = SCHEMA.DictOf( + key_schema = KEYID_SCHEMA, + value_schema = ANY_PUBKEY_SCHEMA) + +ANY_STRING_SCHEMA = SCHEMA.AnyString() +LIST_OF_ANY_STRING_SCHEMA = SCHEMA.ListOf(ANY_STRING_SCHEMA) + + + def datetime_to_unix_timestamp(datetime_object): diff --git a/securesystemslib/keys.py b/securesystemslib/keys.py index ac558bfc..e0376db1 100755 --- a/securesystemslib/keys.py +++ b/securesystemslib/keys.py @@ -836,10 +836,10 @@ def verify_signature(key_dict, signature, data): # This check will ensure 'key_dict' has the appropriate number # of objects and object types, and that all dict keys are properly named. # Raise 'securesystemslib.exceptions.FormatError' if the check fails. - securesystemslib.formats.ANYKEY_SCHEMA.check_match(key_dict) + securesystemslib.formats.ANY_VERIFICATION_KEY_SCHEMA.check_match(key_dict) # Does 'signature' have the correct format? - securesystemslib.formats.SIGNATURE_SCHEMA.check_match(signature) + securesystemslib.formats.ANY_SIGNATURE_SCHEMA.check_match(signature) # Verify that the KEYID in 'key_dict' matches the KEYID listed in the # 'signature'. diff --git a/tests/test_formats.py b/tests/test_formats.py index 984cd453..a5c4e5c3 100755 --- a/tests/test_formats.py +++ b/tests/test_formats.py @@ -171,7 +171,7 @@ def test_schemas(self): 'method': 'evp', 'sig': 'A4582BCF323BCEF'}]}), - 'KEYDICT_SCHEMA': (securesystemslib.formats.KEYDICT_SCHEMA, + 'ANY_KEYDICT_SCHEMA': (securesystemslib.formats.ANY_KEYDICT_SCHEMA, {'123abc': {'keytype': 'rsa', 'scheme': 'rsassa-pss-sha256', 'keyval': {'public': 'pubkey', 'private': 'privkey'}}})} From 358ca336fd08254cdad8afce2977b52226be05b2 Mon Sep 17 00:00:00 2001 From: Daniel Elero Date: Fri, 20 Sep 2019 14:20:11 +0200 Subject: [PATCH 2/2] Addrss CR comments --- securesystemslib/formats.py | 20 ++++---------------- securesystemslib/keys.py | 4 ++-- 2 files changed, 6 insertions(+), 18 deletions(-) diff --git a/securesystemslib/formats.py b/securesystemslib/formats.py index 533e1ad4..8659f57f 100755 --- a/securesystemslib/formats.py +++ b/securesystemslib/formats.py @@ -86,6 +86,9 @@ # additional keys which are not defined. Thus, any additions to them will be # easily backwards compatible with clients that are already deployed. +ANY_STRING_SCHEMA = SCHEMA.AnyString() +LIST_OF_ANY_STRING_SCHEMA = SCHEMA.ListOf(ANY_STRING_SCHEMA) + # A datetime in 'YYYY-MM-DDTHH:MM:SSZ' ISO 8601 format. The "Z" zone designator # for the zero UTC offset is always used (i.e., a numerical offset is not # supported.) Example: '2015-10-21T13:20:00Z'. Note: This is a simple format @@ -287,6 +290,7 @@ keyid_hash_algorithms = SCHEMA.Optional(HASHALGORITHMS_SCHEMA), keyval = KEYVAL_SCHEMA) +# GPG key scheme definitions GPG_HASH_ALGORITHM_STRING = "pgp+SHA2" GPG_RSA_PUBKEY_METHOD_STRING = "pgp+rsa-pkcsv1.5" GPG_DSA_PUBKEY_METHOD_STRING = "pgp+dsa-fips-180-2" @@ -385,19 +389,6 @@ def _create_gpg_pubkey_with_subkey_schema(pubkey_schema): keyid = KEYID_SCHEMA, sig = HEX_SCHEMA) -# A schema holding the result of checking the signatures of a particular -# 'SIGNABLE_SCHEMA' role. -# For example, how many of the signatures for the 'Target' role are -# valid? This SCHEMA holds this information. See 'sig.py' for -# more information. -SIGNATURESTATUS_SCHEMA = SCHEMA.Object( - object_name = 'SIGNATURESTATUS_SCHEMA', - threshold = SCHEMA.Integer(), - good_sigs = KEYIDS_SCHEMA, - bad_sigs = KEYIDS_SCHEMA, - unknown_sigs = KEYIDS_SCHEMA, - untrusted_sigs = KEYIDS_SCHEMA) - # A dict where the dict keys hold a keyid and the dict values a key object. KEYDICT_SCHEMA = SCHEMA.DictOf( key_schema = KEYID_SCHEMA, @@ -434,9 +425,6 @@ def _create_gpg_pubkey_with_subkey_schema(pubkey_schema): key_schema = KEYID_SCHEMA, value_schema = ANY_PUBKEY_SCHEMA) -ANY_STRING_SCHEMA = SCHEMA.AnyString() -LIST_OF_ANY_STRING_SCHEMA = SCHEMA.ListOf(ANY_STRING_SCHEMA) - diff --git a/securesystemslib/keys.py b/securesystemslib/keys.py index e0376db1..ac558bfc 100755 --- a/securesystemslib/keys.py +++ b/securesystemslib/keys.py @@ -836,10 +836,10 @@ def verify_signature(key_dict, signature, data): # This check will ensure 'key_dict' has the appropriate number # of objects and object types, and that all dict keys are properly named. # Raise 'securesystemslib.exceptions.FormatError' if the check fails. - securesystemslib.formats.ANY_VERIFICATION_KEY_SCHEMA.check_match(key_dict) + securesystemslib.formats.ANYKEY_SCHEMA.check_match(key_dict) # Does 'signature' have the correct format? - securesystemslib.formats.ANY_SIGNATURE_SCHEMA.check_match(signature) + securesystemslib.formats.SIGNATURE_SCHEMA.check_match(signature) # Verify that the KEYID in 'key_dict' matches the KEYID listed in the # 'signature'.