mirror of
https://github.com/Llewellynvdm/Tomb.git
synced 2024-12-31 21:21:56 +00:00
Add KDF support #82
Include pbkdf2 tools inside tomb It also supports parameters (itertime).
This commit is contained in:
parent
6bb655df0b
commit
2e6a3df756
36
KEY_SPECIFICATIONS.txt
Normal file
36
KEY_SPECIFICATIONS.txt
Normal file
@ -0,0 +1,36 @@
|
|||||||
|
Overview
|
||||||
|
=========
|
||||||
|
|
||||||
|
|
||||||
|
What's a key?
|
||||||
|
It basicly is a gpg simmetrically encrypted, ascii-armored file.
|
||||||
|
It's encryption key is a function (see below, on KDF section) of your tomb
|
||||||
|
passphrase.
|
||||||
|
|
||||||
|
|
||||||
|
Layout
|
||||||
|
======
|
||||||
|
|
||||||
|
Before coming to the gpg part, there could be some "header" lines specifying
|
||||||
|
metatada. They're done like this:
|
||||||
|
_FIELD_params_params_and_more_params_
|
||||||
|
|
||||||
|
where FIELD should be the description for the header.
|
||||||
|
Pay much attention to the fact that there should ONLY be ASCII characters there,
|
||||||
|
to avoid encoding issues and whatever. Needs something more? Use base64encode.
|
||||||
|
(Of course, you're free to pack params into a single field, base64encoding
|
||||||
|
whatever you want).
|
||||||
|
And every header field should be in only one line.
|
||||||
|
|
||||||
|
KDF
|
||||||
|
===
|
||||||
|
|
||||||
|
Key Derivation Functions, are functions which will make your key stronger
|
||||||
|
spending some CPU time: the basic idea is that you have to compute that function
|
||||||
|
just once in a while, but an attacker that wants to bruteforce has to compute it
|
||||||
|
for every passphrase he's checking. This will make the bruteforce much more
|
||||||
|
expensive.
|
||||||
|
|
||||||
|
The header line format is _KDF_$method_$params_$params_... where $method is the
|
||||||
|
method we are using (ie: scrypt) and params is something that it needs (ie:
|
||||||
|
salt).
|
@ -1 +1 @@
|
|||||||
SUBDIRS = src share doc
|
SUBDIRS = src src/kdf share doc
|
||||||
|
@ -89,6 +89,7 @@ dnl ---------------------------------------------------------------
|
|||||||
|
|
||||||
PKG_CHECK_MODULES(GTK2, [gtk+-2.0 >= 2.16], :,
|
PKG_CHECK_MODULES(GTK2, [gtk+-2.0 >= 2.16], :,
|
||||||
AC_MSG_ERROR([*** Gtk+2 >=2.16 development files not found!]))
|
AC_MSG_ERROR([*** Gtk+2 >=2.16 development files not found!]))
|
||||||
|
AM_PATH_LIBGCRYPT([1.5.0], :, AC_MSG_ERROR([gcrypt development files not found]))
|
||||||
AC_SUBST([GTK2_CFLAGS])
|
AC_SUBST([GTK2_CFLAGS])
|
||||||
AC_SUBST([GTK2_LIBS])
|
AC_SUBST([GTK2_LIBS])
|
||||||
|
|
||||||
@ -130,6 +131,7 @@ dnl alphabetic order on dir/subdir, but Makefile sorts before everything
|
|||||||
AC_CONFIG_FILES([
|
AC_CONFIG_FILES([
|
||||||
Makefile
|
Makefile
|
||||||
src/Makefile
|
src/Makefile
|
||||||
|
src/kdf/Makefile
|
||||||
doc/Makefile
|
doc/Makefile
|
||||||
share/Makefile
|
share/Makefile
|
||||||
])
|
])
|
||||||
|
27
doc/tomb.1
27
doc/tomb.1
@ -111,7 +111,7 @@ the size of the new \fIfile\fR to be created, in megabytes.
|
|||||||
.IP "-k \fI<keyfile>\fR"
|
.IP "-k \fI<keyfile>\fR"
|
||||||
When opening a tomb, this option can be used to specify the location
|
When opening a tomb, this option can be used to specify the location
|
||||||
of the key to use. Keys are created with the same name of the tomb
|
of the key to use. Keys are created with the same name of the tomb
|
||||||
file adding a '.gpg' suffix, but can be later renamed and transported
|
file adding a '.key' suffix, but can be later renamed and transported
|
||||||
on other media. When a key is not found, the program asks to insert a
|
on other media. When a key is not found, the program asks to insert a
|
||||||
USB storage device and it will look for the key file inside it.
|
USB storage device and it will look for the key file inside it.
|
||||||
If \fI<keyfile>\fR is "-" (dash), it will read stdin
|
If \fI<keyfile>\fR is "-" (dash), it will read stdin
|
||||||
@ -123,6 +123,31 @@ tomb create -s 100 tombname -k /media/usb/tombname
|
|||||||
.EE
|
.EE
|
||||||
to put the key on a usb pendrive
|
to put the key on a usb pendrive
|
||||||
|
|
||||||
|
.B
|
||||||
|
.IP "--kdf \fI<method>\fR"
|
||||||
|
This will specify the KDF method to use for the tomb we're creating.
|
||||||
|
Please note that no stable release of tomb supports KDF; if you use it,
|
||||||
|
your tomb might be unusable with an older version of tomb.
|
||||||
|
|
||||||
|
You can specify parameters with --kdf=method:param. That is, for example,
|
||||||
|
\fI--kdf=pbkdf2:2.5\fR will use pbkdf2 with an itertime of 2.5 seconds
|
||||||
|
|
||||||
|
Supported methods are: pbkdf2, null
|
||||||
|
|
||||||
|
.B pbkdf2
|
||||||
|
is probably the most used kdf in security applications, so it's a good choice.
|
||||||
|
It accepts one parameter, that is the seconds it will take on this computer to
|
||||||
|
derive the key. The default is 1.
|
||||||
|
|
||||||
|
.B null
|
||||||
|
is just the same as not using --kdf at all: it will stick to the "classic"
|
||||||
|
behaviour
|
||||||
|
|
||||||
|
.B
|
||||||
|
.IP "--kdf \fI<method>\fR"
|
||||||
|
This will specify the KDF method to use for the tomb we're creating.
|
||||||
|
Please note that no stable release of tomb supports KDF; if you use it,
|
||||||
|
your tomb might be unusable with an older version of tomb.
|
||||||
.B
|
.B
|
||||||
.IP "-n"
|
.IP "-n"
|
||||||
Skip processing of post-hooks and bind-hooks if found inside the tomb.
|
Skip processing of post-hooks and bind-hooks if found inside the tomb.
|
||||||
|
4
src/kdf/.gitignore
vendored
Normal file
4
src/kdf/.gitignore
vendored
Normal file
@ -0,0 +1,4 @@
|
|||||||
|
tomb-kdf-pbkdf2
|
||||||
|
tomb-kdf-pbkdf2-gensalt
|
||||||
|
tomb-kdf-pbkdf2-getiter
|
||||||
|
tomb-utils-hexencode
|
13
src/kdf/Makefile.am
Normal file
13
src/kdf/Makefile.am
Normal file
@ -0,0 +1,13 @@
|
|||||||
|
bin_PROGRAMS = tomb-kdf-pbkdf2 tomb-kdf-pbkdf2-gensalt tomb-kdf-pbkdf2-getiter hexencode
|
||||||
|
tomb_kdf_pbkdf2_SOURCES = pbkdf2/pbkdf2.c
|
||||||
|
tomb_kdf_pbkdf2_CFLAGS = $(LIBGCRYPT_CFLAGS)
|
||||||
|
tomb_kdf_pbkdf2_LDADD = $(LIBGCRYPT_LIBS)
|
||||||
|
|
||||||
|
tomb_kdf_pbkdf2_gensalt_SOURCES = pbkdf2/gen_salt.c
|
||||||
|
|
||||||
|
tomb_kdf_pbkdf2_getiter_SOURCES = pbkdf2/benchmark.c
|
||||||
|
tomb_kdf_pbkdf2_getiter_CFLAGS = $(LIBGCRYPT_CFLAGS)
|
||||||
|
tomb_kdf_pbkdf2_getiter_LDADD = $(LIBGCRYPT_LIBS)
|
||||||
|
|
||||||
|
hexencode_SOURCES = hexencode.c
|
||||||
|
|
20
src/kdf/README
Normal file
20
src/kdf/README
Normal file
@ -0,0 +1,20 @@
|
|||||||
|
PLANS
|
||||||
|
------
|
||||||
|
|
||||||
|
While this can be useful for general purpose, it specially fits tomb, and it's designed for easy integration and compilation.
|
||||||
|
|
||||||
|
Binary name will then be:
|
||||||
|
tomb-kdf-${algo}
|
||||||
|
tomb-kdf-${algo}-gensalt
|
||||||
|
tomb-kdf-${algo}-getiter
|
||||||
|
|
||||||
|
hexencode (or similar utils, should they be developed), go with:
|
||||||
|
tomb-utils-hexencode
|
||||||
|
|
||||||
|
Base64 vs hexencode
|
||||||
|
-------------------
|
||||||
|
|
||||||
|
While base64 is easier to use (shell command, more compact), pbkdf2 use hex
|
||||||
|
in its specifications.
|
||||||
|
This could be solved with an option (-x for hex, defaults to base64)
|
||||||
|
|
49
src/kdf/hexencode.c
Normal file
49
src/kdf/hexencode.c
Normal file
@ -0,0 +1,49 @@
|
|||||||
|
/*
|
||||||
|
* A simple utility that reads from stdin and output the hexencoding (on a single line) of the input
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <getopt.h>
|
||||||
|
|
||||||
|
static int decode_mode = 0;
|
||||||
|
int main(int argc, char *argv[]) {
|
||||||
|
char c;
|
||||||
|
char buf[3];
|
||||||
|
int read_bytes;
|
||||||
|
int opt;
|
||||||
|
static struct option long_options[] =
|
||||||
|
{
|
||||||
|
{"decode", no_argument, &decode_mode, 1},
|
||||||
|
{"encode", no_argument, &decode_mode, 0},
|
||||||
|
{0,0,0,0}
|
||||||
|
};
|
||||||
|
int option_index = 0;
|
||||||
|
|
||||||
|
while(1) {
|
||||||
|
option_index = 0;
|
||||||
|
opt = getopt_long(argc, argv, "", long_options, &option_index);
|
||||||
|
if(opt == -1)
|
||||||
|
break;
|
||||||
|
switch(opt) {
|
||||||
|
case 0:
|
||||||
|
break;
|
||||||
|
case '?':
|
||||||
|
return 127;
|
||||||
|
default:
|
||||||
|
abort();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if(decode_mode == 0) {
|
||||||
|
while(( c = (char)getchar() ) != EOF)
|
||||||
|
printf("%02x", c);
|
||||||
|
return 0;
|
||||||
|
} else {
|
||||||
|
while( (read_bytes=fread(buf, sizeof(char), 2, stdin)) != 0) {
|
||||||
|
if(read_bytes == 1) buf[1]='\0';
|
||||||
|
sscanf(buf, "%x", &c);
|
||||||
|
printf("%c", c);
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
}
|
59
src/kdf/pbkdf2/benchmark.c
Normal file
59
src/kdf/pbkdf2/benchmark.c
Normal file
@ -0,0 +1,59 @@
|
|||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
|
#include <sys/time.h>
|
||||||
|
|
||||||
|
#include <gcrypt.h>
|
||||||
|
|
||||||
|
static long bench(int ic) {
|
||||||
|
char *pass = "mypass";
|
||||||
|
unsigned char *salt = "abcdefghijklmno";
|
||||||
|
int salt_len = strlen(salt);
|
||||||
|
int result_len = 64;
|
||||||
|
unsigned char *result = calloc(result_len, sizeof(char));
|
||||||
|
struct timeval start, end;
|
||||||
|
long microtime;
|
||||||
|
|
||||||
|
gettimeofday(&start, NULL);
|
||||||
|
gcry_kdf_derive( pass, strlen(pass), GCRY_KDF_PBKDF2, GCRY_MD_SHA1, salt, salt_len, ic, result_len, result);
|
||||||
|
gettimeofday(&end, NULL);
|
||||||
|
microtime = 1000000*end.tv_sec+end.tv_usec - (1000000*start.tv_sec+start.tv_usec);
|
||||||
|
|
||||||
|
return (long)microtime;
|
||||||
|
}
|
||||||
|
int main(int argc, char *argv[])
|
||||||
|
{
|
||||||
|
long desired_time = 1000000;
|
||||||
|
long microtime;
|
||||||
|
int ic=100;
|
||||||
|
int tries=0;
|
||||||
|
if(argc >= 2)
|
||||||
|
sscanf(argv[1], "%ld", &desired_time);
|
||||||
|
if (!gcry_check_version ("1.5.0")) {
|
||||||
|
fputs ("libgcrypt version mismatch\n", stderr);
|
||||||
|
exit (2);
|
||||||
|
}
|
||||||
|
/* Allocate a pool of 16k secure memory. This make the secure memory
|
||||||
|
available and also drops privileges where needed. */
|
||||||
|
gcry_control (GCRYCTL_INIT_SECMEM, 16384, 0);
|
||||||
|
/* It is now okay to let Libgcrypt complain when there was/is
|
||||||
|
a problem with the secure memory. */
|
||||||
|
gcry_control (GCRYCTL_RESUME_SECMEM_WARN);
|
||||||
|
/* Tell Libgcrypt that initialization has completed. */
|
||||||
|
gcry_control (GCRYCTL_INITIALIZATION_FINISHED, 0);
|
||||||
|
|
||||||
|
|
||||||
|
microtime = bench(ic);
|
||||||
|
while( abs(desired_time-microtime) > (desired_time/10) /*little difference */
|
||||||
|
&& tries++ <= 5) {
|
||||||
|
float ratio = (float)desired_time/microtime;
|
||||||
|
if(ratio > 1000) ratio=1000.0;
|
||||||
|
ic*=ratio;
|
||||||
|
if(ic<1) ic=1;
|
||||||
|
microtime = bench(ic);
|
||||||
|
}
|
||||||
|
printf("%d\n", ic);
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
}
|
39
src/kdf/pbkdf2/gen_salt.c
Normal file
39
src/kdf/pbkdf2/gen_salt.c
Normal file
@ -0,0 +1,39 @@
|
|||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
|
void print_hex(unsigned char *buf, int len)
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
|
||||||
|
for(i=0;i<len;i++){
|
||||||
|
printf("%02x", buf[i]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
int main(int argc, char **argv) {
|
||||||
|
int len=32;
|
||||||
|
int res;
|
||||||
|
unsigned char *buf;
|
||||||
|
FILE *rand;
|
||||||
|
if(argc>=2) {
|
||||||
|
if(sscanf(argv[1], "%d", &len) != 1) {
|
||||||
|
fprintf(stderr, "Error: len must be an integer\n");
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
buf = calloc(len, sizeof(char));
|
||||||
|
memset(buf, 9, len);
|
||||||
|
rand = fopen("/dev/random", "r");
|
||||||
|
res = fread(buf, sizeof(char), len, rand);
|
||||||
|
if( res != len) {
|
||||||
|
fprintf(stderr, "Error reading /dev/random: %d != %d, \n", res, len);
|
||||||
|
fclose(rand);
|
||||||
|
free(buf);
|
||||||
|
return 2;
|
||||||
|
}
|
||||||
|
fclose(rand);
|
||||||
|
print_hex(buf, len);
|
||||||
|
free(buf);
|
||||||
|
return 0;
|
||||||
|
}
|
144
src/kdf/pbkdf2/pbkdf2.c
Normal file
144
src/kdf/pbkdf2/pbkdf2.c
Normal file
@ -0,0 +1,144 @@
|
|||||||
|
/*
|
||||||
|
** SYNOPSIS
|
||||||
|
** echo "passphrase" | pbkdf2 salt_hex count > 48_byte_hex_key_and_iv
|
||||||
|
**
|
||||||
|
** DESCRIPTION
|
||||||
|
**
|
||||||
|
** Make the "Password-Based Key Derivation Function v2" function found in
|
||||||
|
** the openssl library available to the command line, as it is not available
|
||||||
|
** for use from the "openssl" command. At the time of writing the "openssl"
|
||||||
|
** command only encrypts using the older, 'fast' pbkdf1.5 method.
|
||||||
|
**
|
||||||
|
** The 'salt_hex' is the salt to be used, as a hexadecimal string. Typically
|
||||||
|
** this is 8 bytes (64 bit), and is an assigned randomly during encryption.
|
||||||
|
**
|
||||||
|
** The 'count' is iteration count used to make the calculation of the key
|
||||||
|
** from the passphrase longer so as to take 1/2 to 2 seconds to generate.
|
||||||
|
** This complexity prevents slows down brute force attacks enormously.
|
||||||
|
**
|
||||||
|
** The output of the above is a 48 bytes in hexadeximal, which is typically
|
||||||
|
** used for 32 byte encryption key KEY and a 16 byte IV as needed by
|
||||||
|
** Crypt-AES-256 (or some other encryption method).
|
||||||
|
**
|
||||||
|
** NOTE: While the "openssl" command can accept a hex encoded 'key' and 'iv'
|
||||||
|
** it only does so on the command line, which is insecure. As such I
|
||||||
|
** recommend that the output only be used with API access to the "OpenSSL"
|
||||||
|
** cryptography libraries.
|
||||||
|
**
|
||||||
|
*************
|
||||||
|
**
|
||||||
|
** Anthony Thyssen 4 November 2009 A.Thyssen@griffith.edu.au
|
||||||
|
**
|
||||||
|
** Based on a test program "pkcs5.c" found on
|
||||||
|
** http://www.mail-archive.com/openssl-users@openssl.org
|
||||||
|
** which uses openssl to perform PBKDF2 (RFC2898) iteritive (slow) password
|
||||||
|
** hashing.
|
||||||
|
**
|
||||||
|
** Build
|
||||||
|
** gcc -o pbkdf2 pbkdf2.c -lcrypto
|
||||||
|
**
|
||||||
|
*/
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
|
#include <gcrypt.h>
|
||||||
|
|
||||||
|
/* TODO: move print_hex and hex_to_binary to utils.h, with separate compiling */
|
||||||
|
void print_hex(unsigned char *buf, int len)
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
|
||||||
|
for(i=0;i<len;i++)
|
||||||
|
printf("%02x", buf[i]);
|
||||||
|
printf("\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
int hex_to_binary(unsigned char *buf, char *hex)
|
||||||
|
{
|
||||||
|
int ret;
|
||||||
|
int count=0;
|
||||||
|
while(*hex) {
|
||||||
|
if( hex[1] ) {
|
||||||
|
ret = sscanf( hex, "%2x", (unsigned int*) buf++ );
|
||||||
|
hex += 2;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
ret = sscanf( hex++, "%1x", (unsigned int*)buf++ );
|
||||||
|
}
|
||||||
|
count++;
|
||||||
|
if( ret != 1)
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
*buf = 0; // null terminate -- precaution
|
||||||
|
return count;
|
||||||
|
}
|
||||||
|
|
||||||
|
int main(int argc, char *argv[])
|
||||||
|
{
|
||||||
|
char *pass = NULL;
|
||||||
|
unsigned char *salt;
|
||||||
|
int salt_len; // salt length in bytes
|
||||||
|
int ic=0; // iterative count
|
||||||
|
int result_len;
|
||||||
|
unsigned char *result; // result (binary - 32+16 chars)
|
||||||
|
int i;
|
||||||
|
|
||||||
|
if ( argc != 4 ) {
|
||||||
|
fprintf(stderr, "usage: %s salt count len <passwd >binary_key_iv\n", argv[0]);
|
||||||
|
exit(10);
|
||||||
|
}
|
||||||
|
|
||||||
|
//TODO: move to base64decode
|
||||||
|
salt=calloc(strlen(argv[1])/2+3, sizeof(char));
|
||||||
|
salt_len=hex_to_binary(salt, argv[1]);
|
||||||
|
if( salt_len <= 0 ) {
|
||||||
|
fprintf(stderr, "Error: %s is not a valid salt (it must be a hexadecimal string)\n", argv[1]);
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
if( sscanf(argv[2], "%d", &ic) == 0 || ic<=0) {
|
||||||
|
fprintf(stderr, "Error: count must be a positive integer\n");
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
if( sscanf(argv[3], "%d", &result_len) == 0 || result_len<=0) {
|
||||||
|
fprintf(stderr, "Error: result_len must be a positive integer\n");
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
fscanf(stdin, "%ms", &pass);
|
||||||
|
if ( pass[strlen(pass)-1] == '\n' )
|
||||||
|
pass[strlen(pass)-1] = '\0';
|
||||||
|
|
||||||
|
// PBKDF 2
|
||||||
|
result = calloc(result_len, sizeof(unsigned char*));
|
||||||
|
if (!gcry_check_version ("1.5.0")) {
|
||||||
|
fputs ("libgcrypt version mismatch\n", stderr);
|
||||||
|
exit (2);
|
||||||
|
}
|
||||||
|
/* Allocate a pool of 16k secure memory. This make the secure memory
|
||||||
|
available and also drops privileges where needed. */
|
||||||
|
gcry_control (GCRYCTL_INIT_SECMEM, 16384, 0);
|
||||||
|
/* It is now okay to let Libgcrypt complain when there was/is
|
||||||
|
a problem with the secure memory. */
|
||||||
|
gcry_control (GCRYCTL_RESUME_SECMEM_WARN);
|
||||||
|
/* Tell Libgcrypt that initialization has completed. */
|
||||||
|
gcry_control (GCRYCTL_INITIALIZATION_FINISHED, 0);
|
||||||
|
|
||||||
|
gcry_kdf_derive( pass, strlen(pass), GCRY_KDF_PBKDF2, GCRY_MD_SHA1, salt, salt_len, ic, result_len, result);
|
||||||
|
print_hex(result, result_len); // Key + IV (as hex string)
|
||||||
|
|
||||||
|
//clear and free everything
|
||||||
|
for(i=0; i<result_len;i++)
|
||||||
|
result[i]=0;
|
||||||
|
free(result);
|
||||||
|
for(i=0; i<strlen(pass); i++) //blank
|
||||||
|
pass[i]=0;
|
||||||
|
free(pass);
|
||||||
|
for(i=0; i<strlen(argv[1])/2+3; i++) //blank
|
||||||
|
salt[i]=0;
|
||||||
|
free(salt);
|
||||||
|
|
||||||
|
return(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* vim: set noexpandtab ts=4 sw=4: */
|
22
src/kdf/test.sh
Normal file
22
src/kdf/test.sh
Normal file
@ -0,0 +1,22 @@
|
|||||||
|
#!/usr/bin/env zsh
|
||||||
|
|
||||||
|
error=0
|
||||||
|
while read line; do
|
||||||
|
pass=`cut -f1 <<<$line`
|
||||||
|
salt=`cut -f2 <<<$line`
|
||||||
|
iter=`cut -f3 <<<$line`
|
||||||
|
keylen=`cut -f4 <<<$line`
|
||||||
|
expected=`cut -f5 <<<$line`
|
||||||
|
hexsalt=`cut -f6 <<<$line`
|
||||||
|
#TODO: check!
|
||||||
|
derived=`./pbkdf2 $hexsalt $iter $keylen <<<$pass`
|
||||||
|
if [[ $derived != $expected ]]; then
|
||||||
|
echo ./pbkdf2 $hexsalt $iter $keylen "<<<$pass"
|
||||||
|
echo "Expected $expected, got $derived" >&2
|
||||||
|
error=$((error + 1))
|
||||||
|
fi
|
||||||
|
done < test.txt
|
||||||
|
|
||||||
|
if [[ $error == 1 ]]; then
|
||||||
|
exit $error
|
||||||
|
fi
|
BIN
src/kdf/test.txt
Normal file
BIN
src/kdf/test.txt
Normal file
Binary file not shown.
125
src/tomb
125
src/tomb
@ -166,6 +166,17 @@ check_bin() {
|
|||||||
# resize suite check bin!
|
# resize suite check bin!
|
||||||
which e2fsck > /dev/null || die "Cannot find e2fsck. Please install it." 1
|
which e2fsck > /dev/null || die "Cannot find e2fsck. Please install it." 1
|
||||||
which resize2fs > /dev/null || die "Cannot find resize2fs. Please install it." 1
|
which resize2fs > /dev/null || die "Cannot find resize2fs. Please install it." 1
|
||||||
|
|
||||||
|
if which tomb-kdf-pbkdf2 &> /dev/null; then
|
||||||
|
KDF_PBKDF2="tomb-kdf-pbkdf2"
|
||||||
|
else
|
||||||
|
local our_pbkdf2
|
||||||
|
our_pbkdf2="$(dirname $(readlink -f $TOMBEXEC))/kdf/tomb-kdf-pbkdf2"
|
||||||
|
if which $our_pbkdf2 &> /dev/null; then
|
||||||
|
KDF_PBKDF2=$our_pbkdf2
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
# }}}
|
# }}}
|
||||||
@ -732,15 +743,15 @@ create_tomb() {
|
|||||||
|
|
||||||
# here user is prompted for key password
|
# here user is prompted for key password
|
||||||
for c in 1 2 3; do
|
for c in 1 2 3; do
|
||||||
# 3 tries to write two times a matching password
|
# 3 tries to write two times a matching password
|
||||||
tombpass=`exec_as_user ${TOMBEXEC} askpass "Secure key for ${tombname}"`
|
tombpass=`exec_as_user ${TOMBEXEC} askpass "Secure key for ${tombname}"`
|
||||||
tombpasstmp=$tombpass
|
tombpasstmp=$tombpass
|
||||||
tombpass=`exec_as_user ${TOMBEXEC} askpass "Secure key for ${tombname} (again)"`
|
tombpass=`exec_as_user ${TOMBEXEC} askpass "Secure key for ${tombname} (again)"`
|
||||||
if [ "$tombpasstmp" = "$tombpass" ]; then
|
if [ "$tombpasstmp" = "$tombpass" ]; then
|
||||||
break;
|
break;
|
||||||
fi
|
fi
|
||||||
unset tombpasstmp
|
unset tombpasstmp
|
||||||
unset tombpass
|
unset tombpass
|
||||||
done
|
done
|
||||||
|
|
||||||
if [ -z $tombpass ]; then
|
if [ -z $tombpass ]; then
|
||||||
@ -751,9 +762,36 @@ create_tomb() {
|
|||||||
fi
|
fi
|
||||||
|
|
||||||
|
|
||||||
gpg \
|
_verbose "KDF method chosen is: '`option_value --kdf`'"
|
||||||
--openpgp --batch --no-options --no-tty --passphrase-fd 0 2>/dev/null \
|
kdf_method=$(cut -d: -f1 <<<`option_value --kdf` )
|
||||||
-o "${tombkey}" -c -a ${keytmp}/tomb.tmp <<< ${tombpass}
|
case $kdf_method in
|
||||||
|
pbkdf2)
|
||||||
|
#one parameter: iter time in seconds
|
||||||
|
seconds=$(cut -d: -f2 -s <<<`option_value --kdf`)
|
||||||
|
if [[ -z $seconds ]]; then
|
||||||
|
seconds=1
|
||||||
|
fi
|
||||||
|
local -i microseconds
|
||||||
|
microseconds=$((seconds*1000000))
|
||||||
|
_verbose "Microseconds: $microseconds"
|
||||||
|
pbkdf2_salt=`${KDF_PBKDF2}-gensalt`
|
||||||
|
pbkdf2_iter=`${KDF_PBKDF2}-getiter $microseconds`
|
||||||
|
tombpass=`${KDF_PBKDF2} $pbkdf2_salt $pbkdf2_iter 64 <<<${tombpass}` #64bytes=512bits is the key length (huge!)
|
||||||
|
header="_KDF_pbkdf2sha1_${pbkdf2_salt}_${pbkdf2_iter}_64\n"
|
||||||
|
;;
|
||||||
|
""|null)
|
||||||
|
|
||||||
|
header=""
|
||||||
|
;;
|
||||||
|
*)
|
||||||
|
_warning "KDF method non recognized"
|
||||||
|
return 1
|
||||||
|
header=""
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
( echo -n $header; gpg \
|
||||||
|
--openpgp --batch --no-options --no-tty --passphrase-fd 0 2>/dev/null \
|
||||||
|
-o - -c -a ${keytmp}/tomb.tmp <<< ${tombpass} ) > $tombkey
|
||||||
|
|
||||||
unset tombpass
|
unset tombpass
|
||||||
chown ${_uid}:${_gid} ${tombkey}
|
chown ${_uid}:${_gid} ${tombkey}
|
||||||
@ -924,31 +962,46 @@ mount_tomb() {
|
|||||||
|
|
||||||
_warning "Password is required for key ${keyname}"
|
_warning "Password is required for key ${keyname}"
|
||||||
for c in 1 2 3; do
|
for c in 1 2 3; do
|
||||||
if [ $c = 1 ]; then
|
if [ $c = 1 ]; then
|
||||||
tombpass=`exec_as_user ${TOMBEXEC} askpass "Open tomb ${keyname}"`
|
tombpass=`exec_as_user ${TOMBEXEC} askpass "Open tomb ${keyname}"`
|
||||||
else
|
else
|
||||||
tombpass=`exec_as_user ${TOMBEXEC} askpass "Open tomb $keyname (retry $c)"`
|
tombpass=`exec_as_user ${TOMBEXEC} askpass "Open tomb $keyname (retry $c)"`
|
||||||
fi
|
fi
|
||||||
(gpg --batch --passphrase-fd 0 --no-tty --no-options \
|
#TODO: read the first line: if it looks like a KDF, do KDF
|
||||||
-d "${tombkey}" 2> /dev/null <<< ${tombpass} ) \
|
firstline=`head -n1 < $tombkey`
|
||||||
| cryptsetup --key-file - luksOpen ${nstloop} ${mapper}
|
if [[ $firstline =~ '^_KDF_' ]]; then
|
||||||
unset tombpass
|
_verbose "KDF: `cut -d_ -f 3 <<<$firstline`"
|
||||||
|
case `cut -d_ -f 3 <<<$firstline` in
|
||||||
|
pbkdf2sha1)
|
||||||
|
pbkdf2_param=`cut -d_ -f 4- <<<$firstline | tr '_' ' '`
|
||||||
|
tombpass=$(${KDF_PBKDF2} ${=pbkdf2_param} 2> /dev/null <<<$tombpass)
|
||||||
|
;;
|
||||||
|
*)
|
||||||
|
_failure "No suitable program for KDF `cut -f 3 <<<$firstline`"
|
||||||
|
return 1
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
fi
|
||||||
|
(gpg --batch --passphrase-fd 0 --no-tty --no-options \
|
||||||
|
-d "${tombkey}" 2> /dev/null <<< ${tombpass} ) \
|
||||||
|
| cryptsetup --key-file - luksOpen ${nstloop} ${mapper}
|
||||||
|
unset tombpass
|
||||||
|
|
||||||
# if key was from stdin delete temp file and dir
|
# if key was from stdin delete temp file and dir
|
||||||
if [ $tombkeydir ]; then
|
if [ $tombkeydir ]; then
|
||||||
${=WIPE} ${tombkey}
|
${=WIPE} ${tombkey}
|
||||||
rmdir $tombkeydir
|
rmdir $tombkeydir
|
||||||
fi
|
fi
|
||||||
|
|
||||||
# if key was from stdin delete temp file and dir
|
# if key was from stdin delete temp file and dir
|
||||||
if [ $tombkeydir ]; then
|
if [ $tombkeydir ]; then
|
||||||
${WIPE[@]} ${tombkey}
|
${WIPE[@]} ${tombkey}
|
||||||
rmdir $tombkeydir
|
rmdir $tombkeydir
|
||||||
fi
|
fi
|
||||||
|
|
||||||
if [ -r /dev/mapper/${mapper} ]; then
|
if [ -r /dev/mapper/${mapper} ]; then
|
||||||
break; # password was correct
|
break; # password was correct
|
||||||
fi
|
fi
|
||||||
done
|
done
|
||||||
|
|
||||||
if ! [ -r /dev/mapper/${mapper} ]; then
|
if ! [ -r /dev/mapper/${mapper} ]; then
|
||||||
@ -1679,7 +1732,7 @@ main() {
|
|||||||
subcommands_opts[__default]=""
|
subcommands_opts[__default]=""
|
||||||
subcommands_opts[open]="f n -nohook=n k: -key=k U: -uid=U G: -gid=G o: -mount-options=o -ignore-swap"
|
subcommands_opts[open]="f n -nohook=n k: -key=k U: -uid=U G: -gid=G o: -mount-options=o -ignore-swap"
|
||||||
subcommands_opts[mount]=${subcommands_opts[open]}
|
subcommands_opts[mount]=${subcommands_opts[open]}
|
||||||
subcommands_opts[create]="f s: -size=s -force k: -key=k U: -uid=U G: -gid=G -ignore-swap"
|
subcommands_opts[create]="f s: -size=s -force k: -key=k U: -uid=U G: -gid=G -ignore-swap -kdf:"
|
||||||
subcommands_opts[passwd]="f -ignore-swap"
|
subcommands_opts[passwd]="f -ignore-swap"
|
||||||
subcommands_opts[close]=""
|
subcommands_opts[close]=""
|
||||||
subcommands_opts[help]=""
|
subcommands_opts[help]=""
|
||||||
@ -1756,7 +1809,7 @@ main() {
|
|||||||
continue #it shouldnt be appended to PARAM
|
continue #it shouldnt be appended to PARAM
|
||||||
elif [[ $arg[1] == '-' ]]; then
|
elif [[ $arg[1] == '-' ]]; then
|
||||||
if [[ $ok == 0 ]]; then
|
if [[ $ok == 0 ]]; then
|
||||||
die "unrecognized option $arg" 127
|
die "unrecognized option $arg for subcommand $subcommand" 127
|
||||||
fi
|
fi
|
||||||
fi
|
fi
|
||||||
PARAM+=$arg
|
PARAM+=$arg
|
||||||
|
Loading…
Reference in New Issue
Block a user