Vojtech Trefny eabe00
From c2b06150df0b876c7d442097b6c9ca90c9ca2ecc Mon Sep 17 00:00:00 2001
Vojtech Trefny eabe00
From: Vojtech Trefny <vtrefny@redhat.com>
Vojtech Trefny eabe00
Date: Thu, 4 May 2023 11:35:44 +0200
Vojtech Trefny eabe00
Subject: [PATCH] Do not set memory limit for LUKS2 when running in FIPS mode
Vojtech Trefny eabe00
Vojtech Trefny eabe00
With FIPS enabled LUKS uses pbkdf and not argon so the memory
Vojtech Trefny eabe00
limit is not a valid parameter.
Vojtech Trefny eabe00
Vojtech Trefny eabe00
Resolves: rhbz#2193096
Vojtech Trefny eabe00
---
Vojtech Trefny eabe00
 blivet/devicelibs/crypto.py                   | 11 +++++++
Vojtech Trefny eabe00
 blivet/formats/luks.py                        | 12 ++++----
Vojtech Trefny eabe00
 tests/unit_tests/formats_tests/luks_test.py   | 30 +++++++++++++++++++
Vojtech Trefny eabe00
 .../unit_tests/formats_tests/methods_test.py  |  3 +-
Vojtech Trefny eabe00
 4 files changed, 50 insertions(+), 6 deletions(-)
Vojtech Trefny eabe00
Vojtech Trefny eabe00
diff --git a/blivet/devicelibs/crypto.py b/blivet/devicelibs/crypto.py
Vojtech Trefny eabe00
index f0caf0f7..68e68db1 100644
Vojtech Trefny eabe00
--- a/blivet/devicelibs/crypto.py
Vojtech Trefny eabe00
+++ b/blivet/devicelibs/crypto.py
Vojtech Trefny eabe00
@@ -21,6 +21,7 @@
Vojtech Trefny eabe00
 #
Vojtech Trefny eabe00
Vojtech Trefny eabe00
 import hashlib
Vojtech Trefny eabe00
+import os
Vojtech Trefny eabe00
Vojtech Trefny eabe00
 import gi
Vojtech Trefny eabe00
 gi.require_version("BlockDev", "2.0")
Vojtech Trefny eabe00
@@ -100,3 +101,13 @@ def calculate_integrity_metadata_size(device_size, algorithm=DEFAULT_INTEGRITY_A
Vojtech Trefny eabe00
     jsize = (jsize / SECTOR_SIZE + 1) * SECTOR_SIZE  # round up to sector
Vojtech Trefny eabe00
Vojtech Trefny eabe00
     return msize + jsize
Vojtech Trefny eabe00
+
Vojtech Trefny eabe00
+
Vojtech Trefny eabe00
+def is_fips_enabled():
Vojtech Trefny eabe00
+    if not os.path.exists("/proc/sys/crypto/fips_enabled"):
Vojtech Trefny eabe00
+        # if the file doesn't exist, we are definitely not in FIPS mode
Vojtech Trefny eabe00
+        return False
Vojtech Trefny eabe00
+
Vojtech Trefny eabe00
+    with open("/proc/sys/crypto/fips_enabled", "r") as f:
Vojtech Trefny eabe00
+        enabled = f.read()
Vojtech Trefny eabe00
+    return enabled.strip() == "1"
Vojtech Trefny eabe00
diff --git a/blivet/formats/luks.py b/blivet/formats/luks.py
Vojtech Trefny eabe00
index 2637e0c5..adf3c711 100644
Vojtech Trefny eabe00
--- a/blivet/formats/luks.py
Vojtech Trefny eabe00
+++ b/blivet/formats/luks.py
Vojtech Trefny eabe00
@@ -303,11 +303,13 @@ class LUKS(DeviceFormat):
Vojtech Trefny eabe00
             if luks_data.pbkdf_args:
Vojtech Trefny eabe00
                 self.pbkdf_args = luks_data.pbkdf_args
Vojtech Trefny eabe00
             else:
Vojtech Trefny eabe00
-                mem_limit = crypto.calculate_luks2_max_memory()
Vojtech Trefny eabe00
-                if mem_limit:
Vojtech Trefny eabe00
-                    self.pbkdf_args = LUKS2PBKDFArgs(max_memory_kb=int(mem_limit.convert_to(KiB)))
Vojtech Trefny eabe00
-                    luks_data.pbkdf_args = self.pbkdf_args
Vojtech Trefny eabe00
-                    log.info("PBKDF arguments for LUKS2 not specified, using defaults with memory limit %s", mem_limit)
Vojtech Trefny eabe00
+                # argon is not used with FIPS so we don't need to adjust the memory when in FIPS mode
Vojtech Trefny eabe00
+                if not crypto.is_fips_enabled():
Vojtech Trefny eabe00
+                    mem_limit = crypto.calculate_luks2_max_memory()
Vojtech Trefny eabe00
+                    if mem_limit:
Vojtech Trefny eabe00
+                        self.pbkdf_args = LUKS2PBKDFArgs(max_memory_kb=int(mem_limit.convert_to(KiB)))
Vojtech Trefny eabe00
+                        luks_data.pbkdf_args = self.pbkdf_args
Vojtech Trefny eabe00
+                        log.info("PBKDF arguments for LUKS2 not specified, using defaults with memory limit %s", mem_limit)
Vojtech Trefny eabe00
Vojtech Trefny eabe00
         if self.pbkdf_args:
Vojtech Trefny eabe00
             pbkdf = blockdev.CryptoLUKSPBKDF(type=self.pbkdf_args.type,
Vojtech Trefny eabe00
diff --git a/tests/unit_tests/formats_tests/luks_test.py b/tests/unit_tests/formats_tests/luks_test.py
Vojtech Trefny eabe00
index ec7b7592..1127e968 100644
Vojtech Trefny eabe00
--- a/tests/unit_tests/formats_tests/luks_test.py
Vojtech Trefny eabe00
+++ b/tests/unit_tests/formats_tests/luks_test.py
Vojtech Trefny eabe00
@@ -6,9 +6,14 @@ except ImportError:
Vojtech Trefny eabe00
 import unittest
Vojtech Trefny eabe00
Vojtech Trefny eabe00
 from blivet.formats.luks import LUKS
Vojtech Trefny eabe00
+from blivet.size import Size
Vojtech Trefny eabe00
+from blivet.static_data import luks_data
Vojtech Trefny eabe00
Vojtech Trefny eabe00
Vojtech Trefny eabe00
 class LUKSNodevTestCase(unittest.TestCase):
Vojtech Trefny eabe00
+    def setUp(self):
Vojtech Trefny eabe00
+        luks_data.pbkdf_args = None
Vojtech Trefny eabe00
+
Vojtech Trefny eabe00
     def test_create_discard_option(self):
Vojtech Trefny eabe00
         # flags.discard_new=False --> no discard
Vojtech Trefny eabe00
         fmt = LUKS(exists=False)
Vojtech Trefny eabe00
@@ -51,6 +56,31 @@ class LUKSNodevTestCase(unittest.TestCase):
Vojtech Trefny eabe00
         fmt = LUKS(cipher="aes-cbc-plain64")
Vojtech Trefny eabe00
         self.assertEqual(fmt.key_size, 0)
Vojtech Trefny eabe00
Vojtech Trefny eabe00
+    def test_luks2_pbkdf_memory_fips(self):
Vojtech Trefny eabe00
+        fmt = LUKS()
Vojtech Trefny eabe00
+        with patch("blivet.formats.luks.blockdev.crypto") as bd:
Vojtech Trefny eabe00
+            # fips enabled, pbkdf memory should not be set
Vojtech Trefny eabe00
+            with patch("blivet.formats.luks.crypto") as crypto:
Vojtech Trefny eabe00
+                attrs = {"is_fips_enabled.return_value": True,
Vojtech Trefny eabe00
+                         "get_optimal_luks_sector_size.return_value": 0,
Vojtech Trefny eabe00
+                         "calculate_luks2_max_memory.return_value": Size("256 MiB")}
Vojtech Trefny eabe00
+                crypto.configure_mock(**attrs)
Vojtech Trefny eabe00
+
Vojtech Trefny eabe00
+                fmt._create()
Vojtech Trefny eabe00
+                crypto.calculate_luks2_max_memory.assert_not_called()
Vojtech Trefny eabe00
+                self.assertEqual(bd.luks_format.call_args[1]["extra"].pbkdf.max_memory_kb, 0)
Vojtech Trefny eabe00
+
Vojtech Trefny eabe00
+            # fips disabled, pbkdf memory should be set
Vojtech Trefny eabe00
+            with patch("blivet.formats.luks.crypto") as crypto:
Vojtech Trefny eabe00
+                attrs = {"is_fips_enabled.return_value": False,
Vojtech Trefny eabe00
+                         "get_optimal_luks_sector_size.return_value": 0,
Vojtech Trefny eabe00
+                         "calculate_luks2_max_memory.return_value": Size("256 MiB")}
Vojtech Trefny eabe00
+                crypto.configure_mock(**attrs)
Vojtech Trefny eabe00
+
Vojtech Trefny eabe00
+                fmt._create()
Vojtech Trefny eabe00
+                crypto.calculate_luks2_max_memory.assert_called()
Vojtech Trefny eabe00
+                self.assertEqual(bd.luks_format.call_args[1]["extra"].pbkdf.max_memory_kb, 256 * 1024)
Vojtech Trefny eabe00
+
Vojtech Trefny eabe00
     def test_sector_size(self):
Vojtech Trefny eabe00
         fmt = LUKS()
Vojtech Trefny eabe00
         self.assertEqual(fmt.luks_sector_size, 512)
Vojtech Trefny eabe00
diff --git a/tests/unit_tests/formats_tests/methods_test.py b/tests/unit_tests/formats_tests/methods_test.py
Vojtech Trefny eabe00
index 2743b7db..5d30c260 100644
Vojtech Trefny eabe00
--- a/tests/unit_tests/formats_tests/methods_test.py
Vojtech Trefny eabe00
+++ b/tests/unit_tests/formats_tests/methods_test.py
Vojtech Trefny eabe00
@@ -366,7 +366,8 @@ class LUKSMethodsTestCase(FormatMethodsTestCase):
Vojtech Trefny eabe00
Vojtech Trefny eabe00
     def _test_create_backend(self):
Vojtech Trefny eabe00
         self.format.exists = False
Vojtech Trefny eabe00
-        self.format.create()
Vojtech Trefny eabe00
+        with patch("blivet.devicelibs.crypto.is_fips_enabled", return_value=False):
Vojtech Trefny eabe00
+            self.format.create()
Vojtech Trefny eabe00
         self.assertTrue(self.patches["blockdev"].crypto.luks_format.called)  # pylint: disable=no-member
Vojtech Trefny eabe00
Vojtech Trefny eabe00
     def _test_setup_backend(self):
Vojtech Trefny eabe00
--
Vojtech Trefny eabe00
2.40.1
Vojtech Trefny eabe00