Skip to content

Commit

Permalink
FEATURE: add multidevice support
Browse files Browse the repository at this point in the history
  • Loading branch information
Benjamin Pereto committed Apr 1, 2018
1 parent 4a74a1f commit e9ad85d
Show file tree
Hide file tree
Showing 2 changed files with 84 additions and 59 deletions.
5 changes: 3 additions & 2 deletions README-dracut.md
Original file line number Diff line number Diff line change
Expand Up @@ -54,8 +54,9 @@ adding a line to `/etc/crypttab`. It should read like:
Usually there is already an entry for your device.

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

[general]
Expand Down
138 changes: 81 additions & 57 deletions bin/ykfde.c
Original file line number Diff line number Diff line change
Expand Up @@ -117,7 +117,9 @@ int main(int argc, char **argv) {
size_t len;
int8_t rc = EXIT_FAILURE;
/* cryptsetup */
const char * device_name;
const char * device_name_config;
char * device_names[5]; // magic number - store up to 5 devices
int device_num = -1;
int8_t luks_slot = -1;
struct crypt_device *cryptdevice;
crypt_status_info cryptstatus;
Expand Down Expand Up @@ -214,11 +216,28 @@ int main(int argc, char **argv) {
goto out10;
}

if ((device_name = iniparser_getstring(ini, "general:" CONFDEVNAME, NULL)) == NULL) {
device_name_config = iniparser_getstring(ini, "general:" CONFDEVNAME, NULL);
if (device_name_config == NULL) {
/* read from crypttab? */
/* get device from currently open devices? */
fprintf(stderr, "Could not read LUKS device from configuration file.\n");
goto out20;
} else {
/* split if multiple devices */
char *device = strtok((char *)device_name_config, " ");

device_num = 0;

while (device != NULL)
{
fprintf(stdout, "loaded device: %s \n", device);
char *ptr = malloc(strlen(device)+1);
ptr = device;

device_names[device_num++] = ptr;
device = strtok (NULL, " ");
}

}

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

/* get status of crypt device
* We expect this to be active (or busy). It is the actual root device, no? */
cryptstatus = crypt_status(cryptdevice, device_name);
if (cryptstatus != CRYPT_ACTIVE && cryptstatus != CRYPT_BUSY) {
fprintf(stderr, "Device %s is invalid or inactive.\n", device_name);
goto out50;
}

/* initialize crypt device */
if (crypt_init_by_name(&cryptdevice, device_name) < 0) {
fprintf(stderr, "Device %s failed to initialize.\n", device_name);
goto out60;
}
/* loop over all devices */
for(i = 0; i < device_num; i++) {

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

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

if (read(challengefile, challenge_old, CHALLENGELEN) < 0) {
perror("Failed reading challenge from file");
cryptkeyslot = crypt_keyslot_status(cryptdevice, luks_slot);

if (cryptkeyslot == CRYPT_SLOT_INVALID) {
fprintf(stderr, "Key slot %d is invalid.\n", luks_slot);
goto out60;
}
} else if (cryptkeyslot == CRYPT_SLOT_ACTIVE || cryptkeyslot == CRYPT_SLOT_ACTIVE_LAST) {
/* read challenge from file */
if ((challengefile = open(challengefilename, O_RDONLY)) < 0) {
perror("Failed opening challenge file for reading");
goto out60;
}

challengefile = close(challengefile);
/* finished reading challenge */
if (read(challengefile, challenge_old, CHALLENGELEN) < 0) {
perror("Failed reading challenge from file");
goto out60;
}

/* copy the second factor */
len = strlen(second_factor);
memcpy(challenge_old, second_factor, len < MAX2FLEN ? len : MAX2FLEN);
challengefile = close(challengefile);
/* finished reading challenge */

/* do challenge/response and encode to hex */
if (yk_challenge_response(yk, yk_slot, true,
CHALLENGELEN, (unsigned char *) challenge_old,
RESPONSELEN, (unsigned char *) response_old) == 0) {
perror("yk_challenge_response() failed");
goto out60;
}
yubikey_hex_encode((char *) passphrase_old, (char *) response_old, SHA1_DIGEST_SIZE);
/* copy the second factor */
len = strlen(second_factor);
memcpy(challenge_old, second_factor, len < MAX2FLEN ? len : MAX2FLEN);

if (crypt_keyslot_change_by_passphrase(cryptdevice, luks_slot, luks_slot,
passphrase_old, PASSPHRASELEN,
passphrase_new, PASSPHRASELEN) < 0) {
fprintf(stderr, "Could not update passphrase for key slot %d.\n", luks_slot);
goto out60;
}
/* do challenge/response and encode to hex */
if (yk_challenge_response(yk, yk_slot, true,
CHALLENGELEN, (unsigned char *) challenge_old,
RESPONSELEN, (unsigned char *) response_old) == 0) {
perror("yk_challenge_response() failed");
goto out60;
}
yubikey_hex_encode((char *) passphrase_old, (char *) response_old, SHA1_DIGEST_SIZE);

if (unlink(challengefilename) < 0) {
fprintf(stderr, "Failed to delete old challenge file.\n");
goto out60;
}
} else { /* ck == CRYPT_SLOT_INACTIVE */
if ((passphrase = ask_secret("existing LUKS passphrase")) == NULL)
goto out60;
if (crypt_keyslot_change_by_passphrase(cryptdevice, luks_slot, luks_slot,
passphrase_old, PASSPHRASELEN,
passphrase_new, PASSPHRASELEN) < 0) {
fprintf(stderr, "Could not update passphrase for %s in key slot %d.\n", device_names[i], luks_slot);
goto out60;
}

if (crypt_keyslot_add_by_passphrase(cryptdevice, luks_slot,
passphrase, strlen(passphrase),
passphrase_new, PASSPHRASELEN) < 0) {
fprintf(stderr, "Could not add passphrase for key slot %d.\n", luks_slot);
goto out60;
} else { /* ck == CRYPT_SLOT_INACTIVE */
if ((passphrase = ask_secret("existing LUKS passphrase")) == NULL)
goto out60;

if (crypt_keyslot_add_by_passphrase(cryptdevice, luks_slot,
passphrase, strlen(passphrase),
passphrase_new, PASSPHRASELEN) < 0) {
fprintf(stderr, "Could not add passphrase for %s in key slot %d.\n", device_names[i], luks_slot);
goto out60;
}
}
}

if (unlink(challengefilename) < 0) {
fprintf(stderr, "Failed to delete old challenge file.\n");
goto out60;
}

if (rename(challengefiletmpname, challengefilename) < 0) {
fprintf(stderr, "Failed to rename new challenge file.\n");
goto out60;
Expand Down

0 comments on commit e9ad85d

Please sign in to comment.