From 472e46554fb46c64fdc96012607bfe22ab1358f4 Mon Sep 17 00:00:00 2001 From: Francisco Trivino Date: Fri, 27 May 2022 17:31:40 +0200 Subject: [PATCH] Vault: Migrate to RSA-OAEP PKCS#1 v1.5 padding support has been removed as it will not be allowed in FIPS mode after 2023. None of the FIPS certified modules in RHEL will support it as a FIPS approved mechanism. This commit migrates PKCS#1 v1.5 padding to RSA-OAEP. Mew installations of KRA will use RSA-OAEP as default key wrapping algorithm. Upgrade will also provoke enabling the new algo. Fixes: https://pagure.io/freeipa/issue/9191 Signed-off-by: Francisco Trivino --- install/share/ipaca_default.ini | 3 +++ ipaclient/plugins/vault.py | 24 +++++++++++++++++++----- ipaserver/install/krainstance.py | 12 ++++++++++++ ipaserver/install/server/upgrade.py | 11 +++++++++++ 4 files changed, 45 insertions(+), 5 deletions(-) diff --git a/install/share/ipaca_default.ini b/install/share/ipaca_default.ini index 696bee95b2a..a92a35035a7 100644 --- a/install/share/ipaca_default.ini +++ b/install/share/ipaca_default.ini @@ -164,3 +164,6 @@ pki_audit_signing_subject_dn=cn=KRA Audit,%(ipa_subject_base)s # We will use the dbuser created for the CA. pki_share_db=True pki_share_dbuser_dn=uid=pkidbuser,ou=people,o=ipaca + +# default KRA padding +pki_use_oaep_rsa_keywrap=True diff --git a/ipaclient/plugins/vault.py b/ipaclient/plugins/vault.py index bdd988ad186..f2580df22a9 100644 --- a/ipaclient/plugins/vault.py +++ b/ipaclient/plugins/vault.py @@ -706,23 +706,37 @@ def _do_internal(self, algo, transport_cert, raise_unexpected, *args, **options): public_key = transport_cert.public_key() - # wrap session key with transport certificate + # wrap session key with transport certificate using OAEP padding wrapped_session_key = public_key.encrypt( algo.key, - padding.PKCS1v15() + padding.OAEP( + mgf=padding.MGF1(algorithm=hashes.SHA256()), + algorithm=hashes.SHA256(), + label=None + ) ) options['session_key'] = wrapped_session_key name = self.name + '_internal' try: # ipalib.errors.NotFound exception can be propagated + # Try OAEP padding return self.api.Command[name](*args, **options) except (errors.InternalError, errors.ExecutionError, errors.GenericError): - _kra_config_cache.remove(self.api.env.domain) - if raise_unexpected: - raise + # If the OAEP attempt fails, fall back to PKCS1v15 padding + try: + wrapped_session_key = public_key.encrypt( + algo.key, + padding.PKCS1v15() + ) + options['session_key'] = wrapped_session_key + return self.api.Command[name](*args, **options) + except Exception as e: + _kra_config_cache.remove(self.api.env.domain) + if raise_unexpected: + raise e return None def internal(self, algo, transport_cert, *args, **options): diff --git a/ipaserver/install/krainstance.py b/ipaserver/install/krainstance.py index d0636a56c3d..0fd148697da 100644 --- a/ipaserver/install/krainstance.py +++ b/ipaserver/install/krainstance.py @@ -284,6 +284,18 @@ def enable_ephemeral(self): # A restart is required + def enable_oaep_wrap_algo(self): + """ + Enable KRA OAEP key wrap algorithm + """ + with installutils.stopped_service('pki-tomcatd', 'pki-tomcat'): + directivesetter.set_directive( + self.config, + 'keyWrap.useOAEP', + 'true', quotes=False, separator='=') + + # A restart is required + def update_cert_config(self, nickname, cert): """ When renewing a KRA subsystem certificate the configuration file diff --git a/ipaserver/install/server/upgrade.py b/ipaserver/install/server/upgrade.py index f42faea049c..593cb69e9fc 100644 --- a/ipaserver/install/server/upgrade.py +++ b/ipaserver/install/server/upgrade.py @@ -1794,6 +1794,17 @@ def upgrade_configuration(): else: logger.info('ephemeralRequest is already enabled') + logger.info('[Ensuring KRA OAEP key wrap algo is enabled]') + value = directivesetter.get_directive( + paths.KRA_CS_CFG_PATH, + 'keyWrap.useOAEP', + separator='=') + if value is None or value.lower() != 'true': + logger.info('Use the OAEP key wrap algo') + kra.enable_oaep_wrap_algo() + else: + logger.info('OAEP key wrap algo is already enabled') + # several upgrade steps require running CA. If CA is configured, # always run ca.start() because we need to wait until CA is really ready # by checking status using http