mirror of
https://github.com/Llewellynvdm/Tomb.git
synced 2025-01-08 08:08:51 +00:00
commit
212b0e38a2
49
doc/tomb.1
49
doc/tomb.1
@ -49,8 +49,10 @@ more recipient GPG ids can be indicated (comma separated). The default cipher
|
||||
to protect the key is AES256, a custom one can be specified using the \fI-o\fR
|
||||
option, for a list of supported ciphers use \fI-v\fR. For additional protection
|
||||
against dictionary attacks on keys, the \fI--kdf\fR option can be used when
|
||||
forging a key, making sure that the binaries in \fIextras/kdf\fR were compiled
|
||||
and installed on the system.
|
||||
forging a key. Two KDF are currently supported: \fIargon2\fR and \fIpbkdf2\fR.
|
||||
\fIpbkdf2\fR is available from \fIextras/kdf\fR and needs to be compiled and
|
||||
installed on the system. \fIargon2\fR is generally available from distribution
|
||||
repositories.
|
||||
|
||||
.B
|
||||
.IP "lock"
|
||||
@ -283,24 +285,45 @@ Provide a new set of recipient(s) to encrypt a tomb key. \fIgpg_ids\fR
|
||||
can be one or more GPG key ID, comma separated. All GPG keys must be
|
||||
trusted keys in GPG.
|
||||
.B
|
||||
.IP "--kdf \fI<itertime>\fR"
|
||||
Activate the KDF feature against dictionary attacks when creating a key: forces
|
||||
a delay of \fI<itertime>\fR times every time this key is used. The actual time
|
||||
to wait depends on the CPU speed (default) or the RAM size (argon2) of the
|
||||
computer where the key is used. Using 5 or 10 is a sane amount for modern
|
||||
computers, the value is multiplied by 1 million.
|
||||
.B
|
||||
.IP "--kdftype \fIargon2 | pbkdf2\fR"
|
||||
Adopt the \fIargon2\fR algorithm for KDF, stressing the RAM capacity rather
|
||||
than the CPU speed of the computer decrypting the tomb. Requires the
|
||||
\fIargon2\fR binary by P-H-C to be installed, as packaged by most distros.
|
||||
.IP "--kdf \fI[argon2 | pbkdf2]\fR"
|
||||
Enable the KDF feature against dictionary attacks when creating a key.
|
||||
The required argument currently allows to choose between \fIargon2\fR
|
||||
or \fIpbkdf2\fR.
|
||||
\fIargon2\fR is using a mix of RAM capacity, number of threads and
|
||||
iterations to achieve a time cost.
|
||||
\fIpbkdf2\fR is only about calculation speed to achieve a time cost.
|
||||
Due to a low memory footprint and no restrictions regarding threads, this
|
||||
time cost can be somewhat negated due to parallelization. Especially on
|
||||
GPUs with their high number of cores.
|
||||
\fIargon2\fR requires the respective binary by P-H-C to be installed, as
|
||||
packaged by most distros. \fIpbkdf2\fR is available from the \fItomb\fR
|
||||
sources and is a custom implementation of the algorithm.
|
||||
Default is \fIpbkdf2\fR.
|
||||
.B
|
||||
.IP "--kdfiter \fI<itertime>\fR"
|
||||
Available for \fIargon2\fR and \fIpbkdf2\fR. In general this controls how
|
||||
often the algorithm will be run. In case of \fIpbkdf2\fR the argument will
|
||||
be interpret as an interval in seconds. The actual number of iterations to
|
||||
achieve this delay will be calculated with \fItomb-kdb-pbkdf2-getiter\fR,
|
||||
which needs to available (normally installed alongside tomb's pbkdf2 tools).
|
||||
Reason being that the actual time to wait depends on the CPU speed.
|
||||
OWASP recommendations from 2023 suggest a minimal iteration count of 600000
|
||||
for \fIpbkdf2\fR, which should be achieved with the current default value.
|
||||
Default is 3 (based on the \fIargon2\fR default).
|
||||
.B
|
||||
.IP "--kdfmem \fI<memory>\fR"
|
||||
In case of \fIargon2\fR KDF algorithm, this value specifies the size of RAM
|
||||
used: it consists of a number which is the elevated power of two in kilobytes.
|
||||
Default is 18 which is 250 MiB (2^18 = 262,144 kilobytes).
|
||||
.B
|
||||
.IP "--kdfpar \fI<# of threads>\fR"
|
||||
In case of \fIargon2\fR KDF algorithm, this value specifies the number of
|
||||
threads that should be used. This helps to remedy the effects of an increased
|
||||
time cost for your system whereas setups of ASICs or GPUs don't profit. Only
|
||||
increase if memory or iteration got increased that much, that key decryption
|
||||
takes massively longer on regular systems.
|
||||
Default is 1 thread (based on the \fIargon2\fR default).
|
||||
.B
|
||||
.IP "--sudo \fI<executable>\fR"
|
||||
Select a different tool than sudo for privilege escalation.
|
||||
Alternatives supported so far are: pkexec, doas, sup, sud. For any
|
||||
|
31
extras/test/30_kdf-pbkdf2.sh
Normal file
31
extras/test/30_kdf-pbkdf2.sh
Normal file
@ -0,0 +1,31 @@
|
||||
#!/usr/bin/env zsh
|
||||
|
||||
export test_description="Testing tomb with pbkdf2 KDF key"
|
||||
|
||||
source ./setup
|
||||
|
||||
if test_have_prereq KDF; then
|
||||
test_export "kdf"
|
||||
test_expect_success 'Testing pbkdf2 KDF: tomb creation' '
|
||||
tt_dig -s 20 &&
|
||||
tt_forge --tomb-pwd $DUMMYPASS --kdf pbkdf2 &&
|
||||
print $DUMMYPASS \
|
||||
| gpg --batch --passphrase-fd 0 --no-tty --no-options -d $tomb_key \
|
||||
| xxd &&
|
||||
tt_lock --tomb-pwd $DUMMYPASS
|
||||
'
|
||||
|
||||
test_expect_success 'Testing pbkdf2 KDF: tomb passwd' '
|
||||
tt passwd -k $tomb_key \
|
||||
--unsafe --tomb-old-pwd $DUMMYPASS --tomb-pwd $DUMMYPASSNEW &&
|
||||
tt passwd -k $tomb_key \
|
||||
--unsafe --tomb-old-pwd $DUMMYPASSNEW --tomb-pwd $DUMMYPASS
|
||||
'
|
||||
|
||||
test_expect_success 'Testing pbkdf2 KDF: tomb open & close' '
|
||||
tt_open --tomb-pwd $DUMMYPASS &&
|
||||
tt_close
|
||||
'
|
||||
fi
|
||||
|
||||
test_done
|
@ -1,58 +0,0 @@
|
||||
#!/usr/bin/env zsh
|
||||
|
||||
export test_description="Testing tomb with KDF keys"
|
||||
|
||||
source ./setup
|
||||
|
||||
if test_have_prereq KDF; then
|
||||
test_export "kdf"
|
||||
test_expect_success 'Testing KDF: tomb creation' '
|
||||
tt_dig -s 20 &&
|
||||
tt_forge --tomb-pwd $DUMMYPASS --kdf 1 &&
|
||||
print $DUMMYPASS \
|
||||
| gpg --batch --passphrase-fd 0 --no-tty --no-options -d $tomb_key \
|
||||
| xxd &&
|
||||
tt_lock --tomb-pwd $DUMMYPASS
|
||||
'
|
||||
|
||||
test_expect_success 'Testing KDF: tomb passwd' '
|
||||
tt passwd -k $tomb_key \
|
||||
--unsafe --tomb-old-pwd $DUMMYPASS --tomb-pwd $DUMMYPASSNEW &&
|
||||
tt passwd -k $tomb_key \
|
||||
--unsafe --tomb-old-pwd $DUMMYPASSNEW --tomb-pwd $DUMMYPASS
|
||||
'
|
||||
|
||||
test_expect_success 'Testing KDF: tomb open & close' '
|
||||
tt_open --tomb-pwd $DUMMYPASS &&
|
||||
tt_close
|
||||
'
|
||||
fi
|
||||
|
||||
# clean to avoid overwrite errors
|
||||
# rm -f "$tomb_key" "$tomb"
|
||||
|
||||
if test_have_prereq ARGON2; then
|
||||
test_export "argon2"
|
||||
test_expect_success 'Testing KDF ARGON2: tomb creation' '
|
||||
tt_dig -s 20 &&
|
||||
tt_forge --tomb-pwd $DUMMYPASS --kdftype argon2 --kdfmem 18 --kdf 1 &&
|
||||
print $DUMMYPASS \
|
||||
| gpg --batch --passphrase-fd 0 --no-tty --no-options -d $tomb_key \
|
||||
| xxd &&
|
||||
tt_lock --tomb-pwd $DUMMYPASS
|
||||
'
|
||||
|
||||
test_expect_success 'Testing KDF ARGON2: tomb passwd' '
|
||||
tt passwd -k $tomb_key \
|
||||
--unsafe --tomb-old-pwd $DUMMYPASS --tomb-pwd $DUMMYPASSNEW &&
|
||||
tt passwd -k $tomb_key \
|
||||
--unsafe --tomb-old-pwd $DUMMYPASSNEW --tomb-pwd $DUMMYPASS
|
||||
'
|
||||
|
||||
test_expect_success 'Testing KDF ARGON2: tomb open & close' '
|
||||
tt_open --tomb-pwd $DUMMYPASS &&
|
||||
tt_close
|
||||
'
|
||||
fi
|
||||
|
||||
test_done
|
31
extras/test/31_kdf-argon2.sh
Normal file
31
extras/test/31_kdf-argon2.sh
Normal file
@ -0,0 +1,31 @@
|
||||
#!/usr/bin/env zsh
|
||||
|
||||
export test_description="Testing tomb with argon2 KDF key"
|
||||
|
||||
source ./setup
|
||||
|
||||
if test_have_prereq ARGON; then
|
||||
test_export "argon"
|
||||
test_expect_success 'Testing argon2 KDF: tomb creation' '
|
||||
tt_dig -s 20 &&
|
||||
tt_forge --tomb-pwd $DUMMYPASS --kdf argon2 &&
|
||||
print $DUMMYPASS \
|
||||
| gpg --batch --passphrase-fd 0 --no-tty --no-options -d $tomb_key \
|
||||
| xxd &&
|
||||
tt_lock --tomb-pwd $DUMMYPASS
|
||||
'
|
||||
|
||||
test_expect_success 'Testing argon2 KDF: tomb passwd' '
|
||||
tt passwd -k $tomb_key --kdf argon2 \
|
||||
--unsafe --tomb-old-pwd $DUMMYPASS --tomb-pwd $DUMMYPASSNEW &&
|
||||
tt passwd -k $tomb_key --kdf argon2 \
|
||||
--unsafe --tomb-old-pwd $DUMMYPASSNEW --tomb-pwd $DUMMYPASS
|
||||
'
|
||||
|
||||
test_expect_success 'Testing argon2 KDF: tomb open & close' '
|
||||
tt_open --tomb-pwd $DUMMYPASS &&
|
||||
tt_close
|
||||
'
|
||||
fi
|
||||
|
||||
test_done
|
@ -50,6 +50,7 @@ MEDIA="/media"
|
||||
command -v steghide > /dev/null && test_set_prereq STEGHIDE
|
||||
command -v e2fsck resize2fs > /dev/null && test_set_prereq RESIZER
|
||||
command -v tomb-kdb-pbkdf2 > /dev/null && test_set_prereq KDF
|
||||
command -v argon2 > /dev/null && test_set_prereq ARGON
|
||||
command -v qrencode > /dev/null && test_set_prereq QRENCODE
|
||||
command -v lsof > /dev/null && test_set_prereq LSOF
|
||||
command -v python3 > /dev/null && test_set_prereq PYTHON3
|
||||
|
99
tomb
99
tomb
@ -66,6 +66,7 @@ typeset -i RECOLL=1
|
||||
typeset -i QRENCODE=1
|
||||
typeset -i LSOF=1
|
||||
typeset -i ACL=1
|
||||
typeset -i ARGON2=1
|
||||
|
||||
# Default mount options
|
||||
typeset MOUNTOPTS="rw,noatime,nodev"
|
||||
@ -749,8 +750,13 @@ usage() {
|
||||
_print " -R provide GnuPG hidden recipients (separated by comma)"
|
||||
_print " --sudo super user exec alternative to sudo (doas or none)"
|
||||
|
||||
[[ $KDF == 1 ]] && {
|
||||
_print " --kdf forge keys armored against dictionary attacks"
|
||||
[[ $KDF == 1 ]] || [[ $ARGON2 == 1 ]] && {
|
||||
_print " --kdf forge keys armored against dictionary attacks (pbkdf2, argon2)"
|
||||
_print " --kdfiter Number of iterations (meaning depending on KDF algorithm) (pbkdf2, argon2)"
|
||||
}
|
||||
[[ $ARGON2 == 1 ]] && {
|
||||
_print " --kdfmem memory to be used (argon2)"
|
||||
_print " --kdfpar number of threads (argon2)"
|
||||
}
|
||||
|
||||
echo
|
||||
@ -1225,11 +1231,14 @@ get_lukskey() {
|
||||
kdf_salt="${firstline[(ws:_:)3]}"
|
||||
kdf_ic="${firstline[(ws:_:)4]}"
|
||||
kdf_mem="${firstline[(ws:_:)5]}"
|
||||
kdf_par="${firstline[(ws:_:)6]}"
|
||||
# ToDo also parse kdf_len?
|
||||
_message "Unlocking KDF key protection (::1 kdf::)" $kdf_hash
|
||||
_verbose "KDF salt: $kdf_salt"
|
||||
_verbose "KDF ic: $kdf_ic"
|
||||
_verbose "KDF mem: $kdf_mem"
|
||||
_password=$(argon2 $kdf_salt -m $kdf_mem -t $kdf_ic -l 64 -r 2>/dev/null <<<$_password)
|
||||
_verbose "KDF # threads: $kdf_par"
|
||||
_password=$(argon2 $kdf_salt -m $kdf_mem -t $kdf_ic -p $kdf_par -l 64 -r 2>/dev/null <<<$_password)
|
||||
;;
|
||||
|
||||
*)
|
||||
@ -1470,50 +1479,58 @@ gen_key() {
|
||||
fi
|
||||
|
||||
header=""
|
||||
[[ $KDF == 1 ]] && {
|
||||
[[ $KDF == 1 ]] || [[ $ARGON2 == 1 ]] && {
|
||||
{ option_is_set --kdf } && {
|
||||
# KDF is a new key strengthening technique against brute forcing
|
||||
# KDF is a key strengthening technique against brute forcing
|
||||
# see: https://github.com/dyne/Tomb/issues/82
|
||||
itertime="`option_value --kdf`"
|
||||
# removing support of floating points because they can't be type checked well
|
||||
# if [[ "$itertime" != <-> ]]; then
|
||||
# unset tombpass
|
||||
# unset tombpasstmp
|
||||
# _warning "Wrong argument for --kdf: must be an integer number (iteration seconds)."
|
||||
# _failure "Depending on the speed of machines using this tomb, use 1 to 10, or more"
|
||||
# return 1
|
||||
# fi
|
||||
# # --kdf takes one parameter: iter time (on present machine) in seconds
|
||||
# Two KDF are currently supported:
|
||||
# * pbkdf2 (time restrictive)
|
||||
# * argon2 (memory, parallelismn restrictive and through those time)
|
||||
|
||||
kdftype="`option_value --kdftype`"
|
||||
kdftype=${kdftype:-pbkdf2}
|
||||
# --kdfiter takes one integer value as parameter
|
||||
# argon2: # of iterations (default of 3);
|
||||
# pbkdf2: calculates # of iterations to reach this as time cost in seconds
|
||||
itertime="`option_value --kdfiter`"
|
||||
itertime=${itertime:-3}
|
||||
|
||||
# Generating salt (either via tomb-kdb-pbkdf2 or a shell fallback)
|
||||
if $(command -v tomb-kdb-pbkdf2-gensalt 1>/dev/null 2>/dev/null); then
|
||||
kdfsalt=`tomb-kdb-pbkdf2-gensalt`
|
||||
else
|
||||
kdfsalt=$(LC_CTYPE=C tr -cd 'a-f0-9' < /dev/random | head -c 64)
|
||||
fi
|
||||
_message "kdf salt: ::1 kdfsalt::" $kdfsalt
|
||||
|
||||
# --kdf takes one parameter: what KDF
|
||||
kdftype="`option_value --kdf`"
|
||||
case ${kdftype} in
|
||||
pbkdf2)
|
||||
pbkdf2)
|
||||
local -i microseconds
|
||||
microseconds=$(( itertime * 1000000 ))
|
||||
_success "Using KDF, iteration time: ::1 microseconds::" $microseconds
|
||||
_message "generating salt"
|
||||
pbkdf2_salt=`tomb-kdb-pbkdf2-gensalt`
|
||||
_message "calculating iterations"
|
||||
_success "Using pbkdf2 as KDF"
|
||||
_message "iteration time: ::1 microseconds::" $microseconds
|
||||
pbkdf2_iter=`tomb-kdb-pbkdf2-getiter $microseconds`
|
||||
_message "encoding the password"
|
||||
_message "iterations: ::1 pbkdf2_iter::" $pbkdf2_iter
|
||||
# We use a length of 64bytes = 512bits (more than needed!?)
|
||||
tombpass=`tomb-kdb-pbkdf2 $pbkdf2_salt $pbkdf2_iter 64 <<<"${tombpass}"`
|
||||
|
||||
header="_KDF_pbkdf2sha1_${pbkdf2_salt}_${pbkdf2_iter}_64\n"
|
||||
tombpass=`tomb-kdb-pbkdf2 $kdfsalt $pbkdf2_iter 64 <<<"${tombpass}"`
|
||||
header="_KDF_pbkdf2sha1_${kdfsalt}_${pbkdf2_iter}_64\n"
|
||||
;;
|
||||
argon2)
|
||||
_success "Using KDF Argon2"
|
||||
argon2)
|
||||
_success "Using Argon2 as KDF"
|
||||
_message "iterations: ::1 kdfiterations::" $itertime
|
||||
kdfmem="`option_value --kdfmem`"
|
||||
kdfmem=${kdfmem:-18}
|
||||
_message "memory used: 2^::1 kdfmemory::" $kdfmem
|
||||
itertime="`option_value --kdf`"
|
||||
itertime=${itertime:-3}
|
||||
kdfsalt=`tomb-kdb-pbkdf2-gensalt`
|
||||
_message "kdf salt: ::1 kdfsalt::" $kdfsalt
|
||||
_message "kdf iterations: ::1 kdfiterations::" $itertime
|
||||
tombpass=`argon2 $kdfsalt -m $kdfmem -t $itertime -l 64 -r <<<"${tombpass}"`
|
||||
header="_KDF_argon2_${kdfsalt}_${itertime}_${kdfmem}_64\n"
|
||||
kdfpar="`option_value --kdfpar`"
|
||||
kdfpar=${kdfpar:-1}
|
||||
_message "parallelismn: ::1 kdfparallel::" $kdfpar
|
||||
tombpass=`argon2 $kdfsalt -m $kdfmem -t $itertime -p $kdfpar -l 64 -r <<<"${tombpass}"`
|
||||
header="_KDF_argon2_${kdfsalt}_${itertime}_${kdfmem}_${kdfpar}_64\n"
|
||||
;;
|
||||
*)
|
||||
_warning "unrecognized KDF ::1::" $kdftype
|
||||
_warning "key won\'t be protected via a KDF implementation"
|
||||
_warning "only pbkdf2 and argon2 are valid arguments"
|
||||
;;
|
||||
esac
|
||||
}
|
||||
@ -1976,7 +1993,7 @@ forge_key() {
|
||||
$destkey $algo
|
||||
|
||||
[[ $KDF == 1 ]] && { ! option_is_set -g } && {
|
||||
_message "Using KDF to protect the key password (`option_value --kdf` rounds)"
|
||||
_message "Using KDF to protect the key password"
|
||||
}
|
||||
|
||||
TOMBKEYFILE="$destkey" # Set global variable
|
||||
@ -3129,19 +3146,19 @@ main() {
|
||||
main_opts=(q -quiet=q D -debug=D h -help=h v -version=v f -force=f -tmp: U: G: T: -no-color -unsafe g -gpgkey=g -sudo:)
|
||||
subcommands_opts[__default]=""
|
||||
# -o in open and mount is used to pass alternate mount options
|
||||
subcommands_opts[open]="n -nohook=n k: -kdf: -kdftype: -kdfmem: o: -ignore-swap -tomb-pwd: r: R: p -preserve-ownership=p"
|
||||
subcommands_opts[open]="n -nohook=n k: o: -ignore-swap -tomb-pwd: r: R: p -preserve-ownership=p"
|
||||
subcommands_opts[mount]=${subcommands_opts[open]}
|
||||
|
||||
subcommands_opts[create]="" # deprecated, will issue warning
|
||||
|
||||
# -o in forge and lock is used to pass an alternate cipher.
|
||||
subcommands_opts[forge]="-ignore-swap k: -kdf: -kdftype: -kdfmem: o: -tomb-pwd: -use-random r: R: "
|
||||
subcommands_opts[forge]="-ignore-swap k: -kdf: -kdfiter: -kdfmem: -kdfpar: o: -tomb-pwd: -use-random r: R: "
|
||||
subcommands_opts[dig]="-ignore-swap s: -size=s "
|
||||
subcommands_opts[lock]="-ignore-swap k: -kdf: -kdftype: -kdfmem: o: -tomb-pwd: r: R: -filesystem: "
|
||||
subcommands_opts[setkey]="k: -ignore-swap -kdf: -kdftype: -kdfmem: -tomb-old-pwd: -tomb-pwd: r: R: "
|
||||
subcommands_opts[lock]="-ignore-swap k: o: -tomb-pwd: r: R: -filesystem: "
|
||||
subcommands_opts[setkey]="k: -ignore-swap -tomb-old-pwd: -tomb-pwd: r: R: "
|
||||
subcommands_opts[engrave]="k: "
|
||||
|
||||
subcommands_opts[passwd]="k: -ignore-swap -kdf: -kdftype: -kdfmem: -tomb-old-pwd: -tomb-pwd: r: R: "
|
||||
subcommands_opts[passwd]="k: -ignore-swap -kdf: -kdfiter: -kdfmem: -kdfpar: -tomb-old-pwd: -tomb-pwd: r: R: "
|
||||
subcommands_opts[close]=""
|
||||
subcommands_opts[help]=""
|
||||
subcommands_opts[slam]=""
|
||||
|
Loading…
Reference in New Issue
Block a user