File crypto-policies-opensslcnf.patch of Package crypto-policies

From c941ac758909928f1d0ffa1f9fdd8877a3bb53cf Mon Sep 17 00:00:00 2001
From: Alexander Sosedkin <asosedkin@redhat.com>
Date: Wed, 29 Jan 2025 14:07:55 +0100
Subject: [PATCH] openssl: stop generating `openssl` in favour of `opensslcnf`

---
 python/policygenerators/__init__.py           |   7 +-
 python/policygenerators/openssl.py            | 187 +++++++++---------
 tests/openssl.py                              |  13 +-
 tests/outputs/BSI-openssl.txt                 |   1 -
 tests/outputs/DEFAULT-openssl.txt             |   1 -
 tests/outputs/DEFAULT:GOST-openssl.txt        |   1 -
 tests/outputs/DEFAULT:TEST-PQ-openssl.txt     |   1 -
 tests/outputs/EMPTY-openssl.txt               |   1 -
 tests/outputs/FEDORA40-openssl.txt            |   1 -
 tests/outputs/FIPS-openssl.txt                |   1 -
 tests/outputs/FIPS:ECDHE-ONLY-openssl.txt     |   1 -
 tests/outputs/FIPS:NO-ENFORCE-EMS-openssl.txt |   1 -
 tests/outputs/FIPS:OSPP-openssl.txt           |   1 -
 tests/outputs/FUTURE-openssl.txt              |   1 -
 tests/outputs/GOST-ONLY-openssl.txt           |   1 -
 tests/outputs/LEGACY-openssl.txt              |   1 -
 tests/outputs/LEGACY:AD-SUPPORT-openssl.txt   |   1 -
 tests/outputs/TEST-FEDORA41-openssl.txt       |   1 -
 18 files changed, 97 insertions(+), 125 deletions(-)
 delete mode 100644 tests/outputs/BSI-openssl.txt
 delete mode 100644 tests/outputs/DEFAULT-openssl.txt
 delete mode 100644 tests/outputs/DEFAULT:GOST-openssl.txt
 delete mode 100644 tests/outputs/DEFAULT:TEST-PQ-openssl.txt
 delete mode 100644 tests/outputs/EMPTY-openssl.txt
 delete mode 100644 tests/outputs/FEDORA40-openssl.txt
 delete mode 100644 tests/outputs/FIPS-openssl.txt
 delete mode 100644 tests/outputs/FIPS:ECDHE-ONLY-openssl.txt
 delete mode 100644 tests/outputs/FIPS:NO-ENFORCE-EMS-openssl.txt
 delete mode 100644 tests/outputs/FIPS:OSPP-openssl.txt
 delete mode 100644 tests/outputs/FUTURE-openssl.txt
 delete mode 100644 tests/outputs/GOST-ONLY-openssl.txt
 delete mode 100644 tests/outputs/LEGACY-openssl.txt
 delete mode 100644 tests/outputs/LEGACY:AD-SUPPORT-openssl.txt
 delete mode 100644 tests/outputs/TEST-FEDORA41-openssl.txt

Index: fedora-crypto-policies-20250124.4d262e7/python/policygenerators/__init__.py
===================================================================
--- fedora-crypto-policies-20250124.4d262e7.orig/python/policygenerators/__init__.py
+++ fedora-crypto-policies-20250124.4d262e7/python/policygenerators/__init__.py
@@ -11,11 +11,7 @@ from .krb5 import KRB5Generator
 from .libssh import LibsshGenerator
 from .nss import NSSGenerator
 from .openssh import OpenSSHClientGenerator, OpenSSHServerGenerator
-from .openssl import (
-    OpenSSLConfigGenerator,
-    OpenSSLFIPSGenerator,
-    OpenSSLGenerator,
-)
+from .openssl import OpenSSLFIPSGenerator, OpenSSLGenerator
 #from .sequoia import RPMSequoiaGenerator, SequoiaGenerator
 
 __all__ = [
@@ -27,7 +23,6 @@ __all__ = [
     'NSSGenerator',
     'OpenSSHClientGenerator',
     'OpenSSHServerGenerator',
-    'OpenSSLConfigGenerator',
     'OpenSSLFIPSGenerator',
     'OpenSSLGenerator',
 ]
Index: fedora-crypto-policies-20250124.4d262e7/python/policygenerators/openssl.py
===================================================================
--- fedora-crypto-policies-20250124.4d262e7.orig/python/policygenerators/openssl.py
+++ fedora-crypto-policies-20250124.4d262e7/python/policygenerators/openssl.py
@@ -3,6 +3,7 @@
 # Copyright (c) 2019 Red Hat, Inc.
 # Copyright (c) 2019 Tomáš Mráz <tmraz@fedoraproject.org>
 
+import re
 from subprocess import CalledProcessError, check_output
 
 from .configgenerator import ConfigGenerator
@@ -23,7 +24,7 @@ activate = 1
 
 
 class OpenSSLGenerator(ConfigGenerator):
-    CONFIG_NAME = 'openssl'
+    CONFIG_NAME = 'opensslcnf'
 
     cipher_not_map = {
         'AES-256-CTR': '',
@@ -126,103 +127,6 @@ class OpenSSLGenerator(ConfigGenerator):
         },
     }
 
-    @classmethod
-    def generate_ciphers(cls, policy):
-        s = ''
-        p = policy.enabled
-        ip = policy.disabled
-        # We cannot separate RSA strength from DH params.
-        min_dh_size = policy.integers['min_dh_size']
-        min_rsa_size = policy.integers['min_rsa_size']
-        if min_dh_size < 1023 or min_rsa_size < 1023:
-            s = cls.append(s, '@SECLEVEL=0')
-        elif min_dh_size < 2048 or min_rsa_size < 2048:
-            s = cls.append(s, '@SECLEVEL=1')
-        elif min_dh_size < 3072 or min_rsa_size < 3072:
-            s = cls.append(s, '@SECLEVEL=2')
-        else:
-            s = cls.append(s, '@SECLEVEL=3')
-
-        for i in p['key_exchange']:
-            try:
-                s = cls.append(s, cls.key_exchange_map[i])
-            except KeyError:
-                pass
-
-        for i in ip['key_exchange']:
-            try:
-                s = cls.append(s, cls.key_exchange_not_map[i])
-            except KeyError:
-                pass
-
-        for i in ip['cipher']:
-            try:
-                s = cls.append(s, cls.cipher_not_map[i])
-            except KeyError:
-                pass
-        for keyword, cipherset in cls.cipher_notany_multimap.items():
-            if all(c in ip['cipher'] for c in cipherset):
-                s = cls.append(s, keyword)
-
-        for i in ip['mac']:
-            try:
-                s = cls.append(s, cls.mac_not_map[i])
-            except KeyError:
-                pass
-
-        # These ciphers are not necessary for any
-        # policy level, and only increase the attack surface.
-        # FIXME! must be fixed for custom policies
-        for c in ('-SHA384', '-CAMELLIA', '-ARIA', '-AESCCM8'):
-            s = cls.append(s, c)
-
-        return s
-
-    @classmethod
-    def generate_ciphersuites(cls, policy):
-        s = ''
-        p = policy.enabled
-        # we need the output sorted by order of `cipher`
-        # finer sorting nuances are currently ignored
-        for c in p['cipher']:
-            cipher_submap = {name: spec for name, spec
-                             in cls.ciphersuite_map.items()
-                             if spec['cipher'] == {c}}
-            for ciphersuite_name, ciphersuite_spec in cipher_submap.items():
-                if all(any(val in algvalues for val in p[algclass])
-                       for algclass, algvalues in ciphersuite_spec.items()):
-                    s = cls.append(s, ciphersuite_name)
-        return s
-
-    @classmethod
-    def generate_config(cls, unscoped_policy):
-        policy = unscoped_policy.scoped({'tls', 'ssl', 'openssl'})
-        return cls.generate_ciphers(policy) + '\n'
-
-    @classmethod
-    def test_config(cls, config):
-        output = b''
-        assert config.endswith('\n')  # noqa: S101
-        try:
-            output = check_output(['openssl',  # noqa: S607
-                                   'ciphers', config[:-1]])
-        except CalledProcessError:
-            cls.eprint('There is an error in openssl generated policy')
-            cls.eprint(f'Policy:\n{config}')
-            return False
-        except OSError:
-            # Ignore missing openssl
-            return True
-        if b'NULL' in output or b'ADH' in output:
-            cls.eprint('There is NULL or ADH in openssl generated policy')
-            cls.eprint(f'Policy:\n{config}')
-            return False
-        return True
-
-
-class OpenSSLConfigGenerator(OpenSSLGenerator):
-    CONFIG_NAME = 'opensslcnf'
-
     # has to cover everything c-p has
     protocol_map = {
         'SSL3.0': 'SSLv3',
@@ -340,6 +244,74 @@ class OpenSSLConfigGenerator(OpenSSLGene
     }
 
     @classmethod
+    def generate_ciphers(cls, policy):
+        s = ''
+        p = policy.enabled
+        ip = policy.disabled
+        # We cannot separate RSA strength from DH params.
+        min_dh_size = policy.integers['min_dh_size']
+        min_rsa_size = policy.integers['min_rsa_size']
+        if min_dh_size < 1023 or min_rsa_size < 1023:
+            s = cls.append(s, '@SECLEVEL=0')
+        elif min_dh_size < 2048 or min_rsa_size < 2048:
+            s = cls.append(s, '@SECLEVEL=1')
+        elif min_dh_size < 3072 or min_rsa_size < 3072:
+            s = cls.append(s, '@SECLEVEL=2')
+        else:
+            s = cls.append(s, '@SECLEVEL=3')
+
+        for i in p['key_exchange']:
+            try:
+                s = cls.append(s, cls.key_exchange_map[i])
+            except KeyError:
+                pass
+
+        for i in ip['key_exchange']:
+            try:
+                s = cls.append(s, cls.key_exchange_not_map[i])
+            except KeyError:
+                pass
+
+        for i in ip['cipher']:
+            try:
+                s = cls.append(s, cls.cipher_not_map[i])
+            except KeyError:
+                pass
+        for keyword, cipherset in cls.cipher_notany_multimap.items():
+            if all(c in ip['cipher'] for c in cipherset):
+                s = cls.append(s, keyword)
+
+        for i in ip['mac']:
+            try:
+                s = cls.append(s, cls.mac_not_map[i])
+            except KeyError:
+                pass
+
+        # These ciphers are not necessary for any
+        # policy level, and only increase the attack surface.
+        # FIXME! must be fixed for custom policies
+        for c in ('-SHA384', '-CAMELLIA', '-ARIA', '-AESCCM8'):
+            s = cls.append(s, c)
+
+        return s
+
+    @classmethod
+    def generate_ciphersuites(cls, policy):
+        s = ''
+        p = policy.enabled
+        # we need the output sorted by order of `cipher`
+        # finer sorting nuances are currently ignored
+        for c in p['cipher']:
+            cipher_submap = {name: spec for name, spec
+                             in cls.ciphersuite_map.items()
+                             if spec['cipher'] == {c}}
+            for ciphersuite_name, ciphersuite_spec in cipher_submap.items():
+                if all(any(val in algvalues for val in p[algclass])
+                       for algclass, algvalues in ciphersuite_spec.items()):
+                    s = cls.append(s, ciphersuite_name)
+        return s
+
+    @classmethod
     def generate_config(cls, unscoped_policy):
         policy = unscoped_policy.scoped({'tls', 'ssl', 'openssl'})
         p = policy.enabled
@@ -378,7 +350,24 @@ class OpenSSLConfigGenerator(OpenSSLGene
         return s
 
     @classmethod
-    def test_config(cls, config):  # pylint: disable=unused-argument
+    def test_config(cls, config):
+        output = b''
+        ciphers, = re.findall(r'^CipherString = (.*)$', config, re.MULTILINE)
+
+        try:
+            output = check_output(['openssl',  # noqa: S607
+                                   'ciphers', ciphers])
+        except CalledProcessError:
+            cls.eprint('There is an error in openssl generated policy')
+            cls.eprint(f'Policy:\n{config}')
+            return False
+        except OSError:
+            # Ignore missing openssl
+            return True
+        if b'ADH' in output:
+            cls.eprint('There is ADH in openssl generated policy')
+            cls.eprint(f'Policy:\n{config}')
+            return False
         return True
 
 
Index: fedora-crypto-policies-20250124.4d262e7/tests/openssl.py
===================================================================
--- fedora-crypto-policies-20250124.4d262e7.orig/tests/openssl.py
+++ fedora-crypto-policies-20250124.4d262e7/tests/openssl.py
@@ -1,26 +1,29 @@
 #!/usr/bin/python3
 
+import re
 import subprocess
 import sys
 from pathlib import Path
 
 print('Checking the OpenSSL configuration')
 
-for policy_path in Path('tests', 'outputs').glob('*-openssl.txt'):
-    policy = policy_path.name.removesuffix('-openssl.txt')
+for policy_path in Path('tests', 'outputs').glob('*-opensslcnf.txt'):
+    policy = policy_path.name.removesuffix('-opensslcnf.txt')
     if policy in {'EMPTY', 'GOST-ONLY'}:
         continue
     print(f'Checking policy {policy}')
 
-    tmp = policy_path.read_text(encoding='utf-8').rstrip()
+    ciphers, = re.findall(r'^CipherString = (.*)$',
+                          policy_path.read_text(encoding='utf-8'),
+                          re.MULTILINE)
 
     try:
-        p = subprocess.run(['openssl', 'ciphers', tmp],  # noqa: S607
+        p = subprocess.run(['openssl', 'ciphers', ciphers],  # noqa: S607
                            check=True,
                            encoding='utf-8',
                            stdout=subprocess.PIPE, stderr=subprocess.STDOUT)
     except subprocess.CalledProcessError as e:
         print(f'openssl ciphers error {e.returncode}:', file=sys.stderr)
         print(e.stdout, file=sys.stderr)
-        print(f'ciphers: {tmp}', file=sys.stderr)
+        print(f'ciphers: {ciphers}', file=sys.stderr)
         sys.exit(1)
Index: fedora-crypto-policies-20250124.4d262e7/tests/outputs/BSI-openssl.txt
===================================================================
--- fedora-crypto-policies-20250124.4d262e7.orig/tests/outputs/BSI-openssl.txt
+++ /dev/null
@@ -1 +0,0 @@
-@SECLEVEL=3:kEECDH:kEDH:kPSK:kDHEPSK:kECDHEPSK:kRSAPSK:-kRSA:-aDSS:-CHACHA20:-3DES:!DES:!RC4:!RC2:!IDEA:-SEED:!eNULL:!aNULL:-SHA1:!MD5:-SHA384:-CAMELLIA:-ARIA:-AESCCM8
Index: fedora-crypto-policies-20250124.4d262e7/tests/outputs/DEFAULT-openssl.txt
===================================================================
--- fedora-crypto-policies-20250124.4d262e7.orig/tests/outputs/DEFAULT-openssl.txt
+++ /dev/null
@@ -1 +0,0 @@
-@SECLEVEL=2:kEECDH:kRSA:kEDH:kPSK:kDHEPSK:kECDHEPSK:kRSAPSK:-aDSS:-3DES:!DES:!RC4:!RC2:!IDEA:-SEED:!eNULL:!aNULL:!MD5:-SHA384:-CAMELLIA:-ARIA:-AESCCM8
Index: fedora-crypto-policies-20250124.4d262e7/tests/outputs/DEFAULT:GOST-openssl.txt
===================================================================
--- fedora-crypto-policies-20250124.4d262e7.orig/tests/outputs/DEFAULT:GOST-openssl.txt
+++ /dev/null
@@ -1 +0,0 @@
-@SECLEVEL=2:kGOST:kEECDH:kRSA:kEDH:kPSK:kDHEPSK:kECDHEPSK:kRSAPSK:-aDSS:-3DES:!DES:!RC4:!RC2:!IDEA:-SEED:!eNULL:!aNULL:!MD5:-SHA384:-CAMELLIA:-ARIA:-AESCCM8
Index: fedora-crypto-policies-20250124.4d262e7/tests/outputs/DEFAULT:TEST-PQ-openssl.txt
===================================================================
--- fedora-crypto-policies-20250124.4d262e7.orig/tests/outputs/DEFAULT:TEST-PQ-openssl.txt
+++ /dev/null
@@ -1 +0,0 @@
-@SECLEVEL=2:kEECDH:kRSA:kEDH:kPSK:kDHEPSK:kECDHEPSK:kRSAPSK:-aDSS:-3DES:!DES:!RC4:!RC2:!IDEA:-SEED:!eNULL:!aNULL:!MD5:-SHA384:-CAMELLIA:-ARIA:-AESCCM8
Index: fedora-crypto-policies-20250124.4d262e7/tests/outputs/EMPTY-openssl.txt
===================================================================
--- fedora-crypto-policies-20250124.4d262e7.orig/tests/outputs/EMPTY-openssl.txt
+++ /dev/null
@@ -1 +0,0 @@
-@SECLEVEL=0:-kPSK:-kDHEPSK:-kECDHEPSK:-kRSAPSK:-kEECDH:-kRSA:-aRSA:-aDSS:-AES256:-AES128:-CHACHA20:-SHA256:-3DES:!DES:!RC4:!RC2:!IDEA:-SEED:!eNULL:!aNULL:-CBC:-AESCCM:-AESGCM:-SHA1:!MD5:-SHA384:-CAMELLIA:-ARIA:-AESCCM8
Index: fedora-crypto-policies-20250124.4d262e7/tests/outputs/FEDORA40-openssl.txt
===================================================================
--- fedora-crypto-policies-20250124.4d262e7.orig/tests/outputs/FEDORA40-openssl.txt
+++ /dev/null
@@ -1 +0,0 @@
-@SECLEVEL=2:kEECDH:kRSA:kEDH:kPSK:kDHEPSK:kECDHEPSK:kRSAPSK:-aDSS:-3DES:!DES:!RC4:!RC2:!IDEA:-SEED:!eNULL:!aNULL:!MD5:-SHA384:-CAMELLIA:-ARIA:-AESCCM8
Index: fedora-crypto-policies-20250124.4d262e7/tests/outputs/FIPS-openssl.txt
===================================================================
--- fedora-crypto-policies-20250124.4d262e7.orig/tests/outputs/FIPS-openssl.txt
+++ /dev/null
@@ -1 +0,0 @@
-@SECLEVEL=2:kEECDH:kEDH:kPSK:kDHEPSK:kECDHEPSK:-kRSAPSK:-kRSA:-aDSS:-CHACHA20:-3DES:!DES:!RC4:!RC2:!IDEA:-SEED:!eNULL:!aNULL:!MD5:-SHA384:-CAMELLIA:-ARIA:-AESCCM8
Index: fedora-crypto-policies-20250124.4d262e7/tests/outputs/FIPS:ECDHE-ONLY-openssl.txt
===================================================================
--- fedora-crypto-policies-20250124.4d262e7.orig/tests/outputs/FIPS:ECDHE-ONLY-openssl.txt
+++ /dev/null
@@ -1 +0,0 @@
-@SECLEVEL=2:kEECDH:kECDHEPSK:-kPSK:-kDHEPSK:-kRSAPSK:-kRSA:-aRSA:-aDSS:-CHACHA20:-3DES:!DES:!RC4:!RC2:!IDEA:-SEED:!eNULL:!aNULL:!MD5:-SHA384:-CAMELLIA:-ARIA:-AESCCM8
Index: fedora-crypto-policies-20250124.4d262e7/tests/outputs/FIPS:NO-ENFORCE-EMS-openssl.txt
===================================================================
--- fedora-crypto-policies-20250124.4d262e7.orig/tests/outputs/FIPS:NO-ENFORCE-EMS-openssl.txt
+++ /dev/null
@@ -1 +0,0 @@
-@SECLEVEL=2:kEECDH:kEDH:kPSK:kDHEPSK:kECDHEPSK:-kRSAPSK:-kRSA:-aDSS:-CHACHA20:-3DES:!DES:!RC4:!RC2:!IDEA:-SEED:!eNULL:!aNULL:!MD5:-SHA384:-CAMELLIA:-ARIA:-AESCCM8
Index: fedora-crypto-policies-20250124.4d262e7/tests/outputs/FIPS:OSPP-openssl.txt
===================================================================
--- fedora-crypto-policies-20250124.4d262e7.orig/tests/outputs/FIPS:OSPP-openssl.txt
+++ /dev/null
@@ -1 +0,0 @@
-@SECLEVEL=3:kEECDH:kEDH:kPSK:kDHEPSK:kECDHEPSK:-kRSAPSK:-kRSA:-aDSS:-AES128:-CHACHA20:-3DES:!DES:!RC4:!RC2:!IDEA:-SEED:!eNULL:!aNULL:-AESCCM:-SHA1:!MD5:-SHA384:-CAMELLIA:-ARIA:-AESCCM8
Index: fedora-crypto-policies-20250124.4d262e7/tests/outputs/FUTURE-openssl.txt
===================================================================
--- fedora-crypto-policies-20250124.4d262e7.orig/tests/outputs/FUTURE-openssl.txt
+++ /dev/null
@@ -1 +0,0 @@
-@SECLEVEL=3:kEECDH:kEDH:kPSK:kDHEPSK:kECDHEPSK:-kRSAPSK:-kRSA:-aDSS:-AES128:-SHA256:-3DES:!DES:!RC4:!RC2:!IDEA:-SEED:!eNULL:!aNULL:-CBC:-SHA1:!MD5:-SHA384:-CAMELLIA:-ARIA:-AESCCM8
Index: fedora-crypto-policies-20250124.4d262e7/tests/outputs/GOST-ONLY-openssl.txt
===================================================================
--- fedora-crypto-policies-20250124.4d262e7.orig/tests/outputs/GOST-ONLY-openssl.txt
+++ /dev/null
@@ -1 +0,0 @@
-@SECLEVEL=2:kGOST:-kPSK:-kDHEPSK:-kECDHEPSK:-kRSAPSK:-kEECDH:-kRSA:-aRSA:-aDSS:-AES256:-AES128:-CHACHA20:-SHA256:-3DES:!DES:!RC4:!RC2:!IDEA:-SEED:!eNULL:!aNULL:-CBC:-AESCCM:-AESGCM:-SHA1:!MD5:-SHA384:-CAMELLIA:-ARIA:-AESCCM8
Index: fedora-crypto-policies-20250124.4d262e7/tests/outputs/LEGACY-openssl.txt
===================================================================
--- fedora-crypto-policies-20250124.4d262e7.orig/tests/outputs/LEGACY-openssl.txt
+++ /dev/null
@@ -1 +0,0 @@
-@SECLEVEL=1:kEECDH:kRSA:kEDH:kPSK:kDHEPSK:kECDHEPSK:kRSAPSK:!DES:!RC4:!RC2:!IDEA:-SEED:!eNULL:!aNULL:!MD5:-SHA384:-CAMELLIA:-ARIA:-AESCCM8
Index: fedora-crypto-policies-20250124.4d262e7/tests/outputs/LEGACY:AD-SUPPORT-openssl.txt
===================================================================
--- fedora-crypto-policies-20250124.4d262e7.orig/tests/outputs/LEGACY:AD-SUPPORT-openssl.txt
+++ /dev/null
@@ -1 +0,0 @@
-@SECLEVEL=1:kEECDH:kRSA:kEDH:kPSK:kDHEPSK:kECDHEPSK:kRSAPSK:!DES:!RC4:!RC2:!IDEA:-SEED:!eNULL:!aNULL:!MD5:-SHA384:-CAMELLIA:-ARIA:-AESCCM8
Index: fedora-crypto-policies-20250124.4d262e7/tests/outputs/TEST-FEDORA41-openssl.txt
===================================================================
--- fedora-crypto-policies-20250124.4d262e7.orig/tests/outputs/TEST-FEDORA41-openssl.txt
+++ /dev/null
@@ -1 +0,0 @@
-@SECLEVEL=2:kEECDH:kRSA:kEDH:kPSK:kDHEPSK:kECDHEPSK:kRSAPSK:-aDSS:-3DES:!DES:!RC4:!RC2:!IDEA:-SEED:!eNULL:!aNULL:!MD5:-SHA384:-CAMELLIA:-ARIA:-AESCCM8
openSUSE Build Service is sponsored by