Add sharing support for tomb key.

A tomb key can be encrypted with more than one recipient. Therefore, a
tomb can be shared between different user. The multiple recipients are
given using the -r (or/and -R) option and must be separated by ','.

Multiple recipients can be given for the commands: forge, setket and passwd
This commit is contained in:
Alexandre Pujol 2017-02-03 17:28:56 +00:00
parent 53b7460274
commit 15164f5578
2 changed files with 82 additions and 13 deletions

View File

@ -58,7 +58,7 @@ command -v qrencode > /dev/null || QRENCODE=0
typeset -A results typeset -A results
tests=(dig forge lock badpass open close passwd chksum bind setkey recip-dig tests=(dig forge lock badpass open close passwd chksum bind setkey recip-dig
recip-forge recip-lock recip-open recip-close recip-passwd recip-resize recip-forge recip-lock recip-open recip-close recip-passwd recip-resize
recip-setkey) recip-setkey shared shared-passwd shared-setkey)
{ test $RESIZER = 1 } && { tests+=(resize) } { test $RESIZER = 1 } && { tests+=(resize) }
{ test $KDF = 1 } && { tests+=(kdforge kdfpass kdflock kdfopen) } { test $KDF = 1 } && { tests+=(kdforge kdfpass kdflock kdfopen) }
{ test $STEGHIDE = 1 } && { tests+=(stgin stgout stgopen stgpipe stgimpl { test $STEGHIDE = 1 } && { tests+=(stgin stgout stgopen stgpipe stgimpl
@ -191,6 +191,44 @@ test-tomb-recip() {
tt close recip tt close recip
} }
test-tomb-shared() {
notice "wiping all shared.tomb* in /tmp"
rm -f /tmp/shared.tomb /tmp/shared.tomb.key
notice "Testing sharing a tomb"
res=0
tt dig -s 20 /tmp/shared.tomb
{ test $? = 0 } || { res=1 }
tt forge /tmp/shared.tomb.key -r $gpgid_1,$gpgid_2 \
--ignore-swap --unsafe --use-urandom
{ test $? = 0 } || { res=1 }
tt lock /tmp/shared.tomb -k /tmp/shared.tomb.key \
--ignore-swap --unsafe -r $gpgid_1
{ test $? = 0 } || { res=1 }
tt open /tmp/shared.tomb -k /tmp/shared.tomb.key -r $gpgid_1
{ test $? = 0 } || { res=1 }
tt close shared
{ test $? = 0 } || { res=1 }
{ test $res = 0 } && { results+=(shared SUCCESS) }
notice "Testing changing recipients on a shared Tomb"
tt passwd -k /tmp/shared.tomb.key -r $gpgid_1,$gpgid_2 \
-R $gpgid_2,$gpgid_1
{ test $? = 0 } && { results+=(shared-passwd SUCCESS) }
notice "Testing setkey on a shared Tomb"
rm -f /tmp/new.shared.tomb.key
res=0
tt forge /tmp/new.shared.tomb.key -r $gpgid_1,$gpgid_2 \
--ignore-swap --unsafe --use-urandom
{ test $? = 0 } || { res=1 }
tt setkey -k /tmp/new.shared.tomb.key /tmp/shared.tomb.key /tmp/shared.tomb \
-r $gpgid_2,$gpgid_1
{ test $? = 0 } || { res=1 }
{ test $res = 0 } && { results+=(shared-setkey SUCCESS) }
}
test-bind-hooks() { test-bind-hooks() {
notice "Testing bind hooks" notice "Testing bind hooks"
@ -300,6 +338,7 @@ startloops=(`sudo losetup -a |cut -d: -f1`)
# isolated function (also called with source) # isolated function (also called with source)
test-tomb-create test-tomb-create
test-tomb-recip test-tomb-recip
test-tomb-shared
notice "Testing open with wrong password" notice "Testing open with wrong password"

52
tomb
View File

@ -825,13 +825,43 @@ _ensure_dependencies() {
# {{{ Key operations # {{{ Key operations
# $1 is the key ID we are checking # $@ is the list of all the recipient used to encrypt a tomb key
is_valid_recipients() { is_valid_recipients() {
local gpg_id="$1" # Unique argument is the GPG ID to test typeset -a recipients
recipients=($@)
_verbose "is_valid_recipients" _verbose "is_valid_recipients"
# All the keys ID must be valid (the public keys must be present in the database)
for gpg_id in ${recipients[@]}; do
gpg --list-keys "$gpg_id" &> /dev/null
[[ $? != 0 ]] && {
_warning "$gpg_id is not a valid key ID."
return 1
}
done
# At least one private key must be present
for gpg_id in $recipients; do
gpg --list-secret-keys "$gpg_id" &> /dev/null gpg --list-secret-keys "$gpg_id" &> /dev/null
return $? [[ $? = 0 ]] && {
return 0
}
done
return 1
}
# $@ is the list of all the recipient used to encrypt a tomb key
# Print the recipient arg to be used in gpg.
_recipients_arg() {
typeset -a recipients
recipients=($@)
for gpg_id in ${recipients[@]}; do
print -R -n "--recipient $gpg_id "
done
return 0
} }
# $1 is the encrypted key contents we are checking # $1 is the encrypted key contents we are checking
@ -952,9 +982,9 @@ gpg_decrypt() {
gpgpopt=(--passphrase-fd 0) gpgpopt=(--passphrase-fd 0)
{ option_is_set -r } && { { option_is_set -r } && {
local gpgkey=`option_value -r` typeset -a recipients
_verbose "using $gpgkey to decrypt a tomb key" recipients=(${(s:,:)$(option_value -r)})
{ ! is_valid_recipients "$gpgkey" } && { { is_valid_recipients $recipients } || {
_failure "You set an invalid GPG ID." _failure "You set an invalid GPG ID."
} }
gpgpass="$TOMBKEY" gpgpass="$TOMBKEY"
@ -1173,20 +1203,20 @@ gen_key() {
tombpasstmp="" tombpasstmp=""
{ option_is_set -r } && { { option_is_set -r } && {
typeset -a recipients
{ option_is_set -R } && { { option_is_set -R } && {
local gpgkey=`option_value -R` recipients=(${(s:,:)$(option_value -R)})
} || { } || {
local gpgkey=`option_value -r` recipients=(${(s:,:)$(option_value -r)})
} }
_verbose "using $gpgkey to encrypt a tomb key" { is_valid_recipients $recipients } || {
{ is_valid_recipients "$gpgkey" } || {
_failure "You set an invalid GPG ID." _failure "You set an invalid GPG ID."
} }
# Set gpg inputs and options # Set gpg inputs and options
gpgpass="$TOMBSECRET" gpgpass="$TOMBSECRET"
gpgopt=(--encrypt --recipient "$gpgkey") gpgopt=(--encrypt `_recipients_arg $recipients`)
opt='' opt=''
} || { } || {
if [ "$1" = "" ]; then if [ "$1" = "" ]; then