diff options
Diffstat (limited to 'tests/hazmat/primitives/test_pkcs12.py')
-rw-r--r-- | tests/hazmat/primitives/test_pkcs12.py | 202 |
1 files changed, 175 insertions, 27 deletions
diff --git a/tests/hazmat/primitives/test_pkcs12.py b/tests/hazmat/primitives/test_pkcs12.py index f084d578c..297483e2f 100644 --- a/tests/hazmat/primitives/test_pkcs12.py +++ b/tests/hazmat/primitives/test_pkcs12.py @@ -10,61 +10,85 @@ import pytest from cryptography import x509 from cryptography.hazmat.backends.interfaces import DERSerializationBackend +from cryptography.hazmat.backends.openssl.backend import _RC2 +from cryptography.hazmat.primitives import serialization from cryptography.hazmat.primitives.serialization import load_pem_private_key from cryptography.hazmat.primitives.serialization.pkcs12 import ( - load_key_and_certificates + load_key_and_certificates, + serialize_key_and_certificates, ) from .utils import load_vectors_from_file +from ...doubles import DummyKeySerializationEncryption @pytest.mark.requires_backend_interface(interface=DERSerializationBackend) -class TestPKCS12(object): - @pytest.mark.parametrize( - ("filename", "password"), - [ - ("cert-key-aes256cbc.p12", b"cryptography"), - ("cert-none-key-none.p12", b"cryptography"), - ("cert-rc2-key-3des.p12", b"cryptography"), - ("no-password.p12", None), - ] - ) - def test_load_pkcs12_ec_keys(self, filename, password, backend): +class TestPKCS12Loading(object): + def _test_load_pkcs12_ec_keys(self, filename, password, backend): cert = load_vectors_from_file( os.path.join("x509", "custom", "ca", "ca.pem"), lambda pemfile: x509.load_pem_x509_certificate( pemfile.read(), backend - ), mode="rb" + ), + mode="rb", ) key = load_vectors_from_file( os.path.join("x509", "custom", "ca", "ca_key.pem"), lambda pemfile: load_pem_private_key( pemfile.read(), None, backend - ), mode="rb" + ), + mode="rb", ) parsed_key, parsed_cert, parsed_more_certs = load_vectors_from_file( os.path.join("pkcs12", filename), lambda derfile: load_key_and_certificates( derfile.read(), password, backend - ), mode="rb" + ), + mode="rb", ) assert parsed_cert == cert assert parsed_key.private_numbers() == key.private_numbers() assert parsed_more_certs == [] + @pytest.mark.parametrize( + ("filename", "password"), + [ + ("cert-key-aes256cbc.p12", b"cryptography"), + ("cert-none-key-none.p12", b"cryptography"), + ], + ) + def test_load_pkcs12_ec_keys(self, filename, password, backend): + self._test_load_pkcs12_ec_keys(filename, password, backend) + + @pytest.mark.parametrize( + ("filename", "password"), + [ + ("cert-rc2-key-3des.p12", b"cryptography"), + ("no-password.p12", None), + ], + ) + @pytest.mark.supported( + only_if=lambda backend: backend.cipher_supported(_RC2(), None), + skip_message="Does not support RC2", + ) + @pytest.mark.skip_fips(reason="Unsupported algorithm in FIPS mode") + def test_load_pkcs12_ec_keys_rc2(self, filename, password, backend): + self._test_load_pkcs12_ec_keys(filename, password, backend) + def test_load_pkcs12_cert_only(self, backend): cert = load_vectors_from_file( os.path.join("x509", "custom", "ca", "ca.pem"), lambda pemfile: x509.load_pem_x509_certificate( pemfile.read(), backend - ), mode="rb" + ), + mode="rb", ) parsed_key, parsed_cert, parsed_more_certs = load_vectors_from_file( os.path.join("pkcs12", "cert-aes256cbc-no-key.p12"), lambda data: load_key_and_certificates( data.read(), b"cryptography", backend ), - mode="rb" + mode="rb", ) assert parsed_cert is None assert parsed_key is None @@ -75,14 +99,15 @@ class TestPKCS12(object): os.path.join("x509", "custom", "ca", "ca_key.pem"), lambda pemfile: load_pem_private_key( pemfile.read(), None, backend - ), mode="rb" + ), + mode="rb", ) parsed_key, parsed_cert, parsed_more_certs = load_vectors_from_file( os.path.join("pkcs12", "no-cert-key-aes256cbc.p12"), lambda data: load_key_and_certificates( data.read(), b"cryptography", backend ), - mode="rb" + mode="rb", ) assert parsed_key.private_numbers() == key.private_numbers() assert parsed_cert is None @@ -90,15 +115,11 @@ class TestPKCS12(object): def test_non_bytes(self, backend): with pytest.raises(TypeError): - load_key_and_certificates( - b"irrelevant", object(), backend - ) + load_key_and_certificates(b"irrelevant", object(), backend) def test_not_a_pkcs12(self, backend): with pytest.raises(ValueError): - load_key_and_certificates( - b"invalid", b"pass", backend - ) + load_key_and_certificates(b"invalid", b"pass", backend) def test_invalid_password(self, backend): with pytest.raises(ValueError): @@ -106,13 +127,15 @@ class TestPKCS12(object): os.path.join("pkcs12", "cert-key-aes256cbc.p12"), lambda derfile: load_key_and_certificates( derfile.read(), b"invalid", backend - ), mode="rb" + ), + mode="rb", ) def test_buffer_protocol(self, backend): p12 = load_vectors_from_file( os.path.join("pkcs12", "cert-key-aes256cbc.p12"), - lambda derfile: derfile.read(), mode="rb" + lambda derfile: derfile.read(), + mode="rb", ) p12buffer = bytearray(p12) parsed_key, parsed_cert, parsed_more_certs = load_key_and_certificates( @@ -121,3 +144,128 @@ class TestPKCS12(object): assert parsed_key is not None assert parsed_cert is not None assert parsed_more_certs == [] + + +def _load_cert(backend, path): + return load_vectors_from_file( + path, + lambda pemfile: x509.load_pem_x509_certificate( + pemfile.read(), backend + ), + mode="rb", + ) + + +def _load_ca(backend): + cert = _load_cert(backend, os.path.join("x509", "custom", "ca", "ca.pem")) + key = load_vectors_from_file( + os.path.join("x509", "custom", "ca", "ca_key.pem"), + lambda pemfile: load_pem_private_key(pemfile.read(), None, backend), + mode="rb", + ) + return cert, key + + +class TestPKCS12Creation(object): + @pytest.mark.parametrize("name", [None, b"name"]) + @pytest.mark.parametrize( + ("encryption_algorithm", "password"), + [ + (serialization.BestAvailableEncryption(b"password"), b"password"), + (serialization.NoEncryption(), None), + ], + ) + def test_generate(self, backend, name, encryption_algorithm, password): + cert, key = _load_ca(backend) + p12 = serialize_key_and_certificates( + name, key, cert, None, encryption_algorithm + ) + + parsed_key, parsed_cert, parsed_more_certs = load_key_and_certificates( + p12, password, backend + ) + assert parsed_cert == cert + assert parsed_key.private_numbers() == key.private_numbers() + assert parsed_more_certs == [] + + def test_generate_with_cert_key_ca(self, backend): + cert, key = _load_ca(backend) + cert2 = _load_cert( + backend, os.path.join("x509", "custom", "dsa_selfsigned_ca.pem") + ) + cert3 = _load_cert(backend, os.path.join("x509", "letsencryptx3.pem")) + encryption = serialization.NoEncryption() + p12 = serialize_key_and_certificates( + None, key, cert, [cert2, cert3], encryption + ) + + parsed_key, parsed_cert, parsed_more_certs = load_key_and_certificates( + p12, None, backend + ) + assert parsed_cert == cert + assert parsed_key.private_numbers() == key.private_numbers() + assert parsed_more_certs == [cert2, cert3] + + def test_generate_wrong_types(self, backend): + cert, key = _load_ca(backend) + cert2 = _load_cert(backend, os.path.join("x509", "letsencryptx3.pem")) + encryption = serialization.NoEncryption() + with pytest.raises(TypeError) as exc: + serialize_key_and_certificates( + b"name", cert, cert, None, encryption + ) + assert ( + str(exc.value) + == "Key must be RSA, DSA, or EllipticCurve private key." + ) + + with pytest.raises(TypeError) as exc: + serialize_key_and_certificates(b"name", key, key, None, encryption) + assert str(exc.value) == "cert must be a certificate" + + with pytest.raises(TypeError) as exc: + serialize_key_and_certificates(b"name", key, cert, None, key) + assert str(exc.value) == ( + "Key encryption algorithm must be a " + "KeySerializationEncryption instance" + ) + + with pytest.raises(TypeError) as exc: + serialize_key_and_certificates(None, key, cert, cert2, encryption) + + with pytest.raises(TypeError) as exc: + serialize_key_and_certificates(None, key, cert, [key], encryption) + assert str(exc.value) == "all values in cas must be certificates" + + def test_generate_no_cert(self, backend): + _, key = _load_ca(backend) + p12 = serialize_key_and_certificates( + None, key, None, None, serialization.NoEncryption() + ) + parsed_key, parsed_cert, parsed_more_certs = load_key_and_certificates( + p12, None, backend + ) + assert parsed_cert is None + assert parsed_key.private_numbers() == key.private_numbers() + assert parsed_more_certs == [] + + def test_must_supply_something(self): + with pytest.raises(ValueError) as exc: + serialize_key_and_certificates( + None, None, None, None, serialization.NoEncryption() + ) + assert str(exc.value) == ( + "You must supply at least one of key, cert, or cas" + ) + + def test_generate_unsupported_encryption_type(self, backend): + cert, key = _load_ca(backend) + with pytest.raises(ValueError) as exc: + serialize_key_and_certificates( + None, + key, + cert, + None, + DummyKeySerializationEncryption(), + ) + assert str(exc.value) == "Unsupported key encryption type" |