From 163f06cab678d517ab30ab6da59ae339f39ee7cf Mon Sep 17 00:00:00 2001 From: Francisco Trivino Date: Fri, 27 May 2022 17:31:40 +0200 Subject: [PATCH] Vault: add support for RSA-OAEP wrapping algo None of the FIPS certified modules in RHEL support PKCS#1 v1.5 as FIPS approved mechanism. This commit adds support for RSA-OAEP padding as a fallback. Fixes: https://pagure.io/freeipa/issue/9191 Signed-off-by: Francisco Trivino Reviewed-By: Rob Crittenden (cherry picked from commit b1fb31fd20c900c9ff1d5d28dfe136439f6bf605) --- ipaclient/plugins/vault.py | 57 ++++++++++++++++++++++++++++++-------- 1 file changed, 45 insertions(+), 12 deletions(-) diff --git a/ipaclient/plugins/vault.py b/ipaclient/plugins/vault.py index d4c84eb6b..ed16c73ae 100644 --- a/ipaclient/plugins/vault.py +++ b/ipaclient/plugins/vault.py @@ -119,8 +119,8 @@ def encrypt(data, symmetric_key=None, public_key=None): return public_key_obj.encrypt( data, padding.OAEP( - mgf=padding.MGF1(algorithm=hashes.SHA1()), - algorithm=hashes.SHA1(), + mgf=padding.MGF1(algorithm=hashes.SHA256()), + algorithm=hashes.SHA256(), label=None ) ) @@ -154,8 +154,8 @@ def decrypt(data, symmetric_key=None, private_key=None): return private_key_obj.decrypt( data, padding.OAEP( - mgf=padding.MGF1(algorithm=hashes.SHA1()), - algorithm=hashes.SHA1(), + mgf=padding.MGF1(algorithm=hashes.SHA256()), + algorithm=hashes.SHA256(), label=None ) ) @@ -705,14 +705,39 @@ class ModVaultData(Local): return transport_cert, wrapping_algo def _do_internal(self, algo, transport_cert, raise_unexpected, - *args, **options): + use_oaep=False, *args, **options): public_key = transport_cert.public_key() # wrap session key with transport certificate - wrapped_session_key = public_key.encrypt( - algo.key, - padding.PKCS1v15() - ) + # KRA may be configured using either the default PKCS1v15 or RSA-OAEP. + # there is no way to query this info using the REST interface. + if not use_oaep: + # PKCS1v15() causes an OpenSSL exception when FIPS is enabled + # if so, we fallback to RSA-OAEP + try: + wrapped_session_key = public_key.encrypt( + algo.key, + padding.PKCS1v15() + ) + except ValueError: + wrapped_session_key = public_key.encrypt( + algo.key, + padding.OAEP( + mgf=padding.MGF1(algorithm=hashes.SHA256()), + algorithm=hashes.SHA256(), + label=None + ) + ) + else: + wrapped_session_key = public_key.encrypt( + algo.key, + padding.OAEP( + mgf=padding.MGF1(algorithm=hashes.SHA256()), + algorithm=hashes.SHA256(), + label=None + ) + ) + options['session_key'] = wrapped_session_key name = self.name + '_internal' @@ -723,7 +748,7 @@ class ModVaultData(Local): errors.ExecutionError, errors.GenericError): _kra_config_cache.remove(self.api.env.domain) - if raise_unexpected: + if raise_unexpected and use_oaep: raise return None @@ -733,15 +758,23 @@ class ModVaultData(Local): """ # try call with cached transport certificate result = self._do_internal(algo, transport_cert, False, - *args, **options) + False, *args, **options) if result is not None: return result # retrieve transport certificate (cached by vaultconfig_show) transport_cert = self._get_vaultconfig(force_refresh=True)[0] + # call with the retrieved transport certificate + result = self._do_internal(algo, transport_cert, True, + False, *args, **options) + + if result is not None: + return result + + # call and use_oaep this time, last attempt return self._do_internal(algo, transport_cert, True, - *args, **options) + True, *args, **options) @register(no_fail=True) -- 2.43.0