Merge branch 'calamares' of https://github.com/calamares/calamares into development

This commit is contained in:
Philip Mueller 2023-06-15 20:05:16 +02:00
commit 100f408dae
7 changed files with 100 additions and 34 deletions

View File

@ -54,6 +54,7 @@ class cpuinfo(object):
self.number_of_cores = 0 self.number_of_cores = 0
cpu = self._cpuinfo() cpu = self._cpuinfo()
if 'vendor_id' in cpu['proc0']:
self.is_intel = cpu['proc0']['vendor_id'].lower() == "genuineintel" self.is_intel = cpu['proc0']['vendor_id'].lower() == "genuineintel"
self.is_amd = cpu['proc0']['vendor_id'].lower() == "authenticamd" self.is_amd = cpu['proc0']['vendor_id'].lower() == "authenticamd"
self.number_of_cores = len(cpu) self.number_of_cores = len(cpu)

View File

@ -9,7 +9,6 @@ calamares_add_plugin(luksbootkeyfile
SOURCES SOURCES
LuksBootKeyFileJob.cpp LuksBootKeyFileJob.cpp
SHARED_LIB SHARED_LIB
NO_CONFIG
) )
calamares_add_test(luksbootkeyfiletest SOURCES Tests.cpp LuksBootKeyFileJob.cpp) calamares_add_test(luksbootkeyfiletest SOURCES Tests.cpp LuksBootKeyFileJob.cpp)

View File

@ -135,34 +135,64 @@ generateTargetKeyfile()
} }
static bool static bool
setupLuks( const LuksDevice& d ) setupLuks( const LuksDevice& d, const QString& luks2Hash )
{ {
// Sometimes this error is thrown: "All key slots full" // Get luksDump for this device
// luksAddKey will fail. So, remove the first slot to make room
auto luks_dump = CalamaresUtils::System::instance()->targetEnvCommand( auto luks_dump = CalamaresUtils::System::instance()->targetEnvCommand(
{ "cryptsetup", "luksDump", d.device }, QString(), QString(), std::chrono::seconds( 5 ) ); { QStringLiteral( "cryptsetup" ), QStringLiteral( "luksDump" ), d.device },
if ( luks_dump.getExitCode() == 0 ) QString(),
QString(),
std::chrono::seconds( 5 ) );
if ( luks_dump.getExitCode() != 0 )
{ {
QRegularExpression re( QStringLiteral( R"(\d+:\s*enabled)" ), QRegularExpression::CaseInsensitiveOption ); cWarning() << "Could not get LUKS information on " << d.device << ':' << luks_dump.getOutput() << "(exit code"
int count = luks_dump.getOutput().count( re ); << luks_dump.getExitCode() << ')';
cDebug() << "Luks Dump slot count: " << count; return false;
if ( count >= 7 ) }
// 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() )
{ {
auto r = CalamaresUtils::System::instance()->targetEnvCommand( cWarning() << "Could not get LUKS version on device: " << d.device;
{ "cryptsetup", "luksKillSlot", d.device, "1" }, QString(), d.passphrase, std::chrono::seconds( 60 ) ); return false;
if ( r.getExitCode() != 0 ) }
bool ok;
luks_version = match.captured(1).toInt(&ok);
if( ! ok )
{ {
cWarning() << "Could not kill a slot to make room on" << d.device << ':' << r.getOutput() cWarning() << "Could not get LUKS version on device: " << d.device;
<< "(exit code" << r.getExitCode() << ')'; return false;
}
cDebug() << "LUKS" << luks_version << " found on device: " << d.device;
// Check the number of slots used for LUKS1 devices
if ( luks_version == 1 )
{
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; return false;
} }
} }
}
// Adding the key can take some times, measured around 15 seconds with // Add the key to the keyfile
// a HDD (spinning rust) and a slow-ish computer. Give it a minute. 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( 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 ) if ( r.getExitCode() != 0 )
{ {
cWarning() << "Could not configure LUKS keyfile on" << d.device << ':' << r.getOutput() << "(exit code" cWarning() << "Could not configure LUKS keyfile on" << d.device << ':' << r.getOutput() << "(exit code"
@ -259,15 +289,15 @@ LuksBootKeyFileJob::exec()
if ( it == s.devices.begin() ) if ( it == s.devices.begin() )
{ {
// Then there was no root partition // User has configured non-root partition for encryption
cDebug() << Logger::SubEntry << "No root partition."; cDebug() << Logger::SubEntry << "No root partition, skipping keyfile creation.";
return Calamares::JobResult::ok(); 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() ) 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."; cDebug() << Logger::SubEntry << "/boot partition is not encrypted, skipping keyfile creation.";
return Calamares::JobResult::ok(); return Calamares::JobResult::ok();
} }
@ -295,13 +325,22 @@ LuksBootKeyFileJob::exec()
continue; continue;
} }
if ( !setupLuks( d ) ) if ( !setupLuks( d, m_luks2Hash ) )
return Calamares::JobResult::error( {
tr( "Encrypted rootfs setup error" ), // Could not configure the LUKS partition
tr( "Could not configure LUKS key file on partition %1." ).arg( d.device ) ); // 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(); return Calamares::JobResult::ok();
} }
void
LuksBootKeyFileJob::setConfigurationMap( const QVariantMap& configurationMap )
{
m_luks2Hash = CalamaresUtils::getString(
configurationMap, QStringLiteral( "luks2Hash" ), QString() );
}
CALAMARES_PLUGIN_FACTORY_DEFINITION( LuksBootKeyFileJobFactory, registerPlugin< LuksBootKeyFileJob >(); ) CALAMARES_PLUGIN_FACTORY_DEFINITION( LuksBootKeyFileJobFactory, registerPlugin< LuksBootKeyFileJob >(); )

View File

@ -30,6 +30,11 @@ public:
QString prettyName() const override; QString prettyName() const override;
Calamares::JobResult exec() override; Calamares::JobResult exec() override;
void setConfigurationMap( const QVariantMap& configurationMap ) override;
private:
QString m_luks2Hash;
}; };
CALAMARES_PLUGIN_FACTORY_DECLARATION( LuksBootKeyFileJobFactory ) CALAMARES_PLUGIN_FACTORY_DECLARATION( LuksBootKeyFileJobFactory )

View File

@ -0,0 +1,13 @@
# 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.
#
# There are three usable values: pbkdf2, argon2i or argon2id.
#
# When not set, the cryptsetup default is used
#luks2Hash: argon2id

View File

@ -0,0 +1,9 @@
# SPDX-FileCopyrightText: 2023 Arjen Balfoort <arjenbalfoort@hotmail.com>
# 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, enum: [ pbkdf2, argon2i, argon2id ] }

View File

@ -31,7 +31,7 @@
# # finally masks pacman-init (an ArchLinux-only service). # # finally masks pacman-init (an ArchLinux-only service).
# # # #
# units: # units:
# - name: "NetworkManager" # - name: "NetworkManager.service"
# action: "enable" # action: "enable"
# mandatory: true # mandatory: true
# #
@ -40,12 +40,12 @@
# # The property "mandatory" is taken to be false by default here # # The property "mandatory" is taken to be false by default here
# # because it is not specified # # because it is not specified
# #
# - name: "graphical" # - name: "graphical.target"
# action: "enable" # action: "enable"
# # The property "mandatory" is taken to be false by default here # # The property "mandatory" is taken to be false by default here
# # because it is not specified # # because it is not specified
# #
# - name: "pacman-init" # - name: "pacman-init.service"
# action: "mask" # action: "mask"
# # The property "mandatory" is taken to be false by default here # # The property "mandatory" is taken to be false by default here
# # because it is not specified # # because it is not specified