25 #include <sys/mount.h>
30 #include <libcryptsetup.h>
32 #include <QDataStream>
33 #include <QTextStream>
35 #include <QLatin1Char>
43 #define SIGNON_LUKS_DEFAULT_HASH "ripemd160"
45 #define SIGNON_LUKS_CIPHER_NAME "aes"
46 #define SIGNON_LUKS_CIPHER_MODE "xts-plain"
47 #define SIGNON_LUKS_CIPHER \
48 SIGNON_LUKS_CIPHER_NAME "-" SIGNON_LUKS_CIPHER_MODE
49 #define SIGNON_LUKS_KEY_SIZE 256
50 #define SIGNON_LUKS_BASE_KEYSLOT 0
52 #define SIGNON_EXTERNAL_PROCESS_READ_TIMEOUT 300
54 #define KILO_BYTE_SIZE 1024
55 #define MEGA_BYTE_SIZE (KILO_BYTE_SIZE * 1024)
61 connect(&m_process, SIGNAL(error(QProcess::ProcessError)),
62 this, SLOT(error(QProcess::ProcessError)));
70 const QStringList &args,
74 QTextStream stream(&trace);
75 stream << appPath << QLatin1Char(
' ') << args.join(QLatin1String(
" "));
78 m_process.start(appPath, args);
79 if (!m_process.waitForStarted()) {
80 BLAME() <<
"Wait for started failed";
88 if (!m_process.bytesAvailable()) {
89 BLAME() <<
"Coult not read output of external process ";
93 while(m_process.bytesAvailable())
94 m_output += m_process.readAllStandardOutput();
98 if (!m_process.waitForFinished()) {
99 TRACE() <<
"Wait for finished failed";
106 void SystemCommandLineCallHandler::error(QProcess::ProcessError err)
108 TRACE() <<
"Process erorr:" << err;
115 const quint32 fileSize)
117 int fd = open(fileName.toLatin1().data(),
122 BLAME() <<
"FAILED to create signon secure FS partition file. ERRNO:"
128 BLAME() <<
"FAILED to set signon secure FS partition file size. ERRNO:"
134 TRACE() <<
"Failed to close secure FS partition file after creation.";
137 TRACE() <<
"Failed to set file permissions "
138 "for the secure storage container.";
144 const quint32 fileSystemType)
146 QString mkfsApp = QString::fromLatin1(
"/sbin/mkfs.ext2");
147 switch (fileSystemType) {
148 case Ext2: mkfsApp = QString::fromLatin1(
"/sbin/mkfs.ext2");
break;
149 case Ext3: mkfsApp = QString::fromLatin1(
"/sbin/mkfs.ext3");
break;
150 case Ext4: mkfsApp = QString::fromLatin1(
"/sbin/mkfs.ext4");
break;
157 QStringList() << fileName);
164 const QString &mountPath,
165 const QString &fileSystemTtpe)
168 return (::
mount(toMount.toUtf8().constData(),
169 mountPath.toUtf8().constData(),
170 fileSystemTtpe.toUtf8().constData(),
171 MS_SYNCHRONOUS | MS_NOEXEC, NULL) == 0);
180 TRACE() << mountPath.toUtf8().constData();
181 int ret = ::umount2(mountPath.toUtf8().constData(), MNT_FORCE);
185 case EAGAIN:
TRACE() <<
"EAGAIN";
break;
186 case EBUSY:
TRACE() <<
"EBUSY";
break;
187 case EFAULT:
TRACE() <<
"EFAULT";
break;
188 case EINVAL:
TRACE() <<
"EINVAL";
break;
189 case ENAMETOOLONG:
TRACE() <<
"ENAMETOOLONG";
break;
190 case ENOENT:
TRACE() <<
"ENOENT";
break;
191 case ENOMEM:
TRACE() <<
"ENOMEM";
break;
192 case EPERM:
TRACE() <<
"EPERM";
break;
193 default:
TRACE() <<
"umount unknown error - ignoring.";
205 const QString &blockDevice)
209 QLatin1String(
"/sbin/losetup"),
210 QStringList() << deviceName << blockDevice);
218 QLatin1String(
"/sbin/losetup"),
219 QStringList() << QLatin1String(
"-f"),
222 deviceName = QString::fromLocal8Bit(handler.
output().trimmed());
233 return handler.
makeCall(QLatin1String(
"/sbin/losetup"),
235 QString::fromLatin1(
"-d") << deviceName);
241 #define MYCRYPT_FLAG_VERIFY (1 << 0)
242 #define MYCRYPT_FLAG_READONLY (1 << 1)
243 #define MYCRYPT_FLAG_VERIFY_IF_POSSIBLE (1 << 2)
244 #define MYCRYPT_FLAG_VERIFY_ON_DELKEY (1 << 3)
245 #define MYCRYPT_FLAG_NON_EXCLUSIVE_ACCESS (1 << 4)
247 struct my_crypt_options {
252 const char *key_file;
253 const char *new_key_file;
257 uint64_t iteration_time;
259 size_t align_payload;
261 int (*icb_yesDialog)(
char *msg);
262 void (*icb_log)(
int klass,
char *msg);
268 static int yesDialog(
char *msg)
274 static void cmdLineLog(
int type,
char *msg)
277 case CRYPT_LOG_NORMAL:
280 case CRYPT_LOG_ERROR:
281 TRACE() <<
"Error: " << msg;
284 TRACE() <<
"Internal error on logging class for msg: " << msg;
289 static void log_wrapper(
int level,
const char *msg,
void *usrptr)
291 void (*xlog)(
int level,
char *msg) = (
void (*)(int,
char*)) usrptr;
292 xlog(level, (
char *)msg);
295 static int yesDialog_wrapper(
const char *msg,
void *usrptr)
297 int (*xyesDialog)(
char *msg) = (
int (*)(
char*)) usrptr;
298 return xyesDialog((
char*)msg);
305 struct crypt_device *cd = NULL;
306 struct crypt_params_luks1 cp = {
308 options->align_payload,
313 if ((r = crypt_init(&cd, options->device)))
316 crypt_set_log_callback(cd, log_wrapper, (
void*) options->icb_log);
317 crypt_set_confirm_callback(cd, yesDialog_wrapper,
318 (
void*) options->icb_yesDialog);
320 crypt_set_timeout(cd, options->timeout);
321 crypt_set_password_retry(cd, options->tries);
322 crypt_set_iterarion_time(cd, options->iteration_time ?: 1000);
325 r = crypt_format(cd, CRYPT_LUKS1,
327 NULL, NULL, options->key_size, &cp);
332 r = crypt_keyslot_add_by_volume_key(cd, options->key_slot, NULL, 0,
336 return (r < 0) ? r : 0;
341 const QString &deviceName)
343 struct my_crypt_options options;
348 char *localDeviceName = (
char *)malloc(deviceName.length() + 1);
349 Q_ASSERT(localDeviceName != NULL);
351 strcpy(localDeviceName, deviceName.toLatin1().constData());
352 options.device = localDeviceName;
355 options.new_key_file = NULL;
357 char *localKey = (
char *)malloc(key.length());
358 Q_ASSERT(localKey != NULL);
359 memcpy(localKey, key.constData(), key.length());
362 options.iteration_time = 1000;
364 options.align_payload = 0;
366 options.icb_yesDialog = 0;
369 TRACE() <<
"Device: [" << options.device <<
"]";
370 TRACE() <<
"Key size:" << key.length();
375 TRACE() <<
"LUKS format API call result:" << ret <<
"." <<
error();
378 free(localDeviceName);
381 memset(localKey, 0x00, key.length());
389 const char *pwd,
unsigned int pwdLen)
391 struct crypt_device *cd = NULL;
395 if ((r = crypt_init(&cd, options->device)))
398 crypt_set_log_callback(cd, log_wrapper, (
void*) options->icb_log);
399 crypt_set_confirm_callback(cd, yesDialog_wrapper,
400 (
void*) options->icb_yesDialog);
402 crypt_set_timeout(cd, options->timeout);
403 crypt_set_password_retry(cd, options->tries);
404 crypt_set_iterarion_time(cd, options->iteration_time ?: 1000);
407 if ((r = crypt_load(cd, CRYPT_LUKS1, NULL))) {
413 flags |= CRYPT_ACTIVATE_READONLY;
416 flags |= CRYPT_ACTIVATE_NO_UUID;
418 if (options->key_file)
421 r = crypt_activate_by_passphrase(cd, options->name,
426 return (r < 0) ? r : 0;
430 const QString &deviceName,
431 const QString &deviceMap)
433 struct my_crypt_options options;
435 char *localDeviceMap = (
char *)malloc(deviceMap.length() + 1);
436 Q_ASSERT(localDeviceMap != NULL);
437 strcpy(localDeviceMap, deviceMap.toLatin1().constData());
438 options.name = localDeviceMap;
440 char *localDeviceName = (
char *)malloc(deviceName.length() + 1);
441 Q_ASSERT(localDeviceName != NULL);
442 strcpy(localDeviceName, deviceName.toLatin1().constData());
443 options.device = localDeviceName;
445 char *localKey = (
char *)malloc(key.length());
446 Q_ASSERT(localKey != NULL);
447 memcpy(localKey, key.constData(), key.length());
449 options.key_file = NULL;
461 options.icb_yesDialog = yesDialog;
462 options.icb_log = cmdLineLog;
464 TRACE() <<
"Device [" << options.device <<
"]";
465 TRACE() <<
"Map name [" << options.name <<
"]";
466 TRACE() <<
"Key size:" << key.length();
471 TRACE() <<
"LUKS open API call result:" << ret <<
"." <<
error() <<
".";
474 free(localDeviceName);
477 free(localDeviceMap);
480 memset(localKey, 0x00, key.length());
489 struct crypt_device *cd = NULL;
493 if ((r = crypt_init_by_name(&cd, options->name)))
495 r = crypt_deactivate(cd, options->name);
502 struct my_crypt_options options;
504 char *localDeviceMap = (
char *)malloc(deviceMap.length() + 1);
505 Q_ASSERT(localDeviceMap != NULL);
506 strcpy(localDeviceMap, deviceMap.toLatin1().constData());
507 options.name = localDeviceMap;
509 options.icb_yesDialog = yesDialog;
510 options.icb_log = cmdLineLog;
512 TRACE() <<
"Map name [" << options.name <<
"]";
517 TRACE() <<
"Cryptsetup remove API call result:" << ret <<
521 free(localDeviceMap);
528 Q_UNUSED(deviceName);
534 const char *pwd,
unsigned int pwdLen,
535 const char *newPwd,
unsigned int newPwdLen)
537 struct crypt_device *cd = NULL;
540 if ((r = crypt_init(&cd, options->device)))
543 crypt_set_log_callback(cd, log_wrapper, (
void*) options->icb_log);
544 crypt_set_confirm_callback(cd, yesDialog_wrapper,
545 (
void*) options->icb_yesDialog);
547 crypt_set_timeout(cd, options->timeout);
548 crypt_set_password_retry(cd, options->tries);
549 crypt_set_iterarion_time(cd, options->iteration_time ?: 1000);
552 if ((r = crypt_load(cd, CRYPT_LUKS1, NULL))) {
557 if (options->key_file || options->new_key_file)
560 r = crypt_keyslot_add_by_passphrase(cd, options->key_slot,
561 pwd, pwdLen, newPwd, newPwdLen);
564 return (r < 0) ? r : 0;
568 const QByteArray &key,
569 const QByteArray &existingKey)
571 struct my_crypt_options options;
576 char *localDeviceName = (
char *)malloc(deviceName.length() + 1);
577 Q_ASSERT(localDeviceName != NULL);
578 strcpy(localDeviceName, deviceName.toLatin1().constData());
580 options.device = localDeviceName;
581 options.new_key_file = NULL;
582 options.key_file = NULL;
583 options.key_slot = -1;
586 options.iteration_time = 1000;
590 options.icb_yesDialog = yesDialog;
591 options.icb_log = cmdLineLog;
594 existingKey.constData(),
595 existingKey.length(),
596 key.constData(), key.length());
599 free(localDeviceName);
602 TRACE() <<
"Cryptsetup add key API call result:" << ret <<
610 int crypt_luksRemoveKeyBinary(
struct my_crypt_options *options,
611 const char *pwdToRemove,
612 unsigned int pwdToRemoveLen)
614 struct crypt_device *cd = NULL;
618 if ((r = crypt_init(&cd, options->device)))
621 crypt_set_log_callback(cd, log_wrapper, (
void*) options->icb_log);
622 crypt_set_confirm_callback(cd, yesDialog_wrapper,
623 (
void*) options->icb_yesDialog);
625 crypt_set_timeout(cd, options->timeout);
626 crypt_set_password_retry(cd, options->tries);
627 crypt_set_iterarion_time(cd, options->iteration_time ?: 1000);
630 if ((r = crypt_load(cd, CRYPT_LUKS1, NULL))) {
635 if ((key_slot = crypt_keyslot_by_passphrase(cd, NULL, pwdToRemove,
636 pwdToRemoveLen, 0, NULL)) < 0) {
641 r = crypt_keyslot_destroy(cd, key_slot);
645 return (r < 0) ? r : 0;
648 bool CryptsetupHandler::removeKeySlot(
const QString &deviceName,
649 const QByteArray &key,
650 const QByteArray &remainingKey)
652 struct my_crypt_options options;
657 char *localDeviceName = (
char *)malloc(deviceName.length() + 1);
658 Q_ASSERT(localDeviceName != NULL);
659 strcpy(localDeviceName, deviceName.toLatin1().constData());
661 options.device = localDeviceName;
662 options.new_key_file = NULL;
663 options.key_file = NULL;
664 options.key_slot = -1;
669 options.icb_yesDialog = yesDialog;
670 options.icb_log = cmdLineLog;
672 int ret = crypt_luksRemoveKeyBinary(&options, key.constData(), key.length());
675 free(localDeviceName);
678 TRACE() <<
"Cryptsetup remove key API call result:" << ret <<
689 QLatin1String(
"/sbin/modprobe"),
690 QStringList() << QString::fromLatin1(
"dm_mod"));
696 crypt_get_error(buf, 256);
697 return QString::fromLocal8Bit(buf);
static bool setupDevice(const QString &deviceName, const QString &blockDevice)
Mounts a block device to loopback device.
bool makeCall(const QString &appPath, const QStringList &args, bool readOutput=false)
Executes the application at appPath in a separate child process.
#define MYCRYPT_FLAG_READONLY
#define MYCRYPT_FLAG_NON_EXCLUSIVE_ACCESS
static bool formatPartitionFile(const QString &fileName, const quint32 fileSystemType)
Formats a file (block device) for a specific file system type (ext2,ext3,ext4)
static bool createPartitionFile(const QString &fileName, const quint32 fileSize)
Creates a random data file of fileSize Mb.
~SystemCommandLineCallHandler()
Destructor.
QByteArray output() const
int crypt_luksOpenBinary(struct my_crypt_options *options, const char *pwd, unsigned int pwdLen)
static bool formatFile(const QByteArray &key, const QString &deviceName)
Formats the file system.
#define SIGNON_LUKS_CIPHER_MODE
SystemCommandLineCallHandler()
Basic constructor.
#define SIGNON_LUKS_CIPHER_NAME
#define SIGNON_LUKS_KEY_SIZE
const QFile::Permissions signonFilePermissions
static bool loadDmMod()
Loads the dm_mod kernel module.
static bool closeFile(const QString &deviceName)
Closes the file system.
static bool umount(const QString &target)
Unmounts a block device from a specific location.
bool setFilePermissions(const QString &filePath, const QFile::Permissions desiredPermissions, bool keepExisting)
#define SIGNON_EXTERNAL_PROCESS_READ_TIMEOUT
static bool removeFile(const QString &deviceName)
Removes the file system.
#define SIGNON_LUKS_CIPHER
int crypt_luksAddKeyBinary(struct my_crypt_options *options, const char *pwd, unsigned int pwdLen, const char *newPwd, unsigned int newPwdLen)
Handles calls to system command line tools.
int crypt_removeDevice(struct my_crypt_options *options)
int crypt_luksFormatBinary(struct my_crypt_options *options, const char *pwd, unsigned int pwdLen)
static bool addKeySlot(const QString &deviceName, const QByteArray &key, const QByteArray &existingKey)
Adds a key to a free encryption header slot.
#define SIGNON_LUKS_BASE_KEYSLOT
#define MYCRYPT_FLAG_VERIFY
static bool mount(const QString &source, const QString &target, const QString &fileSystemType=QLatin1String("ext2"))
Mounts a block device to a specific location.
static bool releaseDevice(const QString &deviceName)
Releases a used loopback device.
static QString findAvailableDevice()
Finds an available loopback device.
static bool openFile(const QByteArray &key, const QString &deviceName, const QString &deviceMap)
Opens the file system.