Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Implement TAP 9 (Mandatory metadata signing schemes) #48

Merged
merged 35 commits into from
Aug 11, 2017

Conversation

vladimir-v-diaz
Copy link
Contributor

TAP 9 removes the method attribute from signed metadata to prevent malicious actors from controlling it. Instead, the signature scheme is now specified in the "signed" portion of metadata.

This pull request refactors a few functions to accept a signature scheme argument. In addition, the signature scheme is now included in the "keys" field of signed metadata.

TAP 9 and this implementation are backwards incompatible.

The create_signature() functions for keys.py and the specific library modules (e.g., pyca_crypto_keys.py) should
be refactored to accept a 'scheme' argument
create_rsa_signature() and verify_rsa_signature() refactored to accept scheme argument
@coveralls
Copy link

Coverage Status

Coverage remained the same at 100.0% when pulling 1628118 on vladimir-v-diaz:tap9 into 42f8ae4 on secure-systems-lab:master.

@vladimir-v-diaz vladimir-v-diaz merged commit 13bdc05 into secure-systems-lab:master Aug 11, 2017
Copy link
Member

@lukpueh lukpueh left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ignored pycrypto related diff, which is removed in #62.

@@ -179,12 +179,19 @@ def create_signature(public_key, private_key, data):
data:
Byte data used by create_signature() to generate the signature returned.

scheme:
The signature scheme used to generate the signature. For example:
'ecesa-sha2-nistp256'.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ecdsa-sha2-nistp256

<Exceptions>
securesystemslib.exceptions.FormatError, if the arguments are improperly
formatted.

securesystemslib.exceptions.CryptoError, if a signature cannot be created.

securesystemslib.exceptions.UnsupportedAlgorithmError, if 'scheme' is
an not one of the supported signature schemes.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

-an

@@ -126,21 +126,21 @@ def generate_public_and_private(algorithm='ecdsa-sha2-nistp256'):
# supported ECDSA algorithms. It must conform to
# 'securesystemslib.formats.ECDSAALGORITHMS_SCHEMA'. Raise
# 'securesystemslib.exceptions.FormatError' if the check fails.
securesystemslib.formats.ECDSAALGORITHMS_SCHEMA.check_match(algorithm)
securesystemslib.formats.ECDSA_SIG_SCHEMA.check_match(scheme)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Shouldn't this be ECDSA_SIG_SCHEME_SCHEMA now? (just kidding)

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It's actually not purely a joke. Currently the schemas for signatures and signature schemes are not really distinguishable by their names. So *_SIG_SCHEME_SCHEMA might not be the worst of ideas? Especially since there already is a SIG_SCHEME_SCHEMA. :)

password=None, backend=default_backend())
# A defensive check for a valid 'scheme'. The check_match() above
# should have already validated it...
if scheme == 'ecdsa-sha2-nistp256': #pragma: no cover
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't see a reason for doing the exact same check twice in a row. I don't see a big problem either, but it feels strange to me to redo what ECDSA_SIG_SCHEMA.check_match(scheme) already does.

However, I would definitely remove the #pragma: no cover here, because that disables the decreased coverage alert when you remove tests that touch code inside the if-block.

Also, I'm not sure if it is a good idea to fail with different errors FormatError vs. UnsupportedAlgorithmError.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Maybe you can wrapECDSA_SIG_SCHEMA.check_match(scheme) in a try/except block and raise UnsupportedAlgorithmError on FormatError?

@@ -126,21 +126,21 @@ def generate_public_and_private(algorithm='ecdsa-sha2-nistp256'):
# supported ECDSA algorithms. It must conform to
# 'securesystemslib.formats.ECDSAALGORITHMS_SCHEMA'. Raise
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

There are still a couple of mentionings of algorithm that probably should be scheme now in comments, also the UnsupportedAlgorithmError is still used for unsupported schemes. I guess this is not a big deal.

keyid = KEYID_SCHEMA,
keyid_hash_algorithms = SCHEMA.Optional(HASHALGORITHMS_SCHEMA),
keyval = KEYVAL_SCHEMA)

# ECDSA signature schemes.
ECDSA_SIG_SCHEMA = SCHEMA.OneOf([SCHEMA.String('ecdsa-sha2-nistp256')])
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ECDSA_SIG_SCHEMA is already assigned in L187

# Is 'scheme' one of the supported ECDSA signature schemes? A defensive
# check for a valid 'scheme'. The check_match() above should have validated
# it...
if scheme in _SUPPORTED_ECDSA_SCHEMES: #pragma: no cover
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

See comment above about redundant checks with different Errors and #pragma: no cover. Btw. it seems that this comment applies to various places throughout the PR.

The ECDSA algorithm. By default, ECDSA NIST P-256 is used, with SHA256
for hashing.

<Exceptions>
securesystemslib.exceptions.FormatError, if 'algorithm' is improperly or invalid
(i.e., not one of the supported ECDSA algorithms).
securesystemslib.exceptions.FormatError, if 'algorithm' is improperly or
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

s/algorithm/scheme/ (not only here)

# encrypted, or if the key was encrypted but no password was supplied.
# Note: A passphrase or password is not used when generating
# 'private_key', since it should not be encrypted.
except TypeError: #pragma: no cover
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Any reason for the #pragma: no cover here and with the ValueError above?

# encrypted with a symmetric cipher that is not supported by the backend.
except cryptography.exceptions.UnsupportedAlgorithm: #pragma: no cover
raise securesystemslib.exceptions.CryptoError('The private key is'
' encrypted with a unsupported algorithm.')
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

+n

vladimir-v-diaz added a commit that referenced this pull request Nov 6, 2017
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants