Library for managing partitions. Common code for KDE Partition Manager and other projects.
https://www.kde.org/applications/system/kdepartitionmanager/
You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
695 lines
20 KiB
695 lines
20 KiB
/* |
|
SPDX-FileCopyrightText: 2010 Volker Lanz <vl@fidra.de> |
|
SPDX-FileCopyrightText: 2012-2019 Andrius Štikonas <andrius@stikonas.eu> |
|
SPDX-FileCopyrightText: 2015-2016 Teo Mrnjavac <teo@kde.org> |
|
SPDX-FileCopyrightText: 2016 Chantara Tith <tith.chantara@gmail.com> |
|
SPDX-FileCopyrightText: 2017 Christian Morlok <christianmorlok@gmail.com> |
|
SPDX-FileCopyrightText: 2018 Caio Jordão Carvalho <caiojcarvalho@gmail.com> |
|
SPDX-FileCopyrightText: 2020 Arnaud Ferraris <arnaud.ferraris@collabora.com> |
|
SPDX-FileCopyrightText: 2020 Gaël PORTAY <gael.portay@collabora.com> |
|
|
|
SPDX-License-Identifier: GPL-3.0-or-later |
|
*/ |
|
|
|
#include "fs/luks.h" |
|
#include "fs/lvm2_pv.h" |
|
|
|
#include "fs/filesystemfactory.h" |
|
|
|
#include "util/externalcommand.h" |
|
#include "util/capacity.h" |
|
#include "util/helpers.h" |
|
#include "util/report.h" |
|
|
|
#include <cmath> |
|
|
|
#include <QDebug> |
|
#include <QDialog> |
|
#include <QJsonArray> |
|
#include <QJsonObject> |
|
#include <QJsonDocument> |
|
#include <QRegularExpression> |
|
#include <QPointer> |
|
#include <QStorageInfo> |
|
#include <QString> |
|
#include <QUuid> |
|
#include <QWidget> |
|
|
|
#include <KLocalizedString> |
|
#include <KPasswordDialog> |
|
|
|
namespace FS |
|
{ |
|
FileSystem::CommandSupportType luks::m_GetUsed = FileSystem::cmdSupportNone; |
|
FileSystem::CommandSupportType luks::m_GetLabel = FileSystem::cmdSupportNone; |
|
FileSystem::CommandSupportType luks::m_Create = FileSystem::cmdSupportNone; |
|
FileSystem::CommandSupportType luks::m_Grow = FileSystem::cmdSupportNone; |
|
FileSystem::CommandSupportType luks::m_Shrink = FileSystem::cmdSupportNone; |
|
FileSystem::CommandSupportType luks::m_Move = FileSystem::cmdSupportNone; |
|
FileSystem::CommandSupportType luks::m_Check = FileSystem::cmdSupportNone; |
|
FileSystem::CommandSupportType luks::m_Copy = FileSystem::cmdSupportNone; |
|
FileSystem::CommandSupportType luks::m_Backup = FileSystem::cmdSupportNone; |
|
FileSystem::CommandSupportType luks::m_SetLabel = FileSystem::cmdSupportNone; |
|
FileSystem::CommandSupportType luks::m_UpdateUUID = FileSystem::cmdSupportNone; |
|
FileSystem::CommandSupportType luks::m_GetUUID = FileSystem::cmdSupportNone; |
|
|
|
luks::luks(qint64 firstsector, |
|
qint64 lastsector, |
|
qint64 sectorsused, |
|
const QString& label, |
|
const QVariantMap& features, |
|
FileSystem::Type t) |
|
: FileSystem(firstsector, lastsector, sectorsused, label, features, t) |
|
, m_innerFs(nullptr) |
|
, m_isCryptOpen(false) |
|
, m_cryptsetupFound(m_Create != cmdSupportNone) |
|
, m_isMounted(false) |
|
, m_KeySize(-1) |
|
, m_PayloadOffset(-1) |
|
{ |
|
} |
|
|
|
luks::~luks() |
|
{ |
|
delete m_innerFs; |
|
} |
|
|
|
void luks::init() |
|
{ |
|
CommandSupportType cryptsetupFound = findExternal(QStringLiteral("cryptsetup")) ? cmdSupportFileSystem : cmdSupportNone; |
|
|
|
m_Create = cryptsetupFound; |
|
m_UpdateUUID = cryptsetupFound; |
|
m_GetUUID = cryptsetupFound; |
|
m_Grow = cryptsetupFound; |
|
m_Shrink = cryptsetupFound; |
|
|
|
m_SetLabel = cmdSupportNone; |
|
m_GetLabel = cmdSupportFileSystem; |
|
m_Check = cmdSupportCore; |
|
m_Copy = cmdSupportCore; |
|
m_Move = cmdSupportCore; |
|
m_Backup = cmdSupportCore; |
|
m_GetUsed = cmdSupportNone; // libparted does not support LUKS, we do this as a special case |
|
} |
|
|
|
void luks::scan(const QString& deviceNode) |
|
{ |
|
getMapperName(deviceNode); |
|
getLuksInfo(deviceNode); |
|
} |
|
|
|
bool luks::supportToolFound() const |
|
{ |
|
return m_cryptsetupFound && ((m_isCryptOpen && m_innerFs) ? m_innerFs->supportToolFound() : true); |
|
} |
|
|
|
FileSystem::SupportTool luks::supportToolName() const |
|
{ |
|
if (m_isCryptOpen && m_innerFs && m_cryptsetupFound) |
|
return m_innerFs->supportToolName(); |
|
return SupportTool(QStringLiteral("cryptsetup"), |
|
QUrl(QStringLiteral("https://code.google.com/p/cryptsetup/"))); |
|
} |
|
|
|
bool luks::create(Report& report, const QString& deviceNode) |
|
{ |
|
Q_ASSERT(m_innerFs); |
|
Q_ASSERT(!m_passphrase.isEmpty()); |
|
|
|
ExternalCommand createCmd(report, QStringLiteral("cryptsetup"), |
|
{ QStringLiteral("-s"), |
|
QStringLiteral("512"), |
|
QStringLiteral("--batch-mode"), |
|
QStringLiteral("--force-password"), |
|
QStringLiteral("--type"), QStringLiteral("luks1"), |
|
QStringLiteral("luksFormat"), |
|
deviceNode }); |
|
if (!( createCmd.write(m_passphrase.toLocal8Bit() + '\n') && |
|
createCmd.start(-1) && createCmd.exitCode() == 0)) |
|
{ |
|
return false; |
|
} |
|
|
|
ExternalCommand openCmd(report, QStringLiteral("cryptsetup"), |
|
{ QStringLiteral("open"), |
|
deviceNode, |
|
suggestedMapperName(deviceNode) }); |
|
|
|
if (!( openCmd.write(m_passphrase.toLocal8Bit() + '\n') && openCmd.start(-1))) |
|
return false; |
|
|
|
setPayloadSize(); |
|
scan(deviceNode); |
|
|
|
if (mapperName().isEmpty()) |
|
return false; |
|
|
|
if (!m_innerFs->create(report, mapperName())) |
|
return false; |
|
|
|
return true; |
|
} |
|
|
|
QString luks::mountTitle() const |
|
{ |
|
return xi18nc("@title:menu", "Mount"); |
|
} |
|
|
|
QString luks::unmountTitle() const |
|
{ |
|
return xi18nc("@title:menu", "Unmount"); |
|
} |
|
|
|
QString luks::cryptOpenTitle() const |
|
{ |
|
return xi18nc("@title:menu", "Unlock"); |
|
} |
|
|
|
QString luks::cryptCloseTitle() const |
|
{ |
|
return xi18nc("@title:menu", "Lock"); |
|
} |
|
|
|
void luks::setPassphrase(const QString& passphrase) |
|
{ |
|
m_passphrase = passphrase; |
|
} |
|
|
|
QString luks::passphrase() const |
|
{ |
|
return m_passphrase; |
|
} |
|
|
|
bool luks::canMount(const QString&, const QString& mountPoint) const |
|
{ |
|
return m_isCryptOpen && |
|
!m_isMounted && |
|
m_innerFs && |
|
m_innerFs->canMount(mapperName(), mountPoint); |
|
} |
|
|
|
bool luks::canUnmount(const QString&) const |
|
{ |
|
return m_isCryptOpen && |
|
m_isMounted && |
|
m_innerFs && |
|
m_innerFs->canUnmount(mapperName()); |
|
} |
|
|
|
bool luks::isMounted() const |
|
{ |
|
return m_isCryptOpen && m_isMounted; |
|
} |
|
|
|
void luks::setMounted(bool mounted) |
|
{ |
|
m_isMounted = mounted; |
|
} |
|
|
|
bool luks::canCryptOpen(const QString&) const |
|
{ |
|
return !m_isCryptOpen && !m_isMounted && supportToolFound(); |
|
} |
|
|
|
bool luks::canCryptClose(const QString&) const |
|
{ |
|
return m_isCryptOpen && !m_isMounted && m_cryptsetupFound; |
|
} |
|
|
|
bool luks::isCryptOpen() const |
|
{ |
|
return m_isCryptOpen; |
|
} |
|
|
|
void luks::setCryptOpen(bool cryptOpen) |
|
{ |
|
m_isCryptOpen = cryptOpen; |
|
} |
|
|
|
bool luks::cryptOpen(QWidget* parent, const QString& deviceNode) |
|
{ |
|
if (m_isCryptOpen) |
|
{ |
|
if (!mapperName().isEmpty()) |
|
{ |
|
qWarning() << "LUKS device" << deviceNode |
|
<< "already decrypted." |
|
<< "Cannot decrypt again."; |
|
return false; |
|
} |
|
else |
|
{ |
|
qWarning() << "LUKS device" << deviceNode |
|
<< "reportedly decrypted but mapper node not found." |
|
<< "Marking device as NOT decrypted and trying to " |
|
"decrypt again anyway."; |
|
m_isCryptOpen = false; |
|
} |
|
} |
|
|
|
KPasswordDialog dlg( parent ); |
|
dlg.setPrompt(i18n("Enter passphrase for %1:", deviceNode)); |
|
if( !dlg.exec() ) |
|
return false; |
|
|
|
QString passphrase = dlg.password(); |
|
ExternalCommand openCmd(QStringLiteral("cryptsetup"), |
|
{ QStringLiteral("open"), |
|
QStringLiteral("--tries"), QStringLiteral("1"), |
|
deviceNode, |
|
suggestedMapperName(deviceNode) }); |
|
|
|
if (!( openCmd.write(passphrase.toLocal8Bit() + '\n') && |
|
openCmd.start(-1) && openCmd.exitCode() == 0) ) |
|
return false; |
|
|
|
if (m_innerFs) { |
|
delete m_innerFs; |
|
m_innerFs = nullptr; |
|
} |
|
|
|
scan(deviceNode); |
|
|
|
if (mapperName().isEmpty()) |
|
return false; |
|
|
|
loadInnerFileSystem(mapperName()); |
|
m_isCryptOpen = (m_innerFs != nullptr); |
|
|
|
if (!m_isCryptOpen) |
|
return false; |
|
|
|
for (auto &p : LVM::pvList::list()) |
|
if (p.isLuks() && p.partition()->deviceNode() == deviceNode && p.partition()->fileSystem().type() == FileSystem::Type::Lvm2_PV) |
|
p.setLuks(false); |
|
|
|
m_passphrase = passphrase; |
|
return true; |
|
} |
|
|
|
bool luks::cryptClose(const QString& deviceNode) |
|
{ |
|
if (!m_isCryptOpen) |
|
{ |
|
qWarning() << "Cannot close LUKS device" << deviceNode |
|
<< "because it's not open."; |
|
return false; |
|
} |
|
|
|
if (m_isMounted) |
|
{ |
|
qWarning() << "Cannot close LUKS device" << deviceNode |
|
<< "because the filesystem is mounted."; |
|
return false; |
|
} |
|
|
|
ExternalCommand cmd(QStringLiteral("cryptsetup"), |
|
{ QStringLiteral("close"), mapperName() }); |
|
if (!(cmd.run(-1) && cmd.exitCode() == 0)) |
|
return false; |
|
|
|
delete m_innerFs; |
|
m_innerFs = nullptr; |
|
|
|
m_passphrase.clear(); |
|
setLabel(FileSystem::readLabel(deviceNode)); |
|
setUUID(readUUID(deviceNode)); |
|
setSectorsUsed(-1); |
|
|
|
m_isCryptOpen = (m_innerFs != nullptr); |
|
|
|
for (auto &p : LVM::pvList::list()) |
|
if (!p.isLuks() && p.partition()->deviceNode() == deviceNode) |
|
p.setLuks(true); |
|
|
|
return true; |
|
} |
|
|
|
void luks::loadInnerFileSystem(const QString& mapperNode) |
|
{ |
|
Q_ASSERT(!m_innerFs); |
|
FileSystem::Type innerFsType = detectFileSystem(mapperNode); |
|
m_innerFs = FileSystemFactory::cloneWithNewType(innerFsType, |
|
*this); |
|
setLabel(m_innerFs->readLabel(mapperNode)); |
|
setUUID(m_innerFs->readUUID(mapperNode)); |
|
if (m_innerFs->supportGetUsed() == FileSystem::cmdSupportFileSystem) |
|
setSectorsUsed(static_cast<qint64>(std::ceil((m_innerFs->readUsedCapacity(mapperNode) + payloadOffset()) / static_cast<double>(sectorSize()) ))); |
|
m_innerFs->scan(mapperNode); |
|
} |
|
|
|
void luks::createInnerFileSystem(FileSystem::Type type) |
|
{ |
|
Q_ASSERT(!m_innerFs); |
|
m_innerFs = FileSystemFactory::cloneWithNewType(type, *this); |
|
} |
|
|
|
bool luks::check(Report& report, const QString&) const |
|
{ |
|
Q_ASSERT(m_innerFs); |
|
|
|
if (mapperName().isEmpty()) |
|
return false; |
|
|
|
return m_innerFs->check(report, mapperName()); |
|
} |
|
|
|
qint64 luks::readUsedCapacity(const QString& deviceNode) const |
|
{ |
|
if (!m_isCryptOpen) |
|
return -1; |
|
if (m_innerFs) |
|
return m_innerFs->readUsedCapacity(deviceNode); |
|
return -1; |
|
} |
|
|
|
bool luks::mount(Report& report, const QString& deviceNode, const QString& mountPoint) |
|
{ |
|
if (!m_isCryptOpen) |
|
{ |
|
qWarning() << "Cannot mount device" << deviceNode |
|
<< "before decrypting it first."; |
|
return false; |
|
} |
|
|
|
if (m_isMounted) |
|
{ |
|
qWarning() << "Cannot mount device" << deviceNode |
|
<< "because it's already mounted."; |
|
return false; |
|
} |
|
|
|
Q_ASSERT(m_innerFs); |
|
|
|
if (mapperName().isEmpty()) |
|
return false; |
|
|
|
if (m_innerFs->canMount(mapperName(), mountPoint)) |
|
{ |
|
if (m_innerFs->mount(report, mapperName(), mountPoint)) |
|
{ |
|
m_isMounted = true; |
|
|
|
const QStorageInfo storageInfo = QStorageInfo(mountPoint); |
|
if (storageInfo.isValid() && !mountPoint.isEmpty()) |
|
setSectorsUsed( (storageInfo.bytesTotal() - storageInfo.bytesFree() + payloadOffset()) / sectorSize()); |
|
|
|
return true; |
|
} |
|
} |
|
else { |
|
ExternalCommand mountCmd( |
|
report, |
|
QStringLiteral("mount"), |
|
{ QStringLiteral("--verbose"), mapperName(), mountPoint }); |
|
if (mountCmd.run() && mountCmd.exitCode() == 0) |
|
{ |
|
m_isMounted = true; |
|
return true; |
|
} |
|
} |
|
return false; |
|
} |
|
|
|
bool luks::unmount(Report& report, const QString& deviceNode) |
|
{ |
|
if (!m_isCryptOpen) |
|
{ |
|
qWarning() << "Cannot unmount device" << deviceNode |
|
<< "before decrypting it first."; |
|
return false; |
|
} |
|
|
|
if (!m_isMounted) |
|
{ |
|
qWarning() << "Cannot unmount device" << deviceNode |
|
<< "because it's not mounted."; |
|
return false; |
|
} |
|
|
|
Q_ASSERT(m_innerFs); |
|
|
|
if (mapperName().isEmpty()) |
|
return false; |
|
|
|
if (m_innerFs->canUnmount(mapperName())) |
|
{ |
|
if (m_innerFs->unmount(report, mapperName())) |
|
{ |
|
m_isMounted = false; |
|
return true; |
|
} |
|
} |
|
else { |
|
ExternalCommand unmountCmd( report, |
|
QStringLiteral("umount"), |
|
{ QStringLiteral("--verbose"), QStringLiteral("--all-targets"), mapperName() }); |
|
if (unmountCmd.run() && unmountCmd.exitCode() == 0) |
|
{ |
|
m_isMounted = false; |
|
return true; |
|
} |
|
} |
|
return false; |
|
} |
|
|
|
FileSystem::Type luks::type() const |
|
{ |
|
if (m_isCryptOpen && m_innerFs) |
|
return m_innerFs->type(); |
|
return FileSystem::Type::Luks; |
|
} |
|
|
|
QString luks::suggestedMapperName(const QString& deviceNode) const |
|
{ |
|
return QStringLiteral("luks-") + readOuterUUID(deviceNode); |
|
} |
|
|
|
QString luks::readLabel(const QString& deviceNode) const |
|
{ |
|
if (m_isCryptOpen && m_innerFs) |
|
return m_innerFs->readLabel(mapperName()); |
|
|
|
return FileSystem::readLabel(deviceNode); |
|
} |
|
|
|
bool luks::writeLabel(Report& report, const QString&, const QString& newLabel) |
|
{ |
|
Q_ASSERT(m_innerFs); |
|
return m_innerFs->writeLabel(report, mapperName(), newLabel); |
|
} |
|
|
|
bool luks::resize(Report& report, const QString& deviceNode, qint64 newLength) const |
|
{ |
|
Q_ASSERT(m_innerFs); |
|
|
|
if (mapperName().isEmpty()) |
|
return false; |
|
|
|
const qint64 sizeDiff = newLength - length() * sectorSize(); |
|
const qint64 newPayloadSize = m_PayloadSize + sizeDiff; |
|
if ( sizeDiff > 0 ) // grow |
|
{ |
|
ExternalCommand cryptResizeCmd(report, QStringLiteral("cryptsetup"), { QStringLiteral("resize"), mapperName() }); |
|
report.line() << xi18nc("@info:progress", "Resizing LUKS crypt on partition <filename>%1</filename>.", deviceNode); |
|
|
|
if (cryptResizeCmd.run(-1) && cryptResizeCmd.exitCode() == 0) |
|
return m_innerFs->resize(report, mapperName(), newPayloadSize); |
|
} |
|
else if (m_innerFs->resize(report, mapperName(), newPayloadSize)) // shrink |
|
{ |
|
ExternalCommand cryptResizeCmd(report, QStringLiteral("cryptsetup"), |
|
{ QStringLiteral("--size"), QString::number(newPayloadSize / 512), // LUKS1 payload length is specified in multiples of 512 bytes |
|
QStringLiteral("resize"), mapperName() }); |
|
report.line() << xi18nc("@info:progress", "Resizing LUKS crypt on partition <filename>%1</filename>.", deviceNode); |
|
if (cryptResizeCmd.run(-1) && cryptResizeCmd.exitCode() == 0) |
|
return true; |
|
} |
|
report.line() << xi18nc("@info:progress", "Resizing encrypted file system on partition <filename>%1</filename> failed.", deviceNode); |
|
return false; |
|
} |
|
|
|
bool luks::resizeOnline(Report& report, const QString& deviceNode, const QString& mountPoint, qint64 length) const |
|
{ |
|
Q_UNUSED(mountPoint) |
|
return resize(report, deviceNode, length); |
|
} |
|
|
|
QString luks::readUUID(const QString& deviceNode) const |
|
{ |
|
QString outerUuid = readOuterUUID(deviceNode); |
|
if (m_isCryptOpen && m_innerFs) |
|
return m_innerFs->readUUID(mapperName()); |
|
return outerUuid; |
|
} |
|
|
|
QString luks::readOuterUUID(const QString &deviceNode) const |
|
{ |
|
if ( deviceNode.isEmpty() ) |
|
return QString(); |
|
|
|
ExternalCommand cmd(QStringLiteral("cryptsetup"), |
|
{ QStringLiteral("luksUUID"), deviceNode }); |
|
if (cmd.run()) { |
|
if ( cmd.exitCode() ) |
|
{ |
|
qWarning() << "Cannot get luksUUID for device" << deviceNode |
|
<< "\tcryptsetup exit code" << cmd.exitCode() |
|
<< "\toutput:" << cmd.output().trimmed(); |
|
return QString(); |
|
} |
|
QString outerUuid = cmd.output().trimmed(); |
|
const_cast< QString& >( m_outerUuid ) = outerUuid; |
|
return outerUuid; |
|
} |
|
return QStringLiteral("---"); |
|
} |
|
|
|
bool luks::updateUUID(Report& report, const QString& deviceNode) const |
|
{ |
|
const QString uuid = QUuid::createUuid().toString().remove(QRegularExpression(QStringLiteral("\\{|\\}"))); |
|
|
|
ExternalCommand cmd(report, |
|
QStringLiteral("cryptsetup"), |
|
{ QStringLiteral("luksUUID"), |
|
deviceNode, |
|
QStringLiteral("--uuid"), |
|
uuid }); |
|
return cmd.run(-1) && cmd.exitCode() == 0; |
|
} |
|
|
|
void luks::getMapperName(const QString& deviceNode) |
|
{ |
|
ExternalCommand cmd(QStringLiteral("lsblk"), |
|
{ QStringLiteral("--list"), |
|
QStringLiteral("--noheadings"), |
|
QStringLiteral("--paths"), |
|
QStringLiteral("--json"), |
|
QStringLiteral("--output"), |
|
QStringLiteral("type,name"), |
|
deviceNode }); |
|
m_MapperName = QString(); |
|
|
|
if (cmd.run(-1) && cmd.exitCode() == 0) { |
|
const QJsonDocument jsonDocument = QJsonDocument::fromJson(cmd.rawOutput()); |
|
QJsonObject jsonObject = jsonDocument.object(); |
|
const QJsonArray jsonArray = jsonObject[QLatin1String("blockdevices")].toArray(); |
|
for (const auto &deviceLine : jsonArray) { |
|
QJsonObject deviceObject = deviceLine.toObject(); |
|
if (deviceObject[QLatin1String("type")].toString() == QLatin1String("crypt")) { |
|
m_MapperName = deviceObject[QLatin1String("name")].toString(); |
|
break; |
|
} |
|
} |
|
} |
|
} |
|
|
|
void luks::getLuksInfo(const QString& 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()); |
|
if (rem.hasMatch()) |
|
m_CipherName = rem.captured(1); |
|
else |
|
m_CipherName = QLatin1String("---"); |
|
|
|
re.setPattern(QStringLiteral("Cipher mode:\\s+(\\w+)")); |
|
rem = re.match(cmd.output()); |
|
if (rem.hasMatch()) |
|
m_CipherMode = rem.captured(1); |
|
else |
|
m_CipherMode = QLatin1String("---"); |
|
|
|
re.setPattern(QStringLiteral("Hash spec:\\s+(\\w+)")); |
|
rem = re.match(cmd.output()); |
|
if (rem.hasMatch()) |
|
m_HashName = rem.captured(1); |
|
else |
|
m_HashName = QLatin1String("---"); |
|
|
|
re.setPattern(QStringLiteral("MK bits:\\s+(\\d+)")); |
|
rem = re.match(cmd.output()); |
|
if (rem.hasMatch()) |
|
m_KeySize = rem.captured(1).toLongLong(); |
|
else |
|
m_KeySize = -1; |
|
|
|
re.setPattern(QStringLiteral("Payload offset:\\s+(\\d+)")); |
|
rem = re.match(cmd.output()); |
|
if (rem.hasMatch()) |
|
m_PayloadOffset = rem.captured(1).toLongLong() * 512; // assuming LUKS sector size is 512; |
|
else |
|
m_PayloadOffset = -1; |
|
|
|
} |
|
else { |
|
m_CipherName = QLatin1String("---"); |
|
m_CipherMode = QLatin1String("---"); |
|
m_HashName = QLatin1String("---"); |
|
m_KeySize = -1; |
|
m_PayloadOffset = -1; |
|
} |
|
} |
|
|
|
QString luks::outerUuid() const |
|
{ |
|
return m_outerUuid; |
|
} |
|
|
|
bool luks::canEncryptType(FileSystem::Type type) |
|
{ |
|
switch (type) |
|
{ |
|
case Type::Btrfs: |
|
case Type::F2fs: |
|
case Type::Ext2: |
|
case Type::Ext3: |
|
case Type::Ext4: |
|
case Type::Jfs: |
|
case Type::LinuxSwap: |
|
case Type::Lvm2_PV: |
|
case Type::Nilfs2: |
|
case Type::ReiserFS: |
|
case Type::Reiser4: |
|
case Type::Xfs: |
|
case Type::Zfs: |
|
return true; |
|
default: |
|
return false; |
|
} |
|
} |
|
|
|
void luks::initLUKS() |
|
{ |
|
setPayloadSize(); |
|
QString mapperNode = mapperName(); |
|
bool isCryptOpen = !mapperNode.isEmpty(); |
|
setCryptOpen(isCryptOpen); |
|
if (isCryptOpen) { |
|
loadInnerFileSystem(mapperNode); |
|
setMounted(detectMountStatus(innerFS(), mapperNode)); |
|
} |
|
} |
|
|
|
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.write(passphrase.toLocal8Bit() + '\n') && cmd.start(-1) && cmd.exitCode() == 0) |
|
return true; |
|
|
|
return false; |
|
} |
|
|
|
}
|
|
|