commit fd676c50ad13682953f2a2a664ea891f4938a821 Author: James Antill Date: Mon Aug 8 14:02:14 2022 -0400 Import rpm: 5c743a97fdb06d99fc583a7be55ea1dd0050dd6f diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..7f4ecd9 --- /dev/null +++ b/.gitignore @@ -0,0 +1 @@ +SOURCES/cryptography-2.8.tar.gz diff --git a/0001-Block-TripleDES-in-FIPS-mode-6879.patch b/0001-Block-TripleDES-in-FIPS-mode-6879.patch new file mode 100644 index 0000000..b3821b6 --- /dev/null +++ b/0001-Block-TripleDES-in-FIPS-mode-6879.patch @@ -0,0 +1,71 @@ +From d250d169e87168903a543248d0bfd6c37f2f6841 Mon Sep 17 00:00:00 2001 +From: Christian Heimes +Date: Tue, 22 Feb 2022 00:37:32 +0200 +Subject: [PATCH 1/5] Block TripleDES in FIPS mode (#6879) + +* Block TripleDES in FIPS mode + +NIST SP-800-131A rev 2 lists TripleDES Encryption as disallowed in FIPS 140-3 +decryption as legacy use. Three-key TDEA is listed as deprecated +throughout 2023 and disallowed after 2023. + +For simplicity we block all use of TripleDES in FIPS mode. + +Fixes: #6875 +Signed-off-by: Christian Heimes + +* Fix flake +--- + src/cryptography/hazmat/backends/openssl/backend.py | 13 ++++++------- + tests/hazmat/primitives/utils.py | 4 ++++ + 2 files changed, 10 insertions(+), 7 deletions(-) + +diff --git a/src/cryptography/hazmat/backends/openssl/backend.py b/src/cryptography/hazmat/backends/openssl/backend.py +index 736452392..f38269e26 100644 +--- a/src/cryptography/hazmat/backends/openssl/backend.py ++++ b/src/cryptography/hazmat/backends/openssl/backend.py +@@ -134,7 +134,9 @@ class Backend(BackendInterface): + b"aes-192-gcm", + b"aes-256-gcm", + } +- _fips_ciphers = (AES, TripleDES) ++ # TripleDES encryption is disallowed/deprecated throughout 2023 in ++ # FIPS 140-3. To keep it simple we denylist any use of TripleDES (TDEA). ++ _fips_ciphers = (AES,) + # Sometimes SHA1 is still permissible. That logic is contained + # within the various *_supported methods. + _fips_hashes = ( +@@ -323,12 +325,9 @@ class Backend(BackendInterface): + + def cipher_supported(self, cipher, mode): + if self._fips_enabled: +- # FIPS mode requires AES or TripleDES, but only CBC/ECB allowed +- # in TripleDES mode. +- if not isinstance(cipher, self._fips_ciphers) or ( +- isinstance(cipher, TripleDES) +- and not isinstance(mode, (CBC, ECB)) +- ): ++ # FIPS mode requires AES. TripleDES is disallowed/deprecated in ++ # FIPS 140-3. ++ if not isinstance(cipher, self._fips_ciphers): + return False + + try: +diff --git a/tests/hazmat/primitives/utils.py b/tests/hazmat/primitives/utils.py +index 93f117828..a367343ca 100644 +--- a/tests/hazmat/primitives/utils.py ++++ b/tests/hazmat/primitives/utils.py +@@ -469,6 +469,10 @@ def _kbkdf_cmac_counter_mode_test(backend, prf, ctr_loc, params): + algorithm = supported_cipher_algorithms.get(prf) + assert algorithm is not None + ++ # TripleDES is disallowed in FIPS mode. ++ if backend._fips_enabled and algorithm is algorithms.TripleDES: ++ pytest.skip("TripleDES is not supported in FIPS mode.") ++ + ctrkdf = KBKDFCMAC( + algorithm, + Mode.CounterMode, +-- +2.35.1 + diff --git a/0002-Disable-DSA-tests-in-FIPS-mode-6916.patch b/0002-Disable-DSA-tests-in-FIPS-mode-6916.patch new file mode 100644 index 0000000..311bca5 --- /dev/null +++ b/0002-Disable-DSA-tests-in-FIPS-mode-6916.patch @@ -0,0 +1,319 @@ +From ff80e3a27408657fef599f44ae1a9a875e005685 Mon Sep 17 00:00:00 2001 +From: Christian Heimes +Date: Wed, 2 Mar 2022 21:47:04 +0200 +Subject: [PATCH 2/5] Disable DSA tests in FIPS mode (#6916) + +* Disable DSA tests in FIPS mode + +See: #6880 + +* ignore coverage for nested FIPS check + +* Remove if branch + +* Remove skip modulus branch + +* Keep tests that don't use the backend +--- + .../hazmat/backends/openssl/backend.py | 7 ++- + tests/hazmat/primitives/test_dsa.py | 46 +++++++++++-------- + tests/hazmat/primitives/test_serialization.py | 24 ++++++++++ + tests/x509/test_x509.py | 43 ++++++++++++++--- + tests/x509/test_x509_ext.py | 4 ++ + 5 files changed, 98 insertions(+), 26 deletions(-) + +diff --git a/src/cryptography/hazmat/backends/openssl/backend.py b/src/cryptography/hazmat/backends/openssl/backend.py +index f38269e26..a6d0e8872 100644 +--- a/src/cryptography/hazmat/backends/openssl/backend.py ++++ b/src/cryptography/hazmat/backends/openssl/backend.py +@@ -804,7 +804,12 @@ class Backend(BackendInterface): + self.openssl_assert(res == 1) + return evp_pkey + +- def dsa_hash_supported(self, algorithm): ++ def dsa_supported(self) -> bool: ++ return not self._fips_enabled ++ ++ def dsa_hash_supported(self, algorithm: hashes.HashAlgorithm) -> bool: ++ if not self.dsa_supported(): ++ return False + return self.hash_supported(algorithm) + + def dsa_parameters_supported(self, p, q, g): +diff --git a/tests/hazmat/primitives/test_dsa.py b/tests/hazmat/primitives/test_dsa.py +index 6028b600d..60681683d 100644 +--- a/tests/hazmat/primitives/test_dsa.py ++++ b/tests/hazmat/primitives/test_dsa.py +@@ -59,7 +59,12 @@ def test_skip_if_dsa_not_supported(backend): + _skip_if_dsa_not_supported(backend, DummyHashAlgorithm(), 1, 1, 1) + + +-class TestDSA(object): ++ ++@pytest.mark.supported( ++ only_if=lambda backend: backend.dsa_supported(), ++ skip_message="Does not support DSA.", ++) ++class TestDSA: + def test_generate_dsa_parameters(self, backend): + parameters = dsa.generate_parameters(2048, backend) + assert isinstance(parameters, dsa.DSAParameters) +@@ -76,11 +81,6 @@ class TestDSA(object): + ), + ) + def test_generate_dsa_keys(self, vector, backend): +- if ( +- backend._fips_enabled +- and vector["p"] < backend._fips_dsa_min_modulus +- ): +- pytest.skip("Small modulus blocked in FIPS mode") + parameters = dsa.DSAParameterNumbers( + p=vector["p"], q=vector["q"], g=vector["g"] + ).parameters(backend) +@@ -389,7 +389,12 @@ class TestDSA(object): + ).private_key(backend) + + +-class TestDSAVerification(object): ++ ++@pytest.mark.supported( ++ only_if=lambda backend: backend.dsa_supported(), ++ skip_message="Does not support DSA.", ++) ++class TestDSAVerification: + def test_dsa_verification(self, backend, subtests): + vectors = load_vectors_from_file( + os.path.join("asymmetric", "DSA", "FIPS_186-3", "SigVer.rsp"), +@@ -481,17 +486,12 @@ class TestDSAVerification(object): + Prehashed(hashes.SHA1()) # type: ignore[arg-type] + ) + +- def test_prehashed_unsupported_in_verifier_ctx(self, backend): +- public_key = DSA_KEY_1024.private_key(backend).public_key() +- with pytest.raises(TypeError), pytest.warns( +- CryptographyDeprecationWarning +- ): +- public_key.verifier( +- b"0" * 64, Prehashed(hashes.SHA1()) # type: ignore[arg-type] +- ) +- + +-class TestDSASignature(object): ++@pytest.mark.supported( ++ only_if=lambda backend: backend.dsa_supported(), ++ skip_message="Does not support DSA.", ++) ++class TestDSASignature: + def test_dsa_signing(self, backend, subtests): + vectors = load_vectors_from_file( + os.path.join("asymmetric", "DSA", "FIPS_186-3", "SigGen.txt"), +@@ -695,7 +695,11 @@ class TestDSANumberEquality(object): + assert priv != object() + + +-class TestDSASerialization(object): ++@pytest.mark.supported( ++ only_if=lambda backend: backend.dsa_supported(), ++ skip_message="Does not support DSA.", ++) ++class TestDSASerialization: + @pytest.mark.parametrize( + ("fmt", "password"), + itertools.product( +@@ -916,7 +920,11 @@ class TestDSASerialization(object): + ) + + +-class TestDSAPEMPublicKeySerialization(object): ++@pytest.mark.supported( ++ only_if=lambda backend: backend.dsa_supported(), ++ skip_message="Does not support DSA.", ++) ++class TestDSAPEMPublicKeySerialization: + @pytest.mark.parametrize( + ("key_path", "loader_func", "encoding"), + [ +diff --git a/tests/hazmat/primitives/test_serialization.py b/tests/hazmat/primitives/test_serialization.py +index fb6b753de..5a2b9fba5 100644 +--- a/tests/hazmat/primitives/test_serialization.py ++++ b/tests/hazmat/primitives/test_serialization.py +@@ -141,6 +141,10 @@ class TestDERSerialization(object): + assert isinstance(key, rsa.RSAPrivateKey) + _check_rsa_private_numbers(key.private_numbers()) + ++ @pytest.mark.supported( ++ only_if=lambda backend: backend.dsa_supported(), ++ skip_message="Does not support DSA.", ++ ) + @pytest.mark.parametrize( + ("key_path", "password"), + [ +@@ -341,6 +345,10 @@ class TestDERSerialization(object): + with pytest.raises(ValueError): + load_der_public_key(b"invalid data", backend) + ++ @pytest.mark.supported( ++ only_if=lambda backend: backend.dsa_supported(), ++ skip_message="Does not support DSA.", ++ ) + @pytest.mark.parametrize( + "key_file", + [ +@@ -422,6 +430,10 @@ class TestPEMSerialization(object): + assert isinstance(key, rsa.RSAPrivateKey) + _check_rsa_private_numbers(key.private_numbers()) + ++ @pytest.mark.supported( ++ only_if=lambda backend: backend.dsa_supported(), ++ skip_message="Does not support DSA.", ++ ) + @pytest.mark.parametrize( + ("key_path", "password"), + [ +@@ -490,6 +502,10 @@ class TestPEMSerialization(object): + numbers = key.public_numbers() + assert numbers.e == 65537 + ++ @pytest.mark.supported( ++ only_if=lambda backend: backend.dsa_supported(), ++ skip_message="Does not support DSA.", ++ ) + @pytest.mark.parametrize( + ("key_file"), + [ +@@ -894,6 +910,10 @@ class TestPEMSerialization(object): + 16, + ) + ++ @pytest.mark.supported( ++ only_if=lambda backend: backend.dsa_supported(), ++ skip_message="Does not support DSA.", ++ ) + def test_load_pem_dsa_private_key(self, backend): + key = load_vectors_from_file( + os.path.join("asymmetric", "PKCS8", "unenc-dsa-pkcs8.pem"), +@@ -2313,6 +2333,10 @@ class TestOpenSSHSerialization(object): + DummyKeySerializationEncryption(), + ) + ++ @pytest.mark.supported( ++ only_if=lambda backend: backend.dsa_supported(), ++ skip_message="Does not support DSA.", ++ ) + @pytest.mark.parametrize( + ("key_path", "supported"), + [ +diff --git a/tests/x509/test_x509.py b/tests/x509/test_x509.py +index 23e97a768..7a7a52977 100644 +--- a/tests/x509/test_x509.py ++++ b/tests/x509/test_x509.py +@@ -2561,7 +2561,21 @@ class TestCertificateBuilder(object): + only_if=lambda backend: backend.hash_supported(hashes.MD5()), + skip_message="Requires OpenSSL with MD5 support", + ) +- def test_sign_dsa_with_md5(self, backend): ++ @pytest.mark.supported( ++ only_if=lambda backend: backend.dsa_supported(), ++ skip_message="Does not support DSA.", ++ ) ++ @pytest.mark.parametrize( ++ "hash_algorithm", ++ [ ++ hashes.MD5(), ++ hashes.SHA3_224(), ++ hashes.SHA3_256(), ++ hashes.SHA3_384(), ++ hashes.SHA3_512(), ++ ], ++ ) ++ def test_sign_dsa_with_unsupported_hash(self, hash_algorithm, backend): + private_key = DSA_KEY_2048.private_key(backend) + builder = x509.CertificateBuilder() + builder = ( +@@ -2602,6 +2616,10 @@ class TestCertificateBuilder(object): + with pytest.raises(ValueError): + builder.sign(private_key, hashes.MD5(), backend) + ++ @pytest.mark.supported( ++ only_if=lambda backend: backend.dsa_supported(), ++ skip_message="Does not support DSA.", ++ ) + @pytest.mark.parametrize( + ("hashalg", "hashalg_oid"), + [ +@@ -2615,9 +2633,6 @@ class TestCertificateBuilder(object): + def test_build_cert_with_dsa_private_key( + self, hashalg, hashalg_oid, backend + ): +- if backend._fips_enabled and hashalg is hashes.SHA1: +- pytest.skip("SHA1 not supported in FIPS mode") +- + issuer_private_key = DSA_KEY_2048.private_key(backend) + subject_private_key = DSA_KEY_2048.private_key(backend) + +@@ -3646,6 +3661,10 @@ class TestCertificateSigningRequestBuilder(object): + only_if=lambda backend: backend.hash_supported(hashes.MD5()), + skip_message="Requires OpenSSL with MD5 support", + ) ++ @pytest.mark.supported( ++ only_if=lambda backend: backend.dsa_supported(), ++ skip_message="Does not support DSA.", ++ ) + def test_sign_dsa_with_md5(self, backend): + private_key = DSA_KEY_2048.private_key(backend) + builder = x509.CertificateSigningRequestBuilder().subject_name( +@@ -3969,6 +3988,10 @@ class TestCertificateSigningRequestBuilder(object): + assert basic_constraints.value.ca is True + assert basic_constraints.value.path_length == 2 + ++ @pytest.mark.supported( ++ only_if=lambda backend: backend.dsa_supported(), ++ skip_message="Does not support DSA.", ++ ) + def test_build_ca_request_with_dsa(self, backend): + private_key = DSA_KEY_2048.private_key(backend) + +@@ -4319,7 +4342,11 @@ class TestCertificateSigningRequestBuilder(object): + builder.sign(private_key, hashes.SHA512(), backend) + + +-class TestDSACertificate(object): ++@pytest.mark.supported( ++ only_if=lambda backend: backend.dsa_supported(), ++ skip_message="Does not support DSA.", ++) ++class TestDSACertificate: + def test_load_dsa_cert(self, backend): + cert = _load_cert( + os.path.join("x509", "custom", "dsa_selfsigned_ca.pem"), +@@ -4444,7 +4471,11 @@ class TestDSACertificate(object): + ) + + +-class TestDSACertificateRequest(object): ++@pytest.mark.supported( ++ only_if=lambda backend: backend.dsa_supported(), ++ skip_message="Does not support DSA.", ++) ++class TestDSACertificateRequest: + @pytest.mark.parametrize( + ("path", "loader_func"), + [ +diff --git a/tests/x509/test_x509_ext.py b/tests/x509/test_x509_ext.py +index 4173dece6..66ac43d95 100644 +--- a/tests/x509/test_x509_ext.py ++++ b/tests/x509/test_x509_ext.py +@@ -1712,6 +1712,10 @@ class TestSubjectKeyIdentifierExtension(object): + ski = x509.SubjectKeyIdentifier.from_public_key(cert.public_key()) + assert ext.value == ski + ++ @pytest.mark.supported( ++ only_if=lambda backend: backend.dsa_supported(), ++ skip_message="Does not support DSA.", ++ ) + def test_from_dsa_public_key(self, backend): + cert = _load_cert( + os.path.join("x509", "custom", "dsa_selfsigned_ca.pem"), +-- +2.35.1 + diff --git a/0003-fixes-6927-handle-negative-return-values-from-openss.patch b/0003-fixes-6927-handle-negative-return-values-from-openss.patch new file mode 100644 index 0000000..fa3979f --- /dev/null +++ b/0003-fixes-6927-handle-negative-return-values-from-openss.patch @@ -0,0 +1,26 @@ +From 20bafea414bcc08bfcb5b669ecbf9a3438ff7b78 Mon Sep 17 00:00:00 2001 +From: Alex Gaynor +Date: Thu, 3 Mar 2022 15:44:02 -0500 +Subject: [PATCH 3/5] fixes #6927 -- handle negative return values from openssl + (#6928) + +--- + src/cryptography/hazmat/backends/openssl/rsa.py | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/src/cryptography/hazmat/backends/openssl/rsa.py b/src/cryptography/hazmat/backends/openssl/rsa.py +index 9bef49d24..dd5d4990b 100644 +--- a/src/cryptography/hazmat/backends/openssl/rsa.py ++++ b/src/cryptography/hazmat/backends/openssl/rsa.py +@@ -208,7 +208,7 @@ def _rsa_sig_setup(backend, padding, algorithm, key, init_func): + if algorithm is not None: + evp_md = backend._evp_md_non_null_from_algorithm(algorithm) + res = backend._lib.EVP_PKEY_CTX_set_signature_md(pkey_ctx, evp_md) +- if res == 0: ++ if res <= 0: + backend._consume_errors() + raise UnsupportedAlgorithm( + "{} is not supported by this backend for RSA signing.".format( +-- +2.35.1 + diff --git a/0004-Disable-test_openssl_assert_error_on_stack-in-FIPS-m.patch b/0004-Disable-test_openssl_assert_error_on_stack-in-FIPS-m.patch new file mode 100644 index 0000000..7afce54 --- /dev/null +++ b/0004-Disable-test_openssl_assert_error_on_stack-in-FIPS-m.patch @@ -0,0 +1,24 @@ +From 820d9527070ad2c7724dcecf1a35dbac7d68621d Mon Sep 17 00:00:00 2001 +From: Christian Heimes +Date: Tue, 1 Mar 2022 16:22:51 +0100 +Subject: [PATCH 4/5] Disable test_openssl_assert_error_on_stack in FIPS mode + +--- + tests/hazmat/bindings/test_openssl.py | 1 + + 1 file changed, 1 insertion(+) + +diff --git a/tests/hazmat/bindings/test_openssl.py b/tests/hazmat/bindings/test_openssl.py +index 129928ac0..9839aec4d 100644 +--- a/tests/hazmat/bindings/test_openssl.py ++++ b/tests/hazmat/bindings/test_openssl.py +@@ -84,6 +84,7 @@ class TestOpenSSL(object): + with pytest.raises(AttributeError): + b.lib.TLS_ST_OK + ++ @pytest.mark.skip_fips(reason="FIPS maps to different error codes") + def test_openssl_assert_error_on_stack(self): + b = Binding() + b.lib.ERR_put_error( +-- +2.35.1 + diff --git a/0005-Fixed-serialization-of-keyusage-ext-with-no-bits-693.patch b/0005-Fixed-serialization-of-keyusage-ext-with-no-bits-693.patch new file mode 100644 index 0000000..7f2ff56 --- /dev/null +++ b/0005-Fixed-serialization-of-keyusage-ext-with-no-bits-693.patch @@ -0,0 +1,67 @@ +From 89af85f9d4fc2ef3e89ad1b2a58c751f00f54a4f Mon Sep 17 00:00:00 2001 +From: Alex Gaynor +Date: Thu, 3 Mar 2022 16:24:21 -0500 +Subject: [PATCH 5/5] Fixed serialization of keyusage ext with no bits (#6930) + +fixes #6926 +--- + src/rust/src/x509/extensions.rs | 17 +++++++++++------ + tests/x509/test_x509_ext.py | 14 ++++++++++++++ + 2 files changed, 25 insertions(+), 6 deletions(-) + +diff --git a/src/rust/src/x509/extensions.rs b/src/rust/src/x509/extensions.rs +index 606566dd9..68b9839a0 100644 +--- a/src/rust/src/x509/extensions.rs ++++ b/src/rust/src/x509/extensions.rs +@@ -135,12 +135,17 @@ pub(crate) fn encode_extension( + certificate::set_bit(&mut bs, 7, ext.getattr("encipher_only")?.is_true()?); + certificate::set_bit(&mut bs, 8, ext.getattr("decipher_only")?.is_true()?); + } +- let bits = if bs[1] == 0 { &bs[..1] } else { &bs[..] }; +- let unused_bits = bits.last().unwrap().trailing_zeros() as u8; +- Ok(Some(asn1::write_single(&asn1::BitString::new( +- bits, +- unused_bits, +- )))) ++ let (bits, unused_bits) = if bs[1] == 0 { ++ if bs[0] == 0 { ++ (&[][..], 0) ++ } else { ++ (&bs[..1], bs[0].trailing_zeros() as u8) ++ } ++ } else { ++ (&bs[..], bs[1].trailing_zeros() as u8) ++ }; ++ let v = asn1::BitString::new(bits, unused_bits).unwrap(); ++ Ok(Some(asn1::write_single(&v))) + } else if oid == &*oid::AUTHORITY_INFORMATION_ACCESS_OID + || oid == &*oid::SUBJECT_INFORMATION_ACCESS_OID + { +diff --git a/tests/x509/test_x509_ext.py b/tests/x509/test_x509_ext.py +index 66ac43d95..2bbba8ec6 100644 +--- a/tests/x509/test_x509_ext.py ++++ b/tests/x509/test_x509_ext.py +@@ -1137,6 +1137,20 @@ class TestKeyUsage(object): + ), + b"\x03\x02\x02\x94", + ), ++ ( ++ x509.KeyUsage( ++ digital_signature=False, ++ content_commitment=False, ++ key_encipherment=False, ++ data_encipherment=False, ++ key_agreement=False, ++ key_cert_sign=False, ++ crl_sign=False, ++ encipher_only=False, ++ decipher_only=False, ++ ), ++ b"\x03\x01\x00", ++ ), + ], + ) + def test_public_bytes(self, ext, serialized): +-- +2.35.1 + diff --git a/README.md b/README.md new file mode 100644 index 0000000..33554c0 --- /dev/null +++ b/README.md @@ -0,0 +1,59 @@ +# PyCA cryptography + +https://cryptography.io/en/latest/ + +## Packaging python-cryptography + +The example assumes + +* Fedora Rawhide (f34) +* PyCA cryptography release ``3.4`` +* Update Bugzilla issue is ``RHBZ#00000001`` + +### Build new python-cryptography + +Switch and update branch + +```shell +fedpkg switch-branch rawhide +fedpkg pull +``` + +Bump version and get sources + +```shell +rpmdev-bumpspec -c "Update to 3.4 (#00000001)" -n 3.4 python-cryptography.spec +spectool -gf python-cryptography.spec +``` + +Upload new source + +```shell +fedpkg new-sources cryptography-3.4.tar.gz +``` + +Commit changes + +```shell +fedpkg commit --clog +fedpkg push +``` + +Build + +```shell +fedpkg build +``` + +## RHEL/CentOS builds + +RHEL and CentOS use a different approach for Rust crates packaging than +Fedora. On Fedora Rust dependencies are packaged as RPMs, e.g. +``rust-pyo3+default-devel`` RPM. These packages don't exist on RHEL and +CentOS. Instead python-cryptography uses a tar ball with vendored crates. +The tar ball is created by a script: + +```shell +./vendor_rust.py +rhpkg upload cryptography-3.4-vendor.tar.bz2 +``` diff --git a/conftest-skipper.py b/conftest-skipper.py new file mode 100644 index 0000000..5a1de83 --- /dev/null +++ b/conftest-skipper.py @@ -0,0 +1,22 @@ + +class Skipper: + """Skip iso8601 and pretend tests + + RHEL buildroot doesn't have python-iso8601 and python-pretend. Skip + all tests that use the excluded modules. + """ + + def parse_date(self, datestring): + pytest.skip(f"iso8601 module is not available.") + + def stub(self, **kwargs): + pytest.skip(f"pretend module is not available.") + + def raiser(self, exc): + pytest.skip(f"pretend module is not available.") + + +import sys + +sys.modules["iso8601"] = sys.modules["pretend"] = Skipper() + diff --git a/gating.yaml b/gating.yaml new file mode 100644 index 0000000..6f49862 --- /dev/null +++ b/gating.yaml @@ -0,0 +1,7 @@ +# recipients: abokovoy, frenaud, kaleem, ftrivino, cheimes +--- !Policy +product_versions: + - rhel-9 +decision_context: osci_compose_gate +rules: + - !PassingTestCaseRule {test_case_name: osci.brew-build.tier0.functional} diff --git a/python-cryptography.spec b/python-cryptography.spec new file mode 100644 index 0000000..6620f64 --- /dev/null +++ b/python-cryptography.spec @@ -0,0 +1,239 @@ +%if 0%{?fedora} || 0%{?rhel} > 7 +# Enable python3 build by default +%bcond_without python3 +%else +%bcond_with python3 +%endif + +%if 0%{?fedora} > 31 || 0%{?rhel} > 7 +# Disable python2 build by default +%bcond_with python2 +%else +%bcond_without python2 +%endif + +%bcond_with tests + +%{!?python3_pkgversion:%global python3_pkgversion 3} + +%global srcname cryptography + +Name: python-%{srcname} +Version: 2.8 +Release: 3%{?dist} +Summary: PyCA's cryptography library + +License: ASL 2.0 or BSD +URL: https://cryptography.io/en/latest/ +Source0: https://pypi.io/packages/source/c/%{srcname}/%{srcname}-%{version}.tar.gz + +# Exclude i686 arch. Due to a modularity issue it's being added to the +# x86_64 compose of CRB, but we don't want to ship it at all. +# See: https://projects.engineering.redhat.com/browse/RCM-72605 +ExcludeArch: i686 + +BuildRequires: openssl-devel +BuildRequires: gcc + +%if 0%{?with_python2} +BuildRequires: python2-asn1crypto >= 0.21 +BuildRequires: python2-cffi >= 1.7 +BuildRequires: python2-cryptography-vectors = %{version} +BuildRequires: python2-devel +BuildRequires: python2-enum34 +BuildRequires: python2-idna >= 2.1 +BuildRequires: python2-ipaddress +BuildRequires: python2-setuptools +BuildRequires: python2-six >= 1.4.1 + +%if %{with tests} +BuildRequires: python2-hypothesis >= 1.11.4 +BuildRequires: python2-iso8601 +BuildRequires: python2-pretend +BuildRequires: python2-pytest >= 3.2.1 +BuildRequires: python2-pytz +%endif +%endif + +%if 0%{?with_python3} +BuildRequires: python%{python3_pkgversion}-asn1crypto >= 0.21 +BuildRequires: python%{python3_pkgversion}-cffi >= 1.7 +BuildRequires: python%{python3_pkgversion}-devel +BuildRequires: python%{python3_pkgversion}-idna >= 2.1 +BuildRequires: python%{python3_pkgversion}-setuptools +BuildRequires: python%{python3_pkgversion}-six >= 1.4.1 +BuildRequires: python%{python3_pkgversion}-rpm-macros + +%if %{with tests} +BuildRequires: python%{python3_pkgversion}-cryptography-vectors = %{version} +BuildRequires: python%{python3_pkgversion}-hypothesis >= 1.11.4 +BuildRequires: python%{python3_pkgversion}-iso8601 +BuildRequires: python%{python3_pkgversion}-pretend +BuildRequires: python%{python3_pkgversion}-pytest >= 3.2.1 +BuildRequires: python%{python3_pkgversion}-pytz +%endif +%endif + +%description +cryptography is a package designed to expose cryptographic primitives and +recipes to Python developers. + +%if 0%{?with_python2} +%package -n python2-%{srcname} +Summary: PyCA's cryptography library + +%if 0%{?with_python3} +%{?python_provide:%python_provide python2-%{srcname}} +%else +Provides: python-%{srcname} +%endif + +Requires: openssl-libs +Requires: python2-idna >= 2.1 +Requires: python2-asn1crypto >= 0.21 +Requires: python2-six >= 1.4.1 +Requires: python2-cffi >= 1.7 +Requires: python2-enum34 +Requires: python2-ipaddress + +%description -n python2-%{srcname} +cryptography is a package designed to expose cryptographic primitives and +recipes to Python developers. +%endif + +%if 0%{?with_python3} +%package -n python%{python3_pkgversion}-%{srcname} +Summary: PyCA's cryptography library +%{?python_provide:%python_provide python%{python3_pkgversion}-%{srcname}} + +Requires: openssl-libs +Requires: python%{python3_pkgversion}-idna >= 2.1 +Requires: python%{python3_pkgversion}-asn1crypto >= 0.21 +Requires: python%{python3_pkgversion}-six >= 1.4.1 +Requires: python%{python3_pkgversion}-cffi >= 1.7 + +%description -n python%{python3_pkgversion}-%{srcname} +cryptography is a package designed to expose cryptographic primitives and +recipes to Python developers. +%endif + +%prep +%autosetup -p1 -n %{srcname}-%{version} + +%build +%if 0%{?with_python2} +%py2_build +%endif +%if 0%{?with_python3} +%py3_build +%endif + +%install +# Actually other *.c and *.h are appropriate +# see https://github.com/pyca/cryptography/issues/1463 +find . -name .keep -print -delete + +%if 0%{?with_python2} +%py2_install +%endif +%if 0%{?with_python3} +%py3_install +%endif + +%check +%if %{with tests} +%if 0%{?with_python2} +# see https://github.com/pyca/cryptography/issues/4885 and +# see https://bugzilla.redhat.com/show_bug.cgi?id=1761194 for deselected tests +PYTHONPATH=%{buildroot}%{python2_sitearch} %{__python2} -m pytest -k "not (test_buffer_protocol_alternate_modes or test_dh_parameters_supported or test_load_ecdsa_no_named_curve)" +%endif + +%if 0%{?with_python3} +PYTHONPATH=%{buildroot}%{python3_sitearch} %{__python3} -m pytest -k "not (test_buffer_protocol_alternate_modes or test_dh_parameters_supported or test_load_ecdsa_no_named_curve)" +%endif +%endif + + +%if 0%{?with_python2} +%files -n python2-%{srcname} +%doc LICENSE LICENSE.APACHE LICENSE.BSD README.rst docs +%{python2_sitearch}/%{srcname} +%{python2_sitearch}/%{srcname}-%{version}-py*.egg-info +%endif + + +%if 0%{?with_python3} +%files -n python%{python3_pkgversion}-%{srcname} +%doc README.rst docs +%license LICENSE LICENSE.APACHE LICENSE.BSD +%{python3_sitearch}/%{srcname} +%{python3_sitearch}/%{srcname}-%{version}-py*.egg-info +%endif + + +%changelog +* Fri Dec 13 2019 Tomas Orsava - 2.8-3 +- Exclude unsupported i686 arch + +* Thu Nov 21 2019 Lumír Balhar - 2.8-2 +- Adjusted for Python 3.8 module in RHEL 8 + +* Thu Oct 17 2019 Christian Heimes - 2.8-1 +- Update to 2.8 +- Resolves: rhbz#1762779 + +* Sun Oct 13 2019 Christian Heimes - 2.7-3 +- Skip unit tests that fail with OpenSSL 1.1.1.d +- Resolves: rhbz#1761194 +- Fix and simplify Python 3 packaging + +* Sat Oct 12 2019 Christian Heimes - 2.7-2 +- Drop Python 2 package +- Resolves: rhbz#1761081 + +* Tue Sep 03 2019 Randy Barlow - 2.7-1 +- Update to 2.7 (#1715680). + +* Fri Aug 16 2019 Miro Hrončok - 2.6.1-3 +- Rebuilt for Python 3.8 + +* Fri Jul 26 2019 Fedora Release Engineering - 2.6.1-2 +- Rebuilt for https://fedoraproject.org/wiki/Fedora_31_Mass_Rebuild + +* Thu Feb 28 2019 Christian Heimes - 2.6.1-1 +- New upstream release 2.6.1, resolves RHBZ#1683691 + +* Wed Feb 13 2019 Alfredo Moralejo - 2.5-1 +- Updated to 2.5. + +* Sat Feb 02 2019 Fedora Release Engineering - 2.3-3 +- Rebuilt for https://fedoraproject.org/wiki/Fedora_30_Mass_Rebuild + +* Mon Aug 13 2018 Christian Heimes - 2.3-2 +- Use TLSv1.2 in test as workaround for RHBZ#1615143 + +* Wed Jul 18 2018 Christian Heimes - 2.3-1 +- New upstream release 2.3 +- Fix AEAD tag truncation bug, RHBZ#1602752 + +* Fri Jul 13 2018 Fedora Release Engineering - 2.2.1-3 +- Rebuilt for https://fedoraproject.org/wiki/Fedora_29_Mass_Rebuild + +* Fri Jun 15 2018 Miro Hrončok - 2.2.1-2 +- Rebuilt for Python 3.7 + +* Wed Mar 21 2018 Christian Heimes - 2.2.1-1 +- New upstream release 2.2.1 + +* Sun Feb 18 2018 Christian Heimes - 2.1.4-1 +- New upstream release 2.1.4 + +* Sun Feb 18 2018 Christian Heimes - 2.1.3-4 +- Build requires gcc + +* Mon Feb 12 2018 Iryna Shcherbina - 2.1.3-3 +- Update Python 2 dependency declarations to new packaging standards + (See https://fedoraproject.org/wiki/FinalizingFedoraSwitchtoPython3) + +* Fri Feb 09 2018 Fedora Release Engineering - 2.1.3-2 +- Rebuilt for https://fedoraproject.org/wiki/Fedora_28_Mass_Rebuild diff --git a/sources b/sources new file mode 100644 index 0000000..567f837 --- /dev/null +++ b/sources @@ -0,0 +1 @@ +SHA1 (cryptography-2.8.tar.gz) = 94ef5dc1261a4388572ce3ad9af1515691276d2c diff --git a/tests/tests.yml b/tests/tests.yml new file mode 100644 index 0000000..115b5a9 --- /dev/null +++ b/tests/tests.yml @@ -0,0 +1,67 @@ +--- +# +# 1minutetip --buildroot rhel9 +# + +- hosts: localhost + tags: + - classic + roles: + - role: standard-test-source + + - role: standard-test-basic + required_packages: + - python3-cryptography + - python3-pytest + - python3-pytest-subtests + environment: + PYTHONPATH: "{{ srcdir }}/vectors" + tests: + - remove_hypothesis: + # remove tests that depend on python3-hypothesis package + dir: "source" + run: rm -rf tests/hypothesis/ + - remove_iso8601: + # remove tests that depend on python3-iso8601 package + dir: "source" + run: rm -rf tests/test_fernet.py + - remove_scrypt: + # scrypt tests require more memory than available + dir: "source" + run: rm -f tests/hazmat/primitives/test_scrypt.py + - patch_conftest: + dir: "source" + run: "cat ../conftest-skipper.py >> tests/conftest.py" + # tests take some time, split up to avoid CI timeouts. + - unittests-basic: + dir: "source" + run: pytest-3 tests/test_*.py + - unittests-x509: + dir: "source" + run: pytest-3 tests/x509/ + - unittests-hazmat: + dir: "source" + run: pytest-3 -k 'not test_openssl_memleak' tests/hazmat/backends/ tests/hazmat/bindings/ + - unittests-primitives-aead: + dir: "source" + run: pytest-3 tests/hazmat/primitives/test_aead.py + - unittests-primitives-aes: + dir: "source" + run: >- + pytest-3 + tests/hazmat/primitives/test_aes.py::TestAESModeCBC + tests/hazmat/primitives/test_aes.py::TestAESModeCTR + tests/hazmat/primitives/test_aes_gcm.py::TestAESModeGCM + - unittests-primitives-a-e: + dir: "source" + run: >- + pytest-3 + tests/hazmat/primitives/test_arc4.py + tests/hazmat/primitives/test_asym_utils.py + tests/hazmat/primitives/test_[b-e]*.py + - unittests-primitives-f-z: + dir: "source" + run: >- + pytest-3 + tests/hazmat/primitives/test_[f-z]*.py + tests/hazmat/primitives/twofactor diff --git a/vendor_rust.py b/vendor_rust.py new file mode 100755 index 0000000..cd8355e --- /dev/null +++ b/vendor_rust.py @@ -0,0 +1,112 @@ +#!/usr/bin/python3 +"""Vendor PyCA cryptography's Rust crates +""" +import argparse +import os +import re +import tarfile +import tempfile +import shutil +import subprocess +import sys + +VENDOR_DIR = "vendor" +CARGO_TOML = "src/rust/Cargo.toml" +RE_VERSION = re.compile("Version:\s*(.*)") + +parser = argparse.ArgumentParser(description="Vendor Rust packages") +parser.add_argument( + "--spec", default="python-cryptography.spec", help="cryptography source tar bundle" +) + + +def cargo(cmd, manifest): + args = ["cargo", cmd, f"--manifest-path={manifest}"] + return subprocess.check_call( + args, stdout=subprocess.DEVNULL, stderr=sys.stderr, env={} + ) + + +def tar_reset(tarinfo): + """Reset user, group, mtime, and mode to create reproducible tar""" + tarinfo.uid = 0 + tarinfo.gid = 0 + tarinfo.uname = "root" + tarinfo.gname = "root" + tarinfo.mtime = 0 + if tarinfo.type == tarfile.DIRTYPE: + tarinfo.mode = 0o755 + else: + tarinfo.mode = 0o644 + if tarinfo.pax_headers: + raise ValueError(tarinfo.name, tarinfo.pax_headers) + return tarinfo + + +def tar_reproducible(tar, basedir): + """Create reproducible tar file""" + + content = [basedir] + for root, dirs, files in os.walk(basedir): + for directory in dirs: + content.append(os.path.join(root, directory)) + for filename in files: + content.append(os.path.join(root, filename)) + content.sort() + + for fn in content: + tar.add(fn, filter=tar_reset, recursive=False, arcname=fn) + + +def main(): + args = parser.parse_args() + spec = args.spec + + # change cwd to work in bundle directory + here = os.path.dirname(os.path.abspath(spec)) + os.chdir(here) + + # extract version number from bundle name + with open(spec) as f: + for line in f: + mo = RE_VERSION.search(line) + if mo is not None: + version = mo.group(1) + break + else: + raise ValueError(f"Cannot find version in {spec}") + + bundle_file = f"cryptography-{version}.tar.gz" + vendor_file = f"cryptography-{version}-vendor.tar.bz2" + + # remove existing vendor directory and file + if os.path.isdir(VENDOR_DIR): + shutil.rmtree(VENDOR_DIR) + try: + os.unlink(vendor_file) + except FileNotFoundError: + pass + + print(f"Getting crates for {bundle_file}", file=sys.stderr) + + # extract tar file in tempdir + # fetch and vendor Rust crates + with tempfile.TemporaryDirectory(dir=here) as tmp: + with tarfile.open(bundle_file) as tar: + tar.extractall(path=tmp) + manifest = os.path.join(tmp, f"cryptography-{version}", CARGO_TOML) + cargo("fetch", manifest) + cargo("vendor", manifest) + + print("\nCreating tar ball...", file=sys.stderr) + with tarfile.open(vendor_file, "x:bz2") as tar: + tar_reproducible(tar, VENDOR_DIR) + + # remove vendor dir + shutil.rmtree(VENDOR_DIR) + + parser.exit(0, f"Created {vendor_file}\n") + + +if __name__ == "__main__": + main()