File indexing completed on 2024-05-05 05:48:46
0001 /* 0002 SPDX-FileCopyrightText: 2017-2019 Andrius Štikonas <andrius@stikonas.eu> 0003 SPDX-FileCopyrightText: 2020 Arnaud Ferraris <arnaud.ferraris@collabora.com> 0004 SPDX-FileCopyrightText: 2020 Gaël PORTAY <gael.portay@collabora.com> 0005 0006 SPDX-License-Identifier: GPL-3.0-or-later 0007 */ 0008 0009 #include "fs/luks2.h" 0010 0011 #include "util/externalcommand.h" 0012 #include "util/report.h" 0013 0014 #include <QRegularExpression> 0015 0016 #include <KLocalizedString> 0017 0018 namespace FS 0019 { 0020 0021 luks2::luks2(qint64 firstsector, qint64 lastsector, qint64 sectorsused, const QString& label, const QVariantMap& features) 0022 : luks(firstsector, lastsector, sectorsused, label, features, FileSystem::Type::Luks2) 0023 { 0024 } 0025 0026 luks2::~luks2() 0027 { 0028 } 0029 0030 FileSystem::Type luks2::type() const 0031 { 0032 if (m_isCryptOpen && m_innerFs) 0033 return m_innerFs->type(); 0034 return FileSystem::Type::Luks2; 0035 } 0036 0037 bool luks2::create(Report& report, const QString& deviceNode) 0038 { 0039 Q_ASSERT(m_innerFs); 0040 Q_ASSERT(!m_passphrase.isEmpty()); 0041 0042 ExternalCommand createCmd(report, QStringLiteral("cryptsetup"), 0043 { QStringLiteral("-s"), 0044 QStringLiteral("512"), 0045 QStringLiteral("--batch-mode"), 0046 QStringLiteral("--force-password"), 0047 QStringLiteral("--type"), QStringLiteral("luks2"), 0048 QStringLiteral("luksFormat"), 0049 deviceNode }); 0050 if (!( createCmd.write(m_passphrase.toLocal8Bit() + '\n') && 0051 createCmd.start(-1) && createCmd.exitCode() == 0)) 0052 { 0053 return false; 0054 } 0055 0056 ExternalCommand openCmd(report, QStringLiteral("cryptsetup"), 0057 { QStringLiteral("open"), 0058 deviceNode, 0059 suggestedMapperName(deviceNode) }); 0060 0061 if (!( openCmd.write(m_passphrase.toLocal8Bit() + '\n') && openCmd.start(-1))) 0062 return false; 0063 0064 setPayloadSize(); 0065 scan(deviceNode); 0066 0067 if (mapperName().isEmpty()) 0068 return false; 0069 0070 if (!m_innerFs->create(report, mapperName())) 0071 return false; 0072 0073 return true; 0074 } 0075 0076 bool luks2::resize(Report& report, const QString& deviceNode, qint64 newLength) const 0077 { 0078 Q_ASSERT(m_innerFs); 0079 0080 if (mapperName().isEmpty()) 0081 return false; 0082 0083 const qint64 sizeDiff = newLength - length() * sectorSize(); 0084 const qint64 newPayloadSize = m_PayloadSize + sizeDiff; 0085 if ( sizeDiff > 0 ) // grow 0086 { 0087 ExternalCommand cryptResizeCmd(report, QStringLiteral("cryptsetup"), { QStringLiteral("resize"), mapperName() }); 0088 report.line() << xi18nc("@info:progress", "Resizing LUKS crypt on partition <filename>%1</filename>.", deviceNode); 0089 0090 if (m_KeyLocation == KeyLocation::keyring) { 0091 if (m_passphrase.isEmpty()) 0092 return false; 0093 cryptResizeCmd.write(m_passphrase.toLocal8Bit() + '\n'); 0094 } 0095 if (!cryptResizeCmd.start(-1)) 0096 return false; 0097 if ( cryptResizeCmd.exitCode() == 0 ) 0098 return m_innerFs->resize(report, mapperName(), newPayloadSize); 0099 } 0100 else if (m_innerFs->resize(report, mapperName(), newPayloadSize)) 0101 { 0102 ExternalCommand cryptResizeCmd(report, QStringLiteral("cryptsetup"), 0103 { QStringLiteral("--size"), QString::number(newPayloadSize / 512), // FIXME, LUKS2 can have different sector sizes 0104 QStringLiteral("resize"), mapperName() }); 0105 report.line() << xi18nc("@info:progress", "Resizing LUKS crypt on partition <filename>%1</filename>.", deviceNode); 0106 if (m_KeyLocation == KeyLocation::keyring) { 0107 if (m_passphrase.isEmpty()) 0108 return false; 0109 cryptResizeCmd.write(m_passphrase.toLocal8Bit() + '\n'); 0110 } 0111 if (!cryptResizeCmd.start(-1)) 0112 return false; 0113 if ( cryptResizeCmd.exitCode() == 0 ) 0114 return true; 0115 } 0116 report.line() << xi18nc("@info:progress", "Resizing encrypted file system on partition <filename>%1</filename> failed.", deviceNode); 0117 return false; 0118 } 0119 0120 luks::KeyLocation luks2::keyLocation() 0121 { 0122 m_KeyLocation = KeyLocation::unknown; 0123 ExternalCommand statusCmd(QStringLiteral("cryptsetup"), { QStringLiteral("status"), mapperName() }); 0124 if (statusCmd.run(-1) && statusCmd.exitCode() == 0) { 0125 QRegularExpression re(QStringLiteral("key location:\\s+(\\w+)")); 0126 QRegularExpressionMatch rem = re.match(statusCmd.output()); 0127 if (rem.hasMatch()) { 0128 if (rem.captured(1) == QStringLiteral("keyring")) 0129 m_KeyLocation = KeyLocation::keyring; 0130 else if (rem.captured(1) == QStringLiteral("dm-crypt")) 0131 m_KeyLocation = KeyLocation::dmcrypt; 0132 } 0133 } 0134 0135 return m_KeyLocation; 0136 } 0137 0138 }