From 69d2e23f2e454c759a86064be2fa3525501d9e08 Mon Sep 17 00:00:00 2001 From: Quentin Retourne <32574188+nitneuqr@users.noreply.github.com> Date: Thu, 12 Sep 2024 22:44:11 +0200 Subject: [PATCH] more tests for 100% python coverage --- .../hazmat/primitives/serialization/pkcs7.py | 7 +- tests/hazmat/primitives/test_pkcs7.py | 94 ++++++++++++++++++- 2 files changed, 95 insertions(+), 6 deletions(-) diff --git a/src/cryptography/hazmat/primitives/serialization/pkcs7.py b/src/cryptography/hazmat/primitives/serialization/pkcs7.py index 08c6a51bd95a..3a47339ab979 100644 --- a/src/cryptography/hazmat/primitives/serialization/pkcs7.py +++ b/src/cryptography/hazmat/primitives/serialization/pkcs7.py @@ -306,7 +306,7 @@ def set_recipient( raise TypeError("certificate must be a x509.Certificate") if not isinstance(certificate.public_key(), rsa.RSAPublicKey): - raise TypeError("Only RSA keys are supported at this time.") + raise TypeError("Only RSA public keys are supported at this time.") return PKCS7EnvelopeDecryptor( _data=self._data, @@ -320,6 +320,11 @@ def set_private_key( if self._private_key is not None: raise ValueError("private key may only be set once") + if not isinstance(private_key, rsa.RSAPrivateKey): + raise TypeError( + "Only RSA private keys are supported at this time." + ) + return PKCS7EnvelopeDecryptor( _data=self._data, _recipient=self._recipient, diff --git a/tests/hazmat/primitives/test_pkcs7.py b/tests/hazmat/primitives/test_pkcs7.py index 9a70e12ad6a6..2d2edf1181fd 100644 --- a/tests/hazmat/primitives/test_pkcs7.py +++ b/tests/hazmat/primitives/test_pkcs7.py @@ -6,6 +6,7 @@ import email.parser import os import typing +from email.message import EmailMessage import pytest @@ -1087,6 +1088,12 @@ def test_set_data_twice(self, backend): with pytest.raises(ValueError): decryptor.set_data(b"test") + def test_set_recipient_twice(self, backend): + cert, _ = _load_rsa_cert_key() + decryptor = pkcs7.PKCS7EnvelopeDecryptor().set_recipient(cert) + with pytest.raises(ValueError): + decryptor.set_recipient(cert) + def test_unsupported_encryption(self, backend): cert_non_rsa, _ = _load_cert_key() with pytest.raises(TypeError): @@ -1098,10 +1105,17 @@ def test_not_a_cert(self, backend): b"notacert", # type: ignore[arg-type] ) - def test_decrypt_no_recipient(self, backend): - decryptor = pkcs7.PKCS7EnvelopeDecryptor().set_data(b"test") + def test_set_private_key_twice(self, backend): + _, private_key = _load_rsa_cert_key() + decryptor = pkcs7.PKCS7EnvelopeDecryptor().set_private_key(private_key) with pytest.raises(ValueError): - decryptor.decrypt(serialization.Encoding.SMIME, []) + decryptor.set_private_key(private_key) + + def test_not_a_pkey(self, backend): + with pytest.raises(TypeError): + pkcs7.PKCS7EnvelopeDecryptor().set_private_key( + b"notapkey", # type: ignore[arg-type] + ) def test_decrypt_no_data(self, backend): cert, _ = _load_rsa_cert_key() @@ -1109,19 +1123,62 @@ def test_decrypt_no_data(self, backend): with pytest.raises(ValueError): decryptor.decrypt(serialization.Encoding.SMIME, []) - def test_decrypt_invalid_options(self, backend): + def test_decrypt_no_recipient(self, backend): + decryptor = pkcs7.PKCS7EnvelopeDecryptor().set_data(b"test") + with pytest.raises(ValueError): + decryptor.decrypt(serialization.Encoding.SMIME, []) + + def test_decrypt_no_private_key(self, backend): cert, _ = _load_rsa_cert_key() decryptor = ( pkcs7.PKCS7EnvelopeDecryptor() .set_data(b"test") .set_recipient(cert) ) + with pytest.raises(ValueError): + decryptor.decrypt(serialization.Encoding.SMIME, []) + + @pytest.fixture + def decryptor(self, backend) -> pkcs7.PKCS7EnvelopeDecryptor: + cert, private_key = _load_rsa_cert_key() + return ( + pkcs7.PKCS7EnvelopeDecryptor() + .set_data(b"test") + .set_recipient(cert) + .set_private_key(private_key) + ) + + def test_decrypt_invalid_options( + self, backend, decryptor: pkcs7.PKCS7EnvelopeDecryptor + ): with pytest.raises(ValueError): decryptor.decrypt( serialization.Encoding.SMIME, [b"invalid"], # type: ignore[list-item] ) + def test_decrypt_invalid_encoding( + self, backend, decryptor: pkcs7.PKCS7EnvelopeDecryptor + ): + with pytest.raises(ValueError): + decryptor.decrypt(serialization.Encoding.Raw, []) + + @pytest.mark.parametrize( + "invalid_options", + [ + [pkcs7.PKCS7Options.NoAttributes], + [pkcs7.PKCS7Options.NoCapabilities], + [pkcs7.PKCS7Options.NoCerts], + [pkcs7.PKCS7Options.DetachedSignature], + [pkcs7.PKCS7Options.Binary, pkcs7.PKCS7Options.Text], + ], + ) + def test_encrypt_invalid_encryption_options( + self, backend, invalid_options, decryptor: pkcs7.PKCS7EnvelopeDecryptor + ): + with pytest.raises(ValueError): + decryptor.decrypt(serialization.Encoding.DER, invalid_options) + @pytest.mark.parametrize( ("encoding", "options"), [ @@ -1134,7 +1191,6 @@ def test_decrypt_invalid_options(self, backend): ], ) def test_smime_decrypt(self, backend, encoding, options): - """Testing the round-trip of encrypting and decrypting data.""" # Encrypt some data plain = b"hello world\n" cert, private_key = _load_rsa_cert_key() @@ -1154,6 +1210,23 @@ def test_smime_decrypt(self, backend, encoding, options): decrypted = decryptor.decrypt(encoding, options) assert decrypted == plain + def test_smime_decrypt_not_encrypted(self, backend): + # Create a plain email + email_message = EmailMessage() + email_message.set_content("hello world\n") + + # Test decryption failure with plain email + cert, private_key = _load_rsa_cert_key() + decryptor = ( + pkcs7.PKCS7EnvelopeDecryptor() + .set_data(email_message.as_bytes()) + .set_recipient(cert) + .set_private_key(private_key) + ) + + with pytest.raises(ValueError): + decryptor.decrypt(serialization.Encoding.SMIME, []) + @pytest.mark.supported( only_if=lambda backend: backend.pkcs7_supported(), @@ -1253,3 +1326,14 @@ class TestPKCS7EnvelopeBuilderUnsupported: def test_envelope_builder_unsupported(self, backend): with raises_unsupported_algorithm(_Reasons.UNSUPPORTED_PADDING): pkcs7.PKCS7EnvelopeBuilder() + + +@pytest.mark.supported( + only_if=lambda backend: backend.pkcs7_supported() + and not backend.rsa_encryption_supported(padding.PKCS1v15()), + skip_message="Requires OpenSSL with no PKCS1 v1.5 padding support", +) +class TestPKCS7EnvelopeDecryptorUnsupported: + def test_envelope_builder_unsupported(self, backend): + with raises_unsupported_algorithm(_Reasons.UNSUPPORTED_PADDING): + pkcs7.PKCS7EnvelopeDecryptor()