diff --git a/src/fs/luks.cpp b/src/fs/luks.cpp
index eb36ad0..3d63f05 100644
--- a/src/fs/luks.cpp
+++ b/src/fs/luks.cpp
@@ -143,6 +143,7 @@ bool luks::create(Report& report, const QString& deviceNode)
if (!( openCmd.start(-1) && openCmd.write(m_passphrase.toLocal8Bit() + '\n') == m_passphrase.toLocal8Bit().length() + 1 && openCmd.waitFor()))
return false;
+ setPayloadSize();
scan(deviceNode);
if (mapperName().isEmpty())
@@ -259,6 +260,7 @@ bool luks::cryptOpen(QWidget* parent, const QString& deviceNode)
QString passphrase = dlg.password();
ExternalCommand openCmd(QStringLiteral("cryptsetup"),
{ QStringLiteral("open"),
+ QStringLiteral("--tries"), QStringLiteral("1"),
deviceNode,
suggestedMapperName(deviceNode) });
@@ -490,19 +492,18 @@ bool luks::resize(Report& report, const QString& deviceNode, qint64 newLength) c
if (mapperName().isEmpty())
return false;
- qint64 payloadLength = newLength - payloadOffset();
if ( newLength - length() * sectorSize() > 0 )
{
ExternalCommand cryptResizeCmd(report, QStringLiteral("cryptsetup"), { QStringLiteral("resize"), mapperName() });
report.line() << xi18nc("@info:progress", "Resizing LUKS crypt on partition %1.", deviceNode);
if (cryptResizeCmd.run(-1) && cryptResizeCmd.exitCode() == 0)
- return m_innerFs->resize(report, mapperName(), payloadLength);
+ return m_innerFs->resize(report, mapperName(), m_PayloadSize);
}
- else if (m_innerFs->resize(report, mapperName(), payloadLength))
+ else if (m_innerFs->resize(report, mapperName(), m_PayloadSize))
{
ExternalCommand cryptResizeCmd(report, QStringLiteral("cryptsetup"),
- { QStringLiteral("--size"), QString::number(payloadLength / 512), // LUKS payload length is specified in multiples of 512 bytes
+ { QStringLiteral("--size"), QString::number(m_PayloadSize / 512), // LUKS1 payload length is specified in multiples of 512 bytes
QStringLiteral("resize"), mapperName() });
report.line() << xi18nc("@info:progress", "Resizing LUKS crypt on partition %1.", deviceNode);
if (cryptResizeCmd.run(-1) && cryptResizeCmd.exitCode() == 0)
@@ -589,8 +590,7 @@ void luks::getMapperName(const QString& deviceNode)
void luks::getLuksInfo(const QString& deviceNode)
{
- ExternalCommand cmd(QStringLiteral("cryptsetup"),
- { QStringLiteral("luksDump"), deviceNode });
+ ExternalCommand cmd(QStringLiteral("cryptsetup"), { QStringLiteral("luksDump"), deviceNode });
if (cmd.run(-1) && cmd.exitCode() == 0) {
QRegularExpression re(QStringLiteral("Cipher name:\\s+(\\w+)"));
QRegularExpressionMatch rem = re.match(cmd.output());
@@ -667,6 +667,7 @@ bool luks::canEncryptType(FileSystem::Type type)
void luks::initLUKS()
{
+ setPayloadSize();
QString mapperNode = mapperName();
bool isCryptOpen = !mapperNode.isEmpty();
setCryptOpen(isCryptOpen);
@@ -676,4 +677,22 @@ void luks::initLUKS()
}
}
+void luks::setPayloadSize()
+{
+ ExternalCommand dmsetupCmd(QStringLiteral("dmsetup"), { QStringLiteral("table"), mapperName() });
+ dmsetupCmd.run();
+ QRegularExpression re(QStringLiteral("\\d+ (\\d+)"));
+ QRegularExpressionMatch rem = re.match(dmsetupCmd.output());
+ if (rem.hasMatch())
+ m_PayloadSize = rem.captured(1).toLongLong() * sectorSize();
+}
+
+bool luks::testPassphrase(const QString& deviceNode, const QString& passphrase) const {
+ ExternalCommand cmd(QStringLiteral("cryptsetup"), { QStringLiteral("open"), QStringLiteral("--tries"), QStringLiteral("1"), QStringLiteral("--test-passphrase"), deviceNode });
+ if (cmd.start(-1) && cmd.write(passphrase.toLocal8Bit() + '\n') == passphrase.toLocal8Bit().length() + 1 && cmd.waitFor() && cmd.exitCode() == 0)
+ return true;
+
+ return false;
+}
+
}
diff --git a/src/fs/luks.h b/src/fs/luks.h
index e7221c8..9a6ea4e 100644
--- a/src/fs/luks.h
+++ b/src/fs/luks.h
@@ -43,6 +43,12 @@ public:
luks(qint64 firstsector, qint64 lastsector, qint64 sectorsused, const QString& label, FileSystem::Type t = FileSystem::Luks);
~luks() override;
+ enum KeyLocation {
+ unknown,
+ dmcrypt,
+ keyring
+ };
+
public:
void init() override;
void scan(const QString& deviceNode) override;
@@ -167,9 +173,9 @@ public:
QString suggestedMapperName(const QString& deviceNode) const;
void getMapperName(const QString& deviceNode);
- void getLuksInfo(const QString& deviceNode);
+ virtual void getLuksInfo(const QString& deviceNode);
- FileSystem* innerFS() const { return m_innerFs; } // avoid calling this unless necessary
+ FileSystem* innerFS() const { return m_innerFs; }
QString outerUuid() const;
QString mapperName() const { return m_MapperName; }
@@ -182,8 +188,12 @@ public:
static bool canEncryptType(FileSystem::Type type);
void initLUKS();
+ virtual luks::KeyLocation keyLocation() { return luks::dmcrypt; };
+ bool testPassphrase(const QString& deviceNode, const QString& passphrase) const;
+
protected:
virtual QString readOuterUUID(const QString& deviceNode) const;
+ void setPayloadSize();
public:
static CommandSupportType m_GetUsed;
@@ -213,7 +223,10 @@ protected:
QString m_HashName;
qint64 m_KeySize;
qint64 m_PayloadOffset;
+ qint64 m_PayloadSize;
QString m_outerUuid;
+
+ luks::KeyLocation m_KeyLocation = unknown;
};
}
diff --git a/src/fs/luks2.cpp b/src/fs/luks2.cpp
index a895517..9301f17 100644
--- a/src/fs/luks2.cpp
+++ b/src/fs/luks2.cpp
@@ -17,6 +17,13 @@
#include "fs/luks2.h"
+#include "util/externalcommand.h"
+#include "util/report.h"
+
+#include
+
+#include
+
namespace FS
{
@@ -36,4 +43,64 @@ FileSystem::Type luks2::type() const
return FileSystem::Luks2;
}
+bool luks2::resize(Report& report, const QString& deviceNode, qint64 newLength) const
+{
+ Q_ASSERT(m_innerFs);
+
+ if (mapperName().isEmpty())
+ return false;
+
+ if ( newLength - length() * sectorSize() > 0 )
+ {
+ ExternalCommand cryptResizeCmd(report, QStringLiteral("cryptsetup"), { QStringLiteral("resize"), mapperName() });
+ report.line() << xi18nc("@info:progress", "Resizing LUKS crypt on partition %1.", deviceNode);
+
+ cryptResizeCmd.start(-1);
+ if (m_KeyLocation == keyring) {
+ if (m_passphrase.isEmpty())
+ return false;
+ cryptResizeCmd.write(m_passphrase.toLocal8Bit() + '\n');
+ }
+ cryptResizeCmd.waitFor();
+ if ( cryptResizeCmd.exitCode() == 0 )
+ return m_innerFs->resize(report, mapperName(), m_PayloadSize);
+ }
+ else if (m_innerFs->resize(report, mapperName(), m_PayloadSize))
+ {
+ ExternalCommand cryptResizeCmd(report, QStringLiteral("cryptsetup"),
+ { QStringLiteral("--size"), QString::number(m_PayloadSize / 512), // FIXME, LUKS2 can have different sector sizes
+ QStringLiteral("resize"), mapperName() });
+ report.line() << xi18nc("@info:progress", "Resizing LUKS crypt on partition %1.", deviceNode);
+ cryptResizeCmd.start(-1);
+ if (m_KeyLocation == keyring) {
+ if (m_passphrase.isEmpty())
+ return false;
+ cryptResizeCmd.write(m_passphrase.toLocal8Bit() + '\n');
+ }
+ cryptResizeCmd.waitFor();
+ if ( cryptResizeCmd.exitCode() == 0 )
+ return true;
+ }
+ report.line() << xi18nc("@info:progress", "Resizing encrypted file system on partition %1 failed.", deviceNode);
+ return false;
+}
+
+luks::KeyLocation luks2::keyLocation()
+{
+ m_KeyLocation = unknown;
+ ExternalCommand statusCmd(QStringLiteral("cryptsetup"), { QStringLiteral("status"), mapperName() });
+ if (statusCmd.run(-1) && statusCmd.exitCode() == 0) {
+ QRegularExpression re(QStringLiteral("key location:\\s+(\\w+)"));
+ QRegularExpressionMatch rem = re.match(statusCmd.output());
+ if (rem.hasMatch()) {
+ if (rem.captured(1) == QStringLiteral("keyring"))
+ m_KeyLocation = keyring;
+ else if (rem.captured(1) == QStringLiteral("dm-crypt"))
+ m_KeyLocation = dmcrypt;
+ }
+ }
+
+ return m_KeyLocation;
+}
+
}
diff --git a/src/fs/luks2.h b/src/fs/luks2.h
index f8151cb..5f0e12e 100644
--- a/src/fs/luks2.h
+++ b/src/fs/luks2.h
@@ -38,7 +38,11 @@ public:
luks2(qint64 firstsector, qint64 lastsector, qint64 sectorsused, const QString& label);
~luks2() override;
+ bool resize(Report& report, const QString& deviceNode, qint64 length) const override;
+
FileSystem::Type type() const override;
+
+ luks::KeyLocation keyLocation() override;
};
}
diff --git a/src/jobs/setpartgeometryjob.cpp b/src/jobs/setpartgeometryjob.cpp
index 596e14a..7a4fbd7 100644
--- a/src/jobs/setpartgeometryjob.cpp
+++ b/src/jobs/setpartgeometryjob.cpp
@@ -73,7 +73,6 @@ bool SetPartGeometryJob::run(Report& parent)
delete backendPartitionTable;
}
-
delete backendDevice;
} else
report->line() << xi18nc("@info:progress", "Could not open device %1 while trying to resize/move partition %2.", device().deviceNode(), partition().deviceNode());