Skip to content

Commit e9ad85d

Browse files
committed
FEATURE: add multidevice support
1 parent 4a74a1f commit e9ad85d

File tree

2 files changed

+84
-59
lines changed

2 files changed

+84
-59
lines changed

README-dracut.md

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -54,8 +54,9 @@ adding a line to `/etc/crypttab`. It should read like:
5454
Usually there is already an entry for your device.
5555

5656
Update `/etc/ykfde.conf` with correct settings. Add the value of
57-
`mapping-name` from above to `device name` in the `general` section. Then
58-
add a new section with your key's decimal serial number containing the key
57+
`mapping-name` from above to `device name` in the `general` section.
58+
If you have multiple devices add them separated by spaces.
59+
Then add a new section with your key's decimal serial number containing the key
5960
slot setting. The minimal file should look like this:
6061

6162
[general]

bin/ykfde.c

Lines changed: 81 additions & 57 deletions
Original file line numberDiff line numberDiff line change
@@ -117,7 +117,9 @@ int main(int argc, char **argv) {
117117
size_t len;
118118
int8_t rc = EXIT_FAILURE;
119119
/* cryptsetup */
120-
const char * device_name;
120+
const char * device_name_config;
121+
char * device_names[5]; // magic number - store up to 5 devices
122+
int device_num = -1;
121123
int8_t luks_slot = -1;
122124
struct crypt_device *cryptdevice;
123125
crypt_status_info cryptstatus;
@@ -214,11 +216,28 @@ int main(int argc, char **argv) {
214216
goto out10;
215217
}
216218

217-
if ((device_name = iniparser_getstring(ini, "general:" CONFDEVNAME, NULL)) == NULL) {
219+
device_name_config = iniparser_getstring(ini, "general:" CONFDEVNAME, NULL);
220+
if (device_name_config == NULL) {
218221
/* read from crypttab? */
219222
/* get device from currently open devices? */
220223
fprintf(stderr, "Could not read LUKS device from configuration file.\n");
221224
goto out20;
225+
} else {
226+
/* split if multiple devices */
227+
char *device = strtok((char *)device_name_config, " ");
228+
229+
device_num = 0;
230+
231+
while (device != NULL)
232+
{
233+
fprintf(stdout, "loaded device: %s \n", device);
234+
char *ptr = malloc(strlen(device)+1);
235+
ptr = device;
236+
237+
device_names[device_num++] = ptr;
238+
device = strtok (NULL, " ");
239+
}
240+
222241
}
223242

224243
/* init and open first Yubikey */
@@ -330,76 +349,81 @@ int main(int argc, char **argv) {
330349
}
331350
yubikey_hex_encode((char *) passphrase_new, (char *) response_new, SHA1_DIGEST_SIZE);
332351

333-
/* get status of crypt device
334-
* We expect this to be active (or busy). It is the actual root device, no? */
335-
cryptstatus = crypt_status(cryptdevice, device_name);
336-
if (cryptstatus != CRYPT_ACTIVE && cryptstatus != CRYPT_BUSY) {
337-
fprintf(stderr, "Device %s is invalid or inactive.\n", device_name);
338-
goto out50;
339-
}
340-
341-
/* initialize crypt device */
342-
if (crypt_init_by_name(&cryptdevice, device_name) < 0) {
343-
fprintf(stderr, "Device %s failed to initialize.\n", device_name);
344-
goto out60;
345-
}
352+
/* loop over all devices */
353+
for(i = 0; i < device_num; i++) {
346354

347-
cryptkeyslot = crypt_keyslot_status(cryptdevice, luks_slot);
355+
/* get status of crypt device
356+
* We expect this to be active (or busy). It is the actual root device, no? */
357+
cryptstatus = crypt_status(cryptdevice, device_names[i]);
358+
if (cryptstatus != CRYPT_ACTIVE && cryptstatus != CRYPT_BUSY) {
359+
fprintf(stderr, "Device %s is invalid or inactive.\n", device_names[i]);
360+
goto out50;
361+
}
348362

349-
if (cryptkeyslot == CRYPT_SLOT_INVALID) {
350-
fprintf(stderr, "Key slot %d is invalid.\n", luks_slot);
351-
goto out60;
352-
} else if (cryptkeyslot == CRYPT_SLOT_ACTIVE || cryptkeyslot == CRYPT_SLOT_ACTIVE_LAST) {
353-
/* read challenge from file */
354-
if ((challengefile = open(challengefilename, O_RDONLY)) < 0) {
355-
perror("Failed opening challenge file for reading");
363+
/* initialize crypt device */
364+
if (crypt_init_by_name(&cryptdevice, device_names[i]) < 0) {
365+
fprintf(stderr, "Device %s failed to initialize.\n", device_names[i]);
356366
goto out60;
357367
}
358368

359-
if (read(challengefile, challenge_old, CHALLENGELEN) < 0) {
360-
perror("Failed reading challenge from file");
369+
cryptkeyslot = crypt_keyslot_status(cryptdevice, luks_slot);
370+
371+
if (cryptkeyslot == CRYPT_SLOT_INVALID) {
372+
fprintf(stderr, "Key slot %d is invalid.\n", luks_slot);
361373
goto out60;
362-
}
374+
} else if (cryptkeyslot == CRYPT_SLOT_ACTIVE || cryptkeyslot == CRYPT_SLOT_ACTIVE_LAST) {
375+
/* read challenge from file */
376+
if ((challengefile = open(challengefilename, O_RDONLY)) < 0) {
377+
perror("Failed opening challenge file for reading");
378+
goto out60;
379+
}
363380

364-
challengefile = close(challengefile);
365-
/* finished reading challenge */
381+
if (read(challengefile, challenge_old, CHALLENGELEN) < 0) {
382+
perror("Failed reading challenge from file");
383+
goto out60;
384+
}
366385

367-
/* copy the second factor */
368-
len = strlen(second_factor);
369-
memcpy(challenge_old, second_factor, len < MAX2FLEN ? len : MAX2FLEN);
386+
challengefile = close(challengefile);
387+
/* finished reading challenge */
370388

371-
/* do challenge/response and encode to hex */
372-
if (yk_challenge_response(yk, yk_slot, true,
373-
CHALLENGELEN, (unsigned char *) challenge_old,
374-
RESPONSELEN, (unsigned char *) response_old) == 0) {
375-
perror("yk_challenge_response() failed");
376-
goto out60;
377-
}
378-
yubikey_hex_encode((char *) passphrase_old, (char *) response_old, SHA1_DIGEST_SIZE);
389+
/* copy the second factor */
390+
len = strlen(second_factor);
391+
memcpy(challenge_old, second_factor, len < MAX2FLEN ? len : MAX2FLEN);
379392

380-
if (crypt_keyslot_change_by_passphrase(cryptdevice, luks_slot, luks_slot,
381-
passphrase_old, PASSPHRASELEN,
382-
passphrase_new, PASSPHRASELEN) < 0) {
383-
fprintf(stderr, "Could not update passphrase for key slot %d.\n", luks_slot);
384-
goto out60;
385-
}
393+
/* do challenge/response and encode to hex */
394+
if (yk_challenge_response(yk, yk_slot, true,
395+
CHALLENGELEN, (unsigned char *) challenge_old,
396+
RESPONSELEN, (unsigned char *) response_old) == 0) {
397+
perror("yk_challenge_response() failed");
398+
goto out60;
399+
}
400+
yubikey_hex_encode((char *) passphrase_old, (char *) response_old, SHA1_DIGEST_SIZE);
386401

387-
if (unlink(challengefilename) < 0) {
388-
fprintf(stderr, "Failed to delete old challenge file.\n");
389-
goto out60;
390-
}
391-
} else { /* ck == CRYPT_SLOT_INACTIVE */
392-
if ((passphrase = ask_secret("existing LUKS passphrase")) == NULL)
393-
goto out60;
402+
if (crypt_keyslot_change_by_passphrase(cryptdevice, luks_slot, luks_slot,
403+
passphrase_old, PASSPHRASELEN,
404+
passphrase_new, PASSPHRASELEN) < 0) {
405+
fprintf(stderr, "Could not update passphrase for %s in key slot %d.\n", device_names[i], luks_slot);
406+
goto out60;
407+
}
394408

395-
if (crypt_keyslot_add_by_passphrase(cryptdevice, luks_slot,
396-
passphrase, strlen(passphrase),
397-
passphrase_new, PASSPHRASELEN) < 0) {
398-
fprintf(stderr, "Could not add passphrase for key slot %d.\n", luks_slot);
399-
goto out60;
409+
} else { /* ck == CRYPT_SLOT_INACTIVE */
410+
if ((passphrase = ask_secret("existing LUKS passphrase")) == NULL)
411+
goto out60;
412+
413+
if (crypt_keyslot_add_by_passphrase(cryptdevice, luks_slot,
414+
passphrase, strlen(passphrase),
415+
passphrase_new, PASSPHRASELEN) < 0) {
416+
fprintf(stderr, "Could not add passphrase for %s in key slot %d.\n", device_names[i], luks_slot);
417+
goto out60;
418+
}
400419
}
401420
}
402421

422+
if (unlink(challengefilename) < 0) {
423+
fprintf(stderr, "Failed to delete old challenge file.\n");
424+
goto out60;
425+
}
426+
403427
if (rename(challengefiletmpname, challengefilename) < 0) {
404428
fprintf(stderr, "Failed to rename new challenge file.\n");
405429
goto out60;

0 commit comments

Comments
 (0)