From 4bf1b0fa7e73a038c3fa5948d5e67698630ca5ab Mon Sep 17 00:00:00 2001 From: Sunderland93 Date: Wed, 17 May 2023 16:25:57 +0400 Subject: [PATCH 01/14] Add River and Hyprland to desktop list --- src/modules/displaymanager/main.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/modules/displaymanager/main.py b/src/modules/displaymanager/main.py index d7533e122..2a1448e51 100644 --- a/src/modules/displaymanager/main.py +++ b/src/modules/displaymanager/main.py @@ -197,6 +197,8 @@ desktop_environments = [ DesktopEnvironment('/usr/bin/sway', 'sway'), DesktopEnvironment('/usr/bin/ukui-session', 'ukui'), DesktopEnvironment('/usr/bin/cutefish-session', 'cutefish-xsession'), + DesktopEnvironment('/usr/bin/river', 'river'), + DesktopEnvironment('/usr/bin/Hyprland', 'hyprland'), ] From b2c75a1af8fffd997f2548a0019a7c2dd5d31e70 Mon Sep 17 00:00:00 2001 From: Panda <59401553+Rippanda12@users.noreply.github.com> Date: Sat, 20 May 2023 09:11:47 +0300 Subject: [PATCH 02/14] Fix initcpio ARM cpus dont have vendor tag in /proc/cpuinfo --- src/modules/initcpiocfg/main.py | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/modules/initcpiocfg/main.py b/src/modules/initcpiocfg/main.py index 5fd9d93ae..57dc5e432 100644 --- a/src/modules/initcpiocfg/main.py +++ b/src/modules/initcpiocfg/main.py @@ -54,8 +54,9 @@ class cpuinfo(object): self.number_of_cores = 0 cpu = self._cpuinfo() - self.is_intel = cpu['proc0']['vendor_id'].lower() == "genuineintel" - self.is_amd = cpu['proc0']['vendor_id'].lower() == "authenticamd" + if 'vendor_id' in cpu['proc0']: + self.is_intel = cpu['proc0']['vendor_id'].lower() == "genuineintel" + self.is_amd = cpu['proc0']['vendor_id'].lower() == "authenticamd" self.number_of_cores = len(cpu) @staticmethod From d662fb084de4e8b951f24e976dee5bf2661eea05 Mon Sep 17 00:00:00 2001 From: Panda <59401553+Rippanda12@users.noreply.github.com> Date: Sun, 21 May 2023 07:02:22 +0000 Subject: [PATCH 03/14] Add armInstall --- src/modules/partition/Config.cpp | 1 + src/modules/partition/core/PartUtils.cpp | 10 +++++++++- src/modules/partition/core/PartitionActions.cpp | 12 ++++++++++-- src/modules/partition/partition.conf | 7 +++++++ src/modules/partition/partition.schema.yaml | 1 + 5 files changed, 28 insertions(+), 3 deletions(-) diff --git a/src/modules/partition/Config.cpp b/src/modules/partition/Config.cpp index 4519bd278..0a0514c72 100644 --- a/src/modules/partition/Config.cpp +++ b/src/modules/partition/Config.cpp @@ -415,6 +415,7 @@ Config::setConfigurationMap( const QVariantMap& configurationMap ) m_requiredPartitionTableType = CalamaresUtils::getStringList( configurationMap, "requiredPartitionTableType" ); Calamares::GlobalStorage* gs = Calamares::JobQueue::instance()->globalStorage(); + gs->insert( "armInstall", CalamaresUtils::getBool( configurationMap, "armInstall", false ) ); fillGSConfigurationEFI( gs, configurationMap ); fillConfigurationFSTypes( configurationMap ); } diff --git a/src/modules/partition/core/PartUtils.cpp b/src/modules/partition/core/PartUtils.cpp index 3d5e1e762..60f966f27 100644 --- a/src/modules/partition/core/PartUtils.cpp +++ b/src/modules/partition/core/PartUtils.cpp @@ -443,7 +443,15 @@ runOsprober( DeviceModel* dm ) bool isEfiSystem() { - return QDir( "/sys/firmware/efi/efivars" ).exists(); + Calamares::GlobalStorage* gs = Calamares::JobQueue::instance()->globalStorage(); + if ( gs->contains( "armInstall" ) && gs->value( "armInstall" ).toBool() ) + { + return true; + } + else + { + return QDir( "/sys/firmware/efi/efivars" ).exists(); + } } bool diff --git a/src/modules/partition/core/PartitionActions.cpp b/src/modules/partition/core/PartitionActions.cpp index 2287c57bd..631d4ca64 100644 --- a/src/modules/partition/core/PartitionActions.cpp +++ b/src/modules/partition/core/PartitionActions.cpp @@ -95,8 +95,16 @@ doAutopartition( PartitionCoreModule* core, Device* dev, Choices::AutoPartitionO // the logical sector size (usually 512B). EFI starts with 2MiB // empty and a EFI boot partition, while BIOS starts at // the 1MiB boundary (usually sector 2048). - int empty_space_sizeB = isEfi ? 2_MiB : 1_MiB; - + // ARM empty sectors are 16 MiB in size. + int empty_space_sizeB; + if ( gs->contains( "armInstall" ) && gs->value( "armInstall" ).toBool() ) + { + empty_space_sizeB = 16_MiB; + } + else + { + empty_space_sizeB = isEfi ? 2_MiB : 1_MiB; + } // Since sectors count from 0, if the space is 2048 sectors in size, // the first free sector has number 2048 (and there are 2048 sectors // before that one, numbered 0..2047). diff --git a/src/modules/partition/partition.conf b/src/modules/partition/partition.conf index ecd183ca1..b6364d3c0 100644 --- a/src/modules/partition/partition.conf +++ b/src/modules/partition/partition.conf @@ -124,6 +124,13 @@ initialPartitioningChoice: none # one of the items from the options. initialSwapChoice: none +# armInstall +# +# Leaves 16MB empty at the start of a drive when partitioning +# where usually the u-boot loader goes +# +# armInstall: false + # Default partition table type, used when a "erase" disk is made. # # When erasing a disk, a new partition table is created on disk. diff --git a/src/modules/partition/partition.schema.yaml b/src/modules/partition/partition.schema.yaml index dafdc5851..50a51cd9e 100644 --- a/src/modules/partition/partition.schema.yaml +++ b/src/modules/partition/partition.schema.yaml @@ -14,6 +14,7 @@ properties: userSwapChoices: { type: array, items: { type: string, enum: [ none, reuse, small, suspend, file ] } } # ensureSuspendToDisk: { type: boolean, default: true } # Legacy # neverCreateSwap: { type: boolean, default: false } # Legacy + armInstall: { type: boolean, default: false } allowZfsEncryption: { type: boolean, default: true } drawNestedPartitions: { type: boolean, default: false } From 7a67840c9bdd5d8c955aba436848a197859a9b25 Mon Sep 17 00:00:00 2001 From: Evan Goode Date: Mon, 22 May 2023 12:03:22 -0400 Subject: [PATCH 04/14] [packages] Call dnf-3 binary, not dnf DNF is being replaced by a new package manager, DNF 5, in Fedora 39+. The `dnf` binary will soon symlink to DNF 5 instead of DNF 5. The old DNF 4 binary will still be (and always has been) available as /usr/bin/dnf-3. Until Calamares adds support for DNF 5, it should explicitly call the old dnf-3 binary. --- src/modules/packages/main.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/modules/packages/main.py b/src/modules/packages/main.py index e373a3443..26ed30a19 100644 --- a/src/modules/packages/main.py +++ b/src/modules/packages/main.py @@ -282,12 +282,12 @@ class PMDnf(PackageManager): backend = "dnf" def install(self, pkgs, from_local=False): - check_target_env_call(["dnf", "-y", "install"] + pkgs) + check_target_env_call(["dnf-3", "-y", "install"] + pkgs) def remove(self, pkgs): # ignore the error code for now because dnf thinks removing a # nonexistent package is an error - target_env_call(["dnf", "--disablerepo=*", "-C", "-y", + target_env_call(["dnf-3", "--disablerepo=*", "-C", "-y", "remove"] + pkgs) def update_db(self): @@ -295,7 +295,7 @@ class PMDnf(PackageManager): pass def update_system(self): - check_target_env_call(["dnf", "-y", "upgrade"]) + check_target_env_call(["dnf-3", "-y", "upgrade"]) class PMDummy(PackageManager): From 5c4557e4d17499388d6ff10ed5a7a325b5a9a626 Mon Sep 17 00:00:00 2001 From: abalfoort Date: Tue, 23 May 2023 13:47:39 +0200 Subject: [PATCH 05/14] Create key file for LUKS2 devices --- .../luksbootkeyfile/LuksBootKeyFileJob.cpp | 92 ++++++++++++------- 1 file changed, 59 insertions(+), 33 deletions(-) diff --git a/src/modules/luksbootkeyfile/LuksBootKeyFileJob.cpp b/src/modules/luksbootkeyfile/LuksBootKeyFileJob.cpp index 5b0914595..457c0f4dc 100644 --- a/src/modules/luksbootkeyfile/LuksBootKeyFileJob.cpp +++ b/src/modules/luksbootkeyfile/LuksBootKeyFileJob.cpp @@ -137,32 +137,64 @@ generateTargetKeyfile() static bool setupLuks( const LuksDevice& d ) { - // Sometimes this error is thrown: "All key slots full" - // luksAddKey will fail. So, remove the first slot to make room + // Get luksDump for this device + int slots_count = 0; auto luks_dump = CalamaresUtils::System::instance()->targetEnvCommand( - { "cryptsetup", "luksDump", d.device }, QString(), QString(), std::chrono::seconds( 5 ) ); - if ( luks_dump.getExitCode() == 0 ) + { QStringLiteral( "cryptsetup" ), QStringLiteral( "luksDump" ), d.device }, + QString(), + QString(), + std::chrono::seconds( 5 ) ); + if ( luks_dump.getExitCode() != 0 ) { - QRegularExpression re( QStringLiteral( R"(\d+:\s*enabled)" ), QRegularExpression::CaseInsensitiveOption ); - int count = luks_dump.getOutput().count( re ); - cDebug() << "Luks Dump slot count: " << count; - if ( count >= 7 ) - { - auto r = CalamaresUtils::System::instance()->targetEnvCommand( - { "cryptsetup", "luksKillSlot", d.device, "1" }, QString(), d.passphrase, std::chrono::seconds( 60 ) ); - if ( r.getExitCode() != 0 ) - { - cWarning() << "Could not kill a slot to make room on" << d.device << ':' << r.getOutput() - << "(exit code" << r.getExitCode() << ')'; - return false; - } - } + cWarning() << "Could not get LUKS information on " << d.device << ':' << luks_dump.getOutput() << "(exit code" + << luks_dump.getExitCode() << ')'; + return false; } - // Adding the key can take some times, measured around 15 seconds with - // a HDD (spinning rust) and a slow-ish computer. Give it a minute. + // Check for LUKS2 + QString luks2_hash = QString(); + QRegularExpression pbkdf_re( QStringLiteral( R"(pbkdf:\s*(.*))" ), QRegularExpression::CaseInsensitiveOption ); + QRegularExpressionMatch match = pbkdf_re.match( luks_dump.getOutput() ); + if ( match.hasMatch() ) { + luks2_hash = match.captured(1); + cDebug() << "Setup LUKS2 " << luks2_hash << " for " << d.device; + } + else + { + cDebug() << "Setup LUKS1 for " << d.device; + } + + // Output of LUKS1 and LUKS2 differ + auto search_pattern = luks2_hash.isEmpty() ? QStringLiteral( R"(\d+:\s*enabled)" ) : QStringLiteral( R"(\d+:\s*luks2)" ); + QRegularExpression slots_re( search_pattern, QRegularExpression::CaseInsensitiveOption ); + slots_count = luks_dump.getOutput().count( slots_re ); + + // This should be a clean install: remove all existing keys, except the first slot + // Remove slots but leave the first + for ( int i = 1; i < slots_count; i++ ) + { + cDebug() << Logger::SubEntry << "Remove surplus key slot: " << QString::number( i ) << " from " << d.device; + CalamaresUtils::System::instance()->targetEnvCommand( + { QStringLiteral( "cryptsetup" ), QStringLiteral( "luksKillSlot" ), d.device, QString::number( i ) }, + QString(), + d.passphrase, + std::chrono::seconds( 5 ) ); + } + + // For LUKS1 you cannot change the key in slot 1, or you'll end up in Grub command. + // This doesn't seem the case for LUKS2. + // It has not been tested with a LUKS2 encrypted boot because Grub2 does not yet support this. + QStringList args = { QStringLiteral( "cryptsetup" ), QStringLiteral( "luksAddKey" ) }; + if ( !luks2_hash.isEmpty() ) + { + args << "--pbkdf" << luks2_hash; + } + args << d.device << keyfile; auto r = CalamaresUtils::System::instance()->targetEnvCommand( - { "cryptsetup", "luksAddKey", d.device, keyfile }, QString(), d.passphrase, std::chrono::seconds( 60 ) ); + args, + QString(), + d.passphrase, + std::chrono::seconds( 60 ) ); if ( r.getExitCode() != 0 ) { cWarning() << "Could not configure LUKS keyfile on" << d.device << ':' << r.getOutput() << "(exit code" @@ -259,15 +291,15 @@ LuksBootKeyFileJob::exec() if ( it == s.devices.begin() ) { - // Then there was no root partition - cDebug() << Logger::SubEntry << "No root partition."; + // User has configured non-root partition for encryption + cDebug() << Logger::SubEntry << "No root partition, skipping keyfile creation."; return Calamares::JobResult::ok(); } - // /boot partition is not encrypted, keyfile must not be used - // But only if root partition is not encrypted if ( hasUnencryptedSeparateBoot() && !hasEncryptedRoot() ) { + // /boot partition is not encrypted, keyfile must not be used + // But only if root partition is not encrypted cDebug() << Logger::SubEntry << "/boot partition is not encrypted, skipping keyfile creation."; return Calamares::JobResult::ok(); } @@ -289,16 +321,10 @@ LuksBootKeyFileJob::exec() for ( const auto& d : s.devices ) { - // Skip setupLuks for root partition if system has an unencrypted /boot - if ( d.isRoot && hasUnencryptedSeparateBoot() ) - { - continue; - } - if ( !setupLuks( d ) ) return Calamares::JobResult::error( - tr( "Encrypted rootfs setup error" ), - tr( "Could not configure LUKS key file on partition %1." ).arg( d.device ) ); + tr( "Encryption setup error" ), + tr( "Could not configure LUKS on partition %1." ).arg( d.device ) ); } return Calamares::JobResult::ok(); From def9bf18d38a850267a7aa028731bbbb691b128b Mon Sep 17 00:00:00 2001 From: abalfoort Date: Tue, 23 May 2023 15:07:54 +0200 Subject: [PATCH 06/14] Revert removing check on root with unencrypted boot --- src/modules/luksbootkeyfile/LuksBootKeyFileJob.cpp | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/src/modules/luksbootkeyfile/LuksBootKeyFileJob.cpp b/src/modules/luksbootkeyfile/LuksBootKeyFileJob.cpp index 457c0f4dc..482ae5dcc 100644 --- a/src/modules/luksbootkeyfile/LuksBootKeyFileJob.cpp +++ b/src/modules/luksbootkeyfile/LuksBootKeyFileJob.cpp @@ -321,6 +321,12 @@ LuksBootKeyFileJob::exec() for ( const auto& d : s.devices ) { + // Skip setupLuks for root partition if system has an unencrypted /boot + if ( d.isRoot && hasUnencryptedSeparateBoot() ) + { + continue; + } + if ( !setupLuks( d ) ) return Calamares::JobResult::error( tr( "Encryption setup error" ), From e01b45f008b2385d7fb789ca00ccb38f6fcec29a Mon Sep 17 00:00:00 2001 From: abalfoort Date: Tue, 23 May 2023 17:18:10 +0200 Subject: [PATCH 07/14] Check nr used slots --- .../luksbootkeyfile/LuksBootKeyFileJob.cpp | 18 ++++++------------ 1 file changed, 6 insertions(+), 12 deletions(-) diff --git a/src/modules/luksbootkeyfile/LuksBootKeyFileJob.cpp b/src/modules/luksbootkeyfile/LuksBootKeyFileJob.cpp index 482ae5dcc..7331385d3 100644 --- a/src/modules/luksbootkeyfile/LuksBootKeyFileJob.cpp +++ b/src/modules/luksbootkeyfile/LuksBootKeyFileJob.cpp @@ -164,26 +164,20 @@ setupLuks( const LuksDevice& d ) cDebug() << "Setup LUKS1 for " << d.device; } + // Check the number of slots used // Output of LUKS1 and LUKS2 differ auto search_pattern = luks2_hash.isEmpty() ? QStringLiteral( R"(\d+:\s*enabled)" ) : QStringLiteral( R"(\d+:\s*luks2)" ); QRegularExpression slots_re( search_pattern, QRegularExpression::CaseInsensitiveOption ); slots_count = luks_dump.getOutput().count( slots_re ); - // This should be a clean install: remove all existing keys, except the first slot - // Remove slots but leave the first - for ( int i = 1; i < slots_count; i++ ) + if ( ( luks2_hash.isEmpty() && slots_count == 8 ) || + ( !luks2_hash.isEmpty() && slots_count == 32 )) { - cDebug() << Logger::SubEntry << "Remove surplus key slot: " << QString::number( i ) << " from " << d.device; - CalamaresUtils::System::instance()->targetEnvCommand( - { QStringLiteral( "cryptsetup" ), QStringLiteral( "luksKillSlot" ), d.device, QString::number( i ) }, - QString(), - d.passphrase, - std::chrono::seconds( 5 ) ); + // No key slots left: return gracefully + return true; } - // For LUKS1 you cannot change the key in slot 1, or you'll end up in Grub command. - // This doesn't seem the case for LUKS2. - // It has not been tested with a LUKS2 encrypted boot because Grub2 does not yet support this. + // Add the key to the keyfile QStringList args = { QStringLiteral( "cryptsetup" ), QStringLiteral( "luksAddKey" ) }; if ( !luks2_hash.isEmpty() ) { From ca2e36b3f3c3d366c84b089cff610a7d7d98d1f5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Philip=20M=C3=BCller?= Date: Fri, 26 May 2023 13:15:19 +0200 Subject: [PATCH 08/14] Update services-systemd.conf - reflect that file endings are now needed in the example --- src/modules/services-systemd/services-systemd.conf | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/modules/services-systemd/services-systemd.conf b/src/modules/services-systemd/services-systemd.conf index 6e7f34451..330a94c65 100644 --- a/src/modules/services-systemd/services-systemd.conf +++ b/src/modules/services-systemd/services-systemd.conf @@ -31,7 +31,7 @@ # # finally masks pacman-init (an ArchLinux-only service). # # # units: -# - name: "NetworkManager" +# - name: "NetworkManager.service" # action: "enable" # mandatory: true # @@ -40,12 +40,12 @@ # # The property "mandatory" is taken to be false by default here # # because it is not specified # -# - name: "graphical" +# - name: "graphical.target" # action: "enable" # # The property "mandatory" is taken to be false by default here # # because it is not specified # -# - name: "pacman-init" +# - name: "pacman-init.service" # action: "mask" # # The property "mandatory" is taken to be false by default here # # because it is not specified From 06d6f217b5b0cfb59ebbf16903220b6f6f126c1c Mon Sep 17 00:00:00 2001 From: abalfoort Date: Wed, 31 May 2023 14:42:18 +0200 Subject: [PATCH 09/14] Added luksbootkeyfile.conf/yaml --- src/modules/luksbootkeyfile/luksbootkeyfile.conf | 10 ++++++++++ .../luksbootkeyfile/luksbootkeyfile.schema.yaml | 9 +++++++++ 2 files changed, 19 insertions(+) create mode 100644 src/modules/luksbootkeyfile/luksbootkeyfile.conf create mode 100644 src/modules/luksbootkeyfile/luksbootkeyfile.schema.yaml diff --git a/src/modules/luksbootkeyfile/luksbootkeyfile.conf b/src/modules/luksbootkeyfile/luksbootkeyfile.conf new file mode 100644 index 000000000..62875181a --- /dev/null +++ b/src/modules/luksbootkeyfile/luksbootkeyfile.conf @@ -0,0 +1,10 @@ +# SPDX-FileCopyrightText: no +# SPDX-License-Identifier: CC0-1.0 +# +# Luksbootkeyfile configuration. A key file is created for the +# LUKS encrypted devices. +--- +# Set Password-Based Key Derivation Function (PBKDF) algorithm +# for LUKS keyslot. The PBKDF can be: pbkdf2, argon2i or argon2id. +# Default: pbkdf2 +luks2Hash: pbkdf2 diff --git a/src/modules/luksbootkeyfile/luksbootkeyfile.schema.yaml b/src/modules/luksbootkeyfile/luksbootkeyfile.schema.yaml new file mode 100644 index 000000000..8f505fbdc --- /dev/null +++ b/src/modules/luksbootkeyfile/luksbootkeyfile.schema.yaml @@ -0,0 +1,9 @@ +# SPDX-FileCopyrightText: 2023 Arjen Balfoort +# SPDX-License-Identifier: GPL-3.0-or-later +--- +$schema: https://json-schema.org/schema# +$id: https://calamares.io/schemas/luksbootkeyfile +additionalProperties: false +type: object +properties: + luks2Hash: { type: string } From 1e2a51f952ab374874c2aabbb41fcef246e9e0e9 Mon Sep 17 00:00:00 2001 From: abalfoort Date: Wed, 31 May 2023 14:42:39 +0200 Subject: [PATCH 10/14] Remove NO_CONFIG --- src/modules/luksbootkeyfile/CMakeLists.txt | 1 - 1 file changed, 1 deletion(-) diff --git a/src/modules/luksbootkeyfile/CMakeLists.txt b/src/modules/luksbootkeyfile/CMakeLists.txt index a2b52ad94..735d3174f 100644 --- a/src/modules/luksbootkeyfile/CMakeLists.txt +++ b/src/modules/luksbootkeyfile/CMakeLists.txt @@ -9,7 +9,6 @@ calamares_add_plugin(luksbootkeyfile SOURCES LuksBootKeyFileJob.cpp SHARED_LIB - NO_CONFIG ) calamares_add_test(luksbootkeyfiletest SOURCES Tests.cpp LuksBootKeyFileJob.cpp) From c4496ef86b7fb44133ace9f65b6330dcfc2c87fe Mon Sep 17 00:00:00 2001 From: abalfoort Date: Wed, 31 May 2023 14:43:39 +0200 Subject: [PATCH 11/14] Add configurable variable m_luks2Hash --- .../luksbootkeyfile/LuksBootKeyFileJob.cpp | 63 +++++++++++-------- .../luksbootkeyfile/LuksBootKeyFileJob.h | 5 ++ 2 files changed, 41 insertions(+), 27 deletions(-) diff --git a/src/modules/luksbootkeyfile/LuksBootKeyFileJob.cpp b/src/modules/luksbootkeyfile/LuksBootKeyFileJob.cpp index 7331385d3..4d450d58c 100644 --- a/src/modules/luksbootkeyfile/LuksBootKeyFileJob.cpp +++ b/src/modules/luksbootkeyfile/LuksBootKeyFileJob.cpp @@ -135,7 +135,7 @@ generateTargetKeyfile() } static bool -setupLuks( const LuksDevice& d ) +setupLuks( const LuksDevice& d, const QString& luks2Hash ) { // Get luksDump for this device int slots_count = 0; @@ -151,39 +151,33 @@ setupLuks( const LuksDevice& d ) return false; } - // Check for LUKS2 - QString luks2_hash = QString(); - QRegularExpression pbkdf_re( QStringLiteral( R"(pbkdf:\s*(.*))" ), QRegularExpression::CaseInsensitiveOption ); - QRegularExpressionMatch match = pbkdf_re.match( luks_dump.getOutput() ); - if ( match.hasMatch() ) { - luks2_hash = match.captured(1); - cDebug() << "Setup LUKS2 " << luks2_hash << " for " << d.device; - } - else + // Check LUKS version + int luks_version = 0; + QRegularExpression version_re( QStringLiteral( R"(version:\s*([0-9]))" ), QRegularExpression::CaseInsensitiveOption ); + QRegularExpressionMatch match = version_re.match( luks_dump.getOutput() ); + if ( ! match.hasMatch() ) { - cDebug() << "Setup LUKS1 for " << d.device; + cWarning() << "Could not get LUKS version on device: " << d.device; + return false; } + luks_version = match.captured(1).toInt(); + cDebug() << "LUKS" << luks_version << " found on device: " << d.device; // Check the number of slots used // Output of LUKS1 and LUKS2 differ - auto search_pattern = luks2_hash.isEmpty() ? QStringLiteral( R"(\d+:\s*enabled)" ) : QStringLiteral( R"(\d+:\s*luks2)" ); + auto search_pattern = luks_version == 1 ? QStringLiteral( R"(\d+:\s*enabled)" ) : QStringLiteral( R"(\d+:\s*luks2)" ); QRegularExpression slots_re( search_pattern, QRegularExpression::CaseInsensitiveOption ); slots_count = luks_dump.getOutput().count( slots_re ); - - if ( ( luks2_hash.isEmpty() && slots_count == 8 ) || - ( !luks2_hash.isEmpty() && slots_count == 32 )) + if ( luks_version == 1 && slots_count == 8 ) { - // No key slots left: return gracefully - return true; + cWarning() << "No key slots left on LUKS1 device: " << d.device; + return false; } // Add the key to the keyfile - QStringList args = { QStringLiteral( "cryptsetup" ), QStringLiteral( "luksAddKey" ) }; - if ( !luks2_hash.isEmpty() ) - { - args << "--pbkdf" << luks2_hash; - } - args << d.device << keyfile; + QStringList args_luks1 = { QStringLiteral( "cryptsetup" ), QStringLiteral( "luksAddKey" ), d.device, keyfile }; + QStringList args_luks2 = { QStringLiteral( "cryptsetup" ), QStringLiteral( "luksAddKey" ), "--pbkdf", luks2Hash, d.device, keyfile }; + QStringList args = luks_version == 1 ? args_luks1 : args_luks2; auto r = CalamaresUtils::System::instance()->targetEnvCommand( args, QString(), @@ -269,6 +263,12 @@ LuksBootKeyFileJob::exec() "LuksBootKeyFile", tr( "No partitions are defined." ), Calamares::JobResult::InvalidConfiguration ); } + if ( m_luks2Hash.isEmpty() ) + { + return Calamares::JobResult::internalError( + "LuksBootKeyFile", tr( "No luks2Hash is set." ), Calamares::JobResult::InvalidConfiguration ); + } + cDebug() << "There are" << s.devices.count() << "LUKS partitions"; if ( s.devices.count() < 1 ) { @@ -321,13 +321,22 @@ LuksBootKeyFileJob::exec() continue; } - if ( !setupLuks( d ) ) - return Calamares::JobResult::error( - tr( "Encryption setup error" ), - tr( "Could not configure LUKS on partition %1." ).arg( d.device ) ); + if ( !setupLuks( d, m_luks2Hash ) ) + { + // Could not configure the LUKS partition + // This should not stop the installation: do not return Calamares::JobResult::error. + cError() << "Encrypted rootfs setup error: could not configure LUKS key file on partition " << d.device; + } } return Calamares::JobResult::ok(); } +void +LuksBootKeyFileJob::setConfigurationMap( const QVariantMap& configurationMap ) +{ + m_luks2Hash = CalamaresUtils::getString( + configurationMap, QStringLiteral( "luks2Hash" ), QStringLiteral( "pbkdf2" ) ); +} + CALAMARES_PLUGIN_FACTORY_DEFINITION( LuksBootKeyFileJobFactory, registerPlugin< LuksBootKeyFileJob >(); ) diff --git a/src/modules/luksbootkeyfile/LuksBootKeyFileJob.h b/src/modules/luksbootkeyfile/LuksBootKeyFileJob.h index 9681228bd..05288a152 100644 --- a/src/modules/luksbootkeyfile/LuksBootKeyFileJob.h +++ b/src/modules/luksbootkeyfile/LuksBootKeyFileJob.h @@ -30,6 +30,11 @@ public: QString prettyName() const override; Calamares::JobResult exec() override; + + void setConfigurationMap( const QVariantMap& configurationMap ) override; + +private: + QString m_luks2Hash; }; CALAMARES_PLUGIN_FACTORY_DECLARATION( LuksBootKeyFileJobFactory ) From 1963dd341280ac25174b8a9aac10430c44273674 Mon Sep 17 00:00:00 2001 From: abalfoort Date: Wed, 31 May 2023 18:23:00 +0200 Subject: [PATCH 12/14] Optional luks2Hash with enum --- src/modules/luksbootkeyfile/luksbootkeyfile.conf | 9 ++++++--- src/modules/luksbootkeyfile/luksbootkeyfile.schema.yaml | 2 +- 2 files changed, 7 insertions(+), 4 deletions(-) diff --git a/src/modules/luksbootkeyfile/luksbootkeyfile.conf b/src/modules/luksbootkeyfile/luksbootkeyfile.conf index 62875181a..04ffbac6b 100644 --- a/src/modules/luksbootkeyfile/luksbootkeyfile.conf +++ b/src/modules/luksbootkeyfile/luksbootkeyfile.conf @@ -5,6 +5,9 @@ # LUKS encrypted devices. --- # Set Password-Based Key Derivation Function (PBKDF) algorithm -# for LUKS keyslot. The PBKDF can be: pbkdf2, argon2i or argon2id. -# Default: pbkdf2 -luks2Hash: pbkdf2 +# for LUKS keyslot. +# +# There are three usable values: pbkdf2, argon2i or argon2id. +# +# When not set, the cryptsetup default is used +#luks2Hash: argon2id diff --git a/src/modules/luksbootkeyfile/luksbootkeyfile.schema.yaml b/src/modules/luksbootkeyfile/luksbootkeyfile.schema.yaml index 8f505fbdc..6c0917646 100644 --- a/src/modules/luksbootkeyfile/luksbootkeyfile.schema.yaml +++ b/src/modules/luksbootkeyfile/luksbootkeyfile.schema.yaml @@ -6,4 +6,4 @@ $id: https://calamares.io/schemas/luksbootkeyfile additionalProperties: false type: object properties: - luks2Hash: { type: string } + luks2Hash: { type: string, enum: [ pbkdf2, argon2i, argon2id ] } From 33aeabd617559af9ab74d61e44f7d44c95f2093d Mon Sep 17 00:00:00 2001 From: abalfoort Date: Wed, 31 May 2023 18:25:16 +0200 Subject: [PATCH 13/14] Implement requested changes --- .../luksbootkeyfile/LuksBootKeyFileJob.cpp | 46 ++++++++++--------- 1 file changed, 25 insertions(+), 21 deletions(-) diff --git a/src/modules/luksbootkeyfile/LuksBootKeyFileJob.cpp b/src/modules/luksbootkeyfile/LuksBootKeyFileJob.cpp index 4d450d58c..c9c0e1298 100644 --- a/src/modules/luksbootkeyfile/LuksBootKeyFileJob.cpp +++ b/src/modules/luksbootkeyfile/LuksBootKeyFileJob.cpp @@ -138,7 +138,6 @@ static bool setupLuks( const LuksDevice& d, const QString& luks2Hash ) { // Get luksDump for this device - int slots_count = 0; auto luks_dump = CalamaresUtils::System::instance()->targetEnvCommand( { QStringLiteral( "cryptsetup" ), QStringLiteral( "luksDump" ), d.device }, QString(), @@ -153,31 +152,42 @@ setupLuks( const LuksDevice& d, const QString& luks2Hash ) // Check LUKS version int luks_version = 0; - QRegularExpression version_re( QStringLiteral( R"(version:\s*([0-9]))" ), QRegularExpression::CaseInsensitiveOption ); + QRegularExpression version_re( QStringLiteral( R"(version:\s*([0-9]))" ), + QRegularExpression::CaseInsensitiveOption ); QRegularExpressionMatch match = version_re.match( luks_dump.getOutput() ); if ( ! match.hasMatch() ) { cWarning() << "Could not get LUKS version on device: " << d.device; return false; } - luks_version = match.captured(1).toInt(); + bool ok; + luks_version = match.captured(1).toInt(&ok); + if( ! ok ) + { + cWarning() << "Could not get LUKS version on device: " << d.device; + return false; + } cDebug() << "LUKS" << luks_version << " found on device: " << d.device; - // Check the number of slots used - // Output of LUKS1 and LUKS2 differ - auto search_pattern = luks_version == 1 ? QStringLiteral( R"(\d+:\s*enabled)" ) : QStringLiteral( R"(\d+:\s*luks2)" ); - QRegularExpression slots_re( search_pattern, QRegularExpression::CaseInsensitiveOption ); - slots_count = luks_dump.getOutput().count( slots_re ); - if ( luks_version == 1 && slots_count == 8 ) + // Check the number of slots used for LUKS1 devices + if ( luks_version == 1 ) { - cWarning() << "No key slots left on LUKS1 device: " << d.device; - return false; + QRegularExpression slots_re( QStringLiteral( R"(\d+:\s*enabled)" ), + QRegularExpression::CaseInsensitiveOption ); + if ( luks_dump.getOutput().count( slots_re ) == 8 ) + { + cWarning() << "No key slots left on LUKS1 device: " << d.device; + return false; + } } // Add the key to the keyfile - QStringList args_luks1 = { QStringLiteral( "cryptsetup" ), QStringLiteral( "luksAddKey" ), d.device, keyfile }; - QStringList args_luks2 = { QStringLiteral( "cryptsetup" ), QStringLiteral( "luksAddKey" ), "--pbkdf", luks2Hash, d.device, keyfile }; - QStringList args = luks_version == 1 ? args_luks1 : args_luks2; + QStringList args = { QStringLiteral( "cryptsetup" ), QStringLiteral( "luksAddKey" ), d.device, keyfile }; + if ( luks_version == 2 && luks2Hash != QString() ) + { + args.insert(2, "--pbkdf"); + args.insert(3, luks2Hash); + } auto r = CalamaresUtils::System::instance()->targetEnvCommand( args, QString(), @@ -263,12 +273,6 @@ LuksBootKeyFileJob::exec() "LuksBootKeyFile", tr( "No partitions are defined." ), Calamares::JobResult::InvalidConfiguration ); } - if ( m_luks2Hash.isEmpty() ) - { - return Calamares::JobResult::internalError( - "LuksBootKeyFile", tr( "No luks2Hash is set." ), Calamares::JobResult::InvalidConfiguration ); - } - cDebug() << "There are" << s.devices.count() << "LUKS partitions"; if ( s.devices.count() < 1 ) { @@ -336,7 +340,7 @@ void LuksBootKeyFileJob::setConfigurationMap( const QVariantMap& configurationMap ) { m_luks2Hash = CalamaresUtils::getString( - configurationMap, QStringLiteral( "luks2Hash" ), QStringLiteral( "pbkdf2" ) ); + configurationMap, QStringLiteral( "luks2Hash" ), QString() ); } CALAMARES_PLUGIN_FACTORY_DEFINITION( LuksBootKeyFileJobFactory, registerPlugin< LuksBootKeyFileJob >(); ) From 197cbec82c96c485ab263f5d25bccebcbd332117 Mon Sep 17 00:00:00 2001 From: Kasra Hashemi <73937934+zencatalyst@users.noreply.github.com> Date: Thu, 22 Jun 2023 14:47:29 +0330 Subject: [PATCH 14/14] Update README.md Fixed punctuation and grammar issues plus spelling inconsistencies --- README.md | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/README.md b/README.md index 43a336de1..8037612aa 100644 --- a/README.md +++ b/README.md @@ -17,16 +17,16 @@ > Calamares is a distribution-independent system installer, with an advanced partitioning > feature for both manual and automated partitioning operations. Calamares is designed to -> be customizable by distribution maintainers without need for cumbersome patching, -> thanks to third party branding and external modules support. +> be customizable by distribution maintainers without the need for cumbersome patching, +> thanks to third-party branding and external modules support. ## Target Audience Calamares is a Linux installer; users who install Linux on a computer will hopefully use it just **once**, to install their Linux distribution. Calamares is not -a "ready to use" application: distributions apply a huge amount of customisation +a "ready to use" application: distributions apply a huge amount of customization and configuration to Calamares, and the target audience for this repository -is those distributions, and the people who make those Linux distro's. +is those distributions, and the people who make those Linux distros. Calamares has some [generic user documentation](https://calamares.io/docs/users-guide/) for end-users, but most of what we have is for distro developers. @@ -45,10 +45,10 @@ The dependencies are explained in [CONTRIBUTING.md](CONTRIBUTING.md). ## Contributing to Calamares Calamares welcomes PRs. New issues are welcome, too. -There are both the Calamares **core** repository (this one), +There are both the Calamares **core** repository (this one) and an **extensions** repository ([Calamares extensions](https://github.com/calamares/calamares-extensions)). -Contributions to code, modules, documentation, the wiki and the website are all welcome. +Contributions to code, modules, documentation, the wiki, and the website are all welcome. There is more information in the [CONTRIBUTING.md](CONTRIBUTING.md) file. ## Join the Conversation