Skip to contentSkip to conversation

Option "validate passphrase" for command cryptsetup

dm-crypt Louis 9 participants 16 messages Jun 19, 2012 – Jun 20, 2012

lore
Share & tools
lore

Louis

author
#0 lore raw

Hello,
for information, I wrote a small C program to check if the given
passphrase is correct, without doing anything on the disk. The command is used this way:

	$ cryptsetup_check_passphrase /dev/sda1
	Enter passphrase for /dev/sda1: <MY_SECRET_PASSPHRASE>
	Valid key (slot 0)
	$

If you think it can benefit cryptsetup, I offer to write the necessary
patch to include it to cryptsetup (as a "luksValidateKey" LUKS action).

# why do I need such a command ?

We are a group of hacktivists who offer some online services (such as
email addresses). Our disks are encrypted using LUKS. As we are six members operating the server, and we reboot it only a few times a year, it may happen that some of us only use the passphrase once in two years, which is prone to forgetting. So we want a way to, once in a while (at our monthly meetings), check that we still know our passphrase, without risking to do something on the disk (creating, removing partition, deleting passphrases, etc.).

# Security risks

Isn't this function a wonderful tool to try brute force attacks ? I do
not think so. Attacker needs to be root to run it, at which point (s)he can already do a lot of harmful things. Moreover, once (s)he is root, attacker might as well compile the program I just wrote to try this brute force attack. To sum up: Yes, it can be used to brute force the partition, but nothing more that what was possible to do without this tool.

Regards,
Louis

PS : Not to overload this list with many files, I only give you here the C code. If you want the makefile and configure.ac, just ask.

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

#include <libcryptsetup.h>

void usage() {
printf("cryptsetup_check_passphrase LUKSDEVICE\n");
}

int check_passphrase(const char* device_name) {
int keyslot;
int error;
int status;
struct crypt_device *cd = NULL;

if ((error = crypt_init(&cd, device_name))) {
printf("Could not open device \"%s\": %s\n", device_name,

strerror(-error));
    return 1;
  }
  if ((error = crypt_load(cd, NULL, NULL))) {
    printf("Could not load device \"%s\": %s\n", device_name,
strerror(-error));
    return 1;

}

keyslot = crypt_activate_by_passphrase(cd, NULL, CRYPT_ANY_SLOT, NULL,
0, 0);

  if (keyslot >= 0) {
    printf("Valid key (slot %u)\n", keyslot);
    status = 0;
  } else {
    printf("No matching key found: %s\n", strerror(-keyslot));
    status = 1;

}
crypt_free(cd);
return status;
}

int main( int argc, const char* argv[] ) {
int status;

  /* Parsing arguments */
  if (argc != 2) {
    usage();
    return 1;
  }

  /* Check */
  status = check_passphrase(argv[1]);

return status;
}

#1 lore raw
Quoted 7 lines · Louis

Hello,
for information, I wrote a small C program to check if the given
passphrase is correct, without doing anything on the disk. The command is used this way:

If you think it can benefit cryptsetup, I offer to write the necessary
patch to include it to cryptsetup (as a "luksValidateKey" LUKS action).

Special program or command is IMHO overkill, isn't enough just to add option to cryptsetup luksOpen (--dry-run, --no-activate, whatever you prefer)?

So it will work just like

# cryptsetup luksOpen /dev/sdc anything --dry-run --verbose
Enter passphrase for /dev/sdc: 
No key available with this passphrase.
Enter passphrase for /dev/sdc: 
Key slot 0 unlocked.
Command successful.

Trivial to add to code... (while I am doing another RC today, it can be done today even ;-)

Milan

#2 lore raw

I think having this functionality is a good idea.

Arno

Quoted 30 lines · Milan Broz
Quoted 7 lines · Louis

Hello,
for information, I wrote a small C program to check if the given
passphrase is correct, without doing anything on the disk. The command is used this way:

If you think it can benefit cryptsetup, I offer to write the necessary
patch to include it to cryptsetup (as a "luksValidateKey" LUKS action).

Special program or command is IMHO overkill, isn't enough just to add option to cryptsetup luksOpen (--dry-run, --no-activate, whatever you prefer)?

So it will work just like

# cryptsetup luksOpen /dev/sdc anything --dry-run --verbose
Enter passphrase for /dev/sdc: 
No key available with this passphrase.
Enter passphrase for /dev/sdc: 
Key slot 0 unlocked.
Command successful.

Trivial to add to code... (while I am doing another RC today, it can be done today even ;-)

Milan
_______________________________________________
dm-crypt mailing list
[email protected]
http://www.saout.de/mailman/listinfo/dm-crypt

Signature · 6 lines
Arno Wagner,    Dr. sc. techn., Dipl. Inform.,   Email: [email protected] 
GnuPG:  ID: 1E25338F  FP: 0C30 5782 9D93 F785 E79C  0296 797F 6B50 1E25 338F
----
One of the painful things about our time is that those who feel certainty 
are stupid, and those with any imagination and understanding are filled 
with doubt and indecision. -- Bertrand Russell 
#3 lore raw
Quoted 4 lines · Arno Wagner

I think having this functionality is a good idea.

Quoted 2 lines

Trivial to add to code... (while I am doing another RC today, it can be done today even ;-)

Added --without activation option for luksOpen
http://code.google.com/p/cryptsetup/source/detail?r=a38fcafcff9ae75feda12bc84d04b2cdaa591f9f#

# cryptsetup luksOpen /dev/sdc x --without-activation -T 1 ; echo $?
Enter passphrase for /dev/sdc:  (good passphrase)
0
# cryptsetup luksOpen /dev/sdc x --without-activation -T 1 ; echo $?
Enter passphrase for /dev/sdc:  (bad passphrase)
No key available with this passphrase.
2

Milan

#4 lore raw

Am 19.06.2012 15:41, schrieb Milan Broz:

Quoted 9 lines · Arno Wagner
Quoted 4 lines

I think having this functionality is a good idea.

Quoted 2 lines

Trivial to add to code... (while I am doing another RC today, it can be done today even ;-)

Added --without activation option for luksOpen
http://code.google.com/p/cryptsetup/source/detail?r=a38fcafcff9ae75feda12bc84d04b2cdaa591f9f#

Quoted 8 lines
# cryptsetup luksOpen /dev/sdc x --without-activation -T 1 ; echo $?
Enter passphrase for /dev/sdc:  (good passphrase)
0
# cryptsetup luksOpen /dev/sdc x --without-activation -T 1 ; echo $?
Enter passphrase for /dev/sdc:  (bad passphrase)
No key available with this passphrase.
2

I find the option name --without-activation to be quite long and hard to type. Is there any reason why you didn't choose '--dry-run' as you first suggested?

#5 lore raw
Quoted 3 lines · Thomas Bächler

I find the option name --without-activation to be quite long and hard to type. Is there any reason why you didn't choose '--dry-run' as you first suggested?

Actually I wrote --dry-run, --no-activate, --no-activation, --without-activation on paper ... and then asked someone here what's the best:)

Well, I think this option will be rarely used and I guess it is mainly for use in scripts. Option name says exactly what it is doing.

The name --dry-run in more generic, as user, I would expect it can be used even for slot commands etc.

If you have better name for it, no problem to change it still.

Milan

#6 lore raw
Quoted 11 lines · Milan Broz
Quoted 3 lines · Thomas Bächler

I find the option name --without-activation to be quite long and hard to type. Is there any reason why you didn't choose '--dry-run' as you first suggested?

Actually I wrote --dry-run, --no-activate, --no-activation, --without-activation on paper ... and then asked someone here what's the best:)

Well, I think this option will be rarely used and I guess it is mainly for use in scripts. Option name says exactly what it is doing.

It says what technically happens, not was is the intent of using said option. (You have to read the man-page, at least in the git-version of a few minutes ago the intent is right after the technicallity)

I think intent is much easier to understand.

So i'd vote for: --test-passphrase

Bis denn

Signature · 4 lines
Real Programmers consider "what you see is what you get" to be just as 
bad a concept in Text Editors as it is in women. No, the Real Programmer
wants a "you asked for it, you got it" text editor -- complicated, 
cryptic, powerful, unforgiving, dangerous.
#9 lore raw
In reply to Milan Broz

Hello,

Am 19.06.2012 13:26, schrieb Milan Broz:

Quoted 6 lines · Louis
Quoted 4 lines

Hello,
for information, I wrote a small C program to check if the given
passphrase is correct, without doing anything on the disk. The command is used this way:

Quoted 6 lines
Quoted 3 lines

If you think it can benefit cryptsetup, I offer to write the
necessary
patch to include it to cryptsetup (as a "luksValidateKey" LUKS action).

Special program or command is IMHO overkill, isn't enough just to add option to cryptsetup luksOpen (--dry-run, --no-activate, whatever you prefer)?

if I'm not wrong, one difference between Louis' suggestion and the way you implemented it is, that the former works with active devices, and the latter doesn't, right?

I like the idea of a --dry-run option which works for all commands, just like a simulation mode. But as well I like the idea of a command for key validation, which takes the same commandline options as luksOpen, and simply verifies whether the given key (passphrase, keyfile, whatever) is valid.

Regards,
jonas

#10 lore raw
Quoted 3 lines · jonas

if I'm not wrong, one difference between Louis' suggestion and the way you implemented it is, that the former works with active devices, and the latter doesn't, right?

No, it is exactly the same. It works even for active devices. (Check for active device is later.)

Quoted 5 lines

I like the idea of a --dry-run option which works for all commands, just like a simulation mode. But as well I like the idea of a command for key validation, which takes the same commandline options as luksOpen, and simply verifies whether the given key (passphrase, keyfile, whatever) is valid.

Well, universal --dry-run is nice idea but I am not going to implement it now. (and I would perhaps do it differently - do everything as is except final on-disk metadata update or in-kernel device change.)

Well, I have local commit renaming this luksOpen option to --test-passphrase. If there are no other suggestions for today, I'll commit it.

Milan
(grumbling something about bikeshedding :-)

#7 lore raw
In reply to Matthias Schniedermeyer
Quoted 13 lines · Matthias Schniedermeyer
Quoted 11 lines · Milan Broz
Quoted 3 lines · Thomas Bächler

I find the option name --without-activation to be quite long and hard to type. Is there any reason why you didn't choose '--dry-run' as you first suggested?

Actually I wrote --dry-run, --no-activate, --no-activation, --without-activation on paper ... and then asked someone here what's the best:)

Well, I think this option will be rarely used and I guess it is mainly for use in scripts. Option name says exactly what it is doing.

Quoted 7 lines

It says what technically happens, not was is the intent of using said option. (You have to read the man-page, at least in the git-version of a few minutes ago the intent is right after the technicallity)

I think intent is much easier to understand.

So i'd vote for: --test-passphrase

I'd agree, especially since the entire command would then read:

cryptsetup luksOpen /dev/sdc x --test-passphrase -T 1

To read in documentation, on the other hand:

cryptsetup luksOpen /dev/sdc x --without-activation -T 1

I would be asking, "What is not being activated?" So it's very ambiguous. On the other hand, "--test-passphrase" is much clearer, much easier to understand.

Would there still be a delay between invocations?

#11 lore raw
In reply to Milan Broz

Hey Milan,

Am 19.06.2012 18:14, schrieb Milan Broz:

Quoted 8 lines · jonas
Quoted 4 lines

if I'm not wrong, one difference between Louis' suggestion and the way you implemented it is, that the former works with active devices, and the latter doesn't, right?

No, it is exactly the same. It works even for active devices. (Check for active device is later.)

great to hear that I was wrong ;)

Quoted 9 lines
Quoted 5 lines

I like the idea of a --dry-run option which works for all commands, just like a simulation mode. But as well I like the idea of a command for key validation, which takes the same commandline options as luksOpen, and simply verifies whether the given key (passphrase, keyfile, whatever) is valid.

Well, universal --dry-run is nice idea but I am not going to implement it now. (and I would perhaps do it differently - do everything as is except final on-disk metadata update or in-kernel device change.)

Now that my concerns above are proved wrong I don't consider support for global --dry-run option that important anymore.

Quoted 5 lines

Well, I have local commit renaming this luksOpen option to --test-passphrase. If there are no other suggestions for today, I'll commit it.

Milan
(grumbling something about bikeshedding :-)

To make it even worse: I don't consider --test-passphrase a good name for the option. But I don't care that much about names either.

Regards,
jonas

#13 lore raw
In reply to Louis

Louis,

Thanks for this. Yes, I would like the makefile and configure.ac files.

Last year I encountered the very problem your program is meant to avoid:
It was months since I entered my LUKS passphrase and I'd forgotten it.
With the hope that I might remember it one day, I mounted the disk in
another machine and wrote a bash script to try out passphrases on it... but I haven't discovered it yet. Now I'm looking for other options.

So two questions:

Will this program work on just the LUKS header? Or does it work only on the entire mount point (with all the data therein included)?

Is there a delay of some seconds required between invocations?

Thanks much.

Quoted 99 lines · Louis

Hello,
for information, I wrote a small C program to check if the given
passphrase is correct, without doing anything on the disk. The command is used this way:

	$ cryptsetup_check_passphrase /dev/sda1
	Enter passphrase for /dev/sda1:<MY_SECRET_PASSPHRASE>
	Valid key (slot 0)
	$

If you think it can benefit cryptsetup, I offer to write the necessary
patch to include it to cryptsetup (as a "luksValidateKey" LUKS action).

# why do I need such a command ?

We are a group of hacktivists who offer some online services (such as
email addresses). Our disks are encrypted using LUKS. As we are six members operating the server, and we reboot it only a few times a year, it may happen that some of us only use the passphrase once in two years, which is prone to forgetting. So we want a way to, once in a while (at our monthly meetings), check that we still know our passphrase, without risking to do something on the disk (creating, removing partition, deleting passphrases, etc.).

# Security risks

Isn't this function a wonderful tool to try brute force attacks ? I do
not think so. Attacker needs to be root to run it, at which point (s)he can already do a lot of harmful things. Moreover, once (s)he is root, attacker might as well compile the program I just wrote to try this brute force attack. To sum up: Yes, it can be used to brute force the partition, but nothing more that what was possible to do without this tool.

Regards,
Louis

PS : Not to overload this list with many files, I only give you here the C code. If you want the makefile and configure.ac, just ask.

#include<stdio.h>
#include<stdlib.h>
#include<string.h>

#include<libcryptsetup.h>

void usage() {
   printf("cryptsetup_check_passphrase LUKSDEVICE\n");
}
int check_passphrase(const char* device_name) {
   int keyslot;
   int error;
   int status;
   struct crypt_device *cd = NULL;

   if ((error = crypt_init(&cd, device_name))) {
     printf("Could not open device \"%s\": %s\n", device_name,
strerror(-error));
     return 1;
   }
   if ((error = crypt_load(cd, NULL, NULL))) {
     printf("Could not load device \"%s\": %s\n", device_name,
strerror(-error));
     return 1;

}

keyslot = crypt_activate_by_passphrase(cd, NULL, CRYPT_ANY_SLOT, NULL,

0, 0);
   if (keyslot>= 0) {
     printf("Valid key (slot %u)\n", keyslot);
     status = 0;
   } else {
     printf("No matching key found: %s\n", strerror(-keyslot));
     status = 1;
   }
   crypt_free(cd);
   return status;
}
int main( int argc, const char* argv[] ) {
   int status;

   /* Parsing arguments */
   if (argc != 2) {
     usage();
     return 1;
   }

   /* Check */
   status = check_passphrase(argv[1]);

   return status;
}

_______________________________________________
dm-crypt mailing list
[email protected]
http://www.saout.de/mailman/listinfo/dm-crypt

#8 lore raw
In reply to Thomas Bächler
Quoted 3 lines · Thomas Bächler

I find the option name --without-activation to be quite long and hard to type. Is there any reason why you didn't choose '--dry-run' as you first suggested?

ACK for "--dry-run" :-)

#12 lore raw
In reply to Milan Broz

Good discussion here, I like it!

I prefer --test-passphrase, as it does not have the general ring of --dry-run. With --dry-run, people would rightfully expect to be able to use it everywhere.

Just let me know what the final decision is and I will add it to the man-page.

Arno

Quoted 30 lines · Milan Broz
Quoted 3 lines · jonas

if I'm not wrong, one difference between Louis' suggestion and the way you implemented it is, that the former works with active devices, and the latter doesn't, right?

No, it is exactly the same. It works even for active devices. (Check for active device is later.)

Quoted 5 lines

I like the idea of a --dry-run option which works for all commands, just like a simulation mode. But as well I like the idea of a command for key validation, which takes the same commandline options as luksOpen, and simply verifies whether the given key (passphrase, keyfile, whatever) is valid.

Well, universal --dry-run is nice idea but I am not going to implement it now. (and I would perhaps do it differently - do everything as is except final on-disk metadata update or in-kernel device change.)

Well, I have local commit renaming this luksOpen option to --test-passphrase. If there are no other suggestions for today, I'll commit it.

Milan
(grumbling something about bikeshedding :-)
_______________________________________________
dm-crypt mailing list
[email protected]
http://www.saout.de/mailman/listinfo/dm-crypt

Signature · 6 lines
Arno Wagner,    Dr. sc. techn., Dipl. Inform.,   Email: [email protected] 
GnuPG:  ID: 1E25338F  FP: 0C30 5782 9D93 F785 E79C  0296 797F 6B50 1E25 338F
----
One of the painful things about our time is that those who feel certainty 
are stupid, and those with any imagination and understanding are filled 
with doubt and indecision. -- Bertrand Russell 
author
#14 lore raw
In reply to ken
	Hi,
Quoted 1 line · ken

Thanks for this. Yes, I would like the makefile and configure.ac files.

Here they are, at the end of this message. If you really want a license
for it, let's say WTF Public license.
http://en.wikipedia.org/wiki/WTFPL

Quoted 2 lines

Will this program work on just the LUKS header? Or does it work only on the entire mount point (with all the data therein included)?.

I have no idea. The program is very short, and does only four calls to
the Cryptsetup API, so you may be able to understand it and guess it yourself. Or just test it on dummy data.
Sorry not to give you a definitive answer: I am not an expert in
cryptography, and I learned the minimum amount of Cryptestup needed to be able to write this piece of code.

Quoted 1 line

Is there a delay of some seconds required between invocations?

Well, on my computer, it takes more than one second to run, which may
seem long for a simple verification of a passphrase. But I think it is simply the time taken by the API to check the passphrase on my very old computer. There is no such delay in my code to prevent brute force attack, nor (if I am not wrong) in the functions of the Cryptsetup API I am using.

Louis

===================================================
To compile the program, save the following files, make sure cryptsetup library is installed ("apt-get install libcryptsetup-dev" on Debian) and run :

$ touch NEWS README AUTHORS ChangeLog COPYING
$ autoreconf --install
$ ./configure
$ make

Then, to check your passphrase :

$ sudo ./cryptsetup_check_passphrase /dev/sda5
Enter passphrase for /dev/sda5:
Valid key (slot 0)

To integrate it in your brute-force-my-own-disk script, note that :
- the error code is 0 if the key is valid, 1 otherwise;
- if the key is not valid, the program lets you three guesses.

===== cryptsetup_check_passphrase.c =====

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

#include <libcryptsetup.h>

void usage() {
printf("cryptsetup_check_passphrase LUKSDEVICE\n");
}

int check_passphrase(const char* device_name) {
int keyslot;
int error;
struct crypt_device *cd = NULL;

if ((error = crypt_init(&cd, device_name))) {
printf("Could not open device \"%s\": %s\n", device_name,

strerror(-error));
    return 1;
  }
  if ((error = crypt_load(cd, NULL, NULL))) {
    printf("Could not load device \"%s\": %s\n", device_name,
strerror(-error));
    return 1;

}

keyslot = crypt_activate_by_passphrase(cd, NULL, CRYPT_ANY_SLOT, NULL,
0, 0);

  if (keyslot >= 0) {
    printf("Valid key (slot %u)\n", keyslot);
    error = 0;
  } else {
    printf("No matching key found: %s\n", strerror(-keyslot));
    error = 1;

}
crypt_free(cd);
return error;
}

int main( int argc, const char* argv[] ) {
int status;

  /* Parsing arguments */
  if (argc != 2) {
    usage();
    return 1;
  }

  /* Check */
  status = check_passphrase(argv[1]);

return status;
}

===== Makefile.am =====

bin_PROGRAMS = cryptsetup_check_passphrase

cryptsetup_check_passphrase_SOURCES = cryptsetup_check_passphrase.c cryptsetup_check_passphrase_LDADD = $(CRYPTSETUP_LIBS)

===== configure.ac =====

AC_INIT([cryptsetup_check_passphrase], [0.1.0])
AM_INIT_AUTOMAKE([-Wall -Werror])
AC_PROG_CC

AC_LANG_C

PKG_CHECK_MODULES([CRYPTSETUP], [libcryptsetup])

AC_CONFIG_FILES([Makefile])
AC_OUTPUT

Quoted 40 lines · Louis
Quoted 39 lines

Hello,
for information, I wrote a small C program to check if the given
passphrase is correct, without doing anything on the disk. The command is used this way:

    $ cryptsetup_check_passphrase /dev/sda1
    Enter passphrase for /dev/sda1:<MY_SECRET_PASSPHRASE>
    Valid key (slot 0)
    $

If you think it can benefit cryptsetup, I offer to write the
necessary
patch to include it to cryptsetup (as a "luksValidateKey" LUKS action).

# why do I need such a command ?

We are a group of hacktivists who offer some online services (such as
email addresses). Our disks are encrypted using LUKS. As we are six members operating the server, and we reboot it only a few times a year, it may happen that some of us only use the passphrase once in two years, which is prone to forgetting. So we want a way to, once in a while (at our monthly meetings), check that we still know our passphrase, without risking to do something on the disk (creating, removing partition, deleting passphrases, etc.).

# Security risks

Isn't this function a wonderful tool to try brute force attacks ?
I do
not think so. Attacker needs to be root to run it, at which point (s)he can already do a lot of harmful things. Moreover, once (s)he is root, attacker might as well compile the program I just wrote to try this brute force attack. To sum up: Yes, it can be used to brute force the partition, but nothing more that what was possible to do without this tool.

Regards,
Louis

#15 lore raw
Quoted 3 lines · Louis
Quoted 2 lines

Will this program work on just the LUKS header? Or does it work only on the entire mount point (with all the data therein included)?.

I have no idea.

Hmmmm. Well, for you and others:

crypt_init(device)
- check provide devices exists. It is physical device (disk), no mount point of activation name required.
It can be even file with full LUKS header backup.

crypt_load(cd, NULL, NULL, ...)
- load LUKS header (you should use explicitly CRYPT_LUKS1 here to be sure that it is LUKS)

crypt_activate_by_passphrase(cd, NULL, CRYPT_ANY_SLOT, ...)
- tries to activate device with NULL name
this means that device will not be activated and check for device existence is skipped.

btw we have API docs online
http://wiki.cryptsetup.googlecode.com/git/API/index.html
http://wiki.cryptsetup.googlecode.com/git/API/libcryptsetup_8h.html

If you see my change in cryptsetup, "luksOpen --test-passphrase" will work even for provided keyfile and for directly provided master key (--master-key-file). It will simple check if these are correct without activation of device.

The only disadvantage is that you have to provide some fake device name in luksOpen command (it will be ignored, only disk parameter is used).

Quoted 1 line
Quoted 1 line

Is there a delay of some seconds required between invocations?

No.

Quoted 6 lines

Well, on my computer, it takes more than one second to run, which may
seem long for a simple verification of a passphrase. But I think it is simply the time taken by the API to check the passphrase on my very old computer. There is no such delay in my code to prevent brute force attack, nor (if I am not wrong) in the functions of the Cryptsetup API I am using.

No, it is by design. You can run it even in parallel, but your CPU power is limited. See FAQ and LUKS design doc for more info about iteration count.

Milan